[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 collections import defaultdict
from .privmodes import PrivModes
from .Exceptions import IllegalInstructionTrap
from .Exceptions import InstructionAccessFault
from ..helpers import to_unsigned
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):
code: int
@ -10,17 +21,28 @@ class CpuTrap(BaseException):
"""
The isInterrupt bit in the mstatus register
"""
mtval: int
"""
contents of the mtval register
"""
def __init__(self, interrupt: int, code: int, mtval=0):
assert 0 <= interrupt <= 1
type: CpuTrapType
"""
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.mtval = mtval
self.priv = priv
self.type = type
@property
def mcause(self):
@ -28,17 +50,20 @@ class CpuTrap(BaseException):
class IllegalInstructionTrap(CpuTrap):
def __init__(self):
super().__init__(0, 2, 0)
def __init__(self, ins: 'ElfInstruction'):
super().__init__(2, ins.encoded, CpuTrapType.EXCEPTION)
class InstructionAddressMisalignedTrap(CpuTrap):
def __init__(self, addr: int):
super().__init__(0, 0, addr)
super().__init__(0, addr, CpuTrapType.EXCEPTION)
class InstructionAccessFault(CpuTrap):
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:
return
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
def _check_interrupt(self):

@ -49,7 +49,7 @@ class PrivRV32I(RV32I):
def instruction_mret(self, ins: 'LoadedInstruction'):
if self.cpu.mode != PrivModes.MACHINE:
print("MRET not inside machine level code!")
raise IllegalInstructionTrap()
raise IllegalInstructionTrap(ins)
# retore mie
mpie = self.cpu.csr.get_mstatus('mpie')
self.cpu.csr.set_mstatus('mie', mpie)
@ -61,21 +61,21 @@ class PrivRV32I(RV32I):
self.cpu.pc = mepc
def instruction_uret(self, ins: 'LoadedInstruction'):
raise IllegalInstructionTrap()
raise IllegalInstructionTrap(ins)
def instruction_sret(self, ins: 'LoadedInstruction'):
raise IllegalInstructionTrap()
raise IllegalInstructionTrap(ins)
def instruction_scall(self, ins: 'LoadedInstruction'):
"""
Overwrite the scall from userspace RV32I
"""
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:
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:
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'):
rs1, rs2, dst = self.parse_rs_rs_imm(ins)

Loading…
Cancel
Save