From 3dd075fc4f45e2d4e2a848c2d7abef4b1da9e743 Mon Sep 17 00:00:00 2001 From: Siyuan Chai Date: Tue, 30 Jan 2024 00:49:32 -0600 Subject: [PATCH] redo addr dump interface to make it possible for ECPT --- accel/tcg/cputlb.c | 12 +++----- include/exec/exec-all.h | 4 +-- include/exec/memop.h | 16 ++++++++++ include/hw/core/tcg-cpu-ops.h | 5 ++-- include/qemu/qemu-plugin.h | 6 ++-- plugins/api.c | 7 ++--- target/i386/tcg/helper-tcg.h | 4 +-- target/i386/tcg/sysemu/excp_helper.c | 12 ++++---- tests/plugin/execlog.c | 44 +++++----------------------- 9 files changed, 42 insertions(+), 68 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index d220f1bb1bad..13bffbb0642b 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1287,13 +1287,10 @@ static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr) } static unsigned long tlb_fill_pgtables(CPUState *cpu, target_ulong addr, int size, - int mmu_idx, unsigned long *cr3, unsigned long *pud, - unsigned long *pmd, unsigned long *pte, - unsigned int *page_size, unsigned long *entry) { + int mmu_idx, void * trans_info) { CPUClass *cc = CPU_GET_CLASS(cpu); - return cc->tcg_ops->tlb_fill_pgtables(cpu, addr, size, mmu_idx, cr3, pud, pmd, pte, page_size, entry); + return cc->tcg_ops->tlb_fill_pgtables(cpu, addr, size, mmu_idx, trans_info); } - /* * Note: tlb_fill() can trigger a resize of the TLB. This means that all of the * caller's prior references to the TLB table (e.g. CPUTLBEntry pointers) must @@ -1498,13 +1495,12 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index, * Returns guest virtual address, or ~0 on failure. */ unsigned long translate_guest_virtual(CPUArchState *env, target_ulong addr, - unsigned long *cr3, unsigned long *pud, unsigned long *pmd, - unsigned long *pte, unsigned int *size, unsigned long *entry) + void *trans_info) { uintptr_t mmu_idx = cpu_mmu_index(env, true); //the second param is unused on x86 /* guest physical. */ - return tlb_fill_pgtables(env_cpu(env), addr, 0, mmu_idx, cr3, pud, pmd, pte, size, entry); + return tlb_fill_pgtables(env_cpu(env), addr, 0, mmu_idx, trans_info); } diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index f2a7be57c216..eb255676cd7f 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -708,9 +708,9 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr); */ tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr, void **hostp); + unsigned long translate_guest_virtual(CPUArchState *env, target_ulong addr, - unsigned long *cr3, unsigned long *pud, unsigned long *pmd, - unsigned long *pte, unsigned int *size, unsigned long *entry); + void *trans_info); void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length); void tlb_set_dirty(CPUState *cpu, target_ulong vaddr); diff --git a/include/exec/memop.h b/include/exec/memop.h index 529d07b02dd4..7b0dcc1f2c65 100644 --- a/include/exec/memop.h +++ b/include/exec/memop.h @@ -131,4 +131,20 @@ static inline bool memop_big_endian(MemOp op) return (op & MO_BSWAP) == MO_BE; } + +#ifndef PAGE_TABLE_LEAVES +#define PAGE_TABLE_LEAVES 4 +#endif +typedef struct MemRecord +{ + uint8_t header; + uint8_t access_rw; + uint16_t access_cpu; + uint32_t access_sz; + uint64_t vaddr; + uint64_t paddr; + uint64_t pte; + uint64_t leaves[PAGE_TABLE_LEAVES]; +} MemRecord; + #endif diff --git a/include/hw/core/tcg-cpu-ops.h b/include/hw/core/tcg-cpu-ops.h index 6e71d9918173..8be4b824a095 100644 --- a/include/hw/core/tcg-cpu-ops.h +++ b/include/hw/core/tcg-cpu-ops.h @@ -44,10 +44,9 @@ struct TCGCPUOps { * not return. For user-only mode, always raise an exception * and do not return. */ + unsigned long (*tlb_fill_pgtables)(CPUState *cpu, vaddr addr, int size, - int mmu_idx, unsigned long *cr3, unsigned long *pud, - unsigned long *pmd, unsigned long *pte, - unsigned int *page_size, unsigned long *entry); + int mmu_idx, void *trans_info); bool (*tlb_fill)(CPUState *cpu, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h index 2c8c7777c11d..056ac6fd42d4 100644 --- a/include/qemu/qemu-plugin.h +++ b/include/qemu/qemu-plugin.h @@ -484,10 +484,8 @@ const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h); * Get page walk information on each level */ -unsigned long qemu_plugin_pa_by_va(const unsigned long vaddr, unsigned long *cr3, - unsigned long *pud, unsigned long *pmd, - unsigned long *pte, unsigned int *size, unsigned long *entry); - +unsigned long qemu_plugin_pa_by_va(const unsigned long vaddr, void * trans_info); + unsigned long qemu_plugin_read_cr3(void); void qemu_plugin_vm_shutdown(void); diff --git a/plugins/api.c b/plugins/api.c index 4ed728753acb..a09019e4b7bd 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -327,14 +327,11 @@ uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr) return 0; } -unsigned long qemu_plugin_pa_by_va(const unsigned long vaddr, unsigned long *cr3, - unsigned long *pud, unsigned long *pmd, - unsigned long *pte, unsigned int *size, unsigned long *entry) +unsigned long qemu_plugin_pa_by_va(const unsigned long vaddr, void * trans_info) { CPUState *cpu = current_cpu; - return translate_guest_virtual(cpu->env_ptr, vaddr, cr3, pud, pmd, pte, size, entry); + return translate_guest_virtual(cpu->env_ptr, vaddr, trans_info); } - unsigned long qemu_plugin_read_cr3(void) { CPUState *cpu = current_cpu; diff --git a/target/i386/tcg/helper-tcg.h b/target/i386/tcg/helper-tcg.h index 3800e000e47d..61d670939342 100644 --- a/target/i386/tcg/helper-tcg.h +++ b/target/i386/tcg/helper-tcg.h @@ -44,9 +44,7 @@ bool x86_cpu_exec_interrupt(CPUState *cpu, int int_req); unsigned long x86_tlb_fill_pgtables(CPUState *cs, vaddr addr, int size, - int mmu_idx, unsigned long *cr3, unsigned long *pud, - unsigned long *pmd, unsigned long *pte, - unsigned int *page_size, unsigned long *entry); + int mmu_idx, void * trans_info); /* helper.c */ bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size, diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c index 714b54a43397..aeb7841e96fa 100644 --- a/target/i386/tcg/sysemu/excp_helper.c +++ b/target/i386/tcg/sysemu/excp_helper.c @@ -1445,14 +1445,14 @@ static int handle_mmu_fault(CPUState *cs, vaddr addr, int size, } unsigned long x86_tlb_fill_pgtables(CPUState *cs, vaddr addr, int size, - int mmu_idx, unsigned long *cr3, unsigned long *pud, - unsigned long *pmd, unsigned long *pte, - unsigned int *page_size, unsigned long *entry) { + int mmu_idx, void * trans_info) { + X86CPU *cpu = X86_CPU(cs); CPUX86State *env = &cpu->env; int pg_mode; hwaddr paddr; - + MemRecord * rec = (MemRecord *) trans_info; + unsigned int page_size = 0; if (!(env->cr[0] & CR0_PG_MASK)) { paddr = addr; if (!(env->hflags & HF_LMA_MASK)) { @@ -1462,8 +1462,8 @@ unsigned long x86_tlb_fill_pgtables(CPUState *cs, vaddr addr, int size, } else { pg_mode = get_pg_mode(env); paddr = mmu_translate_pgtables(cs, addr, get_hphys, env->cr[3], - mmu_idx, pg_mode, - cr3, pud, pmd, pte, page_size, entry); + mmu_idx, pg_mode, + &rec->leaves[0], &rec->leaves[1], &rec->leaves[2], &rec->leaves[3], &page_size, &rec->pte); } return paddr; diff --git a/tests/plugin/execlog.c b/tests/plugin/execlog.c index 7781b0ca307f..b7e297fdbc24 100644 --- a/tests/plugin/execlog.c +++ b/tests/plugin/execlog.c @@ -34,7 +34,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; #ifndef MAX_CPU_COUNT #define MAX_CPU_COUNT 64 #endif - + // Maximum number of instruction recorded #ifndef MAX_INS_COUNT #define MAX_INS_COUNT (3000000000UL) // 3 billion @@ -45,11 +45,6 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; #define FRONTEND_FETCH_SIZE (16UL) #endif -// Number of translation accesses in a single walk -#ifndef PAGE_TABLE_LEAVES -#define PAGE_TABLE_LEAVES 4 -#endif - // Name of the log file #ifndef DEFAULT_BIN_RECORD_FILE_NAME #define DEFAULT_BIN_RECORD_FILE_NAME "walk_log.bin" @@ -111,18 +106,6 @@ typedef struct FileHandle FILE* fp; } FileHandle; -typedef struct MemRecord -{ - uint8_t header; - uint8_t access_rw; - uint16_t access_cpu; - uint32_t access_sz; - uint64_t vaddr; - uint64_t paddr; - uint64_t pte; - uint64_t leaves[PAGE_TABLE_LEAVES]; -} MemRecord; - typedef struct InsRecord { uint8_t header; @@ -291,7 +274,6 @@ static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t info, uint64_t vaddr, void *udata) { MemRecord rec; - uint32_t discard; if (!should_do_logging()) { return; @@ -302,14 +284,8 @@ static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t info, rec.access_cpu = cpu_index % MAX_CPU_COUNT; /* dummy field for now. introduced because of different QEMU version @jiyuan */ rec.access_sz = 1 << qemu_plugin_mem_size_shift(info); rec.vaddr = vaddr; - rec.paddr = qemu_plugin_pa_by_va(vaddr, - &rec.leaves[0], - &rec.leaves[1], - &rec.leaves[2], - &rec.leaves[3], - &discard, - &rec.pte - ); + rec.paddr = qemu_plugin_pa_by_va(vaddr, + (void *)&rec); // printf("Radix Translate: vaddr=%lx PTE0=%lx PTE1=%lx PTE2=%lx " // "PTE3=%lx paddr=%lx access_rw=%d access_cpu=%d access_sz=%d\n", // rec.vaddr, rec.leaves[0], rec.leaves[1], rec.leaves[2], rec.leaves[3], @@ -404,16 +380,10 @@ static void vcpu_insn_fetch(unsigned int cpu_index, void *udata) rec.access_cpu = cpu; rec.access_sz = FRONTEND_FETCH_SIZE; rec.vaddr = ins_line; - rec.paddr = qemu_plugin_pa_by_va(ins_line, - &rec.leaves[0], - &rec.leaves[1], - &rec.leaves[2], - &rec.leaves[3], - &cpu, // cpu is no longer used, so just reuse it here - &rec.pte - ); - - write_ins_fetch(&rec); + rec.paddr = qemu_plugin_pa_by_va(ins_line, + (void *)&rec); + + write_ins_fetch(&rec); if (BIN_RECORD_INCL_DECD) vcpu_insn_exec(cpu_index, udata);