import enum
from ...interfaces import ISnapshotable
from ..import CPUException
from . import Coprocessor
from ...errors import AccessViolationError
from ...mm import u32_t
from ...util import Flags
[docs]class ReadOnlyRegisterError(CPUException):
def __init__(self, r, *args, **kwargs):
super(ReadOnlyRegisterError, self).__init__('Register cr{:d} is read-only.'.format(r), *args, **kwargs)
[docs]class WriteOnlyRegisterError(CPUException):
def __init__(self, r, *args, **kwargs):
super(WriteOnlyRegisterError, self).__init__('Register cr{:d} is write-only.'.format(r), *args, **kwargs)
[docs]class ControlRegisters(enum.IntEnum):
CR0 = 0 # CPUID
CR1 = 1 # Interrupt Vector Table address
CR2 = 2 # Page Table address
CR3 = 3 # Flags
[docs]class CoreFlags(Flags):
_flags = ['pt_enabled', 'jit']
_labels = 'PJ'
[docs]class ControlCoprocessor(ISnapshotable, Coprocessor):
[docs] def read_cr0(self):
return u32_t((self.core.cpu.id << 16) | self.core.id).value
[docs] def read_cr1(self):
return u32_t(self.core.ivt_address).value
[docs] def write_cr1(self, address):
self.core.ivt_address = address
[docs] def read_cr2(self):
return u32_t(self.core.mmu.pt_address).value
[docs] def write_cr2(self, address):
self.core.mmu.pt_address = address
[docs] def read_cr3(self):
return CoreFlags.create(pt_enabled = self.core.mmu.pt_enabled, jit = self.core.cpu.machine.config.getbool('machine', 'jit', False)).to_int()
[docs] def write_cr3(self, value):
flags = CoreFlags.from_int(value)
self.core.mmu.pt_enabled = flags.pt_enabled
[docs] def read(self, r):
if not self.core.privileged:
raise AccessViolationError('It is not allowed to read control registers in non-privileged mode')
handler = 'read_cr%i' % (r.value if isinstance(r, ControlRegisters) else r)
if not hasattr(self, handler):
raise WriteOnlyRegisterError(r)
return getattr(self, handler)()
[docs] def write(self, r, value):
if not self.core.privileged:
raise AccessViolationError('It is not allowed to modify control registers in non-privileged mode')
handler = 'write_cr%i' % (r.value if isinstance(r, ControlRegisters) else r)
if not hasattr(self, handler):
raise ReadOnlyRegisterError(r)
return getattr(self, handler)(value)