Source code for ducky.cpu.coprocessor.control

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)