ducky.cpu package¶
Subpackages¶
Module contents¶
-
class
ducky.cpu.
CPU
(machine, cpuid, memory_controller, cores=1)[source]¶ Bases:
ducky.interfaces.ISnapshotable
,ducky.interfaces.IMachineWorker
-
class
ducky.cpu.
CPUCore
(coreid, cpu, memory_controller)[source]¶ Bases:
ducky.interfaces.ISnapshotable
,ducky.interfaces.IMachineWorker
This class represents the main workhorse, one of CPU cores. Reads instructions, executes them, has registers, caches, handles interrupts, ...
Parameters: - coreid (int) – id of this core. Usually, it’s its serial number but it has no special meaning.
- cpu (ducky.cpu.CPU) – CPU that owns this core.
- memory_controller (ducky.mm.MemoryController) – use this controller to access main memory.
-
_CPUCore__get_flags
()¶
-
_CPUCore__set_flags
(flags)¶
-
_enter_exception
(index, *args)[source]¶ Prepare CPU for handling exception routine. CPU core loads new
IP
andSP
from proper entry of EVT. OldSP
andFLAGS
are saved on the exception stack, and new call frame is created. Privileged mode flag is set, hardware interrupt flag is cleared.Then, if exception provides its routine with some arguments, these arguments are pushed on the stack.
Exception stack layout then looks like this (original stack is left untouched):
+---------+ <= EVT SP | SP | +---------+ | FLAGS | +---------+ | IP | +---------+ | FP | +---------+ <= FP | arg1 | +---------+ | ... | +---------+ | argN | +---------+ <= SP | ... | +---------+
Parameters: - index (int) – exception ID - EVT index.
- args (u32_t) – if present, these values will be pushed onto the stack.
-
_exit_exception
()[source]¶ Restore CPU state after running an exception routine. Call frame is destroyed, registers are restored. Clearing routine arguments is responsibility of the routine.
-
_handle_exception
(exc, index, *args)[source]¶ This method provides CPU exception classes with a simple recipe on how to deal with the exception:
- tell processor to start exception dance,
- if the exception is raised again, tell processor to plan double fault routine,
- and if yet another exception is raised, halt the core.
-
_raw_pop
()[source]¶ Pop value from stack. 4 byte number is read from address in
SP
, thenSP
is incremented by four.Returns: popped value Return type: u32
-
_raw_push
(val)[source]¶ Push value on stack.
SP
is decremented by four, and value is written at this new address.Parameters: val (u32) – value to be pushed
-
check_protected_ins
()[source]¶ Raise
AccessViolationError
if core is not running in privileged mode.This method should be used by instruction handlers that require privileged mode, e.g. protected instructions.
Raises: ducky.errors.PrivilegedInstructionError – if the core is not in privileged mode
-
create_frame
()[source]¶ Creates new call stack frame, by performing the following operations:
- push
IP
- push
FP
- set
FP
toSP
(i.e.SP
before this method + 2 pushes)
Stack layout then looks like this:
+---------+ | IPx | +---------+ | FPx | +---------+ <= FPy | ... | +---------+ <= original SP | IPy | +---------+ | FPy | +---------+ <= SP, FP | ... | +---------+
FP
then points to the newly created frame, to the savedFP
in particular, and this savedFP
points to its predecesor, thus forming a chain.- push
-
destroy_frame
()[source]¶ Destroys current call stack frame by popping values from the stack, reversing the list of operations performed by
ducky.cpu.CPUCore.create_frame()
:- pop
FP
- pop
IP
After this,
FP
points to the frame from which the instruction that created the currently destroyed frame was executed, and restoredIP
points to the next instruction.Raises: InvalidFrameError – if frame checking is enabled, current SP
is compared with savedFP
to see, if the stack was clean before leaving the frame. This error indicated there is some value left on stack whenret
orretint
were executed. Usually, this signals missingpop
to complement one of previous ``push``es.- pop
-
flags
¶
-
instruction_set
¶
-
irq
(index)[source]¶ This is a wrapper for _enter_exception, for device drivers to call when hardware interrupt arrives.
Parameters: index (int) – exception ID - EVT index
-
reset
(new_ip=0)[source]¶ Reset core’s state. All registers are set to zero, all flags are set to zero, except
HWINT
flag which is set to one, andIP
is set to requested value.Parameters: new_ip (u32_t) – new IP
value, defaults to zero
-
class
ducky.cpu.
CPUCoreState
[source]¶ Bases:
ducky.snapshot.SnapshotNode
-
class
ducky.cpu.
CPUState
(*fields)[source]¶ Bases:
ducky.snapshot.SnapshotNode
-
class
ducky.cpu.
CoreFlags
[source]¶ Bases:
ducky.util.Flags
-
_flags
= ['privileged', 'hwint_allowed', 'equal', 'zero', 'overflow', 'sign']¶
-
_labels
= 'PHEZOS'¶
-
-
ducky.cpu.
DEFAULT_CORE_INST_CACHE_SIZE
= 256¶ Default size of core instruction cache, in instructions.
-
ducky.cpu.
DEFAULT_EVT_ADDRESS
= 0¶ Default EVT address
-
ducky.cpu.
DEFAULT_PT_ADDRESS
= 65536¶ Default PT address
-
class
ducky.cpu.
InstructionCache_Base
(mmu, *args, **kwargs)[source]¶ Bases:
ducky.util.LoggingCapable
,dict
Simple instruction cache class, based on a dictionary, with a limited size.
Parameters: core (ducky.cpu.CPUCore) – CPU core that owns this cache.
-
class
ducky.cpu.
InstructionCache_Full
(mmu, *args, **kwargs)[source]¶ Bases:
ducky.util.LoggingCapable
,list
Simple instruction cache class, based on a list, with unlimited size.
Parameters: core (ducky.cpu.CPUCore) – CPU core that owns this cache.
-
class
ducky.cpu.
InterruptVector
(ip=0, sp=0)[source]¶ Bases:
object
Interrupt vector table entry.
-
SIZE
= 8¶
-
-
class
ducky.cpu.
MMU
(core, memory_controller)[source]¶ Bases:
ducky.interfaces.ISnapshotable
Memory management unit (aka MMU) provides a single point handling all core’s memory operations. All memory reads and writes must go through this unit, which is then responsible for all translations, access control, and caching.
Parameters: - core (ducky.cpu.CPUCore) – parent core.
- memory_controller (ducky.mm.MemoryController) – memory controller that provides access to the main memory.
- memory.force-aligned-access (bool) – if set, MMU will disallow unaligned
reads and writes.
False
by default. - cpu.pt-address (int) – base address of page table.
ducky.cpu.DEFAULT_PT_ADDRESS
by default. - cpu.pt-enabled (bool) – if set, CPU core will start with page table
enabled.
False
by default.
-
_check_access
(access, addr, align=None)[source]¶ Check attempted access against several criteria:
- PT is enabled - disabled PT implies different set of read/write methods that don’t use this method to check access
- access alignment if correct alignment is required
- privileged access implies granted access
- corresponding PTE settings
Parameters: - access –
read
,write
orexecute
. - addr (int) – memory address.
- align (int) – if set, operation is expected to be aligned to this boundary.
Raises: - ducky.errors.UnalignedAccessError – when unaligned access is not allowed, but requested.
- ducky.errors.MemoryAccessError – when access is denied.
-
_fetch_instr
(addr)[source]¶ Read instruction from memory. This method is responsible for the real job of fetching instructions and filling the cache.
Parameters: addr (u24) – absolute address to read from Returns: instruction Return type: InstBinaryFormat_Master
-
_fetch_instr_jit
(addr)[source]¶ Read instruction from memory. This method is responsible for the real job of fetching instructions and filling the cache.
Parameters: addr (u24) – absolute address to read from Returns: instruction Return type: InstBinaryFormat_Master
-
_get_pte
(addr)[source]¶ Find out PTE for particular physical address. If PTE is not in internal PTE cache, it is fetched from PTE table.
Parameters: addr (int) – memory address.
-
_set_access_methods
()[source]¶ Set parent core’s memory-access methods to proper shortcuts. Methods named
MEM_{IN,OUT}{8,16,32}
will be set to corresponding MMU methods.
-
pt_enabled
¶
-
ducky.cpu.
do_log_cpu_core_state
(core, logger=None, disassemble=True, inst_set=None)[source]¶ Log state of a CPU core. Content of its registers, and other interesting or useful internal variables are logged.
Parameters: - core (ducky.cpu.CPUCore) – core whose state should be logged.
- logger – called for each line of output to actualy log it. By default,
core’s
ducky.cpu.CPUCore.DEBUG()
method is used.
-
ducky.cpu.
log_cpu_core_state
(*args, **kwargs)[source]¶ This is a wrapper for ducky.cpu.do_log_cpu_core_state function. Its main purpose is to be removed when debug mode is not set, therefore all debug calls of ducky.cpu.do_log_cpu_core_state will disappear from code, making such code effectively “quiet”.