github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/riscv/exception.go (about)

     1  // RISC-V processor support
     2  // https://github.com/usbarmory/tamago
     3  //
     4  // Copyright (c) WithSecure Corporation
     5  // https://foundry.withsecure.com
     6  //
     7  // Use of this source code is governed by the license
     8  // that can be found in the LICENSE file.
     9  
    10  package riscv
    11  
    12  import (
    13  	"unsafe"
    14  )
    15  
    16  // RISC-V exception codes (non-interrupt)
    17  // (Table 3.6 - Volume II: RISC-V Privileged Architectures V20211203).
    18  const (
    19  	InstructionAddressMisaligned = 0
    20  	InstructionAccessFault       = 1
    21  	IllegalInstruction           = 2
    22  	Breakpoint                   = 3
    23  	LoadAddressMisaligned        = 4
    24  	LoadAccessFault              = 5
    25  	StoreAddressMisaligned       = 6
    26  	StoreAccessFault             = 7
    27  	EnvironmentCallFromU         = 8
    28  	EnvironmentCallFromS         = 9
    29  	EnvironmentCallFromM         = 11
    30  	InstructionPageFault         = 12
    31  	LoadPageFault                = 13
    32  	StorePageFault               = 15
    33  )
    34  
    35  // defined in exception.s
    36  func set_mtvec(addr uint64)
    37  func set_stvec(addr uint64)
    38  func read_mepc() uint64
    39  func read_sepc() uint64
    40  func read_mcause() uint64
    41  func read_scause() uint64
    42  
    43  type ExceptionHandler func()
    44  
    45  func vector(fn ExceptionHandler) uint64 {
    46  	return **((**uint64)(unsafe.Pointer(&fn)))
    47  }
    48  
    49  // DefaultExceptionHandler handles an exception by printing the exception
    50  // program counter and trap cause before panicking.
    51  func DefaultExceptionHandler() {
    52  	mcause := read_mcause()
    53  	size := XLEN - 1
    54  
    55  	irq := int(mcause >> size)
    56  	code := int(mcause) & ^(1 << size)
    57  
    58  	print("machine exception: pc ", int(read_mepc()), " interrupt ", irq, " code ", code, "\n")
    59  	panic("unhandled exception")
    60  }
    61  
    62  // DefaultSupervisorExceptionHandler handles an exception by printing the
    63  // exception program counter and trap cause before panicking.
    64  func DefaultSupervisorExceptionHandler() {
    65  	scause := read_scause()
    66  	size := XLEN - 1
    67  
    68  	irq := int(scause >> size)
    69  	code := int(scause) & ^(1 << size)
    70  
    71  	print("supervisor exception: pc ", int(read_sepc()), " interrupt ", irq, " code ", code, "\n")
    72  	panic("unhandled exception")
    73  }
    74  
    75  //go:nosplit
    76  func (cpu *CPU) initExceptionHandler() {
    77  	set_mtvec(vector(DefaultExceptionHandler))
    78  }
    79  
    80  // SetExceptionHandler updates the CPU machine trap vector vector with the
    81  // address of the argument function.
    82  func (cpu *CPU) SetExceptionHandler(fn ExceptionHandler) {
    83  	set_mtvec(vector(fn))
    84  }
    85  
    86  // SetSupervisorExceptionHandler updates the CPU supervisor trap vector vector
    87  // with the address of the argument function.
    88  func (cpu *CPU) SetSupervisorExceptionHandler(fn ExceptionHandler) {
    89  	set_stvec(vector(fn))
    90  }