> -----Original Message----- > From: Richard Henderson <richard.hender...@linaro.org> > Sent: Thursday, March 20, 2025 10:34 AM > To: Sid Manning <sidn...@quicinc.com>; ltaylorsimp...@gmail.com; > 'Philippe Mathieu-Daudé' <phi...@linaro.org>; 'Brian Cain' > <brian.c...@oss.qualcomm.com>; qemu-devel@nongnu.org > Cc: Matheus Bernardino (QUIC) <quic_mathb...@quicinc.com>; > a...@rev.ng; a...@rev.ng; Marco Liebel (QUIC) > <quic_mlie...@quicinc.com>; alex.ben...@linaro.org; Mark Burton (QUIC) > <quic_mbur...@quicinc.com>; Brian Cain <bc...@quicinc.com> > Subject: Re: [PATCH 28/38] target/hexagon: Initialize htid, modectl regs > > WARNING: This email originated from outside of Qualcomm. Please be wary > of any links or attachments, and do not enable macros. > > On 3/19/25 09:08, Sid Manning wrote: > > > > > >> -----Original Message----- > >> From: Richard Henderson <richard.hender...@linaro.org> > >> Sent: Thursday, March 13, 2025 2:07 PM > >> To: ltaylorsimp...@gmail.com; 'Philippe Mathieu-Daudé' > >> <phi...@linaro.org>; 'Brian Cain' <brian.c...@oss.qualcomm.com>; > >> qemu- de...@nongnu.org > >> Cc: Matheus Bernardino (QUIC) <quic_mathb...@quicinc.com>; > >> a...@rev.ng; a...@rev.ng; Marco Liebel (QUIC) > >> <quic_mlie...@quicinc.com>; alex.ben...@linaro.org; Mark Burton > >> (QUIC) <quic_mbur...@quicinc.com>; Sid Manning > <sidn...@quicinc.com>; > >> Brian Cain <bc...@quicinc.com> > >> Subject: Re: [PATCH 28/38] target/hexagon: Initialize htid, modectl > >> regs > >> > >> WARNING: This email originated from outside of Qualcomm. Please be > >> wary of any links or attachments, and do not enable macros. > >> > >> On 3/13/25 11:47, ltaylorsimp...@gmail.com wrote: > >>> What we are trying to model is an instance of a Hexagon that has a > >>> number > >> of threads and some resources that are shared. The shared resources > >> include the TLB and global S registers. The initial thought was to > >> tie the shared resources to the thread with cpu_index == 0. If we > >> were to model a Qualcomm SoC, there would be multiple ARM cores and > >> multiple Hexagon instances. Each Hexagon instance would have > >> distinct shared resources. So, you are correct that using cpu_index is not > going to scale. > >>> > >>> What is the recommended way to model this? I see a "nr_threads" > >>> field in > >> CPUCore but no clear way to find the threads. PPC has some cores > >> that add a "threads" field. Should we follow this approach? > >> > >> I recommend that the shared resources be modeled as a separate > >> Object, which is linked via object_property_add_link to all of the cpus > >> that > use it. > >> > > [Sid Manning] > > Hi Richard, > > An example of shared resources would be the system registers. They are > broken down into 2 regions. Each thread has its own copy of system > registers 0-15 while registers 16-63 are global. Right now CPUHexagonState > contains a pointer, g_sreg which points back to cpu[0]'s state thus keeping > one copy of the global registers, accesses are done with BQL held to avoid > race conditions. > > > > Your suggestion is to create a new object to represent the set of global > system registers, I tried this: > > > > #define TYPE_HEXAGON_G_SREG "hexagon.global_sreg" > > OBJECT_DECLARE_SIMPLE_TYPE(HexagonGlobalSREGState, > HEXAGON_G_SREG) > > struct HexagonGlobalSREGState { > > SysBusDevice parent_obj; > > SysBusDevice is more than you need -- Object is sufficient here. [Sid Manning] Thanks! Will change that to Object.
> > > uint32_t regs[64]; > > }; > > > > In our virtual machine init: > > vms->g_sreg = > HEXAGON_G_SREG(qdev_new(TYPE_HEXAGON_G_SREG)); > > > > and > > object_property_set_link(OBJECT(cpu), "global-sreg", > > OBJECT(vms->g_sreg), &error_abort); > > > > to attach the global regs to the cpu, but the above doesn't update cpu > elements the same way calls to qdev_prop_set_uint32 will do, > object_property_set_link doesn’t error out and returns true. > > Did you add the DEFINE_PROP_LINK to match? I'd expect something like > > DEFINE_PROP_LINK("global-sreg", HexagonCPU, g_sreg, > TYPE_HEXAGON_G_SREG, HexagonGlobalSREGState *), > > Beyond that, I guess I'd have to see an actual patch to work out what's > wrong. [Sid Manning] Yes, PROP_LINK above is almost exactly what I added. Below is a patch representing what I tried. I hoped that cpu->global_sreg would be updated after the call to object_property_set_link but it was not, in the patch below I manually set it. diff --git a/hw/hexagon/sysreg.h b/hw/hexagon/sysreg.h new file mode 100644 index 0000000000..d7204896cf --- /dev/null +++ b/hw/hexagon/sysreg.h @@ -0,0 +1,47 @@ +/* + * Hexagon system reg + * FIXME + */ + +#ifndef HW_HEXAGON_HART_H +#define HW_HEXAGON_HART_H +#if !defined(CONFIG_USER_ONLY) +#include "hw/sysbus.h" +#include "qom/object.h" + +#define NUM_SREGS 64 +struct HexagonGlobalSREGState { + struct Object parent_obj; + uint32_t regs[NUM_SREGS]; +}; + +#define TYPE_HEXAGON_G_SREG "hexagon.global_sreg" +OBJECT_DECLARE_SIMPLE_TYPE(HexagonGlobalSREGState, HEXAGON_G_SREG) + +static void hexagon_global_sreg_init(Object *obj) +{ + HexagonGlobalSREGState *s = HEXAGON_G_SREG(obj); + /* + * The first 16 registers are thread local and should not come from + * this structure + */ + for (int i = 0; i < 16; i++) { + s->regs[i] = 0xffffffff; + } +} + +static const TypeInfo hexagon_sreg_info = { + .name = TYPE_HEXAGON_G_SREG, + .parent = TYPE_DEVICE, + .instance_size = sizeof(struct HexagonGlobalSREGState), + .instance_init = hexagon_global_sreg_init, +}; + +__attribute__ ((unused)) +static void hexagon_sreg_register_types(void) +{ + type_register_static(&hexagon_sreg_info); +} +#endif +#endif + diff --git a/hw/hexagon/virt.c b/hw/hexagon/virt.c index 1e7ac4e5b7..d2d599ac1d 100644 --- a/hw/hexagon/virt.c +++ b/hw/hexagon/virt.c @@ -10,12 +10,14 @@ #include "hw/char/pl011.h" #include "hw/core/sysbus-fdt.h" #include "hw/hexagon/hexagon.h" +#include "hw/hexagon/sysreg.h" #include "hw/hexagon/virt.h" #include "hw/loader.h" #include "hw/qdev-properties.h" #include "hw/register.h" #include "hw/timer/qct-qtimer.h" #include "qemu/error-report.h" +#include "qapi/error.h" #include "qemu/guest-random.h" #include "qemu/units.h" #include "elf.h" @@ -335,6 +337,7 @@ static void virt_init(MachineState *ms) cpu_model = HEXAGON_CPU_TYPE_NAME("v73"); } + vms->g_sreg = HEXAGON_G_SREG(qdev_new(TYPE_HEXAGON_G_SREG)); HexagonCPU *cpu_0 = NULL; for (int i = 0; i < ms->smp.cpus; i++) { HexagonCPU *cpu = HEXAGON_CPU(object_new(ms->cpu_type)); @@ -356,6 +359,14 @@ static void virt_init(MachineState *ms) qdev_prop_set_uint32(DEVICE(cpu), "qtimer-base-addr", m_cfg->qtmr_region); qdev_prop_set_uint32(DEVICE(cpu), "jtlb-entries", m_cfg->cfgtable.jtlb_size_entries); + bool rc = object_property_set_link(OBJECT(cpu), "global-sreg", + OBJECT(vms->g_sreg), &error_abort); + g_assert(rc == true); + + /* This is doing what I think object_property_set_link should do.*/ + cpu->global_sreg = vms->g_sreg; + + if (!qdev_realize_and_unref(DEVICE(cpu), NULL, errp)) { return; @@ -413,3 +424,5 @@ static const TypeInfo virt_machine_types[] = { { } }; DEFINE_TYPES(virt_machine_types) + +type_init(hexagon_sreg_register_types) diff --git a/include/hw/hexagon/virt.h b/include/hw/hexagon/virt.h index 0c165a786d..dcd09d50b1 100644 --- a/include/hw/hexagon/virt.h +++ b/include/hw/hexagon/virt.h @@ -9,6 +9,7 @@ #define HW_HEXAGONVIRT_H #include "hw/boards.h" +#include "hw/hexagon/sysreg.h" #include "target/hexagon/cpu.h" struct HexagonVirtMachineState { @@ -22,6 +23,7 @@ struct HexagonVirtMachineState { MemoryRegion tcm; MemoryRegion vtcm; DeviceState *l2vic; + HexagonGlobalSREGState *g_sreg; }; void hexagon_load_fdt(const struct HexagonVirtMachineState *vms); diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c index c649aef99e..9773ee0be8 100644 --- a/target/hexagon/cpu.c +++ b/target/hexagon/cpu.c @@ -80,6 +80,8 @@ static const Property hexagon_cpu_properties[] = { DEFINE_PROP_UINT32("exec-start-addr", HexagonCPU, boot_addr, 0xffffffffULL), DEFINE_PROP_UINT64("config-table-addr", HexagonCPU, config_table_addr, 0xffffffffULL), + DEFINE_PROP_LINK("global-sreg", HexagonCPU, global_sreg, + TYPE_HEXAGON_G_SREG, HexagonGlobalSREGState *), #endif DEFINE_PROP_UINT32("dsp-rev", HexagonCPU, rev_reg, 0), DEFINE_PROP_BOOL("lldb-compat", HexagonCPU, lldb_compat, false), @@ -378,6 +380,11 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type) CPUState *cs = CPU(obj); HexagonCPUClass *mcc = HEXAGON_CPU_GET_CLASS(obj); CPUHexagonState *env = cpu_env(cs); +#ifndef CONFIG_USER_ONLY + HexagonCPU *cpu = HEXAGON_CPU(cs); + env->g_sreg = cpu->global_sreg->regs; +#endif + if (mcc->parent_phases.hold) { mcc->parent_phases.hold(obj, type); @@ -389,11 +396,6 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type) set_float_default_nan_pattern(0b11111111, &env->fp_status); #ifndef CONFIG_USER_ONLY - HexagonCPU *cpu = HEXAGON_CPU(cs); - - if (cs->cpu_index == 0) { - memset(env->g_sreg, 0, sizeof(target_ulong) * NUM_SREGS); - } memset(env->t_sreg, 0, sizeof(target_ulong) * NUM_SREGS); memset(env->greg, 0, sizeof(target_ulong) * NUM_GREGS); @@ -468,13 +470,6 @@ static void hexagon_cpu_realize(DeviceState *dev, Error **errp) CPUHexagonState *env = cpu_env(cs); #ifndef CONFIG_USER_ONLY hex_mmu_realize(env); - if (cs->cpu_index == 0) { - env->g_sreg = g_new0(target_ulong, NUM_SREGS); - } else { - CPUState *cpu0 = qemu_get_cpu(0); - CPUHexagonState *env0 = cpu_env(cpu0); - env->g_sreg = env0->g_sreg; - } #endif if (cs->cpu_index == 0) { env->g_pcycle_base = g_malloc0(sizeof(*env->g_pcycle_base)); diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h index 8b334068e2..716dd8253b 100644 --- a/target/hexagon/cpu.h +++ b/target/hexagon/cpu.h @@ -19,10 +19,10 @@ #define HEXAGON_CPU_H #include "fpu/softfloat-types.h" +#include "hw/hexagon/sysreg.h" #define NUM_GREGS 32 #define GREG_WRITES_MAX 32 -#define NUM_SREGS 64 #define SREG_WRITES_MAX 64 #include "cpu-qom.h" @@ -199,6 +199,7 @@ struct ArchCPU { uint32_t hvx_contexts; uint32_t boot_addr; uint64_t config_table_addr; + HexagonGlobalSREGState *global_sreg; #endif }; > > > r~