kernel-mode #1
@ -1,7 +1,7 @@
|
|||||||
from typing import Dict, Union, Callable, Optional
|
from typing import Dict, Union, Callable, Optional
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from .privmodes import PrivModes
|
from .privmodes import PrivModes
|
||||||
from .Exceptions import IllegalInstructionTrap
|
from .Exceptions import InstructionAccessFault
|
||||||
from ..helpers import to_unsigned
|
from ..helpers import to_unsigned
|
||||||
|
|
||||||
MSTATUS_OFFSETS = {
|
MSTATUS_OFFSETS = {
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
from typing import Optional
|
from typing import Optional, NewType
|
||||||
|
from enum import Enum
|
||||||
|
from .privmodes import PrivModes
|
||||||
|
|
||||||
|
import typing
|
||||||
|
if typing.TYPE_CHECKING:
|
||||||
|
from .ElfLoader import ElfInstruction
|
||||||
|
|
||||||
|
class CpuTrapType(Enum):
|
||||||
|
TIMER = 1
|
||||||
|
SOFTWARE = 2
|
||||||
|
EXTERNAL = 3
|
||||||
|
EXCEPTION = 4
|
||||||
|
|
||||||
class CpuTrap(BaseException):
|
class CpuTrap(BaseException):
|
||||||
code: int
|
code: int
|
||||||
@ -10,17 +21,28 @@ class CpuTrap(BaseException):
|
|||||||
"""
|
"""
|
||||||
The isInterrupt bit in the mstatus register
|
The isInterrupt bit in the mstatus register
|
||||||
"""
|
"""
|
||||||
|
|
||||||
mtval: int
|
mtval: int
|
||||||
"""
|
"""
|
||||||
contents of the mtval register
|
contents of the mtval register
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, interrupt: int, code: int, mtval=0):
|
type: CpuTrapType
|
||||||
assert 0 <= interrupt <= 1
|
"""
|
||||||
|
The type (timer, external, software) of the trap
|
||||||
|
"""
|
||||||
|
|
||||||
self.interrupt = interrupt
|
priv: PrivModes
|
||||||
|
"""
|
||||||
|
The privilege level this trap targets
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, code: int, mtval, type: CpuTrapType, priv: PrivModes = PrivModes.MACHINE):
|
||||||
|
self.interrupt = 0 if type == CpuTrapType.EXCEPTION else 1
|
||||||
self.code = code
|
self.code = code
|
||||||
self.mtval = mtval
|
self.mtval = mtval
|
||||||
|
self.priv = priv
|
||||||
|
self.type = type
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mcause(self):
|
def mcause(self):
|
||||||
@ -28,17 +50,20 @@ class CpuTrap(BaseException):
|
|||||||
|
|
||||||
|
|
||||||
class IllegalInstructionTrap(CpuTrap):
|
class IllegalInstructionTrap(CpuTrap):
|
||||||
def __init__(self):
|
def __init__(self, ins: 'ElfInstruction'):
|
||||||
super().__init__(0, 2, 0)
|
super().__init__(2, ins.encoded, CpuTrapType.EXCEPTION)
|
||||||
|
|
||||||
|
|
||||||
class InstructionAddressMisalignedTrap(CpuTrap):
|
class InstructionAddressMisalignedTrap(CpuTrap):
|
||||||
def __init__(self, addr: int):
|
def __init__(self, addr: int):
|
||||||
super().__init__(0, 0, addr)
|
super().__init__(0, addr, CpuTrapType.EXCEPTION)
|
||||||
|
|
||||||
|
|
||||||
class InstructionAccessFault(CpuTrap):
|
class InstructionAccessFault(CpuTrap):
|
||||||
def __init__(self, addr: int):
|
def __init__(self, addr: int):
|
||||||
super().__init__(0, 1, addr)
|
super().__init__(1, addr, CpuTrapType.EXCEPTION)
|
||||||
|
|
||||||
|
|
||||||
|
class TimerInterrupt(CpuTrap):
|
||||||
|
def __init(self):
|
||||||
|
super().__init__(7, 0, CpuTrapType.TIMER)
|
||||||
|
@ -169,7 +169,7 @@ class PrivCPU(CPU):
|
|||||||
if not self._time_interrupt_enabled:
|
if not self._time_interrupt_enabled:
|
||||||
return
|
return
|
||||||
if self._time_timecmp < (time.perf_counter_ns() // self.TIME_RESOLUTION_NS) - self._time_start:
|
if self._time_timecmp < (time.perf_counter_ns() // self.TIME_RESOLUTION_NS) - self._time_start:
|
||||||
self.pending_traps.append(CpuTrap(1, 7, 0))
|
self.pending_traps.append(TimerInterrupt())
|
||||||
self._time_interrupt_enabled = False
|
self._time_interrupt_enabled = False
|
||||||
|
|
||||||
def _check_interrupt(self):
|
def _check_interrupt(self):
|
||||||
|
@ -49,7 +49,7 @@ class PrivRV32I(RV32I):
|
|||||||
def instruction_mret(self, ins: 'LoadedInstruction'):
|
def instruction_mret(self, ins: 'LoadedInstruction'):
|
||||||
if self.cpu.mode != PrivModes.MACHINE:
|
if self.cpu.mode != PrivModes.MACHINE:
|
||||||
print("MRET not inside machine level code!")
|
print("MRET not inside machine level code!")
|
||||||
raise IllegalInstructionTrap()
|
raise IllegalInstructionTrap(ins)
|
||||||
# retore mie
|
# retore mie
|
||||||
mpie = self.cpu.csr.get_mstatus('mpie')
|
mpie = self.cpu.csr.get_mstatus('mpie')
|
||||||
self.cpu.csr.set_mstatus('mie', mpie)
|
self.cpu.csr.set_mstatus('mie', mpie)
|
||||||
@ -61,21 +61,21 @@ class PrivRV32I(RV32I):
|
|||||||
self.cpu.pc = mepc
|
self.cpu.pc = mepc
|
||||||
|
|
||||||
def instruction_uret(self, ins: 'LoadedInstruction'):
|
def instruction_uret(self, ins: 'LoadedInstruction'):
|
||||||
raise IllegalInstructionTrap()
|
raise IllegalInstructionTrap(ins)
|
||||||
|
|
||||||
def instruction_sret(self, ins: 'LoadedInstruction'):
|
def instruction_sret(self, ins: 'LoadedInstruction'):
|
||||||
raise IllegalInstructionTrap()
|
raise IllegalInstructionTrap(ins)
|
||||||
|
|
||||||
def instruction_scall(self, ins: 'LoadedInstruction'):
|
def instruction_scall(self, ins: 'LoadedInstruction'):
|
||||||
"""
|
"""
|
||||||
Overwrite the scall from userspace RV32I
|
Overwrite the scall from userspace RV32I
|
||||||
"""
|
"""
|
||||||
if self.cpu.mode == PrivModes.USER:
|
if self.cpu.mode == PrivModes.USER:
|
||||||
raise CpuTrap(0, 8) # ecall from U mode
|
raise CpuTrap(8, 0, CpuTrapType.SOFTWARE, self.cpu.mode) # ecall from U mode
|
||||||
elif self.cpu.mode == PrivModes.SUPER:
|
elif self.cpu.mode == PrivModes.SUPER:
|
||||||
raise CpuTrap(0, 9) # ecall from S mode - should not happen
|
raise CpuTrap(9, 0, CpuTrapType.SOFTWARE, self.cpu.mode) # ecall from S mode - should not happen
|
||||||
elif self.cpu.mode == PrivModes.MACHINE:
|
elif self.cpu.mode == PrivModes.MACHINE:
|
||||||
raise CpuTrap(0, 11) # ecall from M mode
|
raise CpuTrap(11, 0, CpuTrapType.SOFTWARE, self.cpu.mode) # ecall from M mode
|
||||||
|
|
||||||
def instruction_beq(self, ins: 'LoadedInstruction'):
|
def instruction_beq(self, ins: 'LoadedInstruction'):
|
||||||
rs1, rs2, dst = self.parse_rs_rs_imm(ins)
|
rs1, rs2, dst = self.parse_rs_rs_imm(ins)
|
||||||
|
Loading…
Reference in New Issue
Block a user