小聊 qemu 的 CPUState

jollen 發表於 April 11, 2007 8:16 PM

今天繼續來聊 qemu 的內部實作。在 qemu 裡頭,有一個 object 叫做 CPUState,這是一個重要的 qemu data structure,其實作如下(cpu-all.h):

#elif defined(TARGET_ARM)
#define CPUState CPUARMState
...

我們以 ARM 做為 target,再找到 target-arm/cpu.h

typedef struct CPUARMState {
    /* Regs for current mode.  */
    uint32_t regs[16];
    /* Frequently accessed CPSR bits are stored separately for efficiently.
       This contains all the other bits.  Use cpsr_{read,write} to access
       the whole CPSR.  */
    uint32_t uncached_cpsr;
    uint32_t spsr;

    /* Banked registers.  */
    uint32_t banked_spsr[6];
    uint32_t banked_r13[6];
    uint32_t banked_r14[6];
    
    /* These hold r8-r12.  */
    uint32_t usr_regs[5];
    uint32_t fiq_regs[5];
    
    /* cpsr flag cache for faster execution */
    uint32_t CF; /* 0 or 1 */
    uint32_t VF; /* V is the bit 31. All other bits are undefined */
    uint32_t NZF; /* N is bit 31. Z is computed from NZF */
    uint32_t QF; /* 0 or 1 */

    int thumb; /* 0 = arm mode, 1 = thumb mode */

    /* System control coprocessor (cp15) */
    struct {
        uint32_t c0_cpuid;
        uint32_t c0_cachetype;
        uint32_t c1_sys; /* System control register.  */
        uint32_t c1_coproc; /* Coprocessor access register.  */
        uint32_t c2; /* MMU translation table base.  */
        uint32_t c3; /* MMU domain access control register.  */
        uint32_t c5_insn; /* Fault status registers.  */
        uint32_t c5_data;
        uint32_t c6_insn; /* Fault address registers.  */
        uint32_t c6_data;
        uint32_t c9_insn; /* Cache lockdown registers.  */
        uint32_t c9_data;
        uint32_t c13_fcse; /* FCSE PID.  */
        uint32_t c13_context; /* Context ID.  */
        uint32_t c15_cpar; /* XScale Coprocessor Access Register */
    } cp15;

    /* Coprocessor IO used by peripherals */
    struct {
        ARMReadCPFunc *cp_read;
        ARMWriteCPFunc *cp_write;
        void *opaque;
    } cp[15];

    /* Internal CPU feature flags.  */
    uint32_t features;

    /* exception/interrupt handling */
    jmp_buf jmp_env;
    int exception_index;
    int interrupt_request;
    int user_mode_only;
    int halted;

    /* VFP coprocessor state.  */
    struct {
        float64 regs[16];

        uint32_t xregs[16];
        /* We store these fpcsr fields separately for convenience.  */
        int vec_len;
        int vec_stride;

        /* Temporary variables if we don't have spare fp regs.  */
        float32 tmp0s, tmp1s;
        float64 tmp0d, tmp1d;
        
        float_status fp_status;
    } vfp;

    /* iwMMXt coprocessor state.  */
    struct {
        uint64_t regs[16];
        uint64_t val;

        uint32_t cregs[16];
    } iwmmxt;

#if defined(CONFIG_USER_ONLY)
    /* For usermode syscall translation.  */
    int eabi;
#endif

    CPU_COMMON

} CPUARMState;

這個 object 是 qemu 用來紀錄 ARM 處理器狀態的資料結構,舉例來說,CPUState.regs 紀錄了 ARM 的所有 register 狀態。相關應用,例如,我們只要觀察 r15(pc)暫存器的值,就可以知道現在這台機器的程式執行位置。實際上的應用,像是 qemu 所實作的 gdbserver 即是透過此 object 的資訊,來回覆 gdb client 的命令。

讀者留言 (0)

留言功能維護中。將於近日重新開放。

連絡作者

Jollen Chen,Moko365(仕橙3G教室)講師,熱愛研究 Linux 與 Android 技術。曾為 Motorola、HTC、Foxconn、LG、OPPO、騰迅、廣達電腦、緯創、仁寶等超過 50 家企業講授課程。目前在 MokoVersity 擔任軟體工程師,撰寫 Node.js 程式,也在幾家科技廠兼任 Android Framework 研發顧問。您可透過電子郵件 <jollen (at) jollen (dot) org> 或這裡與我連絡。