[Priv] overhauled instruction architecture

kernel-mode
Anton Lydike 4 years ago
parent c963fe3989
commit de261c4c43

@ -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
"""
priv: PrivModes
"""
The privilege level this trap targets
"""
self.interrupt = interrupt 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…
Cancel
Save