@samitouri / QOSamiQemu / commits / d03b78b0d5

hw/core: Implement new cpu_translate_for_debug()

In cpu_memory_rw_debug() we need to do a virtual-to-physical address translation for debug access. Currently we assume that the translation is valid for an entire guest page, but this may not be true if the target implements some protection regions that have sub-page granularity. (Currently the only such target is the Arm CPUs when using an MPU, as in R-profile and M-profile.) For TCG's emulated accesses, we handle sub-page granularity by the CPU filling in the lg_page_size field of the CPUTLBEntryFull struct to tell us how large the region covered by the result is. But we didn't extend this to the debug-access code path, with the result that debug accesses might incorrectly fail because they are looking at the mapping for the address rounded down to a page boundary. Provide a cpu_translate_for_debug() function which reports to the caller not just the physical address and attributes of the translation but also the lg_page_size for which it is valid. The fallback implementation calls cpu_get_phys_addr_attrs_debug() and assumes target-page-sized validity. NB: the "return true on valid access, false on failure" follows the same convention as TCGCPUOps::tlb_fill_align() (though it is the opposite of what we use in some other places, e.g. in target/arm's get_phys_addr_* functions). Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-id: 20260417173105.1648172-15-peter.maydell@linaro.org Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-ID: <20260430093810.2762539-16-peter.maydell@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

Peter Maydell committed Apr 30, 2026 at 10:38 UTC d03b78b0d5e38ace58f5d3c231759e41181e0a4f
3 files changed +89 -2
hw/core/cpu-system.c
+32
@@ -22,6 +22,7 @@
22 #include "qapi/error.h"
23 #include "system/address-spaces.h"
24 #include "exec/cputlb.h"
25 +#include "exec/target_page.h"
26 #include "system/memory.h"
27 #include "qemu/target-info.h"
28 #include "hw/core/qdev.h"
@@ -55,6 +56,37 @@ bool cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
56 return false;
57 }
58
59 +bool cpu_translate_for_debug(CPUState *cpu, vaddr addr,
60 + TranslateForDebugResult *result)
61 +{
62 + if (cpu->cc->sysemu_ops->translate_for_debug) {
63 + return cpu->cc->sysemu_ops->translate_for_debug(cpu, addr, result);
64 + } else {
65 + /* Fallbacks for CPUs which don't implement translate_for_debug */
66 + if (cpu->cc->sysemu_ops->get_phys_addr_attrs_debug) {
67 + result->physaddr =
68 + cpu->cc->sysemu_ops->get_phys_addr_attrs_debug(cpu, addr,
69 + &result->attrs);
70 + } else {
71 + result->physaddr
72 + = cpu->cc->sysemu_ops->get_phys_addr_debug(cpu, addr);
73 + result->attrs = MEMTXATTRS_UNSPECIFIED;
74 + }
75 + if (result->physaddr == -1) {
76 + return false;
77 + }
78 + /* Indicate that this is a debug access. */
79 + result->attrs.debug = 1;
80 + /*
81 + * Assume memory access permissions are valid for the whole page.
82 + * Targets where this isn't true should implement the
83 + * translate_for_debug method.
84 + */
85 + result->lg_page_size = TARGET_PAGE_BITS;
86 + return true;
87 + }
88 +}
89 +
90 hwaddr cpu_get_phys_addr_attrs_debug(CPUState *cpu, vaddr addr,
91 MemTxAttrs *attrs)
92 {
include/hw/core/cpu.h
+32
@@ -772,6 +772,38 @@ hwaddr cpu_get_phys_addr_attrs_debug(CPUState *cpu, vaddr addr,
772 */
773 hwaddr cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
774
775 +/**
776 + * TranslateForDebugResult: gives result of cpu_translate_for_debug()
777 + *
778 + * @physaddr: the physical address corresponding to the virtual address
779 + * @attrs: the transaction attributes for this access
780 + * @lg_page_size: log2 of the size of the aligned block of memory
781 + * that this physaddr and attrs are valid for.
782 + */
783 +typedef struct TranslateForDebugResult {
784 + hwaddr physaddr;
785 + MemTxAttrs attrs;
786 + uint8_t lg_page_size;
787 +} TranslateForDebugResult;
788 +
789 +/**
790 + * cpu_translate_for_debug:
791 + * @cpu: The CPU use for the virtual-to-physical translation
792 + * @addr: The virtual address
793 + * @result: Struct filled in with results of translation
794 + *
795 + * Perform a virtual-to-physical address translation for debug accesses.
796 + * Use it only for debugging because no protection checks are done.
797 + *
798 + * The address need not be page-aligned; the returned address in @result
799 + * will be the physical address corresponding to that virtual address.
800 + *
801 + * Returns: false on translation failure; true on successful translation
802 + * and fills in the fields of @result.
803 + */
804 +bool cpu_translate_for_debug(CPUState *cpu, vaddr addr,
805 + TranslateForDebugResult *result);
806 +
807 /** cpu_asidx_from_attrs:
808 * @cpu: CPU
809 * @attrs: memory transaction attributes
include/hw/core/sysemu-cpu-ops.h
+25 -2
@@ -33,19 +33,42 @@ typedef struct SysemuCPUOps {
33 * @get_phys_addr_debug: Callback for obtaining a physical address.
34 * This must be able to handle a non-page-aligned address, and will
35 * return the physical address corresponding to that address.
36 + *
37 + * CPUs should prefer to implement translate_for_debug instead of
38 + * this (and must do so if their translations are not always valid
39 + * for a complete target page or they use memory attributes).
40 */
41 hwaddr (*get_phys_addr_debug)(CPUState *cpu, vaddr addr);
42 /**
43 * @get_phys_addr_attrs_debug: Callback for obtaining a physical address
44 * and the associated memory transaction attributes to use for the
45 * access.
42 - * CPUs which use memory transaction attributes should implement this
43 - * instead of get_phys_addr_debug.
46 + *
47 * This must be able to handle a non-page-aligned address, and will
48 * return the physical address corresponding to that address.
49 + *
50 + * CPUs should prefer to implement translate_for_debug instead of
51 + * this (and must do so if their translations are not always valid
52 + * for a complete target page).
53 */
54 hwaddr (*get_phys_addr_attrs_debug)(CPUState *cpu, vaddr addr,
55 MemTxAttrs *attrs);
56 + /**
57 + * @translate_for_debug: Callback for translating a virtual address into
58 + * a physical address for debug purposes.
59 + * The implementation should fill in @result with the physical address,
60 + * transaction attributes, and log2 of the size of the aligned block of
61 + * memory that the translation is valid for.
62 + * This must be able to handle a non-page-aligned address, and will
63 + * return the physical address corresponding to that address.
64 + * The attributes must include the debug flag being set.
65 + * Returns false on translation failure; on success returns true and
66 + * fills in @result.
67 + *
68 + * This is the preferred method to implement for new CPUs.
69 + */
70 + bool (*translate_for_debug)(CPUState *cpu, vaddr addr,
71 + TranslateForDebugResult *result);
72 /**
73 * @asidx_from_attrs: Callback to return the CPU AddressSpace to use for
74 * a memory access with the specified memory transaction attributes.