priv: added __main__ script to module which correctly configures the cpu depending on --kernel or --image options

kernel-mode
Anton Lydike 3 years ago
parent 0651eabe18
commit f2d07f90b5

@ -2,7 +2,7 @@
Laods a memory image with debug information into memory
"""
from ..MMU import MMU
from .PrivMMU import PrivMMU
from ..Config import RunConfig
from ..Executable import Executable, LoadedExecutable, LoadedMemorySection, LoadedInstruction, MemoryFlags
from .ElfLoader import ElfInstruction, ElfLoadedMemorySection, InstructionAccessFault, InstructionAddressMisalignedTrap
@ -10,6 +10,7 @@ from ..decoder import decode
from ..IO.IOModule import IOModule
from .privmodes import PrivModes
from ..colors import FMT_ERROR, FMT_NONE
import json
from functools import lru_cache
from typing import Dict, List, Tuple, Optional, TYPE_CHECKING
@ -18,26 +19,37 @@ if TYPE_CHECKING:
from .PrivCPU import PrivCPU
class ContinuousMMU(MMU):
class MemoryImageMMU(PrivMMU):
io: List[IOModule]
data: bytearray
io_start: int
debug_info: Dict[str, Dict[str, str]]
debug_info: Dict[str, Dict[str, Dict[str, str]]]
def __init__(self, file_name: str, io_start: int = 0xFF0000):
super(MemoryImageMMU, self).__init__(conf=RunConfig())
with open(file_name, 'rb') as memf:
data = memf.read()
with open(file_name + '.dbg', 'r') as dbgf:
debug_info: Dict = json.load(dbgf)
def __init__(self, data: bytes, debug_info: Dict, cpu, io_start: int = 0xFF0000):
super(ContinuousMMU, self).__init__(conf=RunConfig())
self.cpu: 'PrivCPU' = cpu
self.data = bytearray(data)
# TODO: super wasteful memory allocation happening here
if len(data) < io_start:
self.data += bytearray(io_start - len(data))
self.debug_info = debug_info
self.io_start = io_start
self.io = list()
self.kernel_end = 0
for start, name in debug_info['sections'].items():
if name.startswith('programs'):
self.kernel_end = int(start)
break
def get_entrypoint(self):
try:
start = self.debug_info['symbols']['kernel'].get('_start', None)
if start is not None:
return start
return self.debug_info['symbols']['kernel'].get('_ftext')
except KeyError:
print(FMT_ERROR + '[MMU] cannot find kernel entry in debug information! Falling back to 0x100' + FMT_NONE)
return 0x100
@lru_cache(maxsize=2048)
def read_ins(self, addr: int) -> ElfInstruction:
@ -66,13 +78,6 @@ class ContinuousMMU(MMU):
print(FMT_ERROR + "[MMU] possible null dereference (write {:x}) from (pc={:x},sec={},rel={:x})".format(
addr, pc, text_sec.owner + ':' + text_sec.name, pc - text_sec.base
) + FMT_NONE)
if addr < self.kernel_end:
if self.cpu.mode != PrivModes.MACHINE:
pc = self.cpu.pc
text_sec = self.get_sec_containing(pc)
print(FMT_ERROR + "[MMU] kernel access to {:x} from outside kernel mode! (pc={:x},sec={},rel={:x})".format(
addr, pc, text_sec.owner + ':' + text_sec.name, pc - text_sec.base
) + FMT_NONE)
if addr >= self.io_start:
return self.io_at(addr).write(addr, data, size)
@ -88,7 +93,7 @@ class ContinuousMMU(MMU):
self.io.append(io)
def __repr__(self):
return "ImageMMU()"
return "MemoryImageMMU()"
@lru_cache(maxsize=32)
def get_sec_containing(self, addr: int) -> Optional[LoadedMemorySection]:

@ -8,7 +8,7 @@ import time
from riscemu.CPU import *
from .CSR import CSR
from .ElfLoader import ElfExecutable
from .ImageLoader import ContinuousMMU
from .ImageLoader import MemoryImageMMU
from .Exceptions import *
from .PrivMMU import PrivMMU
from ..IO import TextIO
@ -47,22 +47,19 @@ class PrivCPU(CPU):
the equivalent of "1 byte" (this is actually impossible)
"""
def __init__(self, conf):
def __init__(self, conf, mmu: PrivMMU):
super().__init__(conf, [PrivRV32I, RV32M])
self.mode: PrivModes = PrivModes.MACHINE
with open('mem.img', 'rb') as memf:
data = memf.read()
with open('mem.img.dbg', 'r') as dbgf:
debug_info = json.load(dbgf)
mmu.set_cpu(self)
self.pc = mmu.get_entrypoint()
self.mmu = mmu
self.mmu = ContinuousMMU(data, debug_info, self)
self.pc = 0x100
self.mmu.add_io(TextIO.TextIO(0xff0000, 64))
self.syscall_int = None
if hasattr(self.mmu, 'add_io'):
self.mmu.add_io(TextIO.TextIO(0xff0000, 64))
self.syscall_int = None
self.launch_debug = False
self.pending_traps: List[CpuTrap] = list()
self._time_start = 0
@ -87,7 +84,7 @@ class PrivCPU(CPU):
self.launch_debug = True
self.pc += self.INS_XLEN
else:
print(FMT_ERROR + "[CPU] excpetion caught at 0x{:08X}: {}:".format(self.pc - 1, ins) + FMT_NONE)
print(FMT_ERROR + "[CPU] exception caught at 0x{:08X}: {}:".format(self.pc - 1, ins) + FMT_NONE)
print(ex.message())
if self.conf.debug_on_exception:
self.launch_debug = True

