QEMU CPU States (appcert)
This page aims to provide insight into the CPU state models of QEMU. You can expect analysis from X86 and ARM CPU models.
Common CPU Part
A CPU-model is target-dependent. In target-<ISA>/cpu.h, each target system provides its own cpu state model. Nevertheless, there are target-independent parts which are defined in cpu-defs.h. First, the common part is analysed.
CPUTLBEntry: TLB means Tranlation lookaside buffer. CPUTLBEntry is a way to speed up finding the host virtual address of a given guest virtual address through caching.
TranslationBlock: Each cpu model also holds pointers to the current TranslationBlock
current_tb and to the TB-cache
tb_jmp_cache to speed up emulation.
Exception Makros: 4 Exceptions are defined.
#define EXCP_INTERRUPT 0x10000 /* async interruption */ #define EXCP_HLT 0x10001 /* hlt instruction reached */ #define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */ #define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */
X86 CPU State Model
32bit/64bit: Depending on the defined target, 32bit or 64bit cpu-models are compiled (this is decided with preprocessor statements).
registers: Symbolic constants are defined to make it easier to access the general purpose registers. 32bit: EAX, EBX, ECX, EDX 16 bit (2x8): (AH,AL),(BH,BL), (CH,CL) , (DH,DL)
|31..16|15-8|7-0| |AH.|AL.| |AX.....| |EAX............|
Source: http://stackoverflow.com/questions/228200/x86-assembly-registers-why-do-they-work-the-way-they-do/228367#228367 And also 16-bit-segment registers:
CS ............. Holds code segment where program runs DS ............. Holds data segment that program accesses ES - FS - GS ... Extra segmentation registers for far pointer addressing (e.g., video memory)
masks to access EFLAGS: Masks to access bits of the EFLAGS register. EFLAGS is used to hold states of parameters of the last instruction. For example, to access the Carry flag, you can use the mask CC_C which is: 0x0001 (0b00000000000000000001), i.e. the least significant bit.
hidden flags Several "hidden flag"-shifts and their masks are defined. Hidden Flags are internally used by QEMU.
CPUID - feature bits CPUID is an opcode which enables to determine all features of the CPU as well as the vendor and the model. Masks to access CPUID bits are defined.
Additional exceptions Additional 19 exceptions are defined + one exception which is only used in user mode emulation (which is not relevant for us).
Suspended Update of Condition Code Register: The official QEMU paper describes that the condition code register (which is part of EFLAGS register in X86) is not updated after each instruction to save performance. Instead, three variables store the operand
CC_SRC, the operation
CC_OPTand the result of the instruction
CC_DST. When needed from later instructions, the condition code register can be updated.
Registers are stored in an array
regs of size 8 (32 bit) or size 16 (64 bit).
EIP is the Index Pointer which holds the offset to the next instruction
SegmentCache' helps to simulate Segmentation. On X86, linear address space can be separated into segments (e.g., code segment, data segment, ...) which can be used separately and with different permissions. A good description of Segmentation can be found in Intel Software Developer’s Manual Volume 3 (Section 3.1,3.2 - Memory Management)
Other The state of the FPU, The APIC state, the processor features (CPUID), hidden flags.
How S2E modified the state
EFLAGS: S2E splitted the internal representation of EFLAGS. More informations can be found here.
Access to Registers: Register reading and writing calls are redirected to S2E-state. The work is done in C++ code in the method readRegisterConcrete() of class S2EExecutor.
XXX: It's seems that the Data Structure where the Registers are stored -
ObjectState* wos = state->m_cpuRegistersObject - is not ISA-dependent. But the Switch-Statement inside this method surely is.
ARM CPU model
ARM has something similar like EFLAGS in X86: CPSR (Current Program Status Register) and SPSR (Saved CPSR, stores state of CPSR before an exception occurs). CPSR and SPSR are build up like this:
|Alias||Bit#||Long Name||stored in cpu.h in|
|Q||Bit 27||Overflow in DSP||QF|
|?||Bit 19-16||(not used in ARMv5TE)||GE|
|I||Bit 7||Disable IRQ interrupt||uncached_cpsr & CPSR_I|
|F||Bit 6||Disable FIQ interrupt||uncached_cpsr & CPSR_F|
|T||Bit 5||Thumb (1) or ARM (0)||thumb|
|M||Bit 0-4||CPU Mode bits||uncached_cpsr & CPSR_M|
As you can see from the table, frequently used bits (mainly the flags) are cached in own data structures (NF,ZF,...). One can access the whole cpsr with the uncached_cpsr. For convenient access, there are defined bitmasks. For example:
1 << 7 or
In ARM, there are 7 cpu modes which are reflected in the Mode bits (M):
|Mode||Type||in enum arm_cpu_mode|
|User||Non-privileged mode||ARM_CPU_MODE_USR = 0x10|
|System||Privileged mode||ARM_CPU_MODE_SYS = 0x1f|
|Supervisor||Privileged Exception mode||ARM_CPU_MODE_SVC = 0x13|
|Abort||Privileged Exception mode||ARM_CPU_MODE_ABT = 0x17|
|Undef||Privileged Exception mode||ARM_CPU_MODE_UND = 0x1b|
|IRQ||Privileged Exception mode||ARM_CPU_MODE_IRQ = 0x12|
|FIQ||Privileged Exception mode||ARM_CPU_MODE_FIQ = 0x11|
Banked and Unbanked Registers
There are unbanked registers (which are cpu mode independent registers): r0-r7 There are banked registers (whose content depend on the cpu mode): r8-r14
Within the banked registers, r8-r12 have only two banks, one for all modes except FIQ and one for FIQ. r13 and r14 have 6 banks. One for User and System mode, and one bank for each of the 5 exception modes:
|Register||Number of banks||stored in cpu.h in|
|r0 - r7||1 (Unbanked)||regs (all registers for current mode)|
|r8 - r12||2 (one for FIQ, one for other modes)||usr_reqs and fiq_reqs|
|r13 - r14||6||banked_r13, banked_r14|
R15, The Program Counter (PC)
One has to be aware that R15 holds the Program Counter.
Other information stored in the cpu model
Lots of variables to store the coprocessor state (cp15).
More informations on the ARM architecture and it's instructions can be found in the specification, I used the ARMv5TE reference.