diff mbox series

[v3,4/4] target/arm: Add arm_gdb_set_sysreg() callback

Message ID 1519815685-29200-5-git-send-email-abdallah.bouassida@lauterbach.com
State New
Headers show
Series target/arm: Add a dynamic XML-description of the cp-registers to GDB | expand

Commit Message

Abdallah Bouassida Feb. 28, 2018, 11:01 a.m. UTC
This is a callback to set the cp-regs registered by the dynamic XML.

Signed-off-by: Abdallah Bouassida <abdallah.bouassida@lauterbach.com>
---
>> Some of our customers need to connect to Qemu using our tool TRACE32® 
>> via GDB,
>> and for some use case they need to have write access to some particular 
>> cpregs.
>> So, it will be nice to have this capability!
>> Usually, a user won't modify these registers unless he knows what he is 
>> doing!

> I also still don't really like using write_raw_cp_reg() here --
> it will bypass some behaviour you want and in some cases will
> just break the emulation because invariants we assume will
> hold no longer hold. It would be a lot lot safer to not
> provide write access at all, only read access.

Adding to that our customers may need this write access, our tool TRACE32®
needs this also in some particular cases. For example: temporary disabling MMU
to do a physical memory access.

 target/arm/cpu.h     |  2 ++
 target/arm/gdbstub.c | 21 ++++++++++++++++++++-
 target/arm/helper.c  |  2 +-
 3 files changed, 23 insertions(+), 2 deletions(-)

Comments

Peter Maydell Feb. 28, 2018, 12:27 p.m. UTC | #1
On 28 February 2018 at 11:01, Abdallah Bouassida
<abdallah.bouassida@lauterbach.com> wrote:
> This is a callback to set the cp-regs registered by the dynamic XML.
>
> Signed-off-by: Abdallah Bouassida <abdallah.bouassida@lauterbach.com>
> ---
>>> Some of our customers need to connect to Qemu using our tool TRACE32®
>>> via GDB,
>>> and for some use case they need to have write access to some particular
>>> cpregs.
>>> So, it will be nice to have this capability!
>>> Usually, a user won't modify these registers unless he knows what he is
>>> doing!
>
>> I also still don't really like using write_raw_cp_reg() here --
>> it will bypass some behaviour you want and in some cases will
>> just break the emulation because invariants we assume will
>> hold no longer hold. It would be a lot lot safer to not
>> provide write access at all, only read access.
>
> Adding to that our customers may need this write access, our tool TRACE32®
> needs this also in some particular cases. For example: temporary disabling MMU
> to do a physical memory access.

By clearing the SCTLR bit? That's a good example of a case that
won't work reliably. If you clear the SCTLR.M bit via raw_write
this will not perform the tlb_flush() that it needs to, which
means that if anything does a memory access via the QEMU TLB
it may get the wrong cached results. If you always clear the
bit, do one gdb memory access then set the bit then it will
probably not run into problems but you're walking on thin ice.

thanks
-- PMM
diff mbox series

Patch

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 0e35f64..f4fea98 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2120,6 +2120,8 @@  static inline bool cp_access_ok(int current_el,
 /* Raw read of a coprocessor register (as needed for migration, etc) */
 uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri);
 
+void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t v);
+
 /**
  * write_list_to_cpustate
  * @cpu: ARMCPU
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index e08ad79..57bd418 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -183,12 +183,31 @@  static int arm_gdb_get_sysreg(CPUARMState *env, uint8_t *buf, int reg)
     return 0;
 }
 
+static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
+{
+    ARMCPU *cpu = arm_env_get_cpu(env);
+    const ARMCPRegInfo *ri;
+    uint32_t key;
+    uint32_t tmp;
+
+    tmp = ldl_p(buf);
+    key = cpu->dyn_xml.cpregs_keys[reg];
+    ri = get_arm_cp_reginfo(arm_env_get_cpu(env)->cp_regs, key);
+    if (ri) {
+        if (!(ri->type & ARM_CP_CONST)) {
+            write_raw_cp_reg(env, ri, tmp);
+            return cpreg_field_is_64bit(ri) ? 8 : 4;
+        }
+    }
+    return 0;
+}
+
 void arm_register_gdb_regs_for_features(CPUState *cs)
 {
     int n;
 
     n = arm_gen_dynamic_xml(cs);
-    gdb_register_coprocessor(cs, arm_gdb_get_sysreg, NULL,
+    gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
                              n, "system-registers.xml", 0);
 
 }
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 1594ec45..4a4afbf 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -200,7 +200,7 @@  uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri)
     }
 }
 
-static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
+void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
                              uint64_t v)
 {
     /* Raw write of a coprocessor register (as needed for migration, etc).