@ -1,13 +1,29 @@
from ..MMU import *
from abc import abstractmethod
import typing
from .ElfLoader import ElfExecutable
if typing.TYPE_CHECKING:
from .PrivCPU import PrivCPU
class PrivMMU(MMU):
cpu: 'PrivCPU'
@abstractmethod
def get_entrypoint(self) -> int:
raise
def set_cpu(self, cpu: 'PrivCPU'):
self.cpu = cpu
class LoadedElfMMU(PrivMMU):
def __init__(self, elf: ElfExecutable):
super(PrivMMU, self).__init__(conf=RunConfig())
super().__init__(conf=RunConfig())
self.entrypoint = elf.symbols['_start']
self.binaries.append(elf)
for sec in elf.sections:
@ -18,3 +34,6 @@ class PrivMMU(MMU):
def allocate_section(self, name: str, req_size: int, flag: MemoryFlags):
raise NotImplementedError("Not supported!")
def get_entrypoint(self):
return self.entrypoint

@ -1,4 +1,7 @@
from .PrivCPU import PrivCPU, RunConfig
from .ImageLoader import MemoryImageMMU
from .PrivMMU import LoadedElfMMU
from .ElfLoader import ElfExecutable
from ..Tokenizer import RiscVInput
from ..ExecutableParser import ExecutableParser
@ -8,14 +11,23 @@ import sys
if __name__ == '__main__':
import argparse
#parser = argparse.ArgumentParser(description='RISC-V privileged architecture emulator', prog='riscemu')
parser = argparse.ArgumentParser(description='RISC-V privileged architecture emulator', prog='riscemu')
#parser.add_argument('--kernel', type=str, help='Kernel elf loaded with user programs', nargs='?')
#parser.add_argument('--image', type=str, help='Memory image containing kernel', nargs='?')
parser.add_argument('--kernel', type=str, help='Kernel elf loaded with user programs', nargs='?')
parser.add_argument('--image', type=str, help='Memory image containing kernel', nargs='?')
#args = parser.parse_args()
args = parser.parse_args()
mmu = None
cpu = PrivCPU(RunConfig())
if args.kernel is not None:
mmu = LoadedElfMMU(ElfExecutable(args.kernel))
elif args.image is not None:
mmu = MemoryImageMMU(args.image)
if mmu is None:
print("You must specify one of --kernel or --image for running in privilege mode!")
cpu = PrivCPU(RunConfig(), mmu)
cpu.run()

Loading…
Cancel
Save