Re: [PATCH] ui: fix DIV_BY_ZERO in tightvnc

2023-12-12 Thread Дмитрий Фролов




On 13.12.2023 10:31, Marc-André Lureau wrote:

Hi

On Wed, Dec 13, 2023 at 11:08 AM Dmitry Frolov  wrote:

Division by zero may occur in rare constellation of conditions if:
1. not TrueColor mode on the client side
tight_detect_smooth_image16() and tight_detect_smooth_image32(),
defined by macro DEFINE_DETECT_FUNCTION()2, are affected.
2. if all pixels on the screen are equal, then pixels == stats[0]

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Signed-off-by: Dmitry Frolov 

What about the tight_detect_smooth_image24() division?
 errors /= (pixels * 3 - stats[0]);

Here everything is OK, because there is a check some lines above:
    if (stats[0] * 33 / pixels >= 95) {
    return 0;
    }
thus, stats[0] < pixels*95/33,
95/33 < 3.


It should probably have a similar safety check.

The code is originally from libvncserver, but they completely changed
their implementation in:
https://github.com/LibVNC/libvncserver/commit/7124b5fbcf0df8db4d3f73023d77af6ea56409e7
otherwise,
Reviewed-by: Marc-André Lureau 


---
  ui/vnc-enc-tight.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 41f559eb83..f1249ab136 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -284,6 +284,9 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
  for (; c < 256; c++) {  \
  errors += stats[c] * (c * c);   \
  }   \
+if (pixels == stats[0]) {   \
+return 0;   \
+}   \
  errors /= (pixels - stats[0]);  \
  \
  return errors;  \
--
2.34.1






Re: [PATCH] ui: fix DIV_BY_ZERO in tightvnc

2023-12-12 Thread Marc-André Lureau
Hi

On Wed, Dec 13, 2023 at 11:08 AM Dmitry Frolov  wrote:
>
> Division by zero may occur in rare constellation of conditions if:
> 1. not TrueColor mode on the client side
>tight_detect_smooth_image16() and tight_detect_smooth_image32(),
>defined by macro DEFINE_DETECT_FUNCTION()2, are affected.
> 2. if all pixels on the screen are equal, then pixels == stats[0]
>
> Found by Linux Verification Center (linuxtesting.org) with SVACE.
>
> Signed-off-by: Dmitry Frolov 

What about the tight_detect_smooth_image24() division?
errors /= (pixels * 3 - stats[0]);

It should probably have a similar safety check.

The code is originally from libvncserver, but they completely changed
their implementation in:
https://github.com/LibVNC/libvncserver/commit/7124b5fbcf0df8db4d3f73023d77af6ea56409e7

otherwise,
Reviewed-by: Marc-André Lureau 

> ---
>  ui/vnc-enc-tight.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
> index 41f559eb83..f1249ab136 100644
> --- a/ui/vnc-enc-tight.c
> +++ b/ui/vnc-enc-tight.c
> @@ -284,6 +284,9 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
>  for (; c < 256; c++) {  \
>  errors += stats[c] * (c * c);   \
>  }   \
> +if (pixels == stats[0]) {   \
> +return 0;   \
> +}   \
>  errors /= (pixels - stats[0]);  \
>  \
>  return errors;  \
> --
> 2.34.1
>




Re: [PATCH] tcg: Reduce serial context atomicity earlier

2023-12-12 Thread Philippe Mathieu-Daudé

On 12/12/23 20:35, Richard Henderson wrote:

Reduce atomicity while emitting opcodes, instead of later
during code generation.  This ensures that any helper called
also sees the reduced atomicity requirement.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2034
Signed-off-by: Richard Henderson 
---
  tcg/tcg-op-ldst.c | 28 
  tcg/tcg.c |  9 +
  2 files changed, 25 insertions(+), 12 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH v7 5/5] ebpf: Updated eBPF program and skeleton.

2023-12-12 Thread Yuri Benditovich
On Tue, Dec 12, 2023 at 5:33 AM Jason Wang  wrote:

> On Mon, Dec 11, 2023 at 7:51 PM Yuri Benditovich
>  wrote:
> >
> > Hello Jason,
> > Can you please let us know what happens with this series?
>
> It should be my bad, it is in V1 of the pull request but missed
> accidentally in V2 of the pull.
>
> I've merged it here,
>
> https://gitlab.com/jasowang/qemu.git


Yes, the merged tree is OK. I see you changed the target version to 8.3
 It looks like no more changes required for the PULL,
 Please let us know if something is needed.

Thanks,
Yuri



>
> Please check if it's correct.
>
> Thanks
>
> >
> > Thanks
> > Yuri
> >
> > On Fri, Sep 8, 2023 at 9:43 AM Jason Wang  wrote:
> >>
> >> On Mon, Sep 4, 2023 at 7:23 PM Andrew Melnichenko 
> wrote:
> >> >
> >> > Hi Jason,
> >> > According to our previous conversation, I've added checks to the
> meson script.
> >> > Please confirm that everything is correct
> >>
> >> I've queued this series.
> >>
> >> Thanks
> >>
>
>


Re: [PATCH for 8.2] target/riscv: Fix th.dcache.cval1 priviledge check

2023-12-12 Thread Christoph Müllner
On Fri, Dec 8, 2023 at 10:44 AM LIU Zhiwei  wrote:
>
> According to the specification, the th.dcache.cvall1 can be executed
> under all priviledges.
> The specification about xtheadcmo located in,
> https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadcmo/dcache_cval1.adoc
>
> Signed-off-by: LIU Zhiwei 

Reviewed-by: Christoph Muellner 

> ---
>  target/riscv/insn_trans/trans_xthead.c.inc | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/riscv/insn_trans/trans_xthead.c.inc 
> b/target/riscv/insn_trans/trans_xthead.c.inc
> index 810d76665a..dbb6411239 100644
> --- a/target/riscv/insn_trans/trans_xthead.c.inc
> +++ b/target/riscv/insn_trans/trans_xthead.c.inc
> @@ -296,7 +296,7 @@ NOP_PRIVCHECK(th_dcache_csw, REQUIRE_XTHEADCMO, 
> REQUIRE_PRIV_MS)
>  NOP_PRIVCHECK(th_dcache_cisw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
>  NOP_PRIVCHECK(th_dcache_isw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
>  NOP_PRIVCHECK(th_dcache_cpal1, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
> -NOP_PRIVCHECK(th_dcache_cval1, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
> +NOP_PRIVCHECK(th_dcache_cval1, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MSU)
>
>  NOP_PRIVCHECK(th_icache_iall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
>  NOP_PRIVCHECK(th_icache_ialls, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
> --
> 2.17.1
>



[PATCH] ui: fix DIV_BY_ZERO in tightvnc

2023-12-12 Thread Dmitry Frolov
Division by zero may occur in rare constellation of conditions if:
1. not TrueColor mode on the client side
   tight_detect_smooth_image16() and tight_detect_smooth_image32(),
   defined by macro DEFINE_DETECT_FUNCTION()2, are affected.
2. if all pixels on the screen are equal, then pixels == stats[0]

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Signed-off-by: Dmitry Frolov 
---
 ui/vnc-enc-tight.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 41f559eb83..f1249ab136 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -284,6 +284,9 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
 for (; c < 256; c++) {  \
 errors += stats[c] * (c * c);   \
 }   \
+if (pixels == stats[0]) {   \
+return 0;   \
+}   \
 errors /= (pixels - stats[0]);  \
 \
 return errors;  \
-- 
2.34.1




[PATCH v17 06/14] gdbstub: Change gdb_get_reg_cb and gdb_set_reg_cb

2023-12-12 Thread Akihiko Odaki
Align the parameters of gdb_get_reg_cb and gdb_set_reg_cb with the
gdb_read_register and gdb_write_register members of CPUClass to allow
to unify the logic to access registers of the core and coprocessors
in the future.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Alex Bennée 
---
 include/exec/gdbstub.h  |  4 +--
 target/arm/internals.h  | 12 +++
 target/hexagon/internal.h   |  4 +--
 target/microblaze/cpu.h |  4 +--
 gdbstub/gdbstub.c   |  6 ++--
 target/arm/gdbstub.c| 51 +-
 target/arm/gdbstub64.c  | 27 +++-
 target/hexagon/gdbstub.c| 10 --
 target/loongarch/gdbstub.c  | 11 ---
 target/m68k/helper.c| 20 +---
 target/microblaze/gdbstub.c |  9 --
 target/ppc/gdbstub.c| 46 +--
 target/riscv/gdbstub.c  | 46 ---
 target/s390x/gdbstub.c  | 77 ++---
 14 files changed, 236 insertions(+), 91 deletions(-)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index ac6fce99a64e..bcaab1bc750e 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -24,8 +24,8 @@ typedef struct GDBFeatureBuilder {
 
 
 /* Get or set a register.  Returns the size of the register.  */
-typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg);
-typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t *buf, int reg);
+typedef int (*gdb_get_reg_cb)(CPUState *cpu, GByteArray *buf, int reg);
+typedef int (*gdb_set_reg_cb)(CPUState *cpu, uint8_t *buf, int reg);
 
 /**
  * gdb_register_coprocessor() - register a supplemental set of registers
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 1136710741f0..a08f461f444b 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1447,12 +1447,12 @@ static inline uint64_t pmu_counter_mask(CPUARMState 
*env)
 
 #ifdef TARGET_AARCH64
 GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cpu, int base_reg);
-int aarch64_gdb_get_sve_reg(CPUARMState *env, GByteArray *buf, int reg);
-int aarch64_gdb_set_sve_reg(CPUARMState *env, uint8_t *buf, int reg);
-int aarch64_gdb_get_fpu_reg(CPUARMState *env, GByteArray *buf, int reg);
-int aarch64_gdb_set_fpu_reg(CPUARMState *env, uint8_t *buf, int reg);
-int aarch64_gdb_get_pauth_reg(CPUARMState *env, GByteArray *buf, int reg);
-int aarch64_gdb_set_pauth_reg(CPUARMState *env, uint8_t *buf, int reg);
+int aarch64_gdb_get_sve_reg(CPUState *cs, GByteArray *buf, int reg);
+int aarch64_gdb_set_sve_reg(CPUState *cs, uint8_t *buf, int reg);
+int aarch64_gdb_get_fpu_reg(CPUState *cs, GByteArray *buf, int reg);
+int aarch64_gdb_set_fpu_reg(CPUState *cs, uint8_t *buf, int reg);
+int aarch64_gdb_get_pauth_reg(CPUState *cs, GByteArray *buf, int reg);
+int aarch64_gdb_set_pauth_reg(CPUState *cs, uint8_t *buf, int reg);
 void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
 void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp);
 void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index d732b6bb3c73..beb08cb7e382 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -33,8 +33,8 @@
 
 int hexagon_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
 int hexagon_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
-int hexagon_hvx_gdb_read_register(CPUHexagonState *env, GByteArray *mem_buf, 
int n);
-int hexagon_hvx_gdb_write_register(CPUHexagonState *env, uint8_t *mem_buf, int 
n);
+int hexagon_hvx_gdb_read_register(CPUState *env, GByteArray *mem_buf, int n);
+int hexagon_hvx_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n);
 
 void hexagon_debug_vreg(CPUHexagonState *env, int regnum);
 void hexagon_debug_qreg(CPUHexagonState *env, int regnum);
diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h
index b5374365f5f5..1906d8f266af 100644
--- a/target/microblaze/cpu.h
+++ b/target/microblaze/cpu.h
@@ -381,8 +381,8 @@ G_NORETURN void mb_cpu_do_unaligned_access(CPUState *cs, 
vaddr vaddr,
 void mb_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
 int mb_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
 int mb_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
-int mb_cpu_gdb_read_stack_protect(CPUArchState *cpu, GByteArray *buf, int reg);
-int mb_cpu_gdb_write_stack_protect(CPUArchState *cpu, uint8_t *buf, int reg);
+int mb_cpu_gdb_read_stack_protect(CPUState *cs, GByteArray *buf, int reg);
+int mb_cpu_gdb_write_stack_protect(CPUState *cs, uint8_t *buf, int reg);
 
 static inline uint32_t mb_cpu_read_msr(const CPUMBState *env)
 {
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index a80729436b66..21fea7fffae8 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -502,7 +502,6 @@ const GDBFeature *gdb_find_static_feature(const char 
*xmlname)
 static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
 {
 CPUClass *cc = CPU_GET_CLASS(cpu);
- 

[PATCH v17 08/14] gdbstub: Infer number of core registers from XML

2023-12-12 Thread Akihiko Odaki
GDBFeature has the num_regs member so use it where applicable to
remove magic numbers.

Signed-off-by: Akihiko Odaki 
---
 include/hw/core/cpu.h   | 3 ++-
 target/s390x/cpu.h  | 2 --
 gdbstub/gdbstub.c   | 5 -
 target/arm/cpu.c| 1 -
 target/arm/cpu64.c  | 1 -
 target/avr/cpu.c| 1 -
 target/hexagon/cpu.c| 1 -
 target/i386/cpu.c   | 2 --
 target/loongarch/cpu.c  | 2 --
 target/m68k/cpu.c   | 1 -
 target/microblaze/cpu.c | 1 -
 target/riscv/cpu.c  | 1 -
 target/rx/cpu.c | 1 -
 target/s390x/cpu.c  | 1 -
 14 files changed, 6 insertions(+), 17 deletions(-)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index c0c8320413e5..a6214610603f 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -127,7 +127,8 @@ struct SysemuCPUOps;
  * @gdb_adjust_breakpoint: Callback for adjusting the address of a
  *   breakpoint.  Used by AVR to handle a gdb mis-feature with
  *   its Harvard architecture split code and data.
- * @gdb_num_core_regs: Number of core registers accessible to GDB.
+ * @gdb_num_core_regs: Number of core registers accessible to GDB or 0 to infer
+ * from @gdb_core_xml_file.
  * @gdb_core_xml_file: File name for core registers GDB XML description.
  * @gdb_stop_before_watchpoint: Indicates whether GDB expects the CPU to stop
  *   before the insn which triggers a watchpoint rather than after it.
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index fa3aac4f9739..2d81fbfea5cb 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -491,8 +491,6 @@ static inline void cpu_get_tb_cpu_state(CPUS390XState *env, 
vaddr *pc,
 #define S390_R13_REGNUM 15
 #define S390_R14_REGNUM 16
 #define S390_R15_REGNUM 17
-/* Total Core Registers. */
-#define S390_NUM_CORE_REGS 18
 
 static inline void setcc(S390CPU *cpu, uint64_t cc)
 {
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 1d5c1da1b243..801eba9a0b0b 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -546,9 +546,12 @@ void gdb_init_cpu(CPUState *cpu)
 gdb_register_feature(cpu, 0,
  cc->gdb_read_register, cc->gdb_write_register,
  feature);
+cpu->gdb_num_regs = cpu->gdb_num_g_regs = feature->num_regs;
 }
 
-cpu->gdb_num_regs = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
+if (cc->gdb_num_core_regs) {
+cpu->gdb_num_regs = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
+}
 }
 
 void gdb_register_coprocessor(CPUState *cpu,
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index efb22a87f9ed..efcc22b1446c 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2498,7 +2498,6 @@ static void arm_cpu_class_init(ObjectClass *oc, void 
*data)
 #ifndef CONFIG_USER_ONLY
 cc->sysemu_ops = _sysemu_ops;
 #endif
-cc->gdb_num_core_regs = 26;
 cc->gdb_arch_name = arm_gdb_arch_name;
 cc->gdb_get_dynamic_xml = arm_gdb_get_dynamic_xml;
 cc->gdb_stop_before_watchpoint = true;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 1e9c6c85aece..8a5bad54cf70 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -793,7 +793,6 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void 
*data)
 
 cc->gdb_read_register = aarch64_cpu_gdb_read_register;
 cc->gdb_write_register = aarch64_cpu_gdb_write_register;
-cc->gdb_num_core_regs = 34;
 cc->gdb_core_xml_file = "aarch64-core.xml";
 cc->gdb_arch_name = aarch64_gdb_arch_name;
 
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
index 999c010dedb8..4bab9e227286 100644
--- a/target/avr/cpu.c
+++ b/target/avr/cpu.c
@@ -251,7 +251,6 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data)
 cc->gdb_read_register = avr_cpu_gdb_read_register;
 cc->gdb_write_register = avr_cpu_gdb_write_register;
 cc->gdb_adjust_breakpoint = avr_cpu_gdb_adjust_breakpoint;
-cc->gdb_num_core_regs = 35;
 cc->gdb_core_xml_file = "avr-cpu.xml";
 cc->tcg_ops = _tcg_ops;
 }
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 65ac9c75ad08..71678ef9c674 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -384,7 +384,6 @@ static void hexagon_cpu_class_init(ObjectClass *c, void 
*data)
 cc->get_pc = hexagon_cpu_get_pc;
 cc->gdb_read_register = hexagon_gdb_read_register;
 cc->gdb_write_register = hexagon_gdb_write_register;
-cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS;
 cc->gdb_stop_before_watchpoint = true;
 cc->gdb_core_xml_file = "hexagon-core.xml";
 cc->disas_set_info = hexagon_cpu_disas_set_info;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index cd16cb893daf..7c2276b90656 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -7969,10 +7969,8 @@ static void x86_cpu_common_class_init(ObjectClass *oc, 
void *data)
 cc->gdb_arch_name = x86_gdb_arch_name;
 #ifdef TARGET_X86_64
 cc->gdb_core_xml_file = "i386-64bit.xml";
-cc->gdb_num_core_regs = 66;
 #else
 cc->gdb_core_xml_file = 

[PATCH v17 02/14] target/ppc: Use GDBFeature for dynamic XML

2023-12-12 Thread Akihiko Odaki
In preparation for a change to use GDBFeature as a parameter of
gdb_register_coprocessor(), convert the internal representation of
dynamic feature from plain XML to GDBFeature.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Richard Henderson 
---
 target/ppc/cpu-qom.h  |  1 +
 target/ppc/cpu.h  |  4 +---
 target/ppc/cpu_init.c |  4 
 target/ppc/gdbstub.c  | 51 +++
 4 files changed, 21 insertions(+), 39 deletions(-)

diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index 0241609efefe..8247fa23367e 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -20,6 +20,7 @@
 #ifndef QEMU_PPC_CPU_QOM_H
 #define QEMU_PPC_CPU_QOM_H
 
+#include "exec/gdbstub.h"
 #include "hw/core/cpu.h"
 
 #ifdef TARGET_PPC64
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index f8101ffa2963..f87c26f98a67 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1471,8 +1471,7 @@ struct PowerPCCPUClass {
 int bfd_mach;
 uint32_t l1_dcache_size, l1_icache_size;
 #ifndef CONFIG_USER_ONLY
-unsigned int gdb_num_sprs;
-const char *gdb_spr_xml;
+GDBFeature gdb_spr;
 #endif
 const PPCHash64Options *hash64_opts;
 struct ppc_radix_page_info *radix_page_info;
@@ -1525,7 +1524,6 @@ int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t 
*buf, int reg);
 int ppc_cpu_gdb_write_register_apple(CPUState *cpu, uint8_t *buf, int reg);
 #ifndef CONFIG_USER_ONLY
 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu);
 const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name);
 #endif
 int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 40fe14a6c259..a0178c3ce80a 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -6682,10 +6682,6 @@ static void init_ppc_proc(PowerPCCPU *cpu)
 /* PowerPC implementation specific initialisations (SPRs, timers, ...) */
 (*pcc->init_proc)(env);
 
-#if !defined(CONFIG_USER_ONLY)
-ppc_gdb_gen_spr_xml(cpu);
-#endif
-
 /* MSR bits & flags consistency checks */
 if (env->msr_mask & (1 << 25)) {
 switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index ec5731e5d678..e3be3dbd109a 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -300,15 +300,23 @@ int ppc_cpu_gdb_write_register_apple(CPUState *cs, 
uint8_t *mem_buf, int n)
 }
 
 #ifndef CONFIG_USER_ONLY
-void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu)
+static void gdb_gen_spr_feature(CPUState *cs)
 {
-PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
+PowerPCCPU *cpu = POWERPC_CPU(cs);
 CPUPPCState *env = >env;
-GString *xml;
-char *spr_name;
+GDBFeatureBuilder builder;
 unsigned int num_regs = 0;
 int i;
 
+if (pcc->gdb_spr.xml) {
+return;
+}
+
+gdb_feature_builder_init(, >gdb_spr,
+ "org.qemu.power.spr", "power-spr.xml",
+ cs->gdb_num_regs);
+
 for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
 ppc_spr_t *spr = >spr_cb[i];
 
@@ -326,35 +334,13 @@ void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu)
  */
 spr->gdb_id = num_regs;
 num_regs++;
-}
-
-if (pcc->gdb_spr_xml) {
-return;
-}
 
-xml = g_string_new("");
-g_string_append(xml, "");
-g_string_append(xml, "");
-
-for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
-ppc_spr_t *spr = >spr_cb[i];
-
-if (!spr->name) {
-continue;
-}
-
-spr_name = g_ascii_strdown(spr->name, -1);
-g_string_append_printf(xml, "");
+gdb_feature_builder_append_reg(, g_ascii_strdown(spr->name, 
-1),
+   TARGET_LONG_BITS, num_regs,
+   "int", "spr");
 }
 
-g_string_append(xml, "");
-
-pcc->gdb_num_sprs = num_regs;
-pcc->gdb_spr_xml = g_string_free(xml, false);
+gdb_feature_builder_end();
 }
 
 const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name)
@@ -362,7 +348,7 @@ const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const 
char *xml_name)
 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
 
 if (strcmp(xml_name, "power-spr.xml") == 0) {
-return pcc->gdb_spr_xml;
+return pcc->gdb_spr.xml;
 }
 return NULL;
 }
@@ -599,7 +585,8 @@ void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *pcc)
  32, "power-vsx.xml", 0);
 }
 #ifndef CONFIG_USER_ONLY
+gdb_gen_spr_feature(cs);
 gdb_register_coprocessor(cs, gdb_get_spr_reg, gdb_set_spr_reg,
- pcc->gdb_num_sprs, "power-spr.xml", 0);
+ pcc->gdb_spr.num_regs, "power-spr.xml", 0);
 #endif
 }

-- 
2.43.0




[PATCH v17 12/14] plugins: Use different helpers when reading registers

2023-12-12 Thread Akihiko Odaki
This avoids optimizations incompatible when reading registers.

Signed-off-by: Akihiko Odaki 
---
 accel/tcg/plugin-helpers.h |  3 ++-
 include/qemu/plugin.h  |  1 +
 accel/tcg/plugin-gen.c | 43 +++
 plugins/api.c  | 12 ++--
 4 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/accel/tcg/plugin-helpers.h b/accel/tcg/plugin-helpers.h
index 8e685e065454..11796436f350 100644
--- a/accel/tcg/plugin-helpers.h
+++ b/accel/tcg/plugin-helpers.h
@@ -1,4 +1,5 @@
 #ifdef CONFIG_PLUGIN
-DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb, TCG_CALL_NO_RWG | TCG_CALL_PLUGIN, 
void, i32, ptr)
+DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb_no_wg, TCG_CALL_NO_WG | 
TCG_CALL_PLUGIN, void, i32, ptr)
+DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb_no_rwg, TCG_CALL_NO_RWG | 
TCG_CALL_PLUGIN, void, i32, ptr)
 DEF_HELPER_FLAGS_4(plugin_vcpu_mem_cb, TCG_CALL_NO_RWG | TCG_CALL_PLUGIN, 
void, i32, i32, i64, ptr)
 #endif
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
index 7fdc3a4849ff..b0c5ac682939 100644
--- a/include/qemu/plugin.h
+++ b/include/qemu/plugin.h
@@ -73,6 +73,7 @@ enum plugin_dyn_cb_type {
 
 enum plugin_dyn_cb_subtype {
 PLUGIN_CB_REGULAR,
+PLUGIN_CB_REGULAR_R,
 PLUGIN_CB_INLINE,
 PLUGIN_N_CB_SUBTYPES,
 };
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
index 78b331b25107..b37ce7683e69 100644
--- a/accel/tcg/plugin-gen.c
+++ b/accel/tcg/plugin-gen.c
@@ -79,6 +79,7 @@ enum plugin_gen_from {
 
 enum plugin_gen_cb {
 PLUGIN_GEN_CB_UDATA,
+PLUGIN_GEN_CB_UDATA_R,
 PLUGIN_GEN_CB_INLINE,
 PLUGIN_GEN_CB_MEM,
 PLUGIN_GEN_ENABLE_MEM_HELPER,
@@ -90,7 +91,10 @@ enum plugin_gen_cb {
  * These helpers are stubs that get dynamically switched out for calls
  * direct to the plugin if they are subscribed to.
  */
-void HELPER(plugin_vcpu_udata_cb)(uint32_t cpu_index, void *udata)
+void HELPER(plugin_vcpu_udata_cb_no_wg)(uint32_t cpu_index, void *udata)
+{ }
+
+void HELPER(plugin_vcpu_udata_cb_no_rwg)(uint32_t cpu_index, void *udata)
 { }
 
 void HELPER(plugin_vcpu_mem_cb)(unsigned int vcpu_index,
@@ -98,7 +102,7 @@ void HELPER(plugin_vcpu_mem_cb)(unsigned int vcpu_index,
 void *userdata)
 { }
 
-static void gen_empty_udata_cb(void)
+static void gen_empty_udata_cb(void (*gen_helper)(TCGv_i32, TCGv_ptr))
 {
 TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();
 TCGv_ptr udata = tcg_temp_ebb_new_ptr();
@@ -106,12 +110,22 @@ static void gen_empty_udata_cb(void)
 tcg_gen_movi_ptr(udata, 0);
 tcg_gen_ld_i32(cpu_index, tcg_env,
-offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
-gen_helper_plugin_vcpu_udata_cb(cpu_index, udata);
+gen_helper(cpu_index, udata);
 
 tcg_temp_free_ptr(udata);
 tcg_temp_free_i32(cpu_index);
 }
 
+static void gen_empty_udata_cb_no_wg(void)
+{
+gen_empty_udata_cb(gen_helper_plugin_vcpu_udata_cb_no_wg);
+}
+
+static void gen_empty_udata_cb_no_rwg(void)
+{
+gen_empty_udata_cb(gen_helper_plugin_vcpu_udata_cb_no_rwg);
+}
+
 /*
  * For now we only support addi_i64.
  * When we support more ops, we can generate one empty inline cb for each.
@@ -192,7 +206,8 @@ static void plugin_gen_empty_callback(enum plugin_gen_from 
from)
 gen_empty_mem_helper);
 /* fall through */
 case PLUGIN_GEN_FROM_TB:
-gen_wrapped(from, PLUGIN_GEN_CB_UDATA, gen_empty_udata_cb);
+gen_wrapped(from, PLUGIN_GEN_CB_UDATA, gen_empty_udata_cb_no_rwg);
+gen_wrapped(from, PLUGIN_GEN_CB_UDATA_R, gen_empty_udata_cb_no_wg);
 gen_wrapped(from, PLUGIN_GEN_CB_INLINE, gen_empty_inline_cb);
 break;
 default:
@@ -588,6 +603,12 @@ static void plugin_gen_tb_udata(const struct 
qemu_plugin_tb *ptb,
 inject_udata_cb(ptb->cbs[PLUGIN_CB_REGULAR], begin_op);
 }
 
+static void plugin_gen_tb_udata_r(const struct qemu_plugin_tb *ptb,
+  TCGOp *begin_op)
+{
+inject_udata_cb(ptb->cbs[PLUGIN_CB_REGULAR_R], begin_op);
+}
+
 static void plugin_gen_tb_inline(const struct qemu_plugin_tb *ptb,
  TCGOp *begin_op)
 {
@@ -602,6 +623,14 @@ static void plugin_gen_insn_udata(const struct 
qemu_plugin_tb *ptb,
 inject_udata_cb(insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_REGULAR], begin_op);
 }
 
+static void plugin_gen_insn_udata_r(const struct qemu_plugin_tb *ptb,
+TCGOp *begin_op, int insn_idx)
+{
+struct qemu_plugin_insn *insn = g_ptr_array_index(ptb->insns, insn_idx);
+
+inject_udata_cb(insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_REGULAR_R], begin_op);
+}
+
 static void plugin_gen_insn_inline(const struct qemu_plugin_tb *ptb,
TCGOp *begin_op, int insn_idx)
 {
@@ -721,6 +750,9 @@ static void plugin_gen_inject(struct qemu_plugin_tb 
*plugin_tb)
 case PLUGIN_GEN_CB_UDATA:
 plugin_gen_tb_udata(plugin_tb, op);
 break;

[PATCH v17 00/14] plugins: Allow to read registers

2023-12-12 Thread Akihiko Odaki
Based-on: <20231213-riscv-v7-0-a760156a3...@daynix.com>
("[PATCH v7 0/4] gdbstub and TCG plugin improvements")

I and other people in the University of Tokyo, where I research
processor design, found TCG plugins are very useful for processor design
exploration.

The feature we find missing is the capability to read registers from
plugins. In this series, I propose to add such a capability by reusing
gdbstub code.

The reuse of gdbstub code ensures the long-term stability of the TCG
plugin interface for register access without incurring a burden to
maintain yet another interface for register access.

This process to add TCG plugin involves four major changes. The first
one is to add members to GDBFeature necessary for register
identification.

The second one is to make gdb_read_register/gdb_write_register usable
outside of gdbstub context.

The third one is to actually make registers readable for plugins.

The execlog plugin will have new options to demonstrate the new feature.
I also have a plugin that uses this new feature to generate execution
traces for Sniper processor simulator, which is available at:
https://github.com/shioya-lab/sniper/tree/akihikodaki/bb

The below is a summary of patches:
Patch [01, 09] changes to use GDBFeature for dynamic XMLs.
Patch 10 adds members useful to identify registers to GDBFeature.
Patch 11 makes registers readable outside of gdbstub context.
Patch [12, 14] add the feature to read registers from plugins.

V16 -> V17:
  Rebased.

V15 -> V16:
  Added new plugin_dyn_cb_subtype and plugin_gen_cb to remove the global
  translator state change.

V14 -> V15:
  Added kdoc comments to include/exec/gdbstub.h.
  Changed to use g_array_append_val() in gdb_register_feature().
  Separated the CPU flags from event bitmap.

V13 -> V14:
  Fixed RISC-V CSR register numbers.

V12 -> V13:
  Rebased to "[PATCH v4 0/5] gdbstub and TCG plugin improvements".

V11 -> V12:
  Rebased to "[PATCH v2 0/3] gdbstub and TCG plugin improvements".

V10 -> V11:
  Fixed QEMU_PLUGIN_CB_RW_REGS.

V9 -> V10:
  Rebased to "[PATCH 0/4] gdbstub and TCG plugin improvements".
  Dropped patch "plugins: Support C++".
  Removed the unnecessary QEMU_PLUGIN_VERSION change.

V8 -> V9:
  Rebased to "[PATCH 00/25] October maintainer omnibus pre-PR (tests,
  gdbstub, plugins)".
  Added patch "target/riscv: Move MISA limits to class".
  Added patch "target/riscv: Remove misa_mxl validation".
  Added patch "target/riscv: Validate misa_mxl_max only once".
  Added patch "plugins: Use different helpers when reading".
  Moved contrib/plugins/cc.cc to tests/plugin/cc.cc.

V7 -> V8:
  Rebased to "[PATCH v3 00/12] gdbstub and TCG plugin improvements".
  Clarified that initialization and exit hooks affect TCG state.
  Simplified by adding the core feature to gdb_regs.

V6 -> V7:
  Rebased to "[PATCH v2 00/11] gdbstub and TCG plugin improvements".
  Replaced functions to get register identifiers.

V5 -> V6:
  Rebased to "[PATCH 0/8] gdbstub and TCG plugin improvements".

V4 -> V5:
  Corrected g_rw_lock_writer_lock() call. (Richard Henderson)
  Replaced abort() with g_assert_not_reached(). (Richard Henderson)
  Fixed CSR name leak in target/riscv. (Richard Henderson)
  Removed gdb_has_xml variable.

V3 -> V4:
  Added execlog changes I forgot to include in the last version.

V2 -> V3:
  Added patch "hw/core/cpu: Return static value with gdb_arch_name()".
  Added patch "gdbstub: Dynamically allocate target.xml buffer".
  (Alex Bennée)
  Added patch "gdbstub: Introduce GDBFeatureBuilder". (Alex Bennée)
  Dropped Reviewed-by tags for "target/*: Use GDBFeature for dynamic XML".
  Changed gdb_find_static_feature() to abort on failure. (Alex Bennée)
  Changed the execlog plugin to log the register value only when changed.
  (Alex Bennée)
  Dropped 0x prefixes for register value logs for conciseness.

V1 -> V2:
  Added SPDX-License-Identifier: GPL-2.0-or-later. (Philippe Mathieu-Daudé)
  Split long lines. (Philippe Mathieu-Daudé)
  Renamed gdb_features to gdb_static_features (Philippe Mathieu-Daudé)
  Dropped RFC.

Signed-off-by: Akihiko Odaki 
---
Akihiko Odaki (14):
  target/arm: Use GDBFeature for dynamic XML
  target/ppc: Use GDBFeature for dynamic XML
  target/riscv: Use GDBFeature for dynamic XML
  gdbstub: Use GDBFeature for gdb_register_coprocessor
  gdbstub: Use GDBFeature for GDBRegisterState
  gdbstub: Change gdb_get_reg_cb and gdb_set_reg_cb
  gdbstub: Simplify XML lookup
  gdbstub: Infer number of core registers from XML
  hw/core/cpu: Remove gdb_get_dynamic_xml member
  gdbstub: Add members to identify registers to GDBFeature
  gdbstub: Expose functions to read registers
  plugins: Use different helpers when reading registers
  plugins: Allow to read registers
  contrib/plugins: Allow to log registers

 docs/devel/tcg-plugins.rst   |  10 +-
 accel/tcg/plugin-helpers.h   |   3 +-
 include/exec/gdbstub.h   |  44 -
 include/hw/core/cpu.h|   7 +-
 

[PATCH v17 13/14] plugins: Allow to read registers

2023-12-12 Thread Akihiko Odaki
It is based on GDB protocol to ensure interface stability.

The timing of the vcpu init hook is also changed so that the hook will
get called after GDB features are initialized.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1706
Signed-off-by: Akihiko Odaki 
---
 include/qemu/qemu-plugin.h   | 50 ++--
 plugins/api.c| 20 ++
 plugins/qemu-plugins.symbols |  3 +++
 3 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
index 4daab6efd291..e7e21c9ee5b7 100644
--- a/include/qemu/qemu-plugin.h
+++ b/include/qemu/qemu-plugin.h
@@ -11,6 +11,7 @@
 #ifndef QEMU_QEMU_PLUGIN_H
 #define QEMU_QEMU_PLUGIN_H
 
+#include 
 #include 
 #include 
 #include 
@@ -227,8 +228,8 @@ struct qemu_plugin_insn;
  * @QEMU_PLUGIN_CB_R_REGS: callback reads the CPU's regs
  * @QEMU_PLUGIN_CB_RW_REGS: callback reads and writes the CPU's regs
  *
- * Note: currently unused, plugins cannot read or change system
- * register state.
+ * Note: currently QEMU_PLUGIN_CB_RW_REGS is unused, plugins cannot change
+ * system register state.
  */
 enum qemu_plugin_cb_flags {
 QEMU_PLUGIN_CB_NO_REGS,
@@ -708,4 +709,49 @@ uint64_t qemu_plugin_end_code(void);
 QEMU_PLUGIN_API
 uint64_t qemu_plugin_entry_code(void);
 
+/**
+ * qemu_plugin_find_register_file() - find register file
+ *
+ * @vcpu_index: the index of the vcpu context
+ * @name: the name of the register file.
+ *
+ * Returns the identifier of the register file if it was found, and a negative
+ * value otherwise.
+ *
+ * The names of register files are identical with names of GDB's standard
+ * target features with some extensions. For details, see:
+ * https://sourceware.org/gdb/onlinedocs/gdb/Standard-Target-Features.html
+ */
+int qemu_plugin_find_register_file(unsigned int vcpu_index, const char *name);
+
+/**
+ * qemu_plugin_find_register() - find register
+ *
+ * @vcpu_index: the index of the vcpu context
+ * @file: the register file identifier determined with
+ *qemu_plugin_find_register_file().
+ * @name: the name of the register.
+ *
+ * The names of register are identical with names used in GDB's standard
+ * target features with some extensions. For details, see:
+ * https://sourceware.org/gdb/onlinedocs/gdb/Standard-Target-Features.html
+ */
+int qemu_plugin_find_register(unsigned int vcpu_index, int file,
+  const char *name);
+
+/**
+ * qemu_plugin_read_register() - read register
+ *
+ * @buf: the byte array to append the read register content to.
+ * @reg: the register identifier determined with
+ *   qemu_plugin_find_register().
+ *
+ * This function is only available in a context that register read access is
+ * explicitly requested.
+ *
+ * Returns the size of the read register. The content of @buf is in target byte
+ * order.
+ */
+int qemu_plugin_read_register(GByteArray *buf, int reg);
+
 #endif /* QEMU_QEMU_PLUGIN_H */
diff --git a/plugins/api.c b/plugins/api.c
index ac39cdea0b35..3eaad5bf4187 100644
--- a/plugins/api.c
+++ b/plugins/api.c
@@ -35,10 +35,12 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/main-loop.h"
 #include "qemu/plugin.h"
 #include "qemu/log.h"
 #include "tcg/tcg.h"
 #include "exec/exec-all.h"
+#include "exec/gdbstub.h"
 #include "exec/ram_addr.h"
 #include "disas/disas.h"
 #include "plugin.h"
@@ -435,3 +437,21 @@ uint64_t qemu_plugin_entry_code(void)
 #endif
 return entry;
 }
+
+int qemu_plugin_find_register_file(unsigned int vcpu_index, const char *name)
+{
+QEMU_IOTHREAD_LOCK_GUARD();
+return gdb_find_feature(qemu_get_cpu(vcpu_index), name);
+}
+
+int qemu_plugin_find_register(unsigned int vcpu_index, int file,
+  const char *name)
+{
+QEMU_IOTHREAD_LOCK_GUARD();
+return gdb_find_feature_register(qemu_get_cpu(vcpu_index), file, name);
+}
+
+int qemu_plugin_read_register(GByteArray *buf, int reg)
+{
+return gdb_read_register(current_cpu, buf, reg);
+}
diff --git a/plugins/qemu-plugins.symbols b/plugins/qemu-plugins.symbols
index 71f6c90549d4..977f1fcfcbfb 100644
--- a/plugins/qemu-plugins.symbols
+++ b/plugins/qemu-plugins.symbols
@@ -42,4 +42,7 @@
   qemu_plugin_tb_vaddr;
   qemu_plugin_uninstall;
   qemu_plugin_vcpu_for_each;
+  qemu_plugin_find_register_file;
+  qemu_plugin_find_register;
+  qemu_plugin_read_register;
 };

-- 
2.43.0




[PATCH v17 11/14] gdbstub: Expose functions to read registers

2023-12-12 Thread Akihiko Odaki
gdb_find_feature() and gdb_find_feature_register() find registers.
gdb_read_register() actually reads registers.

Signed-off-by: Akihiko Odaki 
---
 include/exec/gdbstub.h | 29 +
 gdbstub/gdbstub.c  | 31 ++-
 2 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index da9ddfe54c5b..12336cb60064 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -111,6 +111,35 @@ void gdb_feature_builder_end(const GDBFeatureBuilder 
*builder);
  */
 const GDBFeature *gdb_find_static_feature(const char *xmlname);
 
+/**
+ * gdb_find_feature() - Find a feature associated with a CPU.
+ * @cpu: The CPU associated with the feature.
+ * @name: The feature's name.
+ *
+ * Return: The feature's number.
+ */
+int gdb_find_feature(CPUState *cpu, const char *name);
+
+/**
+ * gdb_find_feature_register() - Find a register associated with a CPU.
+ * @cpu: The CPU associated with the register.
+ * @feature: The feature's number returned by gdb_find_feature().
+ * @name: The register's name.
+ *
+ * Return: The register's number.
+ */
+int gdb_find_feature_register(CPUState *cpu, int feature, const char *name);
+
+/**
+ * gdb_read_register() - Read a register associated with a CPU.
+ * @cpu: The CPU associated with the register.
+ * @buf: The buffer that the read register will be appended to.
+ * @reg: The register's number returned by gdb_find_feature_register().
+ *
+ * Return: The number of read bytes.
+ */
+int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
+
 void gdb_set_stop_cpu(CPUState *cpu);
 
 /* in gdbstub-xml.c, generated by scripts/feature_to_c.py */
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 420ab2a3766b..9db623f1f730 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -490,7 +490,36 @@ const GDBFeature *gdb_find_static_feature(const char 
*xmlname)
 g_assert_not_reached();
 }
 
-static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
+int gdb_find_feature(CPUState *cpu, const char *name)
+{
+GDBRegisterState *r;
+
+for (guint i = 0; i < cpu->gdb_regs->len; i++) {
+r = _array_index(cpu->gdb_regs, GDBRegisterState, i);
+if (!strcmp(name, r->feature->name)) {
+return i;
+}
+}
+
+return -1;
+}
+
+int gdb_find_feature_register(CPUState *cpu, int feature, const char *name)
+{
+GDBRegisterState *r;
+
+r = _array_index(cpu->gdb_regs, GDBRegisterState, feature);
+
+for (int i = 0; i < r->feature->num_regs; i++) {
+if (r->feature->regs[i] && !strcmp(name, r->feature->regs[i])) {
+return r->base_reg + i;
+}
+}
+
+return -1;
+}
+
+int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
 {
 CPUClass *cc = CPU_GET_CLASS(cpu);
 GDBRegisterState *r;

-- 
2.43.0




[PATCH v17 14/14] contrib/plugins: Allow to log registers

2023-12-12 Thread Akihiko Odaki
This demonstrates how a register can be read from a plugin.

Signed-off-by: Akihiko Odaki 
---
 docs/devel/tcg-plugins.rst |  10 +++-
 contrib/plugins/execlog.c  | 120 +
 2 files changed, 97 insertions(+), 33 deletions(-)

diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst
index 81dcd43a6128..c9f8b275906c 100644
--- a/docs/devel/tcg-plugins.rst
+++ b/docs/devel/tcg-plugins.rst
@@ -497,6 +497,15 @@ arguments if required::
   $ qemu-system-arm $(QEMU_ARGS) \
 -plugin ./contrib/plugins/libexeclog.so,ifilter=st1w,afilter=0x40001808 -d 
plugin
 
+This plugin can also dump a specified register. The specification of register
+follows `GDB standard target features 
`__.
+
+Specify the name of the feature that contains the register and the name of the
+register with ``rfile`` and ``reg`` options, respectively::
+
+  $ qemu-system-arm $(QEMU_ARGS) \
+-plugin ./contrib/plugins/libexeclog.so,rfile=org.gnu.gdb.arm.core,reg=sp 
-d plugin
+
 - contrib/plugins/cache.c
 
 Cache modelling plugin that measures the performance of a given L1 cache
@@ -583,4 +592,3 @@ The following API is generated from the inline 
documentation in
 include the full kernel-doc annotations.
 
 .. kernel-doc:: include/qemu/qemu-plugin.h
-
diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c
index 82dc2f584e20..f3e714c888ff 100644
--- a/contrib/plugins/execlog.c
+++ b/contrib/plugins/execlog.c
@@ -15,27 +15,43 @@
 
 #include 
 
+typedef struct CPU {
+/* Store last executed instruction on each vCPU as a GString */
+GString *last_exec;
+GByteArray *reg_history[2];
+
+int reg;
+} CPU;
+
 QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
 
-/* Store last executed instruction on each vCPU as a GString */
-static GPtrArray *last_exec;
+static CPU *cpus;
+static int num_cpus;
 static GRWLock expand_array_lock;
 
 static GPtrArray *imatches;
 static GArray *amatches;
 
+static char *rfile_name;
+static char *reg_name;
+
 /*
- * Expand last_exec array.
+ * Expand cpu array.
  *
  * As we could have multiple threads trying to do this we need to
  * serialise the expansion under a lock.
  */
-static void expand_last_exec(int cpu_index)
+static void expand_cpu(int cpu_index)
 {
 g_rw_lock_writer_lock(_array_lock);
-while (cpu_index >= last_exec->len) {
-GString *s = g_string_new(NULL);
-g_ptr_array_add(last_exec, s);
+if (cpu_index >= num_cpus) {
+cpus = g_realloc_n(cpus, cpu_index + 1, sizeof(*cpus));
+while (cpu_index >= num_cpus) {
+cpus[num_cpus].last_exec = g_string_new(NULL);
+cpus[num_cpus].reg_history[0] = g_byte_array_new();
+cpus[num_cpus].reg_history[1] = g_byte_array_new();
+num_cpus++;
+}
 }
 g_rw_lock_writer_unlock(_array_lock);
 }
@@ -50,8 +66,8 @@ static void vcpu_mem(unsigned int cpu_index, 
qemu_plugin_meminfo_t info,
 
 /* Find vCPU in array */
 g_rw_lock_reader_lock(_array_lock);
-g_assert(cpu_index < last_exec->len);
-s = g_ptr_array_index(last_exec, cpu_index);
+g_assert(cpu_index < num_cpus);
+s = cpus[cpu_index].last_exec;
 g_rw_lock_reader_unlock(_array_lock);
 
 /* Indicate type of memory access */
@@ -77,28 +93,42 @@ static void vcpu_mem(unsigned int cpu_index, 
qemu_plugin_meminfo_t info,
  */
 static void vcpu_insn_exec(unsigned int cpu_index, void *udata)
 {
-GString *s;
+int n;
+int i;
 
-/* Find or create vCPU in array */
 g_rw_lock_reader_lock(_array_lock);
-if (cpu_index >= last_exec->len) {
-g_rw_lock_reader_unlock(_array_lock);
-expand_last_exec(cpu_index);
-g_rw_lock_reader_lock(_array_lock);
-}
-s = g_ptr_array_index(last_exec, cpu_index);
-g_rw_lock_reader_unlock(_array_lock);
 
 /* Print previous instruction in cache */
-if (s->len) {
-qemu_plugin_outs(s->str);
+if (cpus[cpu_index].last_exec->len) {
+if (cpus[cpu_index].reg >= 0) {
+GByteArray *current = cpus[cpu_index].reg_history[0];
+GByteArray *last = cpus[cpu_index].reg_history[1];
+
+g_byte_array_set_size(current, 0);
+n = qemu_plugin_read_register(current, cpus[cpu_index].reg);
+
+if (n != last->len || memcmp(current->data, last->data, n)) {
+g_string_append(cpus[cpu_index].last_exec, ", reg,");
+for (i = 0; i < n; i++) {
+g_string_append_printf(cpus[cpu_index].last_exec, " %02x",
+   current->data[i]);
+}
+}
+
+cpus[cpu_index].reg_history[0] = last;
+cpus[cpu_index].reg_history[1] = current;
+}
+
+qemu_plugin_outs(cpus[cpu_index].last_exec->str);
 qemu_plugin_outs("\n");
 }
 
 /* Store new instruction in cache */
 /* 

[PATCH v17 05/14] gdbstub: Use GDBFeature for GDBRegisterState

2023-12-12 Thread Akihiko Odaki
Simplify GDBRegisterState by replacing num_regs and xml members with
one member that points to GDBFeature.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Alex Bennée 
---
 gdbstub/gdbstub.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 068180c83c76..a80729436b66 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -47,10 +47,9 @@
 
 typedef struct GDBRegisterState {
 int base_reg;
-int num_regs;
 gdb_get_reg_cb get_reg;
 gdb_set_reg_cb set_reg;
-const char *xml;
+const GDBFeature *feature;
 } GDBRegisterState;
 
 GDBState gdbserver_state;
@@ -391,7 +390,7 @@ static const char *get_feature_xml(const char *p, const 
char **newp,
 g_ptr_array_add(
 xml,
 g_markup_printf_escaped("",
-r->xml));
+r->feature->xmlname));
 }
 }
 g_ptr_array_add(xml, g_strdup(""));
@@ -513,7 +512,7 @@ static int gdb_read_register(CPUState *cpu, GByteArray 
*buf, int reg)
 if (cpu->gdb_regs) {
 for (guint i = 0; i < cpu->gdb_regs->len; i++) {
 r = _array_index(cpu->gdb_regs, GDBRegisterState, i);
-if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
+if (r->base_reg <= reg && reg < r->base_reg + 
r->feature->num_regs) {
 return r->get_reg(env, buf, reg - r->base_reg);
 }
 }
@@ -534,7 +533,7 @@ static int gdb_write_register(CPUState *cpu, uint8_t 
*mem_buf, int reg)
 if (cpu->gdb_regs) {
 for (guint i = 0; i < cpu->gdb_regs->len; i++) {
 r =  _array_index(cpu->gdb_regs, GDBRegisterState, i);
-if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
+if (r->base_reg <= reg && reg < r->base_reg + 
r->feature->num_regs) {
 return r->set_reg(env, mem_buf, reg - r->base_reg);
 }
 }
@@ -553,7 +552,7 @@ void gdb_register_coprocessor(CPUState *cpu,
 for (i = 0; i < cpu->gdb_regs->len; i++) {
 /* Check for duplicates.  */
 s = _array_index(cpu->gdb_regs, GDBRegisterState, i);
-if (strcmp(s->xml, feature->xmlname) == 0) {
+if (s->feature == feature) {
 return;
 }
 }
@@ -565,10 +564,9 @@ void gdb_register_coprocessor(CPUState *cpu,
 g_array_set_size(cpu->gdb_regs, i + 1);
 s = _array_index(cpu->gdb_regs, GDBRegisterState, i);
 s->base_reg = cpu->gdb_num_regs;
-s->num_regs = feature->num_regs;
 s->get_reg = get_reg;
 s->set_reg = set_reg;
-s->xml = feature->xml;
+s->feature = feature;
 
 /* Add to end of list.  */
 cpu->gdb_num_regs += feature->num_regs;

-- 
2.43.0




[PATCH v17 07/14] gdbstub: Simplify XML lookup

2023-12-12 Thread Akihiko Odaki
Now we know all instances of GDBFeature that is used in CPU so we can
traverse them to find XML. This removes the need for a CPU-specific
lookup function for dynamic XMLs.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Alex Bennée 
---
 include/exec/gdbstub.h |   6 +++
 gdbstub/gdbstub.c  | 118 +
 hw/core/cpu-common.c   |   5 ++-
 3 files changed, 69 insertions(+), 60 deletions(-)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index bcaab1bc750e..82a8afa237f0 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -27,6 +27,12 @@ typedef struct GDBFeatureBuilder {
 typedef int (*gdb_get_reg_cb)(CPUState *cpu, GByteArray *buf, int reg);
 typedef int (*gdb_set_reg_cb)(CPUState *cpu, uint8_t *buf, int reg);
 
+/**
+ * gdb_init_cpu(): Initialize the CPU for gdbstub.
+ * @cpu: The CPU to be initialized.
+ */
+void gdb_init_cpu(CPUState *cpu);
+
 /**
  * gdb_register_coprocessor() - register a supplemental set of registers
  * @cpu - the CPU associated with registers
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 21fea7fffae8..1d5c1da1b243 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -352,6 +352,7 @@ static const char *get_feature_xml(const char *p, const 
char **newp,
 {
 CPUState *cpu = gdb_get_first_cpu_in_process(process);
 CPUClass *cc = CPU_GET_CLASS(cpu);
+GDBRegisterState *r;
 size_t len;
 
 /*
@@ -365,7 +366,6 @@ static const char *get_feature_xml(const char *p, const 
char **newp,
 /* Is it the main target xml? */
 if (strncmp(p, "target.xml", len) == 0) {
 if (!process->target_xml) {
-GDBRegisterState *r;
 g_autoptr(GPtrArray) xml = g_ptr_array_new_with_free_func(g_free);
 
 g_ptr_array_add(
@@ -380,18 +380,12 @@ static const char *get_feature_xml(const char *p, const 
char **newp,
 g_markup_printf_escaped("%s",
 cc->gdb_arch_name(cpu)));
 }
-g_ptr_array_add(
-xml,
-g_markup_printf_escaped("",
-cc->gdb_core_xml_file));
-if (cpu->gdb_regs) {
-for (guint i = 0; i < cpu->gdb_regs->len; i++) {
-r = _array_index(cpu->gdb_regs, GDBRegisterState, i);
-g_ptr_array_add(
-xml,
-g_markup_printf_escaped("",
-r->feature->xmlname));
-}
+for (guint i = 0; i < cpu->gdb_regs->len; i++) {
+r = _array_index(cpu->gdb_regs, GDBRegisterState, i);
+g_ptr_array_add(
+xml,
+g_markup_printf_escaped("",
+r->feature->xmlname));
 }
 g_ptr_array_add(xml, g_strdup(""));
 g_ptr_array_add(xml, NULL);
@@ -400,20 +394,11 @@ static const char *get_feature_xml(const char *p, const 
char **newp,
 }
 return process->target_xml;
 }
-/* Is it dynamically generated by the target? */
-if (cc->gdb_get_dynamic_xml) {
-g_autofree char *xmlname = g_strndup(p, len);
-const char *xml = cc->gdb_get_dynamic_xml(cpu, xmlname);
-if (xml) {
-return xml;
-}
-}
-/* Is it one of the encoded gdb-xml/ files? */
-for (int i = 0; gdb_static_features[i].xmlname; i++) {
-const char *name = gdb_static_features[i].xmlname;
-if ((strncmp(name, p, len) == 0) &&
-strlen(name) == len) {
-return gdb_static_features[i].xml;
+/* Is it one of the features? */
+for (guint i = 0; i < cpu->gdb_regs->len; i++) {
+r = _array_index(cpu->gdb_regs, GDBRegisterState, i);
+if (strncmp(p, r->feature->xmlname, len) == 0) {
+return r->feature->xml;
 }
 }
 
@@ -508,12 +493,10 @@ static int gdb_read_register(CPUState *cpu, GByteArray 
*buf, int reg)
 return cc->gdb_read_register(cpu, buf, reg);
 }
 
-if (cpu->gdb_regs) {
-for (guint i = 0; i < cpu->gdb_regs->len; i++) {
-r = _array_index(cpu->gdb_regs, GDBRegisterState, i);
-if (r->base_reg <= reg && reg < r->base_reg + 
r->feature->num_regs) {
-return r->get_reg(cpu, buf, reg - r->base_reg);
-}
+for (guint i = 0; i < cpu->gdb_regs->len; i++) {
+r = _array_index(cpu->gdb_regs, GDBRegisterState, i);
+if (r->base_reg <= reg && reg < r->base_reg + r->feature->num_regs) {
+return r->get_reg(cpu, buf, reg - r->base_reg);
 }
 }
 return 0;
@@ -528,51 +511,70 @@ static int gdb_write_register(CPUState *cpu, uint8_t 
*mem_buf, int reg)
 return cc->gdb_write_register(cpu, mem_buf, reg);
 }
 
-if (cpu->gdb_regs) {
-for (guint i = 0; i < cpu->gdb_regs->len; i++) {
- 

[PATCH v17 10/14] gdbstub: Add members to identify registers to GDBFeature

2023-12-12 Thread Akihiko Odaki
These members will be used to help plugins to identify registers.
The added members in instances of GDBFeature dynamically generated by
CPUs will be filled in later changes.

Signed-off-by: Akihiko Odaki 
---
 include/exec/gdbstub.h  |  3 +++
 gdbstub/gdbstub.c   | 12 +---
 target/riscv/gdbstub.c  |  4 +---
 scripts/feature_to_c.py | 14 +-
 4 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 82a8afa237f0..da9ddfe54c5b 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -13,12 +13,15 @@
 typedef struct GDBFeature {
 const char *xmlname;
 const char *xml;
+const char *name;
+const char * const *regs;
 int num_regs;
 } GDBFeature;
 
 typedef struct GDBFeatureBuilder {
 GDBFeature *feature;
 GPtrArray *xml;
+GPtrArray *regs;
 int base_reg;
 } GDBFeatureBuilder;
 
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 801eba9a0b0b..420ab2a3766b 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -419,9 +419,10 @@ void gdb_feature_builder_init(GDBFeatureBuilder *builder, 
GDBFeature *feature,
 builder->feature = feature;
 builder->xml = g_ptr_array_new();
 g_ptr_array_add(builder->xml, header);
+builder->regs = g_ptr_array_new();
 builder->base_reg = base_reg;
 feature->xmlname = xmlname;
-feature->num_regs = 0;
+feature->name = name;
 }
 
 void gdb_feature_builder_append_tag(const GDBFeatureBuilder *builder,
@@ -440,10 +441,12 @@ void gdb_feature_builder_append_reg(const 
GDBFeatureBuilder *builder,
 const char *type,
 const char *group)
 {
-if (builder->feature->num_regs < regnum) {
-builder->feature->num_regs = regnum;
+if (builder->regs->len <= regnum) {
+g_ptr_array_set_size(builder->regs, regnum + 1);
 }
 
+builder->regs->pdata[regnum] = (gpointer *)name;
+
 if (group) {
 gdb_feature_builder_append_tag(
 builder,
@@ -469,6 +472,9 @@ void gdb_feature_builder_end(const GDBFeatureBuilder 
*builder)
 }
 
 g_ptr_array_free(builder->xml, TRUE);
+
+builder->feature->num_regs = builder->regs->len;
+builder->feature->regs = (void *)g_ptr_array_free(builder->regs, FALSE);
 }
 
 const GDBFeature *gdb_find_static_feature(const char *xmlname)
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 68d0fdc1fd6c..d9b52ffd09b6 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -266,11 +266,9 @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState 
*cs, int base_reg)
 }
 predicate = csr_ops[i].predicate;
 if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) {
-g_autofree char *dynamic_name = NULL;
 name = csr_ops[i].name;
 if (!name) {
-dynamic_name = g_strdup_printf("csr%03x", i);
-name = dynamic_name;
+name = g_strdup_printf("csr%03x", i);
 }
 
 gdb_feature_builder_append_reg(, name, bitsize, i,
diff --git a/scripts/feature_to_c.py b/scripts/feature_to_c.py
index e04d6b2df7f7..807af0e685c3 100644
--- a/scripts/feature_to_c.py
+++ b/scripts/feature_to_c.py
@@ -50,7 +50,9 @@ def writeliteral(indent, bytes):
 sys.stderr.write(f'unexpected start tag: {element.tag}\n')
 exit(1)
 
+feature_name = element.attrib['name']
 regnum = 0
+regnames = []
 regnums = []
 tags = ['feature']
 for event, element in events:
@@ -67,6 +69,7 @@ def writeliteral(indent, bytes):
 if 'regnum' in element.attrib:
 regnum = int(element.attrib['regnum'])
 
+regnames.append(element.attrib['name'])
 regnums.append(regnum)
 regnum += 1
 
@@ -85,6 +88,15 @@ def writeliteral(indent, bytes):
 writeliteral(8, bytes(os.path.basename(input), 'utf-8'))
 sys.stdout.write(',\n')
 writeliteral(8, read)
-sys.stdout.write(f',\n{num_regs},\n}},\n')
+sys.stdout.write(',\n')
+writeliteral(8, bytes(feature_name, 'utf-8'))
+sys.stdout.write(',\n(const char * const []) {\n')
+
+for index, regname in enumerate(regnames):
+sys.stdout.write(f'[{regnums[index] - base_reg}] =\n')
+writeliteral(16, bytes(regname, 'utf-8'))
+sys.stdout.write(',\n')
+
+sys.stdout.write(f'}},\n{num_regs},\n}},\n')
 
 sys.stdout.write('{ NULL }\n};\n')

-- 
2.43.0




[PATCH v17 09/14] hw/core/cpu: Remove gdb_get_dynamic_xml member

2023-12-12 Thread Akihiko Odaki
This function is no longer used.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Alex Bennée 
---
 include/hw/core/cpu.h |  4 
 target/arm/cpu.h  |  6 --
 target/ppc/cpu.h  |  1 -
 target/arm/cpu.c  |  1 -
 target/arm/gdbstub.c  | 18 --
 target/ppc/cpu_init.c |  3 ---
 target/ppc/gdbstub.c  | 10 --
 target/riscv/cpu.c| 14 --
 8 files changed, 57 deletions(-)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index a6214610603f..17f99adc0f41 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -134,9 +134,6 @@ struct SysemuCPUOps;
  *   before the insn which triggers a watchpoint rather than after it.
  * @gdb_arch_name: Optional callback that returns the architecture name known
  * to GDB. The caller must free the returned string with g_free.
- * @gdb_get_dynamic_xml: Callback to return dynamically generated XML for the
- *   gdb stub. Returns a pointer to the XML contents for the specified XML file
- *   or NULL if the CPU doesn't have a dynamically generated content for it.
  * @disas_set_info: Setup architecture specific components of disassembly info
  * @adjust_watchpoint_address: Perform a target-specific adjustment to an
  * address before attempting to match it against watchpoints.
@@ -167,7 +164,6 @@ struct CPUClass {
 
 const char *gdb_core_xml_file;
 const gchar * (*gdb_arch_name)(CPUState *cpu);
-const char * (*gdb_get_dynamic_xml)(CPUState *cpu, const char *xmlname);
 
 void (*disas_set_info)(CPUState *cpu, disassemble_info *info);
 
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index b2f8ac81f06c..c8e77440f0f7 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1182,12 +1182,6 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cpu, 
vaddr addr,
 int arm_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
 int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
-/* Returns the dynamically generated XML for the gdb stub.
- * Returns a pointer to the XML contents for the specified XML file or NULL
- * if the XML name doesn't match the predefined one.
- */
-const char *arm_gdb_get_dynamic_xml(CPUState *cpu, const char *xmlname);
-
 int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
  int cpuid, DumpState *s);
 int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index f87c26f98a67..9f94282e13e9 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1524,7 +1524,6 @@ int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t 
*buf, int reg);
 int ppc_cpu_gdb_write_register_apple(CPUState *cpu, uint8_t *buf, int reg);
 #ifndef CONFIG_USER_ONLY
 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name);
 #endif
 int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
int cpuid, DumpState *s);
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index efcc22b1446c..304538cca52a 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2499,7 +2499,6 @@ static void arm_cpu_class_init(ObjectClass *oc, void 
*data)
 cc->sysemu_ops = _sysemu_ops;
 #endif
 cc->gdb_arch_name = arm_gdb_arch_name;
-cc->gdb_get_dynamic_xml = arm_gdb_get_dynamic_xml;
 cc->gdb_stop_before_watchpoint = true;
 cc->disas_set_info = arm_disas_set_info;
 
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 059d84f98e52..a3bb73cfa7ce 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -474,24 +474,6 @@ static GDBFeature 
*arm_gen_dynamic_m_secextreg_feature(CPUState *cs,
 #endif
 #endif /* CONFIG_TCG */
 
-const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
-{
-ARMCPU *cpu = ARM_CPU(cs);
-
-if (strcmp(xmlname, "system-registers.xml") == 0) {
-return cpu->dyn_sysreg_feature.desc.xml;
-} else if (strcmp(xmlname, "sve-registers.xml") == 0) {
-return cpu->dyn_svereg_feature.desc.xml;
-} else if (strcmp(xmlname, "arm-m-system.xml") == 0) {
-return cpu->dyn_m_systemreg_feature.desc.xml;
-#ifndef CONFIG_USER_ONLY
-} else if (strcmp(xmlname, "arm-m-secext.xml") == 0) {
-return cpu->dyn_m_secextreg_feature.desc.xml;
-#endif
-}
-return NULL;
-}
-
 void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
 {
 CPUState *cs = CPU(cpu);
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index a0178c3ce80a..909d753b0221 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -7380,9 +7380,6 @@ static void ppc_cpu_class_init(ObjectClass *oc, void 
*data)
 #endif
 
 cc->gdb_num_core_regs = 71;
-#ifndef CONFIG_USER_ONLY
-cc->gdb_get_dynamic_xml = ppc_gdb_get_dynamic_xml;
-#endif
 #ifdef USE_APPLE_GDB
 cc->gdb_read_register = ppc_cpu_gdb_read_register_apple;
 cc->gdb_write_register = ppc_cpu_gdb_write_register_apple;
diff --git 

[PATCH v17 01/14] target/arm: Use GDBFeature for dynamic XML

2023-12-12 Thread Akihiko Odaki
In preparation for a change to use GDBFeature as a parameter of
gdb_register_coprocessor(), convert the internal representation of
dynamic feature from plain XML to GDBFeature.

Signed-off-by: Akihiko Odaki 
Acked-by: Richard Henderson 
---
 target/arm/cpu.h   |  21 
 target/arm/internals.h |   2 +-
 target/arm/gdbstub.c   | 142 -
 target/arm/gdbstub64.c |  95 +++--
 4 files changed, 123 insertions(+), 137 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index a0282e0d2817..b2f8ac81f06c 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -25,6 +25,7 @@
 #include "hw/registerfields.h"
 #include "cpu-qom.h"
 #include "exec/cpu-defs.h"
+#include "exec/gdbstub.h"
 #include "qapi/qapi-types-common.h"
 
 /* ARM processors have a weak memory model */
@@ -136,23 +137,21 @@ enum {
  */
 
 /**
- * DynamicGDBXMLInfo:
- * @desc: Contains the XML descriptions.
- * @num: Number of the registers in this XML seen by GDB.
+ * DynamicGDBFeatureInfo:
+ * @desc: Contains the feature descriptions.
  * @data: A union with data specific to the set of registers
  *@cpregs_keys: Array that contains the corresponding Key of
  *  a given cpreg with the same order of the cpreg
  *  in the XML description.
  */
-typedef struct DynamicGDBXMLInfo {
-char *desc;
-int num;
+typedef struct DynamicGDBFeatureInfo {
+GDBFeature desc;
 union {
 struct {
 uint32_t *keys;
 } cpregs;
 } data;
-} DynamicGDBXMLInfo;
+} DynamicGDBFeatureInfo;
 
 /* CPU state for each instance of a generic timer (in cp15 c14) */
 typedef struct ARMGenericTimer {
@@ -878,10 +877,10 @@ struct ArchCPU {
 uint64_t *cpreg_vmstate_values;
 int32_t cpreg_vmstate_array_len;
 
-DynamicGDBXMLInfo dyn_sysreg_xml;
-DynamicGDBXMLInfo dyn_svereg_xml;
-DynamicGDBXMLInfo dyn_m_systemreg_xml;
-DynamicGDBXMLInfo dyn_m_secextreg_xml;
+DynamicGDBFeatureInfo dyn_sysreg_feature;
+DynamicGDBFeatureInfo dyn_svereg_feature;
+DynamicGDBFeatureInfo dyn_m_systemreg_feature;
+DynamicGDBFeatureInfo dyn_m_secextreg_feature;
 
 /* Timers used by the generic (architected) timer */
 QEMUTimer *gt_timer[NUM_GTIMERS];
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 143d57c0fe46..1136710741f0 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1446,7 +1446,7 @@ static inline uint64_t pmu_counter_mask(CPUARMState *env)
 }
 
 #ifdef TARGET_AARCH64
-int arm_gen_dynamic_svereg_xml(CPUState *cpu, int base_reg);
+GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cpu, int base_reg);
 int aarch64_gdb_get_sve_reg(CPUARMState *env, GByteArray *buf, int reg);
 int aarch64_gdb_set_sve_reg(CPUARMState *env, uint8_t *buf, int reg);
 int aarch64_gdb_get_fpu_reg(CPUARMState *env, GByteArray *buf, int reg);
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 28f546a5ff95..5949adfb31ae 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -26,11 +26,11 @@
 #include "cpu-features.h"
 #include "cpregs.h"
 
-typedef struct RegisterSysregXmlParam {
+typedef struct RegisterSysregFeatureParam {
 CPUState *cs;
-GString *s;
+GDBFeatureBuilder builder;
 int n;
-} RegisterSysregXmlParam;
+} RegisterSysregFeatureParam;
 
 /* Old gdb always expect FPA registers.  Newer (xml-aware) gdb only expect
whatever the target description contains.  Due to a historical mishap
@@ -216,7 +216,7 @@ static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray 
*buf, int reg)
 const ARMCPRegInfo *ri;
 uint32_t key;
 
-key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
+key = cpu->dyn_sysreg_feature.data.cpregs.keys[reg];
 ri = get_arm_cp_reginfo(cpu->cp_regs, key);
 if (ri) {
 if (cpreg_field_is_64bit(ri)) {
@@ -233,34 +233,32 @@ static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t 
*buf, int reg)
 return 0;
 }
 
-static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
+static void arm_gen_one_feature_sysreg(GDBFeatureBuilder *builder,
+   DynamicGDBFeatureInfo *dyn_feature,
ARMCPRegInfo *ri, uint32_t ri_key,
-   int bitsize, int regnum)
+   int bitsize, int n)
 {
-g_string_append_printf(s, "name);
-g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
-g_string_append_printf(s, " regnum=\"%d\"", regnum);
-g_string_append_printf(s, " group=\"cp_regs\"/>");
-dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key;
-dyn_xml->num++;
+gdb_feature_builder_append_reg(builder, ri->name, bitsize, n,
+   "int", "cp_regs");
+
+dyn_feature->data.cpregs.keys[n] = ri_key;
 }
 
-static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
-

[PATCH v17 03/14] target/riscv: Use GDBFeature for dynamic XML

2023-12-12 Thread Akihiko Odaki
In preparation for a change to use GDBFeature as a parameter of
gdb_register_coprocessor(), convert the internal representation of
dynamic feature from plain XML to GDBFeature.

Signed-off-by: Akihiko Odaki 
---
 target/riscv/cpu.h |  5 ++--
 target/riscv/cpu.c |  4 +--
 target/riscv/gdbstub.c | 79 ++
 3 files changed, 40 insertions(+), 48 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 060b7f69a743..ad7236d75477 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -24,6 +24,7 @@
 #include "hw/registerfields.h"
 #include "hw/qdev-properties.h"
 #include "exec/cpu-defs.h"
+#include "exec/gdbstub.h"
 #include "qemu/cpu-float.h"
 #include "qom/object.h"
 #include "qemu/int128.h"
@@ -424,8 +425,8 @@ struct ArchCPU {
 
 CPURISCVState env;
 
-char *dyn_csr_xml;
-char *dyn_vreg_xml;
+GDBFeature dyn_csr_feature;
+GDBFeature dyn_vreg_feature;
 
 /* Configuration Settings */
 RISCVCPUConfig cfg;
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index b799f1336041..673e937a5d82 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1534,9 +1534,9 @@ static const char *riscv_gdb_get_dynamic_xml(CPUState 
*cs, const char *xmlname)
 RISCVCPU *cpu = RISCV_CPU(cs);
 
 if (strcmp(xmlname, "riscv-csr.xml") == 0) {
-return cpu->dyn_csr_xml;
+return cpu->dyn_csr_feature.xml;
 } else if (strcmp(xmlname, "riscv-vector.xml") == 0) {
-return cpu->dyn_vreg_xml;
+return cpu->dyn_vreg_feature.xml;
 }
 
 return NULL;
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 365040228a12..76b72a959549 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -214,13 +214,14 @@ static int riscv_gdb_set_virtual(CPURISCVState *cs, 
uint8_t *mem_buf, int n)
 return 0;
 }
 
-static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
+static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState *cs, int base_reg)
 {
 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cs);
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = >env;
-GString *s = g_string_new(NULL);
+GDBFeatureBuilder builder;
 riscv_csr_predicate_fn predicate;
+const char *name;
 int bitsize = 16 << mcc->misa_mxl_max;
 int i;
 
@@ -233,9 +234,9 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int 
base_reg)
 bitsize = 64;
 }
 
-g_string_printf(s, "");
-g_string_append_printf(s, "");
-g_string_append_printf(s, "");
+gdb_feature_builder_init(, >dyn_csr_feature,
+ "org.gnu.gdb.riscv.csr", "riscv-csr.xml",
+ base_reg);
 
 for (i = 0; i < CSR_TABLE_SIZE; i++) {
 if (env->priv_ver < csr_ops[i].min_priv_ver) {
@@ -243,72 +244,64 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int 
base_reg)
 }
 predicate = csr_ops[i].predicate;
 if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) {
-if (csr_ops[i].name) {
-g_string_append_printf(s, "", base_reg + i);
+
+gdb_feature_builder_append_reg(, name, bitsize, i,
+   "int", NULL);
 }
 }
 
-g_string_append_printf(s, "");
-
-cpu->dyn_csr_xml = g_string_free(s, false);
+gdb_feature_builder_end();
 
 #if !defined(CONFIG_USER_ONLY)
 env->debugger = false;
 #endif
 
-return CSR_TABLE_SIZE;
+return >dyn_csr_feature;
 }
 
-static int ricsv_gen_dynamic_vector_xml(CPUState *cs, int base_reg)
+static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
-GString *s = g_string_new(NULL);
-g_autoptr(GString) ts = g_string_new("");
+GDBFeatureBuilder builder;
 int reg_width = cpu->cfg.vlen;
-int num_regs = 0;
 int i;
 
-g_string_printf(s, "");
-g_string_append_printf(s, "");
-g_string_append_printf(s, "");
+gdb_feature_builder_init(, >dyn_vreg_feature,
+ "org.gnu.gdb.riscv.vector", "riscv-vector.xml",
+ base_reg);
 
 /* First define types and totals in a whole VL */
 for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
 int count = reg_width / vec_lanes[i].size;
-g_string_printf(ts, "%s", vec_lanes[i].id);
-g_string_append_printf(s,
-   "",
-   ts->str, vec_lanes[i].gdb_type, count);
+gdb_feature_builder_append_tag(
+, "",
+vec_lanes[i].id, vec_lanes[i].gdb_type, count);
 }
 
 /* Define unions */
-g_string_append_printf(s, "");
+gdb_feature_builder_append_tag(, "");
 for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
-g_string_append_printf(s, "",
-   vec_lanes[i].suffix,
-   vec_lanes[i].id);
+gdb_feature_builder_append_tag(,
+

[PATCH v17 04/14] gdbstub: Use GDBFeature for gdb_register_coprocessor

2023-12-12 Thread Akihiko Odaki
This is a tree-wide change to introduce GDBFeature parameter to
gdb_register_coprocessor(). The new parameter just replaces num_regs
and xml parameters for now. GDBFeature will be utilized to simplify XML
lookup in a following change.

Signed-off-by: Akihiko Odaki 
Acked-by: Alex Bennée 
---
 include/exec/gdbstub.h |  2 +-
 gdbstub/gdbstub.c  | 13 +++--
 target/arm/gdbstub.c   | 35 +++
 target/hexagon/cpu.c   |  3 +--
 target/loongarch/gdbstub.c |  2 +-
 target/m68k/helper.c   |  6 +++---
 target/microblaze/cpu.c|  5 +++--
 target/ppc/gdbstub.c   | 11 ++-
 target/riscv/gdbstub.c | 20 
 target/s390x/gdbstub.c | 28 +++-
 10 files changed, 60 insertions(+), 65 deletions(-)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index d8a3c56fa2b8..ac6fce99a64e 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -38,7 +38,7 @@ typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t 
*buf, int reg);
  */
 void gdb_register_coprocessor(CPUState *cpu,
   gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
-  int num_regs, const char *xml, int g_pos);
+  const GDBFeature *feature, int g_pos);
 
 /**
  * gdbserver_start: start the gdb server
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 46d752bbc2cd..068180c83c76 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -544,7 +544,7 @@ static int gdb_write_register(CPUState *cpu, uint8_t 
*mem_buf, int reg)
 
 void gdb_register_coprocessor(CPUState *cpu,
   gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
-  int num_regs, const char *xml, int g_pos)
+  const GDBFeature *feature, int g_pos)
 {
 GDBRegisterState *s;
 guint i;
@@ -553,7 +553,7 @@ void gdb_register_coprocessor(CPUState *cpu,
 for (i = 0; i < cpu->gdb_regs->len; i++) {
 /* Check for duplicates.  */
 s = _array_index(cpu->gdb_regs, GDBRegisterState, i);
-if (strcmp(s->xml, xml) == 0) {
+if (strcmp(s->xml, feature->xmlname) == 0) {
 return;
 }
 }
@@ -565,17 +565,18 @@ void gdb_register_coprocessor(CPUState *cpu,
 g_array_set_size(cpu->gdb_regs, i + 1);
 s = _array_index(cpu->gdb_regs, GDBRegisterState, i);
 s->base_reg = cpu->gdb_num_regs;
-s->num_regs = num_regs;
+s->num_regs = feature->num_regs;
 s->get_reg = get_reg;
 s->set_reg = set_reg;
-s->xml = xml;
+s->xml = feature->xml;
 
 /* Add to end of list.  */
-cpu->gdb_num_regs += num_regs;
+cpu->gdb_num_regs += feature->num_regs;
 if (g_pos) {
 if (g_pos != s->base_reg) {
 error_report("Error: Bad gdb register numbering for '%s', "
- "expected %d got %d", xml, g_pos, s->base_reg);
+ "expected %d got %d", feature->xml,
+ g_pos, s->base_reg);
 } else {
 cpu->gdb_num_g_regs = cpu->gdb_num_regs;
 }
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 5949adfb31ae..f2b201d31254 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -483,14 +483,14 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
  */
 #ifdef TARGET_AARCH64
 if (isar_feature_aa64_sve(>isar)) {
-int nreg = arm_gen_dynamic_svereg_feature(cs, 
cs->gdb_num_regs)->num_regs;
+GDBFeature *feature = arm_gen_dynamic_svereg_feature(cs, 
cs->gdb_num_regs);
 gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg,
- aarch64_gdb_set_sve_reg, nreg,
- "sve-registers.xml", 0);
+ aarch64_gdb_set_sve_reg, feature, 0);
 } else {
 gdb_register_coprocessor(cs, aarch64_gdb_get_fpu_reg,
  aarch64_gdb_set_fpu_reg,
- 34, "aarch64-fpu.xml", 0);
+ 
gdb_find_static_feature("aarch64-fpu.xml"),
+ 0);
 }
 /*
  * Note that we report pauth information via the feature name
@@ -501,19 +501,22 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
 if (isar_feature_aa64_pauth(>isar)) {
 gdb_register_coprocessor(cs, aarch64_gdb_get_pauth_reg,
  aarch64_gdb_set_pauth_reg,
- 4, "aarch64-pauth.xml", 0);
+ 
gdb_find_static_feature("aarch64-pauth.xml"),
+ 0);
 }
 #endif
 } else {
 if (arm_feature(env, ARM_FEATURE_NEON)) {
 gdb_register_coprocessor(cs, vfp_gdb_get_reg, 

Re: [PATCH v2 1/5] system/cpus: rename qemu_mutex_lock_iothread() to bql_lock()

2023-12-12 Thread Akihiko Odaki

On 2023/12/13 0:39, Stefan Hajnoczi wrote:

The Big QEMU Lock (BQL) has many names and they are confusing. The
actual QemuMutex variable is called qemu_global_mutex but it's commonly
referred to as the BQL in discussions and some code comments. The
locking APIs, however, are called qemu_mutex_lock_iothread() and
qemu_mutex_unlock_iothread().

The "iothread" name is historic and comes from when the main thread was
split into into KVM vcpu threads and the "iothread" (now called the main
loop thread). I have contributed to the confusion myself by introducing
a separate --object iothread, a separate concept unrelated to the BQL.

The "iothread" name is no longer appropriate for the BQL. Rename the
locking APIs to:
- void bql_lock(void)
- void bql_unlock(void)
- bool bql_locked(void)

There are more APIs with "iothread" in their names. Subsequent patches
will rename them. There are also comments and documentation that will be
updated in later patches.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Paul Durrant 
Acked-by: Fabiano Rosas 
Acked-by: David Woodhouse 
Reviewed-by: Cédric Le Goater 
Acked-by: Peter Xu 
Acked-by: Eric Farman 
Reviewed-by: Harsh Prateek Bora 
---
  include/block/aio-wait.h |   2 +-
  include/qemu/main-loop.h |  40 -
  include/qemu/thread.h|   2 +-
  accel/accel-blocker.c|  10 +--
  accel/dummy-cpus.c   |   8 +-
  accel/hvf/hvf-accel-ops.c|   4 +-
  accel/kvm/kvm-accel-ops.c|   4 +-
  accel/kvm/kvm-all.c  |  22 ++---
  accel/tcg/cpu-exec.c |  26 +++---
  accel/tcg/cputlb.c   |  16 ++--
  accel/tcg/tcg-accel-ops-icount.c |   4 +-
  accel/tcg/tcg-accel-ops-mttcg.c  |  12 +--
  accel/tcg/tcg-accel-ops-rr.c |  14 ++--
  accel/tcg/tcg-accel-ops.c|   2 +-
  accel/tcg/translate-all.c|   2 +-
  cpu-common.c |   4 +-
  dump/dump.c  |   4 +-
  hw/core/cpu-common.c |   6 +-
  hw/i386/intel_iommu.c|   6 +-
  hw/i386/kvm/xen_evtchn.c |  16 ++--
  hw/i386/kvm/xen_overlay.c|   2 +-
  hw/i386/kvm/xen_xenstore.c   |   2 +-
  hw/intc/arm_gicv3_cpuif.c|   2 +-
  hw/intc/s390_flic.c  |  18 ++--
  hw/misc/edu.c|   4 +-
  hw/misc/imx6_src.c   |   2 +-
  hw/misc/imx7_src.c   |   2 +-
  hw/net/xen_nic.c |   8 +-
  hw/ppc/pegasos2.c|   2 +-
  hw/ppc/ppc.c |   4 +-
  hw/ppc/spapr.c   |   2 +-
  hw/ppc/spapr_rng.c   |   4 +-
  hw/ppc/spapr_softmmu.c   |   4 +-
  hw/remote/mpqemu-link.c  |  20 ++---
  hw/remote/vfio-user-obj.c|   2 +-
  hw/s390x/s390-skeys.c|   2 +-
  migration/block-dirty-bitmap.c   |   4 +-
  migration/block.c|  16 ++--
  migration/colo.c |  60 +++---
  migration/dirtyrate.c|  12 +--
  migration/migration.c|  52 ++--
  migration/ram.c  |  12 +--
  replay/replay-internal.c |   2 +-
  semihosting/console.c|   8 +-
  stubs/iothread-lock.c|   6 +-
  system/cpu-throttle.c|   4 +-
  system/cpus.c|  51 ++--
  system/dirtylimit.c  |   4 +-
  system/memory.c  |   2 +-
  system/physmem.c |   8 +-
  system/runstate.c|   2 +-
  system/watchpoint.c  |   4 +-
  target/arm/arm-powerctl.c|  14 ++--
  target/arm/helper.c  |   4 +-
  target/arm/hvf/hvf.c |   8 +-
  target/arm/kvm.c |   4 +-
  target/arm/kvm64.c   |   4 +-
  target/arm/ptw.c |   6 +-
  target/arm/tcg/helper-a64.c  |   8 +-
  target/arm/tcg/m_helper.c|   6 +-
  target/arm/tcg/op_helper.c   |  24 +++---
  target/arm/tcg/psci.c|   2 +-
  target/hppa/int_helper.c |   8 +-
  target/i386/hvf/hvf.c|   6 +-
  target/i386/kvm/hyperv.c |   4 +-
  target/i386/kvm/kvm.c|  28 +++
  target/i386/kvm/xen-emu.c|  14 ++--
  target/i386/nvmm/nvmm-accel-ops.c|   4 +-
  target/i386/nvmm/nvmm-all.c  |  20 ++---
  target/i386/tcg/sysemu/fpu_helper.c  |   6 +-
  target/i386/tcg/sysemu/misc_helper.c |   4 +-
  target/i386/whpx/whpx-accel-ops.c|   4 +-
  target/i386/whpx/whpx-all.c  |  24 +++---
  target/loongarch/csr_helper.c|   4 +-
  target/mips/kvm.c|   4 +-
  target/mips/tcg/sysemu/cp0_helper.c  |   4 +-
  target/openrisc/sys_helper.c |  16 ++--
  target/ppc/excp_helper.c   

Re: [PATCH v6] ui/cocoa: Use NSWindow's ability to resize

2023-12-12 Thread Akihiko Odaki

On 2023/12/13 0:38, Rene Engel wrote:


--- Ursprüngliche Nachricht ---
Von: Akihiko Odaki 
Datum: 11.12.2023 06:39:35
An: Peter Maydell ,  Philippe Mathieu-Daudé ,  
Gerd Hoffmann ,  Marc-André Lureau 
Betreff: [PATCH v6] ui/cocoa: Use NSWindow's ability to resize

Tested-by:


Thanks for testing.



This patch works very well on MacOs Sonoma with the Qemu Cocoa output. Thanks

Since you are dealing with the Cocoa output under MacOs, I have a request for you. Is it 
possible to use the Cocoa output with zoom to fit in full screen mode like it is possible 
with the GTK output with "-display gtk,zoom-to-fit=on -full-screen"? >
I mainly start Qemu using a start script that immediately puts Qemu into full 
screen.



It should be possible, at least with this patch. Recently, Carwyn Ellis 
added the support for the command line option (commit 5ec0898b0579 
("ui/cocoa: add zoom-to-fit display option")) so your script can utilize it.


Regards,
Akihiko Odaki



Re: [PATCH v4 0/4] Support RISC-V IOPMP

2023-12-12 Thread Ethan Chen via
Ping again.

On Tue, Dec 05, 2023 at 03:48:07PM +0800, Ethan Chen wrote:
> Ping.
> https://patchew.org/QEMU/20231122053251.440723-1-etha...@andestech.com/
> 
> On Wed, Nov 22, 2023 at 01:32:47PM +0800, Ethan Chen wrote:
> > This series implements IOPMP specification v1.0.0-draft4 rapid-k model.
> > The specification url:
> > https://github.com/riscv-non-isa/iopmp-spec/blob/main/riscv_iopmp_specification.pdf
> > 
> > When IOPMP is enabled, a DMA device ATCDMAC300 is added to RISC-V virt
> > platform. This DMA device is connected to the IOPMP and has the 
> > functionalities
> > required by IOPMP, including:
> > - Support setup the connection to IOPMP
> > - Support asynchronous I/O to handle stall transactions
> > - Send transaction information
> > 
> > IOPMP takes a transaction which partially match an entry as a partially hit
> > error. The transaction size is depending on source device, destination 
> > device
> > and bus.
> > 
> > Source device can send a transaction_info to IOPMP. IOPMP will check 
> > partially
> > hit by transaction_info. If source device does not send a transaction_info,
> > IOPMP checks information in IOMMU and dose not check partially hit.
> > 
> > Changes for v4:
> > 
> >   - Add descriptions of IOPMP and ATCDMAC300
> >   - Refine coding style and comments
> >   - config XILINX_AXI does not include file stream.c but selects config 
> > STREAM
> > instead.
> >   - ATCDMAC300: INT_STATUS is write 1 clear per bit
> > Rename iopmp_address_sink to transcation_info_sink
> >   - IOPMP: Refine error message and remove unused variable
> >   - VIRT: Document new options
> > atcdmac300 is only added when iopmp is enabled
> >   serial setting should not be changed
> > 
> > Ethan Chen (4):
> >   hw/core: Add config stream
> >   Add RISC-V IOPMP support
> >   hw/dma: Add Andes ATCDMAC300 support
> >   hw/riscv/virt: Add IOPMP support
> > 
> >  docs/system/riscv/virt.rst|  11 +
> >  hw/Kconfig|   1 +
> >  hw/core/Kconfig   |   3 +
> >  hw/core/meson.build   |   2 +-
> >  hw/dma/Kconfig|   4 +
> >  hw/dma/atcdmac300.c   | 566 ++
> >  hw/dma/meson.build|   1 +
> >  hw/misc/Kconfig   |   4 +
> >  hw/misc/meson.build   |   1 +
> >  hw/misc/riscv_iopmp.c | 966 ++
> >  hw/riscv/Kconfig  |   2 +
> >  hw/riscv/virt.c   |  65 ++
> >  include/hw/dma/atcdmac300.h   | 180 
> >  include/hw/misc/riscv_iopmp.h | 341 +++
> >  .../hw/misc/riscv_iopmp_transaction_info.h|  28 +
> >  include/hw/riscv/virt.h   |  10 +-
> >  16 files changed, 2183 insertions(+), 2 deletions(-)
> >  create mode 100644 hw/dma/atcdmac300.c
> >  create mode 100644 hw/misc/riscv_iopmp.c
> >  create mode 100644 include/hw/dma/atcdmac300.h
> >  create mode 100644 include/hw/misc/riscv_iopmp.h
> >  create mode 100644 include/hw/misc/riscv_iopmp_transaction_info.h
> > 
> > -- 
> > 2.34.1
> > 



[PATCH v7 0/4] gdbstub and TCG plugin improvements

2023-12-12 Thread Akihiko Odaki
This series extracts fixes and refactorings that can be applied
independently from "[PATCH v9 00/23] plugins: Allow to read registers".

The patch "target/riscv: Move MISA limits to class" was replaced with
patch "target/riscv: Move misa_mxl_max to class" since I found instances
may have different misa_ext_mask.

V6 -> V7:
  Rebased.

V5 -> V6:
  Added patch "default-configs: Add TARGET_XML_FILES definition".
  Rebased.

V4 -> V5:
  Added patch "hw/riscv: Use misa_mxl instead of misa_mxl_max".

V3 -> V4:
  Added patch "gdbstub: Check if gdb_regs is NULL".

V2 -> V3:
  Restored patch sets from the previous version.
  Rebased to commit 800485762e6564e04e2ab315132d477069562d91.

V1 -> V2:
  Added patch "target/riscv: Do not allow MXL_RV32 for TARGET_RISCV64".
  Added patch "target/riscv: Initialize gdb_core_xml_file only once".
  Dropped patch "target/riscv: Remove misa_mxl validation".
  Dropped patch "target/riscv: Move misa_mxl_max to class".
  Dropped patch "target/riscv: Validate misa_mxl_max only once".

Signed-off-by: Akihiko Odaki 
---
Akihiko Odaki (4):
  hw/riscv: Use misa_mxl instead of misa_mxl_max
  target/riscv: Remove misa_mxl validation
  target/riscv: Move misa_mxl_max to class
  target/riscv: Validate misa_mxl_max only once

 target/riscv/cpu.h |   4 +-
 hw/riscv/boot.c|   2 +-
 target/riscv/cpu.c | 139 ++---
 target/riscv/gdbstub.c |  12 ++--
 target/riscv/kvm/kvm-cpu.c |  10 ++--
 target/riscv/machine.c |   7 +--
 target/riscv/tcg/tcg-cpu.c |  44 ++
 target/riscv/translate.c   |   3 +-
 8 files changed, 109 insertions(+), 112 deletions(-)
---
base-commit: 9c74490bff6c8886a922008d0c9ce6cae70dd17e
change-id: 20231213-riscv-fcc9640986cf

Best regards,
-- 
Akihiko Odaki 




[PATCH v7 3/4] target/riscv: Move misa_mxl_max to class

2023-12-12 Thread Akihiko Odaki
misa_mxl_max is common for all instances of a RISC-V CPU class so they
are better put into class.

Signed-off-by: Akihiko Odaki 
---
 target/riscv/cpu.h |   4 +-
 target/riscv/cpu.c | 118 +++--
 target/riscv/gdbstub.c |  12 +++--
 target/riscv/kvm/kvm-cpu.c |  10 ++--
 target/riscv/machine.c |   7 ++-
 target/riscv/tcg/tcg-cpu.c |  12 ++---
 target/riscv/translate.c   |   3 +-
 7 files changed, 87 insertions(+), 79 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index d74b361be641..060b7f69a743 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -169,7 +169,6 @@ struct CPUArchState {
 
 /* RISCVMXL, but uint32_t for vmstate migration */
 uint32_t misa_mxl;  /* current mxl */
-uint32_t misa_mxl_max;  /* max mxl for this cpu */
 uint32_t misa_ext;  /* current extensions */
 uint32_t misa_ext_mask; /* max ext for this cpu */
 uint32_t xl;/* current xlen */
@@ -450,6 +449,7 @@ struct RISCVCPUClass {
 
 DeviceRealize parent_realize;
 ResettablePhases parent_phases;
+uint32_t misa_mxl_max;  /* max mxl for this cpu */
 };
 
 static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
@@ -756,7 +756,7 @@ enum riscv_pmu_event_idx {
 /* used by tcg/tcg-cpu.c*/
 void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en);
 bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset);
-void riscv_cpu_set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext);
+void riscv_cpu_set_misa_ext(CPURISCVState *env, uint32_t ext);
 
 typedef struct RISCVCPUMultiExtConfig {
 const char *name;
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 83c7c0cf07be..2ab61df2217e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -274,9 +274,8 @@ const char *riscv_cpu_get_trap_name(target_ulong cause, 
bool async)
 }
 }
 
-void riscv_cpu_set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
+void riscv_cpu_set_misa_ext(CPURISCVState *env, uint32_t ext)
 {
-env->misa_mxl_max = env->misa_mxl = mxl;
 env->misa_ext_mask = env->misa_ext = ext;
 }
 
@@ -378,11 +377,7 @@ static void riscv_any_cpu_init(Object *obj)
 {
 RISCVCPU *cpu = RISCV_CPU(obj);
 CPURISCVState *env = >env;
-#if defined(TARGET_RISCV32)
-riscv_cpu_set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
-#elif defined(TARGET_RISCV64)
-riscv_cpu_set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
-#endif
+riscv_cpu_set_misa_ext(env, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 
 #ifndef CONFIG_USER_ONLY
 set_satp_mode_max_supported(RISCV_CPU(obj),
@@ -403,16 +398,14 @@ static void riscv_max_cpu_init(Object *obj)
 {
 RISCVCPU *cpu = RISCV_CPU(obj);
 CPURISCVState *env = >env;
-RISCVMXL mlx = MXL_RV64;
 
-#ifdef TARGET_RISCV32
-mlx = MXL_RV32;
-#endif
-riscv_cpu_set_misa(env, mlx, 0);
 env->priv_ver = PRIV_VERSION_LATEST;
 #ifndef CONFIG_USER_ONLY
-set_satp_mode_max_supported(RISCV_CPU(obj), mlx == MXL_RV32 ?
-VM_1_10_SV32 : VM_1_10_SV57);
+#ifdef TARGET_RISCV32
+set_satp_mode_max_supported(cpu, VM_1_10_SV32);
+#else
+set_satp_mode_max_supported(cpu, VM_1_10_SV57);
+#endif
 #endif
 }
 
@@ -420,8 +413,6 @@ static void riscv_max_cpu_init(Object *obj)
 static void rv64_base_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
-/* We set this in the realise function */
-riscv_cpu_set_misa(env, MXL_RV64, 0);
 /* Set latest version of privileged specification */
 env->priv_ver = PRIV_VERSION_LATEST;
 #ifndef CONFIG_USER_ONLY
@@ -433,8 +424,7 @@ static void rv64_sifive_u_cpu_init(Object *obj)
 {
 RISCVCPU *cpu = RISCV_CPU(obj);
 CPURISCVState *env = >env;
-riscv_cpu_set_misa(env, MXL_RV64,
-   RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+riscv_cpu_set_misa_ext(env, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 env->priv_ver = PRIV_VERSION_1_10_0;
 #ifndef CONFIG_USER_ONLY
 set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39);
@@ -452,7 +442,7 @@ static void rv64_sifive_e_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 RISCVCPU *cpu = RISCV_CPU(obj);
 
-riscv_cpu_set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
+riscv_cpu_set_misa_ext(env, RVI | RVM | RVA | RVC | RVU);
 env->priv_ver = PRIV_VERSION_1_10_0;
 #ifndef CONFIG_USER_ONLY
 set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
@@ -469,7 +459,7 @@ static void rv64_thead_c906_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 RISCVCPU *cpu = RISCV_CPU(obj);
 
-riscv_cpu_set_misa(env, MXL_RV64, RVG | RVC | RVS | RVU);
+riscv_cpu_set_misa_ext(env, RVG | RVC | RVS | RVU);
 env->priv_ver = PRIV_VERSION_1_11_0;
 
 cpu->cfg.ext_zfa = true;
@@ -500,7 +490,7 @@ static void rv64_veyron_v1_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 RISCVCPU *cpu = 

[PATCH v7 4/4] target/riscv: Validate misa_mxl_max only once

2023-12-12 Thread Akihiko Odaki
misa_mxl_max is now a class member and initialized only once for each
class. This also moves the initialization of gdb_core_xml_file which
will be referenced before realization in the future.

Signed-off-by: Akihiko Odaki 
---
 target/riscv/cpu.c | 21 +
 target/riscv/tcg/tcg-cpu.c | 23 ---
 2 files changed, 21 insertions(+), 23 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 2ab61df2217e..b799f1336041 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1247,6 +1247,26 @@ static const MISAExtInfo misa_ext_info_arr[] = {
 MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
 };
 
+static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)
+{
+CPUClass *cc = CPU_CLASS(mcc);
+
+/* Validate that MISA_MXL is set properly. */
+switch (mcc->misa_mxl_max) {
+#ifdef TARGET_RISCV64
+case MXL_RV64:
+case MXL_RV128:
+cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
+break;
+#endif
+case MXL_RV32:
+cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
+break;
+default:
+g_assert_not_reached();
+}
+}
+
 static int riscv_validate_misa_info_idx(uint32_t bit)
 {
 int idx;
@@ -1695,6 +1715,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void 
*data)
 RISCVCPUClass *mcc = RISCV_CPU_CLASS(c);
 
 mcc->misa_mxl_max = (uint32_t)(uintptr_t)data;
+riscv_cpu_validate_misa_mxl(mcc);
 }
 
 static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str,
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 7f6712c81a49..eb243e011ca3 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -148,27 +148,6 @@ static void riscv_cpu_validate_misa_priv(CPURISCVState 
*env, Error **errp)
 }
 }
 
-static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu)
-{
-RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
-CPUClass *cc = CPU_CLASS(mcc);
-
-/* Validate that MISA_MXL is set properly. */
-switch (mcc->misa_mxl_max) {
-#ifdef TARGET_RISCV64
-case MXL_RV64:
-case MXL_RV128:
-cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
-break;
-#endif
-case MXL_RV32:
-cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
-break;
-default:
-g_assert_not_reached();
-}
-}
-
 static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp)
 {
 CPURISCVState *env = >env;
@@ -676,8 +655,6 @@ static bool tcg_cpu_realize(CPUState *cs, Error **errp)
 return false;
 }
 
-riscv_cpu_validate_misa_mxl(cpu);
-
 #ifndef CONFIG_USER_ONLY
 CPURISCVState *env = >env;
 Error *local_err = NULL;

-- 
2.43.0




[PATCH v7 2/4] target/riscv: Remove misa_mxl validation

2023-12-12 Thread Akihiko Odaki
It is initialized with a simple assignment and there is little room for
error. In fact, the validation is even more complex.

Signed-off-by: Akihiko Odaki 
Acked-by: LIU Zhiwei 
Reviewed-by: Daniel Henrique Barboza 
Acked-by: Alistair Francis 
---
 target/riscv/tcg/tcg-cpu.c | 15 +++
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 8a35683a345d..ee17f65afb60 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -148,7 +148,7 @@ static void riscv_cpu_validate_misa_priv(CPURISCVState 
*env, Error **errp)
 }
 }
 
-static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp)
+static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu)
 {
 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
 CPUClass *cc = CPU_CLASS(mcc);
@@ -168,11 +168,6 @@ static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, 
Error **errp)
 default:
 g_assert_not_reached();
 }
-
-if (env->misa_mxl_max != env->misa_mxl) {
-error_setg(errp, "misa_mxl_max must be equal to misa_mxl");
-return;
-}
 }
 
 static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp)
@@ -673,7 +668,6 @@ static bool riscv_cpu_is_generic(Object *cpu_obj)
 static bool tcg_cpu_realize(CPUState *cs, Error **errp)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
-Error *local_err = NULL;
 
 if (!riscv_cpu_tcg_compatible(cpu)) {
 g_autofree char *name = riscv_cpu_get_name(cpu);
@@ -682,14 +676,11 @@ static bool tcg_cpu_realize(CPUState *cs, Error **errp)
 return false;
 }
 
-riscv_cpu_validate_misa_mxl(cpu, _err);
-if (local_err != NULL) {
-error_propagate(errp, local_err);
-return false;
-}
+riscv_cpu_validate_misa_mxl(cpu);
 
 #ifndef CONFIG_USER_ONLY
 CPURISCVState *env = >env;
+Error *local_err = NULL;
 
 CPU(cs)->tcg_cflags |= CF_PCREL;
 

-- 
2.43.0




[PATCH v7 1/4] hw/riscv: Use misa_mxl instead of misa_mxl_max

2023-12-12 Thread Akihiko Odaki
The effective MXL value matters when booting.

Signed-off-by: Akihiko Odaki 
---
 hw/riscv/boot.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 0ffca05189f0..bc67c0bd1890 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -36,7 +36,7 @@
 
 bool riscv_is_32bit(RISCVHartArrayState *harts)
 {
-return harts->harts[0].env.misa_mxl_max == MXL_RV32;
+return harts->harts[0].env.misa_mxl == MXL_RV32;
 }
 
 /*

-- 
2.43.0




[PATCH v1 1/2] hw/intc/loongarch_ipi: Use MemTxAttrs interface for ipi ops

2023-12-12 Thread Bibo Mao
There are two interface pairs for MemoryRegionOps, read/write and
read_with_attrs/write_with_attrs. The later is better for ipi device
emulation since initial cpu can be parsed from attrs.requester_id.

And requester_id can be overrided for IOCSR_IPI_SEND and mail_send
function when it is to forward message to another vcpu.

Signed-off-by: Bibo Mao 
---
 hw/intc/loongarch_ipi.c | 136 +++-
 1 file changed, 77 insertions(+), 59 deletions(-)

diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
index 67858b521c..1d3449e77d 100644
--- a/hw/intc/loongarch_ipi.c
+++ b/hw/intc/loongarch_ipi.c
@@ -17,14 +17,16 @@
 #include "target/loongarch/internals.h"
 #include "trace.h"
 
-static void loongarch_ipi_writel(void *, hwaddr, uint64_t, unsigned);
-
-static uint64_t loongarch_ipi_readl(void *opaque, hwaddr addr, unsigned size)
+static MemTxResult loongarch_ipi_readl(void *opaque, hwaddr addr,
+   uint64_t *data,
+   unsigned size, MemTxAttrs attrs)
 {
-IPICore *s = opaque;
+IPICore *s;
+LoongArchIPI *ipi = opaque;
 uint64_t ret = 0;
 int index = 0;
 
+s = >ipi_core;
 addr &= 0xff;
 switch (addr) {
 case CORE_STATUS_OFF:
@@ -49,10 +51,12 @@ static uint64_t loongarch_ipi_readl(void *opaque, hwaddr 
addr, unsigned size)
 }
 
 trace_loongarch_ipi_read(size, (uint64_t)addr, ret);
-return ret;
+*data = ret;
+return MEMTX_OK;
 }
 
-static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr)
+static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr,
+  MemTxAttrs attrs)
 {
 int i, mask = 0, data = 0;
 
@@ -62,7 +66,7 @@ static void send_ipi_data(CPULoongArchState *env, uint64_t 
val, hwaddr addr)
  */
 if ((val >> 27) & 0xf) {
 data = address_space_ldl(>address_space_iocsr, addr,
- MEMTXATTRS_UNSPECIFIED, NULL);
+ attrs, NULL);
 for (i = 0; i < 4; i++) {
 /* get mask for byte writing */
 if (val & (0x1 << (27 + i))) {
@@ -74,7 +78,7 @@ static void send_ipi_data(CPULoongArchState *env, uint64_t 
val, hwaddr addr)
 data &= mask;
 data |= (val >> 32) & ~mask;
 address_space_stl(>address_space_iocsr, addr,
-  data, MEMTXATTRS_UNSPECIFIED, NULL);
+  data, attrs, NULL);
 }
 
 static int archid_cmp(const void *a, const void *b)
@@ -103,80 +107,72 @@ static CPUState *ipi_getcpu(int arch_id)
 CPUArchId *archid;
 
 archid = find_cpu_by_archid(machine, arch_id);
-return CPU(archid->cpu);
-}
-
-static void ipi_send(uint64_t val)
-{
-uint32_t cpuid;
-uint8_t vector;
-CPUState *cs;
-LoongArchCPU *cpu;
-LoongArchIPI *s;
-
-cpuid = extract32(val, 16, 10);
-if (cpuid >= LOONGARCH_MAX_CPUS) {
-trace_loongarch_ipi_unsupported_cpuid("IOCSR_IPI_SEND", cpuid);
-return;
+if (archid) {
+return CPU(archid->cpu);
 }
 
-/* IPI status vector */
-vector = extract8(val, 0, 5);
-
-cs = ipi_getcpu(cpuid);
-cpu = LOONGARCH_CPU(cs);
-s = LOONGARCH_IPI(cpu->env.ipistate);
-loongarch_ipi_writel(>ipi_core, CORE_SET_OFF, BIT(vector), 4);
+return NULL;
 }
 
-static void mail_send(uint64_t val)
+static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs)
 {
 uint32_t cpuid;
 hwaddr addr;
-CPULoongArchState *env;
 CPUState *cs;
-LoongArchCPU *cpu;
 
 cpuid = extract32(val, 16, 10);
 if (cpuid >= LOONGARCH_MAX_CPUS) {
 trace_loongarch_ipi_unsupported_cpuid("IOCSR_MAIL_SEND", cpuid);
-return;
+return MEMTX_DECODE_ERROR;
 }
 
-addr = 0x1020 + (val & 0x1c);
 cs = ipi_getcpu(cpuid);
-cpu = LOONGARCH_CPU(cs);
-env = >env;
-send_ipi_data(env, val, addr);
+if (cs == NULL) {
+return MEMTX_DECODE_ERROR;
+}
+
+/* override requester_id */
+addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c);
+attrs.requester_id = cs->cpu_index;
+send_ipi_data(_CPU(cs)->env, val, addr, attrs);
+return MEMTX_OK;
 }
 
-static void any_send(uint64_t val)
+static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
 {
 uint32_t cpuid;
 hwaddr addr;
-CPULoongArchState *env;
 CPUState *cs;
-LoongArchCPU *cpu;
 
 cpuid = extract32(val, 16, 10);
 if (cpuid >= LOONGARCH_MAX_CPUS) {
 trace_loongarch_ipi_unsupported_cpuid("IOCSR_ANY_SEND", cpuid);
-return;
+return MEMTX_DECODE_ERROR;
 }
 
-addr = val & 0x;
 cs = ipi_getcpu(cpuid);
-cpu = LOONGARCH_CPU(cs);
-env = >env;
-send_ipi_data(env, val, addr);
+if (cs == NULL) {
+return MEMTX_DECODE_ERROR;
+}
+
+/* override requester_id */
+addr = val & 0x;
+attrs.requester_id = cs->cpu_index;
+send_ipi_data(_CPU(cs)->env, val, addr, attrs);
+

[PATCH v1 0/2] hw/loongarch/virt: Set iocsr address space per-board rather percpu

2023-12-12 Thread Bibo Mao
On LoongArch system, there is iocsr address space simliar system io
address space on x86. And each cpu has its separate iocsr address space now,
with this patch, iocsr address space is changed with per-board, and
MemTxAttrs.requester_id is used to differentiate cpu cores.

Bibo Mao (2):
  hw/intc/loongarch_ipi: Use MemTxAttrs interface for ipi ops
  hw/loongarch/virt: Set iocsr address space per-board rather percpu

 hw/intc/loongarch_extioi.c |   3 -
 hw/intc/loongarch_ipi.c| 184 ++---
 hw/loongarch/virt.c|  88 ++
 include/hw/intc/loongarch_extioi.h |   1 -
 include/hw/intc/loongarch_ipi.h|   3 +-
 include/hw/loongarch/virt.h|   3 +
 target/loongarch/cpu.c |  48 
 target/loongarch/cpu.h |   4 +-
 target/loongarch/iocsr_helper.c|  16 +--
 9 files changed, 195 insertions(+), 155 deletions(-)


base-commit: 9c74490bff6c8886a922008d0c9ce6cae70dd17e
-- 
2.39.3




[PATCH v1 2/2] hw/loongarch/virt: Set iocsr address space per-board rather percpu

2023-12-12 Thread Bibo Mao
LoongArch system has iocsr address space, most iocsr registers are
per-board, however some iocsr register spaces banked for percpu such
as ipi mailbox and extioi interrupt status. For banked iocsr space,
each cpu has the same iocsr space, but separate data.

This patch changes iocsr address space per-board rather percpu,
for iocsr registers specified for cpu, MemTxAttrs.requester_id
can be parsed for the cpu. With this patches, the total address space
on board will be simple, only iocsr address space and system memory,
rather than the number of cpu and system memory.

Signed-off-by: Bibo Mao 
---
 hw/intc/loongarch_extioi.c |  3 -
 hw/intc/loongarch_ipi.c| 54 +-
 hw/loongarch/virt.c| 88 +++---
 include/hw/intc/loongarch_extioi.h |  1 -
 include/hw/intc/loongarch_ipi.h|  3 +-
 include/hw/loongarch/virt.h|  3 +
 target/loongarch/cpu.c | 48 
 target/loongarch/cpu.h |  4 +-
 target/loongarch/iocsr_helper.c| 16 +++---
 9 files changed, 121 insertions(+), 99 deletions(-)

diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
index 24fb3af8cc..77b4776958 100644
--- a/hw/intc/loongarch_extioi.c
+++ b/hw/intc/loongarch_extioi.c
@@ -282,9 +282,6 @@ static void loongarch_extioi_instance_init(Object *obj)
 qdev_init_gpio_in(DEVICE(obj), extioi_setirq, EXTIOI_IRQS);
 
 for (cpu = 0; cpu < EXTIOI_CPUS; cpu++) {
-memory_region_init_io(>extioi_iocsr_mem[cpu], OBJECT(s), 
_ops,
-  s, "extioi_iocsr", 0x900);
-sysbus_init_mmio(dev, >extioi_iocsr_mem[cpu]);
 for (pin = 0; pin < LS3A_INTC_IP; pin++) {
 qdev_init_gpio_out(DEVICE(obj), >parent_irq[cpu][pin], 1);
 }
diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
index 1d3449e77d..550e899c69 100644
--- a/hw/intc/loongarch_ipi.c
+++ b/hw/intc/loongarch_ipi.c
@@ -9,6 +9,7 @@
 #include "hw/sysbus.h"
 #include "hw/intc/loongarch_ipi.h"
 #include "hw/irq.h"
+#include "hw/qdev-properties.h"
 #include "qapi/error.h"
 #include "qemu/log.h"
 #include "exec/address-spaces.h"
@@ -26,7 +27,7 @@ static MemTxResult loongarch_ipi_readl(void *opaque, hwaddr 
addr,
 uint64_t ret = 0;
 int index = 0;
 
-s = >ipi_core;
+s = >cpu[attrs.requester_id];
 addr &= 0xff;
 switch (addr) {
 case CORE_STATUS_OFF:
@@ -65,7 +66,7 @@ static void send_ipi_data(CPULoongArchState *env, uint64_t 
val, hwaddr addr,
  * if the mask is 0, we need not to do anything.
  */
 if ((val >> 27) & 0xf) {
-data = address_space_ldl(>address_space_iocsr, addr,
+data = address_space_ldl(env->address_space_iocsr, addr,
  attrs, NULL);
 for (i = 0; i < 4; i++) {
 /* get mask for byte writing */
@@ -77,7 +78,7 @@ static void send_ipi_data(CPULoongArchState *env, uint64_t 
val, hwaddr addr,
 
 data &= mask;
 data |= (val >> 32) & ~mask;
-address_space_stl(>address_space_iocsr, addr,
+address_space_stl(env->address_space_iocsr, addr,
   data, attrs, NULL);
 }
 
@@ -172,7 +173,7 @@ static MemTxResult loongarch_ipi_writel(void *opaque, 
hwaddr addr, uint64_t val,
 uint8_t vector;
 CPUState *cs;
 
-s = >ipi_core;
+s = >cpu[attrs.requester_id];
 addr &= 0xff;
 trace_loongarch_ipi_write(size, (uint64_t)addr, val);
 switch (addr) {
@@ -214,7 +215,6 @@ static MemTxResult loongarch_ipi_writel(void *opaque, 
hwaddr addr, uint64_t val,
 
 /* override requester_id */
 attrs.requester_id = cs->cpu_index;
-ipi = LOONGARCH_IPI(LOONGARCH_CPU(cs)->env.ipistate);
 loongarch_ipi_writel(ipi, CORE_SET_OFF, BIT(vector), 4, attrs);
 break;
 default:
@@ -265,12 +265,18 @@ static const MemoryRegionOps loongarch_ipi64_ops = {
 .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-static void loongarch_ipi_init(Object *obj)
+static void loongarch_ipi_realize(DeviceState *dev, Error **errp)
 {
-LoongArchIPI *s = LOONGARCH_IPI(obj);
-SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+LoongArchIPI *s = LOONGARCH_IPI(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+int i;
+
+if (s->num_cpu == 0) {
+error_setg(errp, "num-cpu must be at least 1");
+return;
+}
 
-memory_region_init_io(>ipi_iocsr_mem, obj, _ipi_ops,
+memory_region_init_io(>ipi_iocsr_mem, OBJECT(dev), _ipi_ops,
   s, "loongarch_ipi_iocsr", 0x48);
 
 /* loongarch_ipi_iocsr performs re-entrant IO through ipi_send */
@@ -278,10 +284,15 @@ static void loongarch_ipi_init(Object *obj)
 
 sysbus_init_mmio(sbd, >ipi_iocsr_mem);
 
-memory_region_init_io(>ipi64_iocsr_mem, obj, _ipi64_ops,
+memory_region_init_io(>ipi64_iocsr_mem, OBJECT(dev),
+  _ipi64_ops,
   s, "loongarch_ipi64_iocsr", 0x118);
 sysbus_init_mmio(sbd, >ipi64_iocsr_mem);

[PATCH] hw/sd/pxa2xx_mmci: Disable reentrancy detection

2023-12-12 Thread Guenter Roeck
All tests using pxa2xx_mmc to access mmc cards on pxa2xx platforms
such as borzoi fail starting with commit a2e1753b80 ("memory: prevent
dma-reentracy issues"). Disable reentrancy guard to fix the problem.

Fixes: a2e1753b80 ("memory: prevent dma-reentracy issues")
Signed-off-by: Guenter Roeck 
---
 hw/sd/pxa2xx_mmci.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index 5e8ea69188..27ae8f2888 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -555,6 +555,8 @@ static void pxa2xx_mmci_instance_init(Object *obj)
 qdev_init_gpio_out_named(dev, >rx_dma, "rx-dma", 1);
 qdev_init_gpio_out_named(dev, >tx_dma, "tx-dma", 1);
 
+s->iomem.disable_reentrancy_guard = true;
+
 qbus_init(>sdbus, sizeof(s->sdbus),
   TYPE_PXA2XX_MMCI_BUS, DEVICE(obj), "sd-bus");
 }
-- 
2.39.2




Re: [risu PATCH 5/5] loongarch: Add block 'clean' and clean_lsx_result()

2023-12-12 Thread gaosong

在 2023/12/12 下午8:39, Peter Maydell 写道:

On Wed, 25 Oct 2023 at 10:29, Song Gao  wrote:

The result of the LSX instruction is in the low 128 bits
of the vreg register. We use clean_lsx_result() to clean up
the high 128 bits of the vreg register.

Signed-off-by: Song Gao
---
  loongarch64.risu   | 2121 ++--
  risugen|2 +-
  risugen_loongarch64.pm |   20 +
  3 files changed, 1405 insertions(+), 738 deletions(-)

diff --git a/loongarch64.risu b/loongarch64.risu
index 596de90..531470d 100644
--- a/loongarch64.risu
+++ b/loongarch64.risu
@@ -64,26 +64,26 @@ mulw_d_wu LA64  0001 1 rk:5 rj:5 rd:5 \
  #div.{w[u]/d[u]} rd,rj,rk
  # div.w{u}, mod.w[u]  rk, rj, need in [0x0 ~0x7FFF]
  # use function set_reg_w($reg)
-div_w LA64  0010 0 rk:5 rj:5 rd:5 \
-!constraints { $rk != 2 && $rj != 2 && $rd != 2; } \
-!memory { set_reg_w($rj); set_reg_w($rk); }
-div_wu LA64  0010 00010 rk:5 rj:5 rd:5 \
-!constraints { $rk != 2 && $rj != 2 && $rd != 2; } \
-!memory { set_reg_w($rj); set_reg_w($rk); }
-div_d LA64  0010 00100 rk:5 rj:5 rd:5 \
-!constraints { $rk != 2 && $rj != 2 && $rd != 2; }
-div_du LA64  0010 00110 rk:5 rj:5 rd:5 \
-!constraints { $rk != 2 && $rj != 2 && $rd != 2; }
-mod_w LA64  0010 1 rk:5 rj:5 rd:5 \
-!constraints { $rk != 2 && $rj != 2 && $rd != 2; } \
-!memory { set_reg_w($rj); set_reg_w($rk); }
-mod_wu LA64  0010 00011 rk:5 rj:5 rd:5 \
-!constraints { $rk != 2 && $rj != 2 && $rd != 2; } \
-!memory { set_reg_w($rj); set_reg_w($rk); }
-mod_d LA64  0010 00101 rk:5 rj:5 rd:5 \
-!constraints { $rk != 2 && $rj != 2 && $rd != 2; }
-mod_du LA64  0010 00111 rk:5 rj:5 rd:5 \
-!constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+#div_w LA64  0010 0 rk:5 rj:5 rd:5 \
+#!constraints { $rk != 2 && $rj != 2 && $rd != 2; } \
+#!memory { set_reg_w($rj); set_reg_w($rk); }
+#div_wu LA64  0010 00010 rk:5 rj:5 rd:5 \
+#!constraints { $rk != 2 && $rj != 2 && $rd != 2; } \
+#!memory { set_reg_w($rj); set_reg_w($rk); }
+#div_d LA64  0010 00100 rk:5 rj:5 rd:5 \
+#!constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+#div_du LA64  0010 00110 rk:5 rj:5 rd:5 \
+#!constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+#mod_w LA64  0010 1 rk:5 rj:5 rd:5 \
+#!constraints { $rk != 2 && $rj != 2 && $rd != 2; } \
+#!memory { set_reg_w($rj); set_reg_w($rk); }
+#mod_wu LA64  0010 00011 rk:5 rj:5 rd:5 \
+#!constraints { $rk != 2 && $rj != 2 && $rd != 2; } \
+#!memory { set_reg_w($rj); set_reg_w($rk); }
+#mod_d LA64  0010 00101 rk:5 rj:5 rd:5 \
+#!constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+#mod_du LA64  0010 00111 rk:5 rj:5 rd:5 \
+#!constraints { $rk != 2 && $rj != 2 && $rd != 2; }

Why do we comment out all these patterns ? The commit
message doesn't say anything about this.


I will drop them.

These instructions, test need patch[1],  but the patch is't merged.
[1] : 
https://lore.kernel.org/all/3c401d0f-a34f-bd29-03a3-dddfae94c...@loongson.cn/#r



  alsl_w LA64   010 sa2:2 rk:5 rj:5 rd:5 \
  !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
@@ -615,665 +615,1248 @@ fstx_d LA64 0011 1011 11000 rk:5 rj:5 fd:5 \
  # LSX instructions
  #

-vadd_b LSX 0111  10100 vk:5 vj:5 vd:5
-vadd_h LSX 0111  10101 vk:5 vj:5 vd:5
+vadd_b LSX 0111  10100 vk:5 vj:5 vd:5 \
+!clean { clean_lsx_result($vd); }
+vadd_h LSX 0111  10101 vk:5 vj:5 vd:5 \
+!clean { clean_lsx_result($vd); }

If there are patterns that need the clean_lsx_result
handling, then add the support for that first, rather
than adding a broken pattern and then editing it to
add the extra block to every pattern, please.

Got it.

diff --git a/risugen b/risugen
index fa94a39..8a67fdf 100755
--- a/risugen
+++ b/risugen
@@ -43,7 +43,7 @@ my @pattern_re = ();# include pattern
  my @not_pattern_re = ();# exclude pattern

  # Valid block names (keys in blocks hash)
-my %valid_blockname = ( constraints => 1, memory => 1, safefloat =>1 );
+my %valid_blockname = ( constraints => 1, memory => 1, safefloat =>1, clean => 
1 );

  sub parse_risu_directive($$@)
  {
diff --git a/risugen_loongarch64.pm b/risugen_loongarch64.pm
index b3f901d..97f00f3 100644
--- a/risugen_loongarch64.pm
+++ b/risugen_loongarch64.pm
@@ -81,6 +81,18 @@ sub nanbox_s($)
  return $fpreg;
  }

+sub clean_lsx_result($)
+{
+my ($vreg) = @_;
+
+# xvinsgr2vr.d vd, r0, 2;
+insn32(0x76ebe000 | 2 << 10 | $vreg);
+# xvinsgr2vr.d vd, r0, 3;
+insn32(0x76ebe000 | 3 << 10 | $vreg);
+
+return $vreg;
+}
+
  sub align($)
  {
  my ($a) = @_;
@@ -405,6 +417,7 @@ sub gen_one_insn($$)
  my $constraint = $rec->{blocks}{"constraints"};
  my $memblock = $rec->{blocks}{"memory"};
  my $safefloat = 

Re: [PATCH 03/19] qapi/schema: name QAPISchemaInclude entities

2023-12-12 Thread John Snow
On Wed, Nov 22, 2023 at 4:38 AM Markus Armbruster  wrote:
>
> John Snow  writes:
>
> > On Tue, Nov 21, 2023, 8:33 AM Markus Armbruster  wrote:
> >
> >> John Snow  writes:
> >>
> >> > It simplifies typing to mandate that entities will always have a name;
> >> > to achieve this we can occasionally assign an internal name. This
> >> > alleviates errors such as:
> >> >
> >> > qapi/schema.py:287: error: Argument 1 to "__init__" of
> >> > "QAPISchemaEntity" has incompatible type "None"; expected "str"
> >> > [arg-type]
> >> >
> >> > Trying to fix it the other way by allowing entities to only have
> >> > optional names opens up a nightmare portal of whackamole to try and
> >> > audit that every other pathway doesn't actually pass a None name when we
> >> > expect it to; this is the simpler direction of consitifying the typing.
> >>
> >> Arguably, that nightmare is compile-time proof of "we are not mistaking
> >> QAPISchemaInclude for a named entity".
> >>
> >> When I added the include directive, I shoehorned it into the existing
> >> representation of the QAPI schema as "list of QAPISchemaEntity" by
> >> making it a subtype of QAPISchemaEntity.  That was a somewhat lazy hack.
> >>
> >> Note that qapi-code-gen.rst distinguishes between definitions and
> >> directives.
> >>
> >> The places where mypy gripes that .name isn't 'str' generally want
> >> something with a name (what qapi-code-gen.rst calls a definition).  If
> >> we somehow pass them an include directive, they'll use None for a name,
> >> which is no good.  mypy is pointing out this problem.
> >>
> >> What to do about it?
> >>
> >> 1. Paper it over: give include directives some made-up name (this
> >> patch).  Now the places use the made-up name instead of None, and mypy
> >> can't see the problem anymore.
> >>
> >> 2. Assert .name is not None until mypy is happy.  I guess that's what
> >> you called opening "a nightmare portal of whackamole".
> >>
> >
> > Yep.
> >
> >
> >> 3. Clean up the typing: have a type for top-level expression (has no
> >> name), and a subtype for definition (has a name).  Rough sketch
> >> appended.  Thoughts?
> >>
> >
> > Oh, that'll work. I tried to keep to "minimal SLOC" but where you want to
> > see deeper fixes, I'm happy to deviate. I'll give it a shot.
>
> I do appreciate the minimal fix!  I *like* exploring "minimal" first.
> In this case, the exploration led me to not like my lazy hack anymore :)
>
> [...]
>
> > I'll try the refactor out in a patch at the end of my series and see how
> > feasible it is.
> >
> > (I haven't reviewed it deeply yet, so if there's an obvious problem I'll
> > find it when I go to implement this. conceptually it seems fine.)
>
> Thanks!
>

Got this working with minor changes to sphinx's qapidox extension,
which isn't typechecked so it escaped notice. I'm going to continue
working through your feedback as-is, then when I get to the end of the
series, I'll attempt to float this patch forward to replace this patch
under discussion.

Thanks!

--js




Re: Inconsistent qemu-system-ppc speed on Apple M1 (was: Re: [PATCH v6] ui/cocoa: Use NSWindow's ability to resize)

2023-12-12 Thread BALATON Zoltan

On Tue, 12 Dec 2023, Peter Maydell wrote:

On Tue, 12 Dec 2023 at 18:46, BALATON Zoltan  wrote:


On Tue, 12 Dec 2023, Marek Glogowski wrote:

Additionally, how can I use this message on qemu-devel.
It has a post for people who use Macos or Asahi Linux. Verify random qemu
sessions under Macos .Some are faster others are slow.
The topic is posted on qemu-disc...@nongnu.org (I don't know if developers
look there often)

https://lists.nongnu.org/archive/html/qemu-discuss/2023-12/msg8.html

The program posted there was prepared by one of the maintainers of ppc qemu
machines "BALATON Zoltan".

We are starting to gather as much information as possible for it.
I hope nobody will be offended about this information in this topic. I do
not want to start a topic and litter other lists


It's better to do that in a separate thead, I've changed the subject
accordingly. I only came up with the idea and scripted it but the actual
test case comes from Marek and the original report from Rene Engel.

This problem was first seen running AmigaOS with qemu-system-ppc but then
we also reproduced it with Linux guest with the test in the qemu-discuss
messgage linked above. The runs are not exactly random but there seem to
be slow and fast sessions with the slow one about half the expected speed.
If we get a fast or slow session seems to be random. This was seen on
Apple M1 and Apple M1 Max under macOS but could not reproduce on x86_64
host under Linux or Apple M2 host under Linux so it may either be related
to Apple M1 or macOS host.


Is this possibly related to https://gitlab.com/qemu-project/qemu/-/issues/334
where App Nap is reported as causing QEMU to slow down when the window
doesn't have focus, or does it happen even when the QEMU window has
focus the whole time the benchmark is running ?


Yes, the original test which found it was running Quake timedemo on 
AmgiaOS with QEMU running in foreground and that does a lot of what is 
listed to prevent App Nap such as playing sound and doing graphics. Also 
the sessions are either fast or slow from the start, they don't start fast 
then become slow but sometimes run fast while most of the time they are 
slow and this happens randomly when starting the same command multiple 
times in a row as the scripted test that runs lame to encode mp3 with 
Linux guest does. So this does not seem related to App Nap to me. It did 
not seem to happen on Linux host even on Apple M2 but more testing with 
those might be needed to confirm that.


Regards,
BALATON Zoltan



[PULL 1/2] target/i386: Fix 32-bit wrapping of pc/eip computation

2023-12-12 Thread Richard Henderson
In 32-bit mode, pc = eip + cs_base is also 32-bit, and must wrap.
Failure to do so results in incorrect memory exceptions to the guest.
Before 732d548732ed, this was implicitly done via truncation to
target_ulong but only in qemu-system-i386, not qemu-system-x86_64.

To fix this, we must add conditional zero-extensions.
Since we have to test for 32 vs 64-bit anyway, note that cs_base
is always zero in 64-bit mode.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2022
Signed-off-by: Richard Henderson 
Reviewed-by: Paolo Bonzini 
Message-Id: <20231212172510.103305-1-richard.hender...@linaro.org>
---
 target/i386/cpu.h   |  9 +++--
 target/i386/tcg/tcg-cpu.c   | 11 +--
 target/i386/tcg/translate.c | 23 +--
 3 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index cd2e295bd6..ef987f344c 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -2324,10 +2324,15 @@ static inline int cpu_mmu_index_kernel(CPUX86State *env)
 static inline void cpu_get_tb_cpu_state(CPUX86State *env, vaddr *pc,
 uint64_t *cs_base, uint32_t *flags)
 {
-*cs_base = env->segs[R_CS].base;
-*pc = *cs_base + env->eip;
 *flags = env->hflags |
 (env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK | AC_MASK));
+if (env->hflags & HF_CS64_MASK) {
+*cs_base = 0;
+*pc = env->eip;
+} else {
+*cs_base = env->segs[R_CS].base;
+*pc = (uint32_t)(*cs_base + env->eip);
+}
 }
 
 void do_cpu_init(X86CPU *cpu);
diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
index 2c6a12c835..6e881e9e27 100644
--- a/target/i386/tcg/tcg-cpu.c
+++ b/target/i386/tcg/tcg-cpu.c
@@ -52,7 +52,12 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs,
 /* The instruction pointer is always up to date with CF_PCREL. */
 if (!(tb_cflags(tb) & CF_PCREL)) {
 CPUX86State *env = cpu_env(cs);
-env->eip = tb->pc - tb->cs_base;
+
+if (tb->flags & HF_CS64_MASK) {
+env->eip = tb->pc;
+} else {
+env->eip = (uint32_t)(tb->pc - tb->cs_base);
+}
 }
 }
 
@@ -66,8 +71,10 @@ static void x86_restore_state_to_opc(CPUState *cs,
 
 if (tb_cflags(tb) & CF_PCREL) {
 env->eip = (env->eip & TARGET_PAGE_MASK) | data[0];
+} else if (tb->flags & HF_CS64_MASK) {
+env->eip = data[0];
 } else {
-env->eip = data[0] - tb->cs_base;
+env->eip = (uint32_t)(data[0] - tb->cs_base);
 }
 if (cc_op != CC_OP_DYNAMIC) {
 env->cc_op = cc_op;
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 587d88692a..037bc47e7c 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -552,8 +552,10 @@ static void gen_update_eip_cur(DisasContext *s)
 assert(s->pc_save != -1);
 if (tb_cflags(s->base.tb) & CF_PCREL) {
 tcg_gen_addi_tl(cpu_eip, cpu_eip, s->base.pc_next - s->pc_save);
+} else if (CODE64(s)) {
+tcg_gen_movi_tl(cpu_eip, s->base.pc_next);
 } else {
-tcg_gen_movi_tl(cpu_eip, s->base.pc_next - s->cs_base);
+tcg_gen_movi_tl(cpu_eip, (uint32_t)(s->base.pc_next - s->cs_base));
 }
 s->pc_save = s->base.pc_next;
 }
@@ -563,8 +565,10 @@ static void gen_update_eip_next(DisasContext *s)
 assert(s->pc_save != -1);
 if (tb_cflags(s->base.tb) & CF_PCREL) {
 tcg_gen_addi_tl(cpu_eip, cpu_eip, s->pc - s->pc_save);
+} else if (CODE64(s)) {
+tcg_gen_movi_tl(cpu_eip, s->base.pc_next);
 } else {
-tcg_gen_movi_tl(cpu_eip, s->pc - s->cs_base);
+tcg_gen_movi_tl(cpu_eip, (uint32_t)(s->base.pc_next - s->cs_base));
 }
 s->pc_save = s->pc;
 }
@@ -610,8 +614,10 @@ static TCGv eip_next_tl(DisasContext *s)
 TCGv ret = tcg_temp_new();
 tcg_gen_addi_tl(ret, cpu_eip, s->pc - s->pc_save);
 return ret;
+} else if (CODE64(s)) {
+return tcg_constant_tl(s->pc);
 } else {
-return tcg_constant_tl(s->pc - s->cs_base);
+return tcg_constant_tl((uint32_t)(s->pc - s->cs_base));
 }
 }
 
@@ -622,8 +628,10 @@ static TCGv eip_cur_tl(DisasContext *s)
 TCGv ret = tcg_temp_new();
 tcg_gen_addi_tl(ret, cpu_eip, s->base.pc_next - s->pc_save);
 return ret;
+} else if (CODE64(s)) {
+return tcg_constant_tl(s->base.pc_next);
 } else {
-return tcg_constant_tl(s->base.pc_next - s->cs_base);
+return tcg_constant_tl((uint32_t)(s->base.pc_next - s->cs_base));
 }
 }
 
@@ -2837,6 +2845,10 @@ static void gen_jmp_rel(DisasContext *s, MemOp ot, int 
diff, int tb_num)
 }
 }
 new_eip &= mask;
+new_pc = new_eip + s->cs_base;
+if (!CODE64(s)) {
+new_pc = (uint32_t)new_pc;
+}
 
 gen_update_cc_op(s);
 set_cc_op(s, CC_OP_DYNAMIC);
@@ -2854,8 +2866,7 @@ static void gen_jmp_rel(DisasContext *s, MemOp ot, int 
diff, int tb_num)
  

[PULL 2/2] tcg: Reduce serial context atomicity earlier

2023-12-12 Thread Richard Henderson
Reduce atomicity while emitting opcodes, instead of later
during code generation.  This ensures that any helper called
also sees the reduced atomicity requirement.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2034
Signed-off-by: Richard Henderson 
Tested-by: Alex Bennée 
Message-Id: <20231212193542.149117-1-richard.hender...@linaro.org>
---
 tcg/tcg-op-ldst.c | 28 
 tcg/tcg.c |  9 +
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/tcg/tcg-op-ldst.c b/tcg/tcg-op-ldst.c
index e2c55df217..f11043b449 100644
--- a/tcg/tcg-op-ldst.c
+++ b/tcg/tcg-op-ldst.c
@@ -77,6 +77,13 @@ static MemOp tcg_canonicalize_memop(MemOp op, bool is64, 
bool st)
 if (st) {
 op &= ~MO_SIGN;
 }
+
+/* In serial mode, reduce atomicity. */
+if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) {
+op &= ~MO_ATOM_MASK;
+op |= MO_ATOM_NONE;
+}
+
 return op;
 }
 
@@ -428,8 +435,7 @@ static bool use_two_i64_for_i128(MemOp mop)
 case MO_ATOM_SUBALIGN:
 case MO_ATOM_WITHIN16:
 case MO_ATOM_WITHIN16_PAIR:
-/* In a serialized context, no atomicity is required. */
-return !(tcg_ctx->gen_tb->cflags & CF_PARALLEL);
+return false;
 default:
 g_assert_not_reached();
 }
@@ -499,13 +505,20 @@ static void maybe_free_addr64(TCGv_i64 a64)
 static void tcg_gen_qemu_ld_i128_int(TCGv_i128 val, TCGTemp *addr,
  TCGArg idx, MemOp memop)
 {
-const MemOpIdx orig_oi = make_memop_idx(memop, idx);
+MemOpIdx orig_oi;
 TCGv_i64 ext_addr = NULL;
 TCGOpcode opc;
 
 check_max_alignment(get_alignment_bits(memop));
 tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
 
+/* In serial mode, reduce atomicity. */
+if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) {
+memop &= ~MO_ATOM_MASK;
+memop |= MO_ATOM_NONE;
+}
+orig_oi = make_memop_idx(memop, idx);
+
 /* TODO: For now, force 32-bit hosts to use the helper. */
 if (TCG_TARGET_HAS_qemu_ldst_i128 && TCG_TARGET_REG_BITS == 64) {
 TCGv_i64 lo, hi;
@@ -608,13 +621,20 @@ void tcg_gen_qemu_ld_i128_chk(TCGv_i128 val, TCGTemp 
*addr, TCGArg idx,
 static void tcg_gen_qemu_st_i128_int(TCGv_i128 val, TCGTemp *addr,
  TCGArg idx, MemOp memop)
 {
-const MemOpIdx orig_oi = make_memop_idx(memop, idx);
+MemOpIdx orig_oi;
 TCGv_i64 ext_addr = NULL;
 TCGOpcode opc;
 
 check_max_alignment(get_alignment_bits(memop));
 tcg_gen_req_mo(TCG_MO_ST_LD | TCG_MO_ST_ST);
 
+/* In serial mode, reduce atomicity. */
+if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) {
+memop &= ~MO_ATOM_MASK;
+memop |= MO_ATOM_NONE;
+}
+orig_oi = make_memop_idx(memop, idx);
+
 /* TODO: For now, force 32-bit hosts to use the helper. */
 
 if (TCG_TARGET_HAS_qemu_ldst_i128 && TCG_TARGET_REG_BITS == 64) {
diff --git a/tcg/tcg.c b/tcg/tcg.c
index d2ea22b397..896a36caeb 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -5440,15 +5440,8 @@ static TCGAtomAlign atom_and_align_for_opc(TCGContext 
*s, MemOp opc,
 MemOp align = get_alignment_bits(opc);
 MemOp size = opc & MO_SIZE;
 MemOp half = size ? size - 1 : 0;
+MemOp atom = opc & MO_ATOM_MASK;
 MemOp atmax;
-MemOp atom;
-
-/* When serialized, no further atomicity required.  */
-if (s->gen_tb->cflags & CF_PARALLEL) {
-atom = opc & MO_ATOM_MASK;
-} else {
-atom = MO_ATOM_NONE;
-}
 
 switch (atom) {
 case MO_ATOM_NONE:
-- 
2.34.1




[PULL 0/2] late fixes for rc4

2023-12-12 Thread Richard Henderson
The following changes since commit 9c74490bff6c8886a922008d0c9ce6cae70dd17e:

  Update version for v8.2.0-rc3 release (2023-12-06 14:34:20 -0500)

are available in the Git repository at:

  https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20231212

for you to fetch changes up to cbb145567c21d2bc41e8197a243c7d5480c6fca0:

  tcg: Reduce serial context atomicity earlier (2023-12-12 13:35:19 -0800)


target/i386: Fix 32-bit wrapping of pc/eip computation (#2022)
tcg: Reduce serial context atomicity earlier (#2034)


Richard Henderson (2):
  target/i386: Fix 32-bit wrapping of pc/eip computation
  tcg: Reduce serial context atomicity earlier

 target/i386/cpu.h   |  9 +++--
 target/i386/tcg/tcg-cpu.c   | 11 +--
 target/i386/tcg/translate.c | 23 +--
 tcg/tcg-op-ldst.c   | 28 
 tcg/tcg.c   |  9 +
 5 files changed, 58 insertions(+), 22 deletions(-)



Re: Inconsistent qemu-system-ppc speed on Apple M1 (was: Re: [PATCH v6] ui/cocoa: Use NSWindow's ability to resize)

2023-12-12 Thread Peter Maydell
On Tue, 12 Dec 2023 at 18:46, BALATON Zoltan  wrote:
>
> On Tue, 12 Dec 2023, Marek Glogowski wrote:
> > Additionally, how can I use this message on qemu-devel.
> > It has a post for people who use Macos or Asahi Linux. Verify random qemu
> > sessions under Macos .Some are faster others are slow.
> > The topic is posted on qemu-disc...@nongnu.org (I don't know if developers
> > look there often)
> >
> > https://lists.nongnu.org/archive/html/qemu-discuss/2023-12/msg8.html
> >
> > The program posted there was prepared by one of the maintainers of ppc qemu
> > machines "BALATON Zoltan".
> >
> > We are starting to gather as much information as possible for it.
> > I hope nobody will be offended about this information in this topic. I do
> > not want to start a topic and litter other lists
>
> It's better to do that in a separate thead, I've changed the subject
> accordingly. I only came up with the idea and scripted it but the actual
> test case comes from Marek and the original report from Rene Engel.
>
> This problem was first seen running AmigaOS with qemu-system-ppc but then
> we also reproduced it with Linux guest with the test in the qemu-discuss
> messgage linked above. The runs are not exactly random but there seem to
> be slow and fast sessions with the slow one about half the expected speed.
> If we get a fast or slow session seems to be random. This was seen on
> Apple M1 and Apple M1 Max under macOS but could not reproduce on x86_64
> host under Linux or Apple M2 host under Linux so it may either be related
> to Apple M1 or macOS host.

Is this possibly related to https://gitlab.com/qemu-project/qemu/-/issues/334
where App Nap is reported as causing QEMU to slow down when the window
doesn't have focus, or does it happen even when the QEMU window has
focus the whole time the benchmark is running ?

thanks
-- PMM



Re: [PATCH for-8.2?] target/i386: Fix 32-bit wrapping of pc/eip computation

2023-12-12 Thread Paolo Bonzini
On Tue, Dec 12, 2023 at 10:22 PM Richard Henderson
 wrote:
> > Looks good, but perhaps you could also squash the following?
> >
> > diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
> > index 2c6a12c8350..83ee89579b8 100644
> > --- a/target/i386/tcg/tcg-cpu.c
> > +++ b/target/i386/tcg/tcg-cpu.c
> > @@ -52,7 +52,11 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs,
> >   /* The instruction pointer is always up to date with CF_PCREL. */
> >   if (!(tb_cflags(tb) & CF_PCREL)) {
> >   CPUX86State *env = cpu_env(cs);
> > -env->eip = tb->pc - tb->cs_base;
> > +if (tb->flags & HF_CS64_MASK) {
> > +env->eip = tb->pc;
> > +} else {
> > +env->eip = (uint32_t) (tb->pc - tb->cs_base);
> > +}
> >   }
> >   }
> >
> >
> > It wouldn't be the same bug as 2022 (it wouldn't be new with the vaddr
> > change) so it's okay to sort out this extra case after release.
>
> Good catch, I'll squash it.  Thanks.

BTW,

Reviewed-by: Paolo Bonzini 

Paolo




Re: [PATCH for-8.2?] target/i386: Fix 32-bit wrapping of pc/eip computation

2023-12-12 Thread Richard Henderson

On 12/12/23 13:08, Paolo Bonzini wrote:

On Tue, Dec 12, 2023 at 6:25 PM Richard Henderson
 wrote:


In 32-bit mode, pc = eip + cs_base is also 32-bit, and must wrap.
Failure to do so results in incorrect memory exceptions to the guest.
Before 732d548732ed, this was implicitly done via truncation to
target_ulong but only in qemu-system-i386, not qemu-system-x86_64.

To fix this, we must add conditional zero-extensions.
Since we have to test for 32 vs 64-bit anyway, note that cs_base
is always zero in 64-bit mode.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2022
Signed-off-by: Richard Henderson 
---

This may be too late for 8.2; if not, then 8.2.1 and 8.1.next.
I think I have found all forms of pc <-> eip, but another set
of eyes would be appreciated.


Looks good, but perhaps you could also squash the following?

diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
index 2c6a12c8350..83ee89579b8 100644
--- a/target/i386/tcg/tcg-cpu.c
+++ b/target/i386/tcg/tcg-cpu.c
@@ -52,7 +52,11 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs,
  /* The instruction pointer is always up to date with CF_PCREL. */
  if (!(tb_cflags(tb) & CF_PCREL)) {
  CPUX86State *env = cpu_env(cs);
-env->eip = tb->pc - tb->cs_base;
+if (tb->flags & HF_CS64_MASK) {
+env->eip = tb->pc;
+} else {
+env->eip = (uint32_t) (tb->pc - tb->cs_base);
+}
  }
  }


It wouldn't be the same bug as 2022 (it wouldn't be new with the vaddr
change) so it's okay to sort out this extra case after release.


Good catch, I'll squash it.  Thanks.


r~




Re: [PATCH for-8.2?] target/i386: Fix 32-bit wrapping of pc/eip computation

2023-12-12 Thread Paolo Bonzini
On Tue, Dec 12, 2023 at 6:25 PM Richard Henderson
 wrote:
>
> In 32-bit mode, pc = eip + cs_base is also 32-bit, and must wrap.
> Failure to do so results in incorrect memory exceptions to the guest.
> Before 732d548732ed, this was implicitly done via truncation to
> target_ulong but only in qemu-system-i386, not qemu-system-x86_64.
>
> To fix this, we must add conditional zero-extensions.
> Since we have to test for 32 vs 64-bit anyway, note that cs_base
> is always zero in 64-bit mode.
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2022
> Signed-off-by: Richard Henderson 
> ---
>
> This may be too late for 8.2; if not, then 8.2.1 and 8.1.next.
> I think I have found all forms of pc <-> eip, but another set
> of eyes would be appreciated.

Looks good, but perhaps you could also squash the following?

diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
index 2c6a12c8350..83ee89579b8 100644
--- a/target/i386/tcg/tcg-cpu.c
+++ b/target/i386/tcg/tcg-cpu.c
@@ -52,7 +52,11 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs,
 /* The instruction pointer is always up to date with CF_PCREL. */
 if (!(tb_cflags(tb) & CF_PCREL)) {
 CPUX86State *env = cpu_env(cs);
-env->eip = tb->pc - tb->cs_base;
+if (tb->flags & HF_CS64_MASK) {
+env->eip = tb->pc;
+} else {
+env->eip = (uint32_t) (tb->pc - tb->cs_base);
+}
 }
 }


It wouldn't be the same bug as 2022 (it wouldn't be new with the vaddr
change) so it's okay to sort out this extra case after release.

Paolo




Re: [PATCH for-8.2?] target/i386: Fix 32-bit wrapping of pc/eip computation

2023-12-12 Thread Stefan Hajnoczi
I am waiting for review comments before tagging v8.2.0-rc4. There are
already other patches queued for -rc4 so we definitely need another
week before the final release anyway.

Stefan



Re: [PATCH] tcg: Reduce serial context atomicity earlier

2023-12-12 Thread Alex Bennée
Richard Henderson  writes:

> Reduce atomicity while emitting opcodes, instead of later
> during code generation.  This ensures that any helper called
> also sees the reduced atomicity requirement.
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2034
> Signed-off-by: Richard Henderson 

Tested-by: Alex Bennée 

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro



[PATCH] tcg: Reduce serial context atomicity earlier

2023-12-12 Thread Richard Henderson
Reduce atomicity while emitting opcodes, instead of later
during code generation.  This ensures that any helper called
also sees the reduced atomicity requirement.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2034
Signed-off-by: Richard Henderson 
---
 tcg/tcg-op-ldst.c | 28 
 tcg/tcg.c |  9 +
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/tcg/tcg-op-ldst.c b/tcg/tcg-op-ldst.c
index e2c55df217..f11043b449 100644
--- a/tcg/tcg-op-ldst.c
+++ b/tcg/tcg-op-ldst.c
@@ -77,6 +77,13 @@ static MemOp tcg_canonicalize_memop(MemOp op, bool is64, 
bool st)
 if (st) {
 op &= ~MO_SIGN;
 }
+
+/* In serial mode, reduce atomicity. */
+if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) {
+op &= ~MO_ATOM_MASK;
+op |= MO_ATOM_NONE;
+}
+
 return op;
 }
 
@@ -428,8 +435,7 @@ static bool use_two_i64_for_i128(MemOp mop)
 case MO_ATOM_SUBALIGN:
 case MO_ATOM_WITHIN16:
 case MO_ATOM_WITHIN16_PAIR:
-/* In a serialized context, no atomicity is required. */
-return !(tcg_ctx->gen_tb->cflags & CF_PARALLEL);
+return false;
 default:
 g_assert_not_reached();
 }
@@ -499,13 +505,20 @@ static void maybe_free_addr64(TCGv_i64 a64)
 static void tcg_gen_qemu_ld_i128_int(TCGv_i128 val, TCGTemp *addr,
  TCGArg idx, MemOp memop)
 {
-const MemOpIdx orig_oi = make_memop_idx(memop, idx);
+MemOpIdx orig_oi;
 TCGv_i64 ext_addr = NULL;
 TCGOpcode opc;
 
 check_max_alignment(get_alignment_bits(memop));
 tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
 
+/* In serial mode, reduce atomicity. */
+if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) {
+memop &= ~MO_ATOM_MASK;
+memop |= MO_ATOM_NONE;
+}
+orig_oi = make_memop_idx(memop, idx);
+
 /* TODO: For now, force 32-bit hosts to use the helper. */
 if (TCG_TARGET_HAS_qemu_ldst_i128 && TCG_TARGET_REG_BITS == 64) {
 TCGv_i64 lo, hi;
@@ -608,13 +621,20 @@ void tcg_gen_qemu_ld_i128_chk(TCGv_i128 val, TCGTemp 
*addr, TCGArg idx,
 static void tcg_gen_qemu_st_i128_int(TCGv_i128 val, TCGTemp *addr,
  TCGArg idx, MemOp memop)
 {
-const MemOpIdx orig_oi = make_memop_idx(memop, idx);
+MemOpIdx orig_oi;
 TCGv_i64 ext_addr = NULL;
 TCGOpcode opc;
 
 check_max_alignment(get_alignment_bits(memop));
 tcg_gen_req_mo(TCG_MO_ST_LD | TCG_MO_ST_ST);
 
+/* In serial mode, reduce atomicity. */
+if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) {
+memop &= ~MO_ATOM_MASK;
+memop |= MO_ATOM_NONE;
+}
+orig_oi = make_memop_idx(memop, idx);
+
 /* TODO: For now, force 32-bit hosts to use the helper. */
 
 if (TCG_TARGET_HAS_qemu_ldst_i128 && TCG_TARGET_REG_BITS == 64) {
diff --git a/tcg/tcg.c b/tcg/tcg.c
index d2ea22b397..896a36caeb 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -5440,15 +5440,8 @@ static TCGAtomAlign atom_and_align_for_opc(TCGContext 
*s, MemOp opc,
 MemOp align = get_alignment_bits(opc);
 MemOp size = opc & MO_SIZE;
 MemOp half = size ? size - 1 : 0;
+MemOp atom = opc & MO_ATOM_MASK;
 MemOp atmax;
-MemOp atom;
-
-/* When serialized, no further atomicity required.  */
-if (s->gen_tb->cflags & CF_PARALLEL) {
-atom = opc & MO_ATOM_MASK;
-} else {
-atom = MO_ATOM_NONE;
-}
 
 switch (atom) {
 case MO_ATOM_NONE:
-- 
2.34.1




Re: [PATCH v2 09/20] util/dsa: Implement DSA task asynchronous completion thread model.

2023-12-12 Thread Fabiano Rosas
Hao Xiang  writes:

> * Create a dedicated thread for DSA task completion.
> * DSA completion thread runs a loop and poll for completed tasks.
> * Start and stop DSA completion thread during DSA device start stop.
>
> User space application can directly submit task to Intel DSA
> accelerator by writing to DSA's device memory (mapped in user space).
> Once a task is submitted, the device starts processing it and write
> the completion status back to the task. A user space application can
> poll the task's completion status to check for completion. This change
> uses a dedicated thread to perform DSA task completion checking.
>
> Signed-off-by: Hao Xiang 
> ---
>  util/dsa.c | 243 -
>  1 file changed, 242 insertions(+), 1 deletion(-)
>
> diff --git a/util/dsa.c b/util/dsa.c
> index f82282ce99..0e68013ffb 100644
> --- a/util/dsa.c
> +++ b/util/dsa.c
> @@ -44,6 +44,7 @@
>  
>  #define DSA_WQ_SIZE 4096
>  #define MAX_DSA_DEVICES 16
> +#define DSA_COMPLETION_THREAD "dsa_completion"
>  
>  typedef QSIMPLEQ_HEAD(dsa_task_queue, buffer_zero_batch_task) dsa_task_queue;
>  
> @@ -61,8 +62,18 @@ struct dsa_device_group {
>  dsa_task_queue task_queue;
>  };
>  
> +struct dsa_completion_thread {
> +bool stopping;
> +bool running;
> +QemuThread thread;
> +int thread_id;
> +QemuSemaphore sem_init_done;
> +struct dsa_device_group *group;
> +};
> +
>  uint64_t max_retry_count;
>  static struct dsa_device_group dsa_group;
> +static struct dsa_completion_thread completion_thread;
>  
>  
>  /**
> @@ -439,6 +450,234 @@ submit_batch_wi_async(struct buffer_zero_batch_task 
> *batch_task)
>  return dsa_task_enqueue(device_group, batch_task);
>  }
>  
> +/**
> + * @brief Poll for the DSA work item completion.
> + *
> + * @param completion A pointer to the DSA work item completion record.
> + * @param opcode The DSA opcode.
> + *
> + * @return Zero if successful, non-zero otherwise.
> + */
> +static int
> +poll_completion(struct dsa_completion_record *completion,
> +enum dsa_opcode opcode)
> +{
> +uint8_t status;
> +uint64_t retry = 0;
> +
> +while (true) {
> +// The DSA operation completes successfully or fails.
> +status = completion->status;
> +if (status == DSA_COMP_SUCCESS ||

Should we read directly from completion->status or is the compiler smart
enough to not optimize 'status' out?

> +status == DSA_COMP_PAGE_FAULT_NOBOF ||
> +status == DSA_COMP_BATCH_PAGE_FAULT ||
> +status == DSA_COMP_BATCH_FAIL) {
> +break;
> +} else if (status != DSA_COMP_NONE) {
> +/* TODO: Error handling here on unexpected failure. */

Let's make sure this is dealt with before merging.

> +fprintf(stderr, "DSA opcode %d failed with status = %d.\n",
> +opcode, status);
> +exit(1);

return instead of exiting.

> +}
> +retry++;
> +if (retry > max_retry_count) {
> +fprintf(stderr, "Wait for completion retry %lu times.\n", retry);
> +exit(1);

same here

> +}
> +_mm_pause();
> +}
> +
> +return 0;
> +}
> +
> +/**
> + * @brief Complete a single DSA task in the batch task.
> + *
> + * @param task A pointer to the batch task structure.
> + */
> +static void
> +poll_task_completion(struct buffer_zero_batch_task *task)
> +{
> +assert(task->task_type == DSA_TASK);
> +
> +struct dsa_completion_record *completion = >completions[0];
> +uint8_t status;
> +
> +poll_completion(completion, task->descriptors[0].opcode);
> +
> +status = completion->status;
> +if (status == DSA_COMP_SUCCESS) {
> +task->results[0] = (completion->result == 0);
> +return;
> +}
> +
> +assert(status == DSA_COMP_PAGE_FAULT_NOBOF);
> +}
> +
> +/**
> + * @brief Poll a batch task status until it completes. If DSA task doesn't
> + *complete properly, use CPU to complete the task.
> + *
> + * @param batch_task A pointer to the DSA batch task.
> + */
> +static void
> +poll_batch_task_completion(struct buffer_zero_batch_task *batch_task)
> +{
> +struct dsa_completion_record *batch_completion = 
> _task->batch_completion;
> +struct dsa_completion_record *completion;
> +uint8_t batch_status;
> +uint8_t status;
> +bool *results = batch_task->results;
> +uint32_t count = batch_task->batch_descriptor.desc_count;
> +
> +poll_completion(batch_completion,
> +batch_task->batch_descriptor.opcode);
> +
> +batch_status = batch_completion->status;
> +
> +if (batch_status == DSA_COMP_SUCCESS) {
> +if (batch_completion->bytes_completed == count) {
> +// Let's skip checking for each descriptors' completion status
> +// if the batch descriptor says all succedded.
> +for (int i = 0; i < count; i++) {
> +

Inconsistent qemu-system-ppc speed on Apple M1 (was: Re: [PATCH v6] ui/cocoa: Use NSWindow's ability to resize)

2023-12-12 Thread BALATON Zoltan

On Tue, 12 Dec 2023, Marek Glogowski wrote:

Additionally, how can I use this message on qemu-devel.
It has a post for people who use Macos or Asahi Linux. Verify random qemu
sessions under Macos .Some are faster others are slow.
The topic is posted on qemu-disc...@nongnu.org (I don't know if developers
look there often)

https://lists.nongnu.org/archive/html/qemu-discuss/2023-12/msg8.html

The program posted there was prepared by one of the maintainers of ppc qemu
machines "BALATON Zoltan".

We are starting to gather as much information as possible for it.
I hope nobody will be offended about this information in this topic. I do
not want to start a topic and litter other lists


It's better to do that in a separate thead, I've changed the subject 
accordingly. I only came up with the idea and scripted it but the actual 
test case comes from Marek and the original report from Rene Engel.


This problem was first seen running AmigaOS with qemu-system-ppc but then 
we also reproduced it with Linux guest with the test in the qemu-discuss 
messgage linked above. The runs are not exactly random but there seem to 
be slow and fast sessions with the slow one about half the expected speed. 
If we get a fast or slow session seems to be random. This was seen on 
Apple M1 and Apple M1 Max under macOS but could not reproduce on x86_64 
host under Linux or Apple M2 host under Linux so it may either be related 
to Apple M1 or macOS host.


What could be tested to narrow it further may be trying the test on Apple 
M1 under Linux or Apple M2 under macOS. (And maybe trying some other 
qemu-system target on Apple M1 macOS to see if it's specific to 
qemu-system-ppc.) Then the question is what might cause it. Marek tested 
that these always run on Performance cores and also experimented with 
taskpolicy -B but that does not seem to change anything. Lacking a better 
idea I could think of frequency scaling maybe but I don't know how to 
check that under macOS. Or maybe something about how macOS schedules QEMU 
thread? Does anybody have an idea how to debug this further?


Thank you,
BALATON Zoltan



Re: [PATCH 2/2] arm: xlnx-versal-virt: Add machine property ospi-flash

2023-12-12 Thread Peter Maydell
On Tue, 5 Dec 2023 at 09:52, Sai Pavan Boddu  wrote:
>
> This property allows users to change flash model on command line as
> below.
>
>ex: "-M xlnx-versal-virt,ospi-flash=mt35xu02gbba"
>
> Signed-off-by: Sai Pavan Boddu 
> ---
>  hw/arm/xlnx-versal-virt.c | 31 ++-
>  1 file changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 537118224f..c57cff74d8 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -49,6 +49,7 @@ struct VersalVirt {
>  struct {
>  bool secure;
>  } cfg;
> +char *ospi_model;
>  };
>
>  static void fdt_create(VersalVirt *s)
> @@ -637,6 +638,22 @@ static void sd_plugin_card(SDHCIState *sd, DriveInfo *di)
> _fatal);
>  }
>
> +static char *versal_get_ospi_model(Object *obj, Error **errp)
> +{
> +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
> +
> +return g_strdup(s->ospi_model);
> +}
> +
> +static void versal_set_ospi_model(Object *obj, const char *value, Error 
> **errp)
> +{
> +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
> +
> +g_free(s->ospi_model);
> +s->ospi_model = g_strdup(value);
> +}
> +
> +
>  static void versal_virt_init(MachineState *machine)
>  {
>  VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine);
> @@ -736,7 +753,7 @@ static void versal_virt_init(MachineState *machine)
>
>  spi_bus = qdev_get_child_bus(DEVICE(>soc.pmc.iou.ospi), "spi0");
>
> -flash_dev = qdev_new("mt35xu01g");
> +flash_dev = qdev_new(s->ospi_model ? s->ospi_model : "mt35xu01g");
>  if (dinfo) {
>  qdev_prop_set_drive_err(flash_dev, "drive",
>  blk_by_legacy_dinfo(dinfo), 
> _fatal);

This doesn't do any checking of the string the user passes,
which means the user can make us hit an abort() with a not
terribly helpful error message:

$ ./build/arm-clang/qemu-system-aarch64 -M xlnx-versal-virt,ospi-flash=bang
qemu-system-aarch64: unknown type 'bang'
Aborted (core dumped)

or complain about trying to create an abstract type:
$ ./build/arm-clang/qemu-system-aarch64 -M
xlnx-versal-virt,ospi-flash=m25p80-generic
**
ERROR:../../qom/object.c:525:object_initialize_with_type: assertion
failed: (type->abstract == false)
Bail out! ERROR:../../qom/object.c:525:object_initialize_with_type:
assertion failed: (type->abstract == false)
Aborted (core dumped)

or do some weird stuff if you pass it something that isn't a
flash device type name:

$ ./build/arm-clang/qemu-system-aarch64 -M xlnx-versal-virt,ospi-flash=e1000
Unexpected error in object_property_find_err() at ../../qom/object.c:1330:
qemu-system-aarch64: Property 'e1000.cs' not found
Aborted (core dumped)

I think you need to check that the string corresponds
to a type that actually exists and is a subtype of TYPE_M25P80
and isn't an abstract type.

thanks
-- PMM



[PATCH for-8.2?] target/i386: Fix 32-bit wrapping of pc/eip computation

2023-12-12 Thread Richard Henderson
In 32-bit mode, pc = eip + cs_base is also 32-bit, and must wrap.
Failure to do so results in incorrect memory exceptions to the guest.
Before 732d548732ed, this was implicitly done via truncation to
target_ulong but only in qemu-system-i386, not qemu-system-x86_64.

To fix this, we must add conditional zero-extensions.
Since we have to test for 32 vs 64-bit anyway, note that cs_base
is always zero in 64-bit mode.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2022
Signed-off-by: Richard Henderson 
---

This may be too late for 8.2; if not, then 8.2.1 and 8.1.next.
I think I have found all forms of pc <-> eip, but another set
of eyes would be appreciated.

r~

---
 target/i386/cpu.h   |  9 +++--
 target/i386/tcg/tcg-cpu.c   |  4 +++-
 target/i386/tcg/translate.c | 23 +--
 3 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index cd2e295bd6..ef987f344c 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -2324,10 +2324,15 @@ static inline int cpu_mmu_index_kernel(CPUX86State *env)
 static inline void cpu_get_tb_cpu_state(CPUX86State *env, vaddr *pc,
 uint64_t *cs_base, uint32_t *flags)
 {
-*cs_base = env->segs[R_CS].base;
-*pc = *cs_base + env->eip;
 *flags = env->hflags |
 (env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK | AC_MASK));
+if (env->hflags & HF_CS64_MASK) {
+*cs_base = 0;
+*pc = env->eip;
+} else {
+*cs_base = env->segs[R_CS].base;
+*pc = (uint32_t)(*cs_base + env->eip);
+}
 }
 
 void do_cpu_init(X86CPU *cpu);
diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
index 2c6a12c835..eb05a69f79 100644
--- a/target/i386/tcg/tcg-cpu.c
+++ b/target/i386/tcg/tcg-cpu.c
@@ -66,8 +66,10 @@ static void x86_restore_state_to_opc(CPUState *cs,
 
 if (tb_cflags(tb) & CF_PCREL) {
 env->eip = (env->eip & TARGET_PAGE_MASK) | data[0];
+} else if (tb->flags & HF_CS64_MASK) {
+env->eip = data[0];
 } else {
-env->eip = data[0] - tb->cs_base;
+env->eip = (uint32_t)(data[0] - tb->cs_base);
 }
 if (cc_op != CC_OP_DYNAMIC) {
 env->cc_op = cc_op;
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 587d88692a..037bc47e7c 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -552,8 +552,10 @@ static void gen_update_eip_cur(DisasContext *s)
 assert(s->pc_save != -1);
 if (tb_cflags(s->base.tb) & CF_PCREL) {
 tcg_gen_addi_tl(cpu_eip, cpu_eip, s->base.pc_next - s->pc_save);
+} else if (CODE64(s)) {
+tcg_gen_movi_tl(cpu_eip, s->base.pc_next);
 } else {
-tcg_gen_movi_tl(cpu_eip, s->base.pc_next - s->cs_base);
+tcg_gen_movi_tl(cpu_eip, (uint32_t)(s->base.pc_next - s->cs_base));
 }
 s->pc_save = s->base.pc_next;
 }
@@ -563,8 +565,10 @@ static void gen_update_eip_next(DisasContext *s)
 assert(s->pc_save != -1);
 if (tb_cflags(s->base.tb) & CF_PCREL) {
 tcg_gen_addi_tl(cpu_eip, cpu_eip, s->pc - s->pc_save);
+} else if (CODE64(s)) {
+tcg_gen_movi_tl(cpu_eip, s->base.pc_next);
 } else {
-tcg_gen_movi_tl(cpu_eip, s->pc - s->cs_base);
+tcg_gen_movi_tl(cpu_eip, (uint32_t)(s->base.pc_next - s->cs_base));
 }
 s->pc_save = s->pc;
 }
@@ -610,8 +614,10 @@ static TCGv eip_next_tl(DisasContext *s)
 TCGv ret = tcg_temp_new();
 tcg_gen_addi_tl(ret, cpu_eip, s->pc - s->pc_save);
 return ret;
+} else if (CODE64(s)) {
+return tcg_constant_tl(s->pc);
 } else {
-return tcg_constant_tl(s->pc - s->cs_base);
+return tcg_constant_tl((uint32_t)(s->pc - s->cs_base));
 }
 }
 
@@ -622,8 +628,10 @@ static TCGv eip_cur_tl(DisasContext *s)
 TCGv ret = tcg_temp_new();
 tcg_gen_addi_tl(ret, cpu_eip, s->base.pc_next - s->pc_save);
 return ret;
+} else if (CODE64(s)) {
+return tcg_constant_tl(s->base.pc_next);
 } else {
-return tcg_constant_tl(s->base.pc_next - s->cs_base);
+return tcg_constant_tl((uint32_t)(s->base.pc_next - s->cs_base));
 }
 }
 
@@ -2837,6 +2845,10 @@ static void gen_jmp_rel(DisasContext *s, MemOp ot, int 
diff, int tb_num)
 }
 }
 new_eip &= mask;
+new_pc = new_eip + s->cs_base;
+if (!CODE64(s)) {
+new_pc = (uint32_t)new_pc;
+}
 
 gen_update_cc_op(s);
 set_cc_op(s, CC_OP_DYNAMIC);
@@ -2854,8 +2866,7 @@ static void gen_jmp_rel(DisasContext *s, MemOp ot, int 
diff, int tb_num)
 }
 }
 
-if (use_goto_tb &&
-translator_use_goto_tb(>base, new_eip + s->cs_base)) {
+if (use_goto_tb && translator_use_goto_tb(>base, new_pc)) {
 /* jump to same page: we can use a direct jump */
 tcg_gen_goto_tb(tb_num);
 if (!(tb_cflags(s->base.tb) & CF_PCREL)) {
-- 
2.34.1




Re: [PATCH-for-9.0 v2 8/8] hw/arm/bcm2836: Add local variable to remove various DEVICE() casts

2023-12-12 Thread Peter Maydell
On Thu, 23 Nov 2023 at 14:39, Philippe Mathieu-Daudé  wrote:
>
> Cast the CPU to DeviceState once.
>
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Peter Maydell 

thanks
-- PMM



Re: [PATCH-for-9.0 v2 7/8] hw/arm/bcm2836: Move code after error checks

2023-12-12 Thread Peter Maydell
On Thu, 23 Nov 2023 at 14:39, Philippe Mathieu-Daudé  wrote:
>
> First run the code that can return errors, then on success
> run what alters the instance state.
>
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  hw/arm/bcm2836.c | 14 +++---
>  1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
> index 03e6eb2fb2..e56935f3e5 100644
> --- a/hw/arm/bcm2836.c
> +++ b/hw/arm/bcm2836.c
> @@ -119,13 +119,6 @@ static void bcm2836_realize(DeviceState *dev, Error 
> **errp)
>  return;
>  }
>
> -sysbus_mmio_map(SYS_BUS_DEVICE(>control), 0, bc->ctrl_base);
> -
> -sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 0,
> -qdev_get_gpio_in_named(DEVICE(>control), "gpu-irq", 0));
> -sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 1,
> -qdev_get_gpio_in_named(DEVICE(>control), "gpu-fiq", 0));
> -
>  for (n = 0; n < BCM283X_NCPUS; n++) {
>  object_property_set_int(OBJECT(>cpu[n].core), "mp-affinity",
>  (bc->clusterid << 8) | n, _abort);
> @@ -158,6 +151,13 @@ static void bcm2836_realize(DeviceState *dev, Error 
> **errp)
>  qdev_connect_gpio_out(DEVICE(>cpu[n].core), GTIMER_SEC,
>  qdev_get_gpio_in_named(DEVICE(>control), "cntpsirq", n));
>  }
> +
> +sysbus_mmio_map(SYS_BUS_DEVICE(>control), 0, bc->ctrl_base);
> +
> +sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 0,
> +qdev_get_gpio_in_named(DEVICE(>control), "gpu-irq", 
> 0));
> +sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 1,
> +qdev_get_gpio_in_named(DEVICE(>control), "gpu-fiq", 
> 0));
>  }
>

There's no particular harm in moving the code, but given the loop
we are already doing some IRQ-connection work before doing some
things which might fail.

We don't in general do a particularly consistent job with
tidying up in realize methods that fail halfway through, but
in general "connect an IRQ between two devices both of which
are owned by this container device" and "map an MR of this device
we own into a container region we also own" are not things
which affect the overall simulation, and in theory should
be cleanup-able later (maybe even automatically by refcount
if we're really lucky).

-- PMM



Re: [PATCH-for-9.0 v2 6/8] hw: Simplify uses of qdev_prop_set_bit(dev, 'start-powered-off')

2023-12-12 Thread Peter Maydell
On Thu, 23 Nov 2023 at 14:39, Philippe Mathieu-Daudé  wrote:
>
> Simplify few qdev_prop_set_bit("start-powered-off") and re-indent.
>
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Peter Maydell 

thanks
-- PMM



Re: [PATCH-for-9.0 v2 5/8] hw: Prefer qdev_prop_set_bit over object_property_set_bool for QDev

2023-12-12 Thread Peter Maydell
On Thu, 23 Nov 2023 at 14:38, Philippe Mathieu-Daudé  wrote:
>
> The QOM API is lower level than the QDev one. When an instance is
> QDev and setting the property can not fail (using _abort),
> prefer qdev_prop_set_bit() over object_property_set_bool().
>
> Mechanical transformation using the following coccinelle patch:
>
>   @@
>   expression o, p, v;
>   @@
>   -object_property_set_bool(OBJECT(o), p, v, _abort)
>   +qdev_prop_set_bit(DEVICE(o), p, v)
>   
>   -object_property_set_bool(o, p, v, _abort)
>   +qdev_prop_set_bit(DEVICE(o), p, v)
>
> manually adding the missing "hw/qdev-properties.h" header.
>
> In hw/arm/armsse.c we use the available 'cpudev' instead of 'cpuobj'.
>
> Suggested-by: Markus Armbruster 
> Signed-off-by: Philippe Mathieu-Daudé 

> @@ -1287,8 +1288,7 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, 
> struct arm_boot_info *info)
>   * CPU.
>   */
>  if (cs != first_cpu) {
> -object_property_set_bool(cpuobj, "start-powered-off", true,
> - _abort);
> +qdev_prop_set_bit(DEVICE(cpuobj), "start-powered-off", true);
>  }
>  }
>  }

This makes this code look a bit weird. Currently we have a loop
which has an "Object *cpuobj" which it uses to set properties,
in both cases using the object_property_* APIs. With this change,
we do half the job using a QOM API and the other half using
a qdev API. It would be good to follow up by converting the
other property-set so we can have a local Device * instead of
the Object *.


> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index eace854335..6733652120 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -263,20 +263,13 @@ static void pc_init1(MachineState *machine,
>  size_t i;
>
>  pci_dev = pci_new_multifunction(-1, pcms->south_bridge);
> -object_property_set_bool(OBJECT(pci_dev), "has-usb",
> - machine_usb(machine), _abort);
> -object_property_set_bool(OBJECT(pci_dev), "has-acpi",
> - x86_machine_is_acpi_enabled(x86ms),
> - _abort);
> -object_property_set_bool(OBJECT(pci_dev), "has-pic", false,
> - _abort);
> -object_property_set_bool(OBJECT(pci_dev), "has-pit", false,
> - _abort);
> -qdev_prop_set_uint32(DEVICE(pci_dev), "smb_io_base", 0xb100);
> -object_property_set_bool(OBJECT(pci_dev), "smm-enabled",
> - x86_machine_is_smm_enabled(x86ms),
> - _abort);
>  dev = DEVICE(pci_dev);
> +qdev_prop_set_bit(dev, "has-usb", machine_usb(machine));
> +qdev_prop_set_bit(dev, "has-acpi", 
> x86_machine_is_acpi_enabled(x86ms));
> +qdev_prop_set_bit(dev, "has-pic", false);
> +qdev_prop_set_bit(dev, "has-pit", false);
> +qdev_prop_set_uint32(DEVICE(pci_dev), "smb_io_base", 0xb100);

This line also can just use "dev".

> +qdev_prop_set_bit(dev, "smm-enabled", 
> x86_machine_is_smm_enabled(x86ms));
>  for (i = 0; i < ISA_NUM_IRQS; i++) {
>  qdev_connect_gpio_out_named(dev, "isa-irqs", i, x86ms->gsi[i]);
>  }

Otherwise
Reviewed-by: Peter Maydell 

thanks
-- PMM



[PATCH] hw/acpi: propagate vcpu hotplug after switch to modern interface

2023-12-12 Thread Aaron Young
If a vcpu with an apic-id that is not supported by the legacy
interface (>255) is hot-plugged, the legacy code will dynamically switch
to the modern interface. However, the hotplug event is not forwarded to
the new interface resulting in the vcpu not being fully/properly added
to the machine config. This BUG is evidenced by OVMF when it
it attempts to count the vcpus and reports an inconsistent vcpu count
reported by the fw_cfg interface and the modern hotpug interface.

Fix is to propagate the hotplug event after making the switch from
the legacy interface to the modern interface.

Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Signed-off-by: Aaron Young 
---
 hw/acpi/cpu_hotplug.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
index 634bbec..6f78db0 100644
--- a/hw/acpi/cpu_hotplug.c
+++ b/hw/acpi/cpu_hotplug.c
@@ -59,7 +59,8 @@ static const MemoryRegionOps AcpiCpuHotplug_ops = {
 },
 };
 
-static void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, CPUState *cpu)
+static void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, CPUState *cpu,
+ bool *swtchd_to_modern)
 {
 CPUClass *k = CPU_GET_CLASS(cpu);
 int64_t cpu_id;
@@ -68,23 +69,34 @@ static void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, 
CPUState *cpu)
 if ((cpu_id / 8) >= ACPI_GPE_PROC_LEN) {
 object_property_set_bool(g->device, "cpu-hotplug-legacy", false,
  _abort);
+*swtchd_to_modern = true;
 return;
 }
 
+*swtchd_to_modern = false;
 g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
 }
 
 void legacy_acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
  AcpiCpuHotplug *g, DeviceState *dev, Error **errp)
 {
-acpi_set_cpu_present_bit(g, CPU(dev));
-acpi_send_event(DEVICE(hotplug_dev), ACPI_CPU_HOTPLUG_STATUS);
+bool swtchd_to_modern;
+Error *local_err = NULL;
+
+acpi_set_cpu_present_bit(g, CPU(dev), _to_modern);
+if (swtchd_to_modern) {
+/* propagate the hotplug to the modern interface */
+hotplug_handler_plug(hotplug_dev, dev, _err);
+} else {
+acpi_send_event(DEVICE(hotplug_dev), ACPI_CPU_HOTPLUG_STATUS);
+}
 }
 
 void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
   AcpiCpuHotplug *gpe_cpu, uint16_t base)
 {
 CPUState *cpu;
+bool swtchd_to_modern;
 
 memory_region_init_io(_cpu->io, owner, _ops,
   gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN);
@@ -92,7 +104,7 @@ void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, 
Object *owner,
 gpe_cpu->device = owner;
 
 CPU_FOREACH(cpu) {
-acpi_set_cpu_present_bit(gpe_cpu, cpu);
+acpi_set_cpu_present_bit(gpe_cpu, cpu, _to_modern);
 }
 }
 
-- 
1.8.3.1




Re: [PATCH-for-9.0 v2 4/8] hw: Simplify accesses to the CPUState::'start-powered-off' property

2023-12-12 Thread Peter Maydell
On Thu, 23 Nov 2023 at 14:38, Philippe Mathieu-Daudé  wrote:
>
> The 'start-powered-off' property has been added to ARM CPUs in
> commit 5de164304a ("arm: Allow secondary KVM CPUs to be booted
> via PSCI"), then eventually got generalized to all CPUs in commit
> c1b701587e ("target/arm: Move start-powered-off property to generic
> CPUState"). Since all CPUs have it, no need to check whether it is
> available. Updating this property can't fail, so use _abort.
>
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  hw/arm/armsse.c  | 6 ++

Reviewed-by: Peter Maydell 

thanks
-- PMM



Re: [PATCH-for-9.0 v2 3/8] hw/arm/bcm2836: Use ARM_CPU 'mp-affinity' property

2023-12-12 Thread Peter Maydell
On Thu, 23 Nov 2023 at 14:38, Philippe Mathieu-Daudé  wrote:
>
> The 'mp-affinity' property is present since commit 15a21fe028
> ("target-arm: Add mp-affinity property for ARM CPU class").
> Use it and remove a /* TODO */ comment. Since all ARM CPUs
> have this property, use _abort, because this call can
> not fail.
>
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Peter Maydell 

thanks
-- PMM



Re: [PATCH-for-9.0 v2 2/8] hw/arm/bcm2836: Simplify use of 'reset-cbar' property

2023-12-12 Thread Peter Maydell
On Thu, 23 Nov 2023 at 14:38, Philippe Mathieu-Daudé  wrote:
>
> bcm2836_realize() is called by
>
>  - bcm2836_class_init() which sets:
>
> bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a7")
>
>  - bcm2837_class_init() which sets:
>
> bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a53")
>
> Both Cortex-A7 / A53 have the ARM_FEATURE_CBAR set. If it isn't,
> then this is a programming error: use _abort.
>
> Signed-off-by: Philippe Mathieu-Daudé 
> ---

Reviewed-by: Peter Maydell 

thanks
-- PMM



Re: [PATCH 1/1] xlnx-versal-ospi: disable reentrancy detection for iomem_dac

2023-12-12 Thread Peter Maydell
On Tue, 5 Dec 2023 at 10:08, Sai Pavan Boddu  wrote:
>
> The OSPI DMA reads flash data through the OSPI linear address space (the
> iomem_dac region), because of this the reentrancy guard introduced in
> commit a2e1753b ("memory: prevent dma-reentracy issues") is disabled for
> the memory region.
>
> Signed-off-by: Sai Pavan Boddu 
> ---
>  hw/ssi/xlnx-versal-ospi.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/hw/ssi/xlnx-versal-ospi.c b/hw/ssi/xlnx-versal-ospi.c
> index 1a61679c2f..5123e7dde7 100644
> --- a/hw/ssi/xlnx-versal-ospi.c
> +++ b/hw/ssi/xlnx-versal-ospi.c
> @@ -1772,6 +1772,7 @@ static void xlnx_versal_ospi_init(Object *obj)
>  memory_region_init_io(>iomem_dac, obj, _dac_ops, s,
>TYPE_XILINX_VERSAL_OSPI "-dac", 0x2000);
>  sysbus_init_mmio(sbd, >iomem_dac);
> +s->iomem_dac.disable_reentrancy_guard = true;

Where we set this flag we should have a comment explaining why
we need to do it, please.

PS: for a single patch you don't need to use a separate cover letter;
cover letters are only needed for multi-patch series.

thanks
-- PMM



[PATCH 31/33] hw/cpu/a9mpcore: Remove legacy code

2023-12-12 Thread Philippe Mathieu-Daudé
Now that all boards set the "cpu-type" property,
the legacy code can be removed.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/cpu/a9mpcore.c  | 8 +++-
 hw/cpu/cortex_mpcore.c | 8 +---
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
index ffdaf392fc..4e2fdb8321 100644
--- a/hw/cpu/a9mpcore.c
+++ b/hw/cpu/a9mpcore.c
@@ -41,12 +41,10 @@ static void a9mp_priv_realize(DeviceState *dev, Error 
**errp)
 DeviceState *scudev, *gtimerdev, *mptimerdev, *wdtdev;
 SysBusDevice *scubusdev, *gtimerbusdev, *mptimerbusdev, *wdtbusdev;
 Error *local_err = NULL;
-CPUState *cpu0;
-Object *cpuobj;
 
-cpu0 = qemu_get_cpu(0);
-cpuobj = OBJECT(cpu0);
-if (strcmp(object_get_typename(cpuobj), ARM_CPU_TYPE_NAME("cortex-a9"))) {
+if (!c->cpu_type) {
+qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-a9"));
+} else if (strcmp(c->cpu_type, ARM_CPU_TYPE_NAME("cortex-a9"))) {
 /* We might allow Cortex-A5 once we model it */
 error_setg(errp,
"Cortex-A9MPCore peripheral can only use Cortex-A9 CPU");
diff --git a/hw/cpu/cortex_mpcore.c b/hw/cpu/cortex_mpcore.c
index 65309636d7..c5de6c3ae4 100644
--- a/hw/cpu/cortex_mpcore.c
+++ b/hw/cpu/cortex_mpcore.c
@@ -57,6 +57,11 @@ static void cortex_mpcore_priv_realize(DeviceState *dev, 
Error **errp)
 return;
 }
 
+if (!s->cpu_type) {
+error_setg(errp, "'cpu-type' property is not set");
+return;
+}
+
 qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cores);
 qdev_prop_set_uint32(gicdev, "num-irq", s->gic_spi_num);
 if (k->gic_priority_bits) {
@@ -85,9 +90,6 @@ static void cortex_mpcore_priv_realize(DeviceState *dev, 
Error **errp)
 
 
 /* CPU */
-if (!s->cpu_type) {
-return;
-}
 for (int i = 0; i < s->num_cores; i++) {
 Object *cpuobj;
 
-- 
2.41.0




[PATCH 25/33] hw/arm/fsl-imx6ul: Let the A7MPcore create/wire the CPU cores

2023-12-12 Thread Philippe Mathieu-Daudé
Set the properties on the a7mpcore object to let it create and
wire the CPU cores. Remove the redundant code.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/arm/fsl-imx6ul.h |  4 
 hw/arm/fsl-imx6ul.c | 24 ++--
 hw/arm/mcimx6ul-evk.c   |  3 ++-
 3 files changed, 8 insertions(+), 23 deletions(-)

diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
index b37d544319..9957ab5be0 100644
--- a/include/hw/arm/fsl-imx6ul.h
+++ b/include/hw/arm/fsl-imx6ul.h
@@ -34,7 +34,6 @@
 #include "hw/usb/chipidea.h"
 #include "hw/usb/imx-usb-phy.h"
 #include "exec/memory.h"
-#include "cpu.h"
 #include "qom/object.h"
 #include "qemu/units.h"
 
@@ -63,11 +62,8 @@ enum FslIMX6ULConfiguration {
 };
 
 struct FslIMX6ULState {
-/*< private >*/
 DeviceStateparent_obj;
 
-/*< public >*/
-ARMCPU cpu;
 CortexMPPrivState  a7mpcore;
 IMXGPTStategpt[FSL_IMX6UL_NUM_GPTS];
 IMXEPITState   epit[FSL_IMX6UL_NUM_EPITS];
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
index 6e4343efaa..512973e3c1 100644
--- a/hw/arm/fsl-imx6ul.c
+++ b/hw/arm/fsl-imx6ul.c
@@ -25,6 +25,7 @@
 #include "sysemu/sysemu.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "target/arm/cpu.h" /* qom */
 
 #define NAME_SIZE 20
 
@@ -34,9 +35,6 @@ static void fsl_imx6ul_init(Object *obj)
 char name[NAME_SIZE];
 int i;
 
-object_initialize_child(obj, "cpu0", >cpu,
-ARM_CPU_TYPE_NAME("cortex-a7"));
-
 /*
  * A7MPCORE
  */
@@ -158,8 +156,6 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 DeviceState *gic;
 int i;
 char name[NAME_SIZE];
-SysBusDevice *sbd;
-DeviceState *d;
 
 if (ms->smp.cpus > 1) {
 error_setg(errp, "%s: Only a single CPU is supported (%d requested)",
@@ -167,26 +163,18 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
-qdev_realize(DEVICE(>cpu), NULL, _abort);
-
 /*
  * A7MPCORE
  */
-object_property_set_int(OBJECT(>a7mpcore), "num-cores", 1, 
_abort);
-object_property_set_int(OBJECT(>a7mpcore), "num-irq",
-FSL_IMX6UL_MAX_IRQ + GIC_INTERNAL, _abort);
+qdev_prop_set_uint32(DEVICE(>a7mpcore), "num-cores", 1);
+qdev_prop_set_string(DEVICE(>a7mpcore), "cpu-type",
+ ARM_CPU_TYPE_NAME("cortex-a7"));
+qdev_prop_set_uint32(DEVICE(>a7mpcore), "gic-spi-num",
+ FSL_IMX6UL_MAX_IRQ + GIC_INTERNAL);
 sysbus_realize(SYS_BUS_DEVICE(>a7mpcore), _abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(>a7mpcore), 0, FSL_IMX6UL_A7MPCORE_ADDR);
 gic = DEVICE(>a7mpcore);
 
-sbd = SYS_BUS_DEVICE(>a7mpcore);
-d = DEVICE(>cpu);
-
-sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(d, ARM_CPU_IRQ));
-sysbus_connect_irq(sbd, 1, qdev_get_gpio_in(d, ARM_CPU_FIQ));
-sysbus_connect_irq(sbd, 2, qdev_get_gpio_in(d, ARM_CPU_VIRQ));
-sysbus_connect_irq(sbd, 3, qdev_get_gpio_in(d, ARM_CPU_VFIQ));
-
 /*
  * A7MPCORE DAP
  */
diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c
index 500427e94b..a19834930f 100644
--- a/hw/arm/mcimx6ul-evk.c
+++ b/hw/arm/mcimx6ul-evk.c
@@ -18,6 +18,7 @@
 #include "hw/qdev-properties.h"
 #include "qemu/error-report.h"
 #include "sysemu/qtest.h"
+#include "target/arm/cpu.h" /* qom */
 
 static void mcimx6ul_evk_init(MachineState *machine)
 {
@@ -64,7 +65,7 @@ static void mcimx6ul_evk_init(MachineState *machine)
 }
 
 if (!qtest_enabled()) {
-arm_load_kernel(>cpu, machine, _info);
+arm_load_kernel(s->a7mpcore.cpu[0], machine, _info);
 }
 }
 
-- 
2.41.0




[PATCH 24/33] hw/arm/fsl-imx6: Let the A9MPcore create/wire the CPU cores

2023-12-12 Thread Philippe Mathieu-Daudé
Set the properties on the a9mpcore object to let it create and
wire the CPU cores. Remove the redundant code.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/arm/fsl-imx6.h |  4 
 hw/arm/fsl-imx6.c | 47 +++
 hw/arm/sabrelite.c|  4 +++-
 3 files changed, 11 insertions(+), 44 deletions(-)

diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
index 21a3b035a4..643c3160c7 100644
--- a/include/hw/arm/fsl-imx6.h
+++ b/include/hw/arm/fsl-imx6.h
@@ -33,7 +33,6 @@
 #include "hw/usb/chipidea.h"
 #include "hw/usb/imx-usb-phy.h"
 #include "exec/memory.h"
-#include "cpu.h"
 #include "qom/object.h"
 
 #define TYPE_FSL_IMX6 "fsl-imx6"
@@ -51,11 +50,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslIMX6State, FSL_IMX6)
 #define FSL_IMX6_NUM_USBS 4
 
 struct FslIMX6State {
-/*< private >*/
 DeviceState parent_obj;
 
-/*< public >*/
-ARMCPU cpu[FSL_IMX6_NUM_CPUS];
 A9MPPrivState  a9mpcore;
 IMX6CCMState   ccm;
 IMX6SRCState   src;
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index 65c7c1a0f9..f05ea62351 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -29,6 +29,7 @@
 #include "chardev/char.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "target/arm/cpu.h"
 
 #define IMX6_ESDHC_CAPABILITIES 0x057834b4
 
@@ -36,17 +37,10 @@
 
 static void fsl_imx6_init(Object *obj)
 {
-MachineState *ms = MACHINE(qdev_get_machine());
 FslIMX6State *s = FSL_IMX6(obj);
 char name[NAME_SIZE];
 int i;
 
-for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX6_NUM_CPUS); i++) {
-snprintf(name, NAME_SIZE, "cpu%d", i);
-object_initialize_child(obj, name, >cpu[i],
-ARM_CPU_TYPE_NAME("cortex-a9"));
-}
-
 object_initialize_child(obj, "a9mpcore", >a9mpcore, TYPE_A9MPCORE_PRIV);
 
 object_initialize_child(obj, "ccm", >ccm, TYPE_IMX6_CCM);
@@ -119,43 +113,18 @@ static void fsl_imx6_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
-for (i = 0; i < smp_cpus; i++) {
-
-/* On uniprocessor, the CBAR is set to 0 */
-if (smp_cpus > 1) {
-object_property_set_int(OBJECT(>cpu[i]), "reset-cbar",
-FSL_IMX6_A9MPCORE_ADDR, _abort);
-}
-
-/* All CPU but CPU 0 start in power off mode */
-if (i) {
-object_property_set_bool(OBJECT(>cpu[i]), "start-powered-off",
- true, _abort);
-}
-
-if (!qdev_realize(DEVICE(>cpu[i]), NULL, errp)) {
-return;
-}
-}
-
-object_property_set_int(OBJECT(>a9mpcore), "num-cores", smp_cpus,
-_abort);
-
-object_property_set_int(OBJECT(>a9mpcore), "num-irq",
-FSL_IMX6_MAX_IRQ + GIC_INTERNAL, _abort);
-
+qdev_prop_set_uint32(DEVICE(>a9mpcore), "num-cores", smp_cpus);
+qdev_prop_set_string(DEVICE(>a9mpcore), "cpu-type",
+ ARM_CPU_TYPE_NAME("cortex-a9"));
+qdev_prop_set_uint64(DEVICE(>a9mpcore), "cpu-reset-cbar",
+ FSL_IMX6_A9MPCORE_ADDR);
+qdev_prop_set_uint32(DEVICE(>a9mpcore), "gic-spi-num",
+ FSL_IMX6_MAX_IRQ + GIC_INTERNAL);
 if (!sysbus_realize(SYS_BUS_DEVICE(>a9mpcore), errp)) {
 return;
 }
 sysbus_mmio_map(SYS_BUS_DEVICE(>a9mpcore), 0, FSL_IMX6_A9MPCORE_ADDR);
 
-for (i = 0; i < smp_cpus; i++) {
-sysbus_connect_irq(SYS_BUS_DEVICE(>a9mpcore), i,
-   qdev_get_gpio_in(DEVICE(>cpu[i]), ARM_CPU_IRQ));
-sysbus_connect_irq(SYS_BUS_DEVICE(>a9mpcore), i + smp_cpus,
-   qdev_get_gpio_in(DEVICE(>cpu[i]), ARM_CPU_FIQ));
-}
-
 if (!sysbus_realize(SYS_BUS_DEVICE(>ccm), errp)) {
 return;
 }
diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c
index 56f184b9ae..751053e8e3 100644
--- a/hw/arm/sabrelite.c
+++ b/hw/arm/sabrelite.c
@@ -99,7 +99,9 @@ static void sabrelite_init(MachineState *machine)
 sabrelite_binfo.secondary_cpu_reset_hook = sabrelite_reset_secondary;
 
 if (!qtest_enabled()) {
-arm_load_kernel(>cpu[0], machine, _binfo);
+CortexMPPrivState *mp = CORTEX_MPCORE_PRIV(>a9mpcore);
+
+arm_load_kernel(mp->cpu[0], machine, _binfo);
 }
 }
 
-- 
2.41.0




[PATCH 28/33] hw/arm/vexpress: Let the A9/A15MPcore create/wire the CPU cores

2023-12-12 Thread Philippe Mathieu-Daudé
Set the properties on the mpcore object to let it create and
wire the CPU cores. Remove the redundant code.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/vexpress.c | 51 ++-
 1 file changed, 6 insertions(+), 45 deletions(-)

diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 294b6f15f2..c104759588 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -210,45 +210,19 @@ static void init_cpus(MachineState *ms, const char 
*cpu_type,
   qemu_irq *pic, bool secure, bool virt)
 {
 DeviceState *dev;
-SysBusDevice *busdev;
-int n;
-unsigned int smp_cpus = ms->smp.cpus;
 
-/* Create the actual CPUs */
-for (n = 0; n < smp_cpus; n++) {
-Object *cpuobj = object_new(cpu_type);
-
-if (!secure) {
-object_property_set_bool(cpuobj, "has_el3", false, NULL);
-}
-if (!virt) {
-if (object_property_find(cpuobj, "has_el2")) {
-object_property_set_bool(cpuobj, "has_el2", false, NULL);
-}
-}
-
-if (object_property_find(cpuobj, "reset-cbar")) {
-object_property_set_int(cpuobj, "reset-cbar", periphbase,
-_abort);
-}
-qdev_realize(DEVICE(cpuobj), NULL, _fatal);
-}
-
-/* Create the private peripheral devices (including the GIC);
- * this must happen after the CPUs are created because a15mpcore_priv
- * wires itself up to the CPU's generic_timer gpio out lines.
- */
 dev = qdev_new(privdev);
+qdev_prop_set_uint32(dev, "num-cores", ms->smp.cpus);
+qdev_prop_set_string(dev, "cpu-type", cpu_type);
 if (!secure) {
 qdev_prop_set_bit(dev, "cpu-has-el3", false);
 }
 if (!virt) {
 qdev_prop_set_bit(dev, "cpu-has-el2", false);
 }
-qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
-busdev = SYS_BUS_DEVICE(dev);
-sysbus_realize_and_unref(busdev, _fatal);
-sysbus_mmio_map(busdev, 0, periphbase);
+qdev_prop_set_uint64(dev, "cpu-reset-cbar", periphbase);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, periphbase);
 
 /* Interrupts [42:0] are from the motherboard;
  * [47:43] are reserved; [63:48] are daughterboard
@@ -256,22 +230,9 @@ static void init_cpus(MachineState *ms, const char 
*cpu_type,
  * external interrupts starting from 32 (because there
  * are internal interrupts 0..31).
  */
-for (n = 0; n < 64; n++) {
+for (int n = 0; n < 64; n++) {
 pic[n] = qdev_get_gpio_in(dev, n);
 }
-
-/* Connect the CPUs to the GIC */
-for (n = 0; n < smp_cpus; n++) {
-DeviceState *cpudev = DEVICE(qemu_get_cpu(n));
-
-sysbus_connect_irq(busdev, n, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
-sysbus_connect_irq(busdev, n + smp_cpus,
-   qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
-sysbus_connect_irq(busdev, n + 2 * smp_cpus,
-   qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
-sysbus_connect_irq(busdev, n + 3 * smp_cpus,
-   qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
-}
 }
 
 static void a9_daughterboard_init(VexpressMachineState *vms,
-- 
2.41.0




[PATCH 32/33] hw/cpu/arm: Remove 'num-cpu' property alias

2023-12-12 Thread Philippe Mathieu-Daudé
All callers access the 'num-cores' property.

Signed-off-by: Philippe Mathieu-Daudé 
---
Better to squash earlier and replace in place, so no need for alias?
---
 hw/cpu/arm11mpcore.c | 1 -
 hw/cpu/cortex_mpcore.c   | 2 --
 hw/cpu/realview_mpcore.c | 1 -
 3 files changed, 4 deletions(-)

diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c
index 67c96a3a7c..32756e05e9 100644
--- a/hw/cpu/arm11mpcore.c
+++ b/hw/cpu/arm11mpcore.c
@@ -133,7 +133,6 @@ static void mpcore_priv_initfn(Object *obj)
 
 static Property mpcore_priv_properties[] = {
 DEFINE_PROP_UINT32("num-cores", ARM11MPCorePriveState, num_cpu, 1),
-DEFINE_PROP_UINT32("num-cpu", ARM11MPCorePriveState, num_cpu, 1), /* alias 
*/
 /* The ARM11 MPCORE TRM says the on-chip controller may have
  * anything from 0 to 224 external interrupt IRQ lines (with another
  * 32 internal). We default to 32+32, which is the number provided by
diff --git a/hw/cpu/cortex_mpcore.c b/hw/cpu/cortex_mpcore.c
index c5de6c3ae4..3cc9feef16 100644
--- a/hw/cpu/cortex_mpcore.c
+++ b/hw/cpu/cortex_mpcore.c
@@ -156,7 +156,6 @@ static void cortex_mpcore_priv_realize(DeviceState *dev, 
Error **errp)
 static Property cortex_mpcore_priv_properties[] = {
 DEFINE_PROP_UINT8("cluster-id", CortexMPPrivState, cluster_id, 0),
 DEFINE_PROP_UINT32("num-cores", CortexMPPrivState, num_cores, 1),
-DEFINE_PROP_UINT32("num-cpu", CortexMPPrivState, num_cores, 1), /* alias */
 
 DEFINE_PROP_STRING("cpu-type", CortexMPPrivState, cpu_type),
 DEFINE_PROP_BOOL("cpu-has-el3", CortexMPPrivState, cpu_has_el3, true),
@@ -175,7 +174,6 @@ static Property cortex_mpcore_priv_properties[] = {
  TYPE_MEMORY_REGION, MemoryRegion *),
 
 DEFINE_PROP_UINT32("gic-spi-num", CortexMPPrivState, gic_spi_num, 0),
-DEFINE_PROP_UINT32("num-irq", CortexMPPrivState, gic_spi_num, 0), /* alias 
*/
 
 DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/hw/cpu/realview_mpcore.c b/hw/cpu/realview_mpcore.c
index e985d230e0..4d4965126b 100644
--- a/hw/cpu/realview_mpcore.c
+++ b/hw/cpu/realview_mpcore.c
@@ -99,7 +99,6 @@ static void mpcore_rirq_init(Object *obj)
 
 object_initialize_child(obj, "a11priv", >priv, TYPE_ARM11MPCORE_PRIV);
 object_property_add_alias(obj, "num-cores", OBJECT(>priv), "num-cores");
-object_property_add_alias(obj, "num-cpu", OBJECT(>priv), "num-cores");
 privbusdev = SYS_BUS_DEVICE(>priv);
 sysbus_init_mmio(sbd, sysbus_mmio_get_region(privbusdev, 0));
 
-- 
2.41.0




[PATCH 21/33] hw/cpu/arm: Create CPUs once in MPCore parent

2023-12-12 Thread Philippe Mathieu-Daudé
Add support for creating the MPCore CPU cluster in the
abstract TYPE_CORTEX_MPCORE_PRIV parent realize() handler.

Only do so if the 'cpu-type' property is set, so current
behavior is not modified. Boards will be converted by
setting this property.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/cpu/cortex_mpcore.h | 12 +
 hw/cpu/cortex_mpcore.c | 88 ++
 2 files changed, 100 insertions(+)

diff --git a/include/hw/cpu/cortex_mpcore.h b/include/hw/cpu/cortex_mpcore.h
index 4e1aa9f7f7..9a4fc2404e 100644
--- a/include/hw/cpu/cortex_mpcore.h
+++ b/include/hw/cpu/cortex_mpcore.h
@@ -16,6 +16,7 @@
 #include "hw/misc/a9scu.h"
 #include "hw/timer/a9gtimer.h"
 #include "hw/timer/arm_mptimer.h"
+#include "target/arm/cpu-qom.h"
 
 /*
  * This is a model of the Arm Cortex-A MPCore family of hardware.
@@ -93,13 +94,24 @@ struct CortexMPPrivState {
 SysBusDevice parent_obj;
 
 MemoryRegion container;
+ARMCPU *cpu[4];
 GICState gic;
 
 /* Properties */
+uint8_t cluster_id;
 uint32_t num_cores;
 
+char *cpu_type;
 bool cpu_has_el3;
 bool cpu_has_el2;
+bool cpu_has_vfp_d32;
+bool cpu_has_neon;
+uint64_t cpu_freq_hz;
+uint64_t cpu_midr;
+uint32_t cpu_psci_conduit;
+uint64_t cpu_reset_cbar;
+bool cpu_reset_hivecs;
+MemoryRegion *cpu_memory;
 
 uint32_t gic_spi_num;
 };
diff --git a/hw/cpu/cortex_mpcore.c b/hw/cpu/cortex_mpcore.c
index 75324268fa..65309636d7 100644
--- a/hw/cpu/cortex_mpcore.c
+++ b/hw/cpu/cortex_mpcore.c
@@ -12,6 +12,7 @@
 #include "hw/cpu/cortex_mpcore.h"
 #include "hw/irq.h"
 #include "sysemu/kvm.h"
+#include "target/arm/cpu.h"
 
 static void cortex_mpcore_priv_set_irq(void *opaque, int irq, int level)
 {
@@ -50,6 +51,12 @@ static void cortex_mpcore_priv_realize(DeviceState *dev, 
Error **errp)
 return;
 }
 
+if (s->num_cores > ARRAY_SIZE(s->cpu)) {
+error_setg(errp,
+   "At most %zu CPU cores are supported", ARRAY_SIZE(s->cpu));
+return;
+}
+
 qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cores);
 qdev_prop_set_uint32(gicdev, "num-irq", s->gic_spi_num);
 if (k->gic_priority_bits) {
@@ -75,14 +82,95 @@ static void cortex_mpcore_priv_realize(DeviceState *dev, 
Error **errp)
 
 /* Pass through inbound GPIO lines to the GIC */
 qdev_init_gpio_in(dev, cortex_mpcore_priv_set_irq, s->gic_spi_num - 32);
+
+
+/* CPU */
+if (!s->cpu_type) {
+return;
+}
+for (int i = 0; i < s->num_cores; i++) {
+Object *cpuobj;
+
+cpuobj = object_new(s->cpu_type);
+object_property_add_child(OBJECT(dev), "cpu[*]", OBJECT(cpuobj));
+object_unref(cpuobj);
+s->cpu[i] = ARM_CPU(cpuobj);
+
+object_property_set_bool(cpuobj, "neon", s->cpu_has_neon,
+_abort);
+object_property_set_bool(cpuobj, "vfp-d32", s->cpu_has_vfp_d32,
+_abort);
+if (object_property_find(cpuobj, "has_el3")) {
+object_property_set_bool(cpuobj, "has_el3", s->cpu_has_el3,
+ _abort);
+}
+if (object_property_find(cpuobj, "has_el2")) {
+object_property_set_bool(cpuobj, "has_el2", s->cpu_has_el2,
+ _abort);
+}
+if (s->cpu_freq_hz) {
+object_property_set_int(cpuobj, "cntfrq", s->cpu_freq_hz,
+_abort);
+}
+object_property_set_int(cpuobj, "midr", s->cpu_midr, _abort);
+object_property_set_bool(cpuobj, "reset-hivecs", s->cpu_reset_hivecs,
+ _abort);
+if (s->num_cores == 1) {
+/* On uniprocessor, the CBAR is set to 0 */
+} else if (object_property_find(cpuobj, "reset-cbar")) {
+object_property_set_int(cpuobj, "reset-cbar",
+s->cpu_reset_cbar, _abort);
+}
+if (i > 0) {
+/*
+ * Secondary CPUs start in powered-down state (and can be
+ * powered up via the SRC system reset controller)
+ */
+object_property_set_bool(cpuobj, "start-powered-off", true,
+ _abort);
+}
+if (s->cluster_id) {
+object_property_set_int(cpuobj, "mp-affinity",
+(s->cluster_id << ARM_AFF1_SHIFT) | i,
+_abort);
+} else {
+object_property_set_int(cpuobj, "mp-affinity",
+arm_cpu_mp_affinity(i, s->num_cores),
+_abort);
+}
+object_property_set_int(cpuobj, "psci-conduit",
+s->cpu_psci_conduit, _abort);
+if (s->cpu_memory) {
+object_property_set_link(cpuobj, "memory",
+ 

[PATCH 26/33] hw/arm/fsl-imx7: Let the A7MPcore create/wire the CPU cores

2023-12-12 Thread Philippe Mathieu-Daudé
Set the properties on the a7mpcore object to let it create and
wire the CPU cores. Remove the redundant code.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/arm/fsl-imx7.h |  4 ---
 hw/arm/fsl-imx7.c | 62 +--
 hw/arm/mcimx7d-sabre.c|  3 +-
 3 files changed, 10 insertions(+), 59 deletions(-)

diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
index a6f3a96029..1f916c 100644
--- a/include/hw/arm/fsl-imx7.h
+++ b/include/hw/arm/fsl-imx7.h
@@ -36,7 +36,6 @@
 #include "hw/net/imx_fec.h"
 #include "hw/pci-host/designware.h"
 #include "hw/usb/chipidea.h"
-#include "cpu.h"
 #include "qom/object.h"
 #include "qemu/units.h"
 
@@ -63,11 +62,8 @@ enum FslIMX7Configuration {
 };
 
 struct FslIMX7State {
-/*< private >*/
 DeviceStateparent_obj;
 
-/*< public >*/
-ARMCPU cpu[FSL_IMX7_NUM_CPUS];
 CortexMPPrivState  a7mpcore;
 IMXGPTStategpt[FSL_IMX7_NUM_GPTS];
 IMXGPIOState   gpio[FSL_IMX7_NUM_GPIOS];
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index bd9266b8b5..f71ffe7910 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -26,25 +26,16 @@
 #include "sysemu/sysemu.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "target/arm/cpu.h" /* qom */
 
 #define NAME_SIZE 20
 
 static void fsl_imx7_init(Object *obj)
 {
-MachineState *ms = MACHINE(qdev_get_machine());
 FslIMX7State *s = FSL_IMX7(obj);
 char name[NAME_SIZE];
 int i;
 
-/*
- * CPUs
- */
-for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX7_NUM_CPUS); i++) {
-snprintf(name, NAME_SIZE, "cpu%d", i);
-object_initialize_child(obj, name, >cpu[i],
-ARM_CPU_TYPE_NAME("cortex-a7"));
-}
-
 /*
  * A7MPCORE
  */
@@ -163,7 +154,6 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
 MachineState *ms = MACHINE(qdev_get_machine());
 FslIMX7State *s = FSL_IMX7(dev);
 DeviceState *gic;
-Object *o;
 int i;
 qemu_irq irq;
 char name[NAME_SIZE];
@@ -175,56 +165,20 @@ static void fsl_imx7_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
-/*
- * CPUs
- */
-for (i = 0; i < smp_cpus; i++) {
-o = OBJECT(>cpu[i]);
-
-/* On uniprocessor, the CBAR is set to 0 */
-if (smp_cpus > 1) {
-object_property_set_int(o, "reset-cbar", FSL_IMX7_A7MPCORE_ADDR,
-_abort);
-}
-
-if (i) {
-/*
- * Secondary CPUs start in powered-down state (and can be
- * powered up via the SRC system reset controller)
- */
-object_property_set_bool(o, "start-powered-off", true,
- _abort);
-}
-
-qdev_realize(DEVICE(o), NULL, _abort);
-}
-
 /*
  * A7MPCORE
  */
-object_property_set_int(OBJECT(>a7mpcore), "num-cores", smp_cpus,
-_abort);
-object_property_set_int(OBJECT(>a7mpcore), "num-irq",
-FSL_IMX7_MAX_IRQ + GIC_INTERNAL, _abort);
-
+qdev_prop_set_uint32(DEVICE(>a7mpcore), "num-cores", ms->smp.cpus);
+qdev_prop_set_string(DEVICE(>a7mpcore), "cpu-type",
+ ARM_CPU_TYPE_NAME("cortex-a7"));
+qdev_prop_set_uint64(DEVICE(>a7mpcore), "cpu-reset-cbar",
+ FSL_IMX7_A7MPCORE_ADDR);
+qdev_prop_set_uint32(DEVICE(>a7mpcore), "gic-spi-num",
+ FSL_IMX7_MAX_IRQ + GIC_INTERNAL);
 sysbus_realize(SYS_BUS_DEVICE(>a7mpcore), _abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(>a7mpcore), 0, FSL_IMX7_A7MPCORE_ADDR);
 gic = DEVICE(>a7mpcore);
 
-for (i = 0; i < smp_cpus; i++) {
-SysBusDevice *sbd = SYS_BUS_DEVICE(>a7mpcore);
-DeviceState  *d   = DEVICE(qemu_get_cpu(i));
-
-irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);
-sysbus_connect_irq(sbd, i, irq);
-irq = qdev_get_gpio_in(d, ARM_CPU_FIQ);
-sysbus_connect_irq(sbd, i + smp_cpus, irq);
-irq = qdev_get_gpio_in(d, ARM_CPU_VIRQ);
-sysbus_connect_irq(sbd, i + 2 * smp_cpus, irq);
-irq = qdev_get_gpio_in(d, ARM_CPU_VFIQ);
-sysbus_connect_irq(sbd, i + 3 * smp_cpus, irq);
-}
-
 /*
  * A7MPCORE DAP
  */
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
index 693a1023b6..782f7591db 100644
--- a/hw/arm/mcimx7d-sabre.c
+++ b/hw/arm/mcimx7d-sabre.c
@@ -20,6 +20,7 @@
 #include "hw/qdev-properties.h"
 #include "qemu/error-report.h"
 #include "sysemu/qtest.h"
+#include "target/arm/cpu.h" /* qom */
 
 static void mcimx7d_sabre_init(MachineState *machine)
 {
@@ -64,7 +65,7 @@ static void mcimx7d_sabre_init(MachineState *machine)
 }
 
 if (!qtest_enabled()) {
-arm_load_kernel(>cpu[0], machine, _info);
+arm_load_kernel(s->a7mpcore.cpu[0], machine, _info);
 }
 }
 
-- 
2.41.0




[PATCH 18/33] hw/cpu/arm: Replace A15MPPrivState by CortexMPPrivState

2023-12-12 Thread Philippe Mathieu-Daudé
A15MPPrivState doesn't contain anything else but its parent,
CortexMPPrivState. Remove it in favor of the parent.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/arm/aspeed_soc.h| 2 +-
 include/hw/arm/fsl-imx6ul.h| 2 +-
 include/hw/arm/fsl-imx7.h  | 2 +-
 include/hw/cpu/cortex_mpcore.h | 5 -
 hw/cpu/a15mpcore.c | 2 +-
 5 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index e0663ab50d..2f51d78e22 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -108,7 +108,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(Aspeed2400SoCState, 
ASPEED2400_SOC)
 struct Aspeed2600SoCState {
 AspeedSoCState parent;
 
-A15MPPrivState a7mpcore;
+CortexMPPrivState a7mpcore;
 ARMCPU cpu[ASPEED_CPUS_NUM]; /* XXX belong to a7mpcore */
 };
 
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
index 5ed22004d1..b37d544319 100644
--- a/include/hw/arm/fsl-imx6ul.h
+++ b/include/hw/arm/fsl-imx6ul.h
@@ -68,7 +68,7 @@ struct FslIMX6ULState {
 
 /*< public >*/
 ARMCPU cpu;
-A15MPPrivState a7mpcore;
+CortexMPPrivState  a7mpcore;
 IMXGPTStategpt[FSL_IMX6UL_NUM_GPTS];
 IMXEPITState   epit[FSL_IMX6UL_NUM_EPITS];
 IMXGPIOState   gpio[FSL_IMX6UL_NUM_GPIOS];
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
index 87faee33c2..a6f3a96029 100644
--- a/include/hw/arm/fsl-imx7.h
+++ b/include/hw/arm/fsl-imx7.h
@@ -68,7 +68,7 @@ struct FslIMX7State {
 
 /*< public >*/
 ARMCPU cpu[FSL_IMX7_NUM_CPUS];
-A15MPPrivState a7mpcore;
+CortexMPPrivState  a7mpcore;
 IMXGPTStategpt[FSL_IMX7_NUM_GPTS];
 IMXGPIOState   gpio[FSL_IMX7_NUM_GPIOS];
 IMX7CCMState   ccm;
diff --git a/include/hw/cpu/cortex_mpcore.h b/include/hw/cpu/cortex_mpcore.h
index 73627bc415..7822d5cbc4 100644
--- a/include/hw/cpu/cortex_mpcore.h
+++ b/include/hw/cpu/cortex_mpcore.h
@@ -117,10 +117,5 @@ struct A9MPPrivState {
 };
 
 #define TYPE_A15MPCORE_PRIV "a15mpcore_priv"
-OBJECT_DECLARE_SIMPLE_TYPE(A15MPPrivState, A15MPCORE_PRIV)
-
-struct A15MPPrivState {
-CortexMPPrivState parent_obj;
-};
 
 #endif
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index ecd04b7af1..87b0786781 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -125,7 +125,7 @@ static const TypeInfo a15mp_types[] = {
 {
 .name   = TYPE_A15MPCORE_PRIV,
 .parent = TYPE_CORTEX_MPCORE_PRIV,
-.instance_size  = sizeof(A15MPPrivState),
+.instance_size  = sizeof(CortexMPPrivState),
 .class_init = a15mp_priv_class_init,
 },
 };
-- 
2.41.0




[PATCH 33/33] hw/cpu/arm: Remove use of qemu_get_cpu() in A7/A15 realize()

2023-12-12 Thread Philippe Mathieu-Daudé
Previous commits (in particular "Create CPUs once in MPCore parent")
allowed creating the MPCore private container vCPUs within the
container. We don't need to call qemu_get_cpu(), which is unsafe in
hegerogeneous context.
Directly access the CortexMPPrivState::cpu array.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/cpu/a15mpcore.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index 5f28a97adb..8dccf15103 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -44,7 +44,7 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
  * appropriate GIC PPI inputs
  */
 for (i = 0; i < c->num_cores; i++) {
-DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
+DeviceState *cpudev = DEVICE(c->cpu[i]);
 int ppibase = c->gic_spi_num - 32 + i * 32;
 int irq;
 /* Mapping from the output timer irq lines from the CPU to the
-- 
2.41.0




[PATCH 27/33] hw/arm/highbank: Let the A9/A15MPcore create/wire the CPU cores

2023-12-12 Thread Philippe Mathieu-Daudé
Set the properties on the mpcore object to let it create and
wire the CPU cores. Remove the redundant code.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/highbank.c | 53 +++
 1 file changed, 8 insertions(+), 45 deletions(-)

diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index a184bee993..b4f8304146 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -180,47 +180,10 @@ static void calxeda_init(MachineState *machine, enum 
cxmachines machine_id)
 SysBusDevice *busdev;
 qemu_irq pic[128];
 int n;
-unsigned int smp_cpus = machine->smp.cpus;
-qemu_irq cpu_irq[4];
-qemu_irq cpu_fiq[4];
-qemu_irq cpu_virq[4];
-qemu_irq cpu_vfiq[4];
 MemoryRegion *sysram;
 MemoryRegion *sysmem;
 char *sysboot_filename;
 
-switch (machine_id) {
-case CALXEDA_HIGHBANK:
-machine->cpu_type = ARM_CPU_TYPE_NAME("cortex-a9");
-break;
-case CALXEDA_MIDWAY:
-machine->cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
-break;
-default:
-assert(0);
-}
-
-for (n = 0; n < smp_cpus; n++) {
-Object *cpuobj;
-ARMCPU *cpu;
-
-cpuobj = object_new(machine->cpu_type);
-cpu = ARM_CPU(cpuobj);
-
-object_property_set_int(cpuobj, "psci-conduit", QEMU_PSCI_CONDUIT_SMC,
-_abort);
-
-if (object_property_find(cpuobj, "reset-cbar")) {
-object_property_set_int(cpuobj, "reset-cbar", MPCORE_PERIPHBASE,
-_abort);
-}
-qdev_realize(DEVICE(cpuobj), NULL, _fatal);
-cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
-cpu_fiq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ);
-cpu_virq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_VIRQ);
-cpu_vfiq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_VFIQ);
-}
-
 sysmem = get_system_memory();
 /* SDRAM at address zero.  */
 memory_region_add_subregion(sysmem, 0, machine->ram);
@@ -251,22 +214,22 @@ static void calxeda_init(MachineState *machine, enum 
cxmachines machine_id)
 sysbus_mmio_map(busdev, 0, 0xfff12000);
 
 dev = qdev_new(TYPE_A9MPCORE_PRIV);
+qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-a9"));
 break;
 case CALXEDA_MIDWAY:
 dev = qdev_new(TYPE_A15MPCORE_PRIV);
+qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-a15"));
 break;
+default:
+g_assert_not_reached();
 }
-qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
-qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
+qdev_prop_set_uint32(dev, "num-cores", machine->smp.cpus);
+qdev_prop_set_uint32(dev, "cpu-psci-conduit", QEMU_PSCI_CONDUIT_SMC);
+qdev_prop_set_uint64(dev, "cpu-reset-cbar", MPCORE_PERIPHBASE);
+qdev_prop_set_uint32(dev, "gic-spi-num", NIRQ_GIC);
 busdev = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(busdev, _fatal);
 sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE);
-for (n = 0; n < smp_cpus; n++) {
-sysbus_connect_irq(busdev, n, cpu_irq[n]);
-sysbus_connect_irq(busdev, n + smp_cpus, cpu_fiq[n]);
-sysbus_connect_irq(busdev, n + 2 * smp_cpus, cpu_virq[n]);
-sysbus_connect_irq(busdev, n + 3 * smp_cpus, cpu_vfiq[n]);
-}
 
 for (n = 0; n < 128; n++) {
 pic[n] = qdev_get_gpio_in(dev, n);
-- 
2.41.0




[PATCH 22/33] hw/arm/aspeed_ast2600: Let the A7MPcore create/wire the CPU cores

2023-12-12 Thread Philippe Mathieu-Daudé
Set the properties on the a7mpcore object to let it create and
wire the CPU cores. Remove the redundant code.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/arm/aspeed_soc.h |  1 -
 hw/arm/aspeed_ast2600.c | 58 -
 2 files changed, 18 insertions(+), 41 deletions(-)

diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 2f51d78e22..a824679b1e 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -109,7 +109,6 @@ struct Aspeed2600SoCState {
 AspeedSoCState parent;
 
 CortexMPPrivState a7mpcore;
-ARMCPU cpu[ASPEED_CPUS_NUM]; /* XXX belong to a7mpcore */
 };
 
 #define TYPE_ASPEED2600_SOC "aspeed2600-soc"
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 88e2a23514..1000fac675 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -156,10 +156,6 @@ static void aspeed_soc_ast2600_init(Object *obj)
 g_assert_not_reached();
 }
 
-for (i = 0; i < sc->num_cpus; i++) {
-object_initialize_child(obj, "cpu[*]", >cpu[i], sc->cpu_type);
-}
-
 snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname);
 object_initialize_child(obj, "scu", >scu, typename);
 qdev_prop_set_uint32(DEVICE(>scu), "silicon-rev",
@@ -270,11 +266,6 @@ static void aspeed_soc_ast2600_init(Object *obj)
  *
  * 
https://developer.arm.com/documentation/ddi0388/e/the-system-control-coprocessors/summary-of-system-control-coprocessor-registers/multiprocessor-affinity-register
  */
-static uint64_t aspeed_calc_affinity(int cpu)
-{
-return (0xf << ARM_AFF1_SHIFT) | cpu;
-}
-
 static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
 {
 int i;
@@ -284,6 +275,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
 Error *err = NULL;
 qemu_irq irq;
 g_autofree char *sram_name = NULL;
+DeviceState *mpdev;
+CortexMPPrivState *mppriv;
 
 /* Default boot region (SPI memory or ROMs) */
 memory_region_init(>spi_boot_container, OBJECT(s),
@@ -305,42 +298,26 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
   "aspeed.emmc-boot-controller",
   sc->memmap[ASPEED_DEV_EMMC_BC], 0x1000);
 
-/* CPU */
-for (i = 0; i < sc->num_cpus; i++) {
-if (sc->num_cpus > 1) {
-object_property_set_int(OBJECT(>cpu[i]), "reset-cbar",
-ASPEED_A7MPCORE_ADDR, _abort);
-}
-object_property_set_int(OBJECT(>cpu[i]), "mp-affinity",
-aspeed_calc_affinity(i), _abort);
-
-object_property_set_int(OBJECT(>cpu[i]), "cntfrq", 112500,
-_abort);
-object_property_set_bool(OBJECT(>cpu[i]), "neon", false,
-_abort);
-object_property_set_bool(OBJECT(>cpu[i]), "vfp-d32", false,
-_abort);
-object_property_set_link(OBJECT(>cpu[i]), "memory",
- OBJECT(s->memory), _abort);
-
-if (!qdev_realize(DEVICE(>cpu[i]), NULL, errp)) {
-return;
-}
-}
-
 /* A7MPCORE */
-object_property_set_int(OBJECT(>a7mpcore), "num-cores", sc->num_cpus,
-_abort);
-object_property_set_int(OBJECT(>a7mpcore), "num-irq",
-ROUND_UP(AST2600_MAX_IRQ + GIC_INTERNAL, 32),
-_abort);
-
+mpdev = DEVICE(>a7mpcore);
+qdev_prop_set_uint32(mpdev, "cluster-id", 0xf);
+qdev_prop_set_uint32(mpdev, "num-cores", sc->num_cpus);
+qdev_prop_set_string(mpdev, "cpu-type", sc->cpu_type);
+qdev_prop_set_uint64(mpdev, "cpu-freq-hz", 112500);
+qdev_prop_set_bit(mpdev, "cpu-has-neon", false);
+qdev_prop_set_bit(mpdev, "cpu-has-vfp-d32", false);
+qdev_prop_set_uint64(mpdev, "cpu-reset-cbar", ASPEED_A7MPCORE_ADDR);
+object_property_set_link(OBJECT(>a7mpcore), "cpu-memory",
+ OBJECT(s->memory), _abort);
+qdev_prop_set_uint32(mpdev, "gic-spi-num",
+ ROUND_UP(AST2600_MAX_IRQ + GIC_INTERNAL, 32));
 sysbus_realize(SYS_BUS_DEVICE(>a7mpcore), _abort);
 aspeed_mmio_map(s, SYS_BUS_DEVICE(>a7mpcore), 0, ASPEED_A7MPCORE_ADDR);
+mppriv = CORTEX_MPCORE_PRIV(>a7mpcore);
 
 for (i = 0; i < sc->num_cpus; i++) {
 SysBusDevice *sbd = SYS_BUS_DEVICE(>a7mpcore);
-DeviceState  *d   = DEVICE(>cpu[i]);
+DeviceState  *d   = DEVICE(mppriv->cpu[i]);
 
 irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);
 sysbus_connect_irq(sbd, i, irq);
@@ -353,7 +330,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
 }
 
 /* SRAM */
-sram_name = g_strdup_printf("aspeed.sram.%d", CPU(>cpu[0])->cpu_index);
+sram_name = g_strdup_printf("aspeed.sram.%d",
+

[PATCH 23/33] hw/arm/exynos4210: Let the A9MPcore create/wire the CPU cores

2023-12-12 Thread Philippe Mathieu-Daudé
Set the properties on the a9mpcore object to let it create and
wire the CPU cores. Remove the redundant code.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/arm/exynos4210.h |  4 +--
 hw/arm/exynos4210.c | 62 +
 hw/arm/exynos4_boards.c |  6 ++--
 3 files changed, 26 insertions(+), 46 deletions(-)

diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
index f95e3232c5..28a64f275c 100644
--- a/include/hw/arm/exynos4210.h
+++ b/include/hw/arm/exynos4210.h
@@ -83,10 +83,8 @@
 #define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
 
 struct Exynos4210State {
-/*< private >*/
 SysBusDevice parent_obj;
-/*< public >*/
-ARMCPU *cpu[EXYNOS4210_NCPUS];
+
 qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
 
 MemoryRegion chipid_mem;
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index 7386a8fe57..c6da908961 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -501,12 +501,6 @@ void exynos4210_write_secondary(ARMCPU *cpu,
info->smp_loader_start);
 }
 
-static uint64_t exynos4210_calc_affinity(int cpu)
-{
-/* Exynos4210 has 0x9 as cluster ID */
-return (0x9 << ARM_AFF1_SHIFT) | cpu;
-}
-
 static DeviceState *pl330_create(uint32_t base, OrIRQState *orgate,
  qemu_irq irq, int nreq, int nevents, int 
width)
 {
@@ -549,26 +543,25 @@ static void exynos4210_realize(DeviceState *socdev, Error 
**errp)
 MemoryRegion *system_mem = get_system_memory();
 SysBusDevice *busdev;
 DeviceState *dev, *mpdev, *uart[4], *pl330[3];
+CortexMPPrivState *mpcore;
 int i, n;
 
-for (n = 0; n < EXYNOS4210_NCPUS; n++) {
-Object *cpuobj = object_new(ARM_CPU_TYPE_NAME("cortex-a9"));
-
-/* By default A9 CPUs have EL3 enabled.  This board does not currently
- * support EL3 so the CPU EL3 property is disabled before realization.
- */
-if (object_property_find(cpuobj, "has_el3")) {
-object_property_set_bool(cpuobj, "has_el3", false, _fatal);
-}
-
-s->cpu[n] = ARM_CPU(cpuobj);
-object_property_set_int(cpuobj, "mp-affinity",
-exynos4210_calc_affinity(n), _abort);
-object_property_set_int(cpuobj, "reset-cbar",
-EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
-_abort);
-qdev_realize(DEVICE(cpuobj), NULL, _fatal);
-}
+/* Private memory region and Internal GIC */
+mpdev = DEVICE(>a9mpcore);
+mpcore = CORTEX_MPCORE_PRIV(>a9mpcore);
+/* Exynos4210 has 0x9 as cluster ID */
+qdev_prop_set_uint32(mpdev, "cluster-id", 0x9);
+qdev_prop_set_uint32(mpdev, "num-cores", EXYNOS4210_NCPUS);
+/*
+ * By default A9 CPUs have EL3 enabled.  This board does not currently
+ * support EL3 so the CPU EL3 property is disabled before realization.
+ */
+qdev_prop_set_bit(mpdev, "cpu-has-el3", false);
+qdev_prop_set_uint64(mpdev, "cpu-reset-cbar",
+ EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
+busdev = SYS_BUS_DEVICE(>a9mpcore);
+sysbus_realize(busdev, _fatal);
+sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
 
 /* IRQ Gate */
 for (i = 0; i < EXYNOS4210_NCPUS; i++) {
@@ -578,23 +571,10 @@ static void exynos4210_realize(DeviceState *socdev, Error 
**errp)
 _abort);
 qdev_realize(orgate, NULL, _abort);
 qdev_connect_gpio_out(orgate, 0,
-  qdev_get_gpio_in(DEVICE(s->cpu[i]), 
ARM_CPU_IRQ));
-}
-
-/* Private memory region and Internal GIC */
-mpdev = DEVICE(>a9mpcore);
-qdev_prop_set_uint32(mpdev, "num-cores", EXYNOS4210_NCPUS);
-/*
- * By default A9 CPUs have EL3 enabled.  This board does not currently
- * support EL3 so the CPU EL3 property is disabled before realization.
- */
-qdev_prop_set_bit(mpdev, "cpu-has-el3", false);
-busdev = SYS_BUS_DEVICE(>a9mpcore);
-sysbus_realize(busdev, _fatal);
-sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
-for (n = 0; n < EXYNOS4210_NCPUS; n++) {
-sysbus_connect_irq(busdev, n,
-   qdev_get_gpio_in(DEVICE(>cpu_irq_orgate[n]), 0));
+  qdev_get_gpio_in(DEVICE(mpcore->cpu[i]),
+   ARM_CPU_IRQ));
+sysbus_connect_irq(busdev, i,
+   qdev_get_gpio_in(DEVICE(>cpu_irq_orgate[i]), 0));
 }
 
 /* Cache controller */
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
index b0e13eb4f0..7eea66d027 100644
--- a/hw/arm/exynos4_boards.c
+++ b/hw/arm/exynos4_boards.c
@@ -136,18 +136,20 @@ static void nuri_init(MachineState *machine)
 {
 Exynos4BoardState *s = exynos4_boards_init_common(machine,
   EXYNOS4_BOARD_NURI);
+

[PATCH 29/33] hw/arm/xilinx_zynq: Let the A9MPcore create/wire the CPU cores

2023-12-12 Thread Philippe Mathieu-Daudé
Set the properties on the mpcore object to let it create and
wire the CPU cores. Remove the redundant code.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/xilinx_zynq.c | 22 +-
 1 file changed, 5 insertions(+), 17 deletions(-)

diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 28430dcfba..736e2115a6 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -192,22 +192,6 @@ static void zynq_init(MachineState *machine)
 exit(EXIT_FAILURE);
 }
 
-cpu = ARM_CPU(object_new(machine->cpu_type));
-
-/* By default A9 CPUs have EL3 enabled.  This board does not
- * currently support EL3 so the CPU EL3 property is disabled before
- * realization.
- */
-if (object_property_find(OBJECT(cpu), "has_el3")) {
-object_property_set_bool(OBJECT(cpu), "has_el3", false, _fatal);
-}
-
-object_property_set_int(OBJECT(cpu), "midr", ZYNQ_BOARD_MIDR,
-_fatal);
-object_property_set_int(OBJECT(cpu), "reset-cbar", MPCORE_PERIPHBASE,
-_fatal);
-qdev_realize(DEVICE(cpu), NULL, _fatal);
-
 /* DDR remapped to address zero.  */
 memory_region_add_subregion(address_space_mem, 0, machine->ram);
 
@@ -239,15 +223,19 @@ static void zynq_init(MachineState *machine)
 sysbus_mmio_map(SYS_BUS_DEVICE(slcr), 0, 0xF800);
 
 dev = qdev_new(TYPE_A9MPCORE_PRIV);
-qdev_prop_set_uint32(dev, "num-cpu", 1);
+qdev_prop_set_uint32(dev, "num-cores", 1);
+qdev_prop_set_string(dev, "cpu-type", machine->cpu_type);
 /*
  * By default A9 CPUs have EL3 enabled.  This board does not
  * currently support EL3 so the CPU EL3 property is disabled before
  * realization.
  */
 qdev_prop_set_bit(dev, "cpu-has-el3", false);
+qdev_prop_set_uint64(dev, "cpu-reset-cbar", MPCORE_PERIPHBASE);
+qdev_prop_set_uint64(dev, "cpu-midr", ZYNQ_BOARD_MIDR);
 busdev = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(busdev, _fatal);
+cpu = CORTEX_MPCORE_PRIV(dev)->cpu[0];
 sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE);
 sysbus_connect_irq(busdev, 0,
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
-- 
2.41.0




[PATCH 09/33] hw/cpu/arm: Merge {a9mpcore.h, a15mpcore.h} as cortex_mpcore.h

2023-12-12 Thread Philippe Mathieu-Daudé
Merge Cortex-A{9,15} MPCore devices in the same header.

Signed-off-by: Philippe Mathieu-Daudé 
---
 MAINTAINERS   |  3 +-
 include/hw/arm/aspeed_soc.h   |  2 +-
 include/hw/arm/exynos4210.h   |  2 +-
 include/hw/arm/fsl-imx6.h |  2 +-
 include/hw/arm/fsl-imx6ul.h   |  2 +-
 include/hw/arm/fsl-imx7.h |  2 +-
 include/hw/arm/npcm7xx.h  |  2 +-
 include/hw/cpu/a15mpcore.h| 44 ---
 .../hw/cpu/{a9mpcore.h => cortex_mpcore.h}| 29 
 hw/arm/exynos4210.c   |  2 +-
 hw/arm/highbank.c |  3 +-
 hw/arm/realview.c |  2 +-
 hw/arm/vexpress.c |  3 +-
 hw/arm/xilinx_zynq.c  |  2 +-
 hw/cpu/a15mpcore.c|  2 +-
 hw/cpu/a9mpcore.c |  2 +-
 16 files changed, 35 insertions(+), 69 deletions(-)
 delete mode 100644 include/hw/cpu/a15mpcore.h
 rename include/hw/cpu/{a9mpcore.h => cortex_mpcore.h} (57%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 695e0bd34f..8a37e5962f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -203,7 +203,8 @@ F: tests/tcg/aarch64/
 F: tests/qtest/arm-cpu-features.c
 F: hw/arm/
 F: hw/cpu/a*mpcore.c
-F: include/hw/cpu/a*mpcore.h
+F: include/hw/cpu/arm11mpcore.h
+F: include/hw/cpu/cortex_mpcore.h
 F: docs/system/target-arm.rst
 F: docs/system/arm/cpu-features.rst
 
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index cb832bc1ee..e0663ab50d 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -12,7 +12,7 @@
 #ifndef ASPEED_SOC_H
 #define ASPEED_SOC_H
 
-#include "hw/cpu/a15mpcore.h"
+#include "hw/cpu/cortex_mpcore.h"
 #include "hw/arm/armv7m.h"
 #include "hw/intc/aspeed_vic.h"
 #include "hw/misc/aspeed_scu.h"
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
index d33fe38586..f95e3232c5 100644
--- a/include/hw/arm/exynos4210.h
+++ b/include/hw/arm/exynos4210.h
@@ -26,7 +26,7 @@
 
 #include "hw/or-irq.h"
 #include "hw/sysbus.h"
-#include "hw/cpu/a9mpcore.h"
+#include "hw/cpu/cortex_mpcore.h"
 #include "hw/intc/exynos4210_gic.h"
 #include "hw/intc/exynos4210_combiner.h"
 #include "hw/core/split-irq.h"
diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
index 519b871014..21a3b035a4 100644
--- a/include/hw/arm/fsl-imx6.h
+++ b/include/hw/arm/fsl-imx6.h
@@ -17,7 +17,7 @@
 #ifndef FSL_IMX6_H
 #define FSL_IMX6_H
 
-#include "hw/cpu/a9mpcore.h"
+#include "hw/cpu/cortex_mpcore.h"
 #include "hw/misc/imx6_ccm.h"
 #include "hw/misc/imx6_src.h"
 #include "hw/misc/imx7_snvs.h"
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
index 14390f6014..5ed22004d1 100644
--- a/include/hw/arm/fsl-imx6ul.h
+++ b/include/hw/arm/fsl-imx6ul.h
@@ -17,7 +17,7 @@
 #ifndef FSL_IMX6UL_H
 #define FSL_IMX6UL_H
 
-#include "hw/cpu/a15mpcore.h"
+#include "hw/cpu/cortex_mpcore.h"
 #include "hw/misc/imx6ul_ccm.h"
 #include "hw/misc/imx6_src.h"
 #include "hw/misc/imx7_snvs.h"
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
index 411fa1c2e3..87faee33c2 100644
--- a/include/hw/arm/fsl-imx7.h
+++ b/include/hw/arm/fsl-imx7.h
@@ -19,7 +19,7 @@
 #ifndef FSL_IMX7_H
 #define FSL_IMX7_H
 
-#include "hw/cpu/a15mpcore.h"
+#include "hw/cpu/cortex_mpcore.h"
 #include "hw/intc/imx_gpcv2.h"
 #include "hw/misc/imx7_ccm.h"
 #include "hw/misc/imx7_snvs.h"
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 72c7722096..7abbf85cbf 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -19,7 +19,7 @@
 #include "hw/boards.h"
 #include "hw/adc/npcm7xx_adc.h"
 #include "hw/core/split-irq.h"
-#include "hw/cpu/a9mpcore.h"
+#include "hw/cpu/cortex_mpcore.h"
 #include "hw/gpio/npcm7xx_gpio.h"
 #include "hw/i2c/npcm7xx_smbus.h"
 #include "hw/mem/npcm7xx_mc.h"
diff --git a/include/hw/cpu/a15mpcore.h b/include/hw/cpu/a15mpcore.h
deleted file mode 100644
index 75d39e5458..00
--- a/include/hw/cpu/a15mpcore.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Cortex-A15MPCore internal peripheral emulation.
- *
- * Copyright (c) 2012 Linaro Limited.
- * Written by Peter Maydell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see .
- */
-#ifndef HW_CPU_A15MPCORE_H

[PATCH 08/33] hw/cpu/arm: Declare CPU QOM types using DEFINE_TYPES() macro

2023-12-12 Thread Philippe Mathieu-Daudé
When multiple QOM types are registered in the same file,
it is simpler to use the the DEFINE_TYPES() macro. In
particular because type array declared with such macro
are easier to review.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/cpu/a15mpcore.c   | 21 +
 hw/cpu/a9mpcore.c| 21 +
 hw/cpu/arm11mpcore.c | 21 +
 hw/cpu/realview_mpcore.c | 21 +
 4 files changed, 36 insertions(+), 48 deletions(-)

diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index a40f142128..c2ee985fb4 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -164,17 +164,14 @@ static void a15mp_priv_class_init(ObjectClass *klass, 
void *data)
 /* We currently have no saveable state */
 }
 
-static const TypeInfo a15mp_priv_info = {
-.name  = TYPE_A15MPCORE_PRIV,
-.parent = TYPE_SYS_BUS_DEVICE,
-.instance_size  = sizeof(A15MPPrivState),
-.instance_init = a15mp_priv_initfn,
-.class_init = a15mp_priv_class_init,
+static const TypeInfo a15mp_types[] = {
+{
+.name   = TYPE_A15MPCORE_PRIV,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size  = sizeof(A15MPPrivState),
+.instance_init  = a15mp_priv_initfn,
+.class_init = a15mp_priv_class_init,
+},
 };
 
-static void a15mp_register_types(void)
-{
-type_register_static(_priv_info);
-}
-
-type_init(a15mp_register_types)
+DEFINE_TYPES(a15mp_types)
diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
index d03f57e579..6b5ce01246 100644
--- a/hw/cpu/a9mpcore.c
+++ b/hw/cpu/a9mpcore.c
@@ -178,17 +178,14 @@ static void a9mp_priv_class_init(ObjectClass *klass, void 
*data)
 device_class_set_props(dc, a9mp_priv_properties);
 }
 
-static const TypeInfo a9mp_priv_info = {
-.name  = TYPE_A9MPCORE_PRIV,
-.parent= TYPE_SYS_BUS_DEVICE,
-.instance_size = sizeof(A9MPPrivState),
-.instance_init = a9mp_priv_initfn,
-.class_init= a9mp_priv_class_init,
+static const TypeInfo a9mp_types[] = {
+{
+.name   = TYPE_A9MPCORE_PRIV,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size  =  sizeof(A9MPPrivState),
+.instance_init  = a9mp_priv_initfn,
+.class_init = a9mp_priv_class_init,
+},
 };
 
-static void a9mp_register_types(void)
-{
-type_register_static(_priv_info);
-}
-
-type_init(a9mp_register_types)
+DEFINE_TYPES(a9mp_types)
diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c
index 89c4e35143..74f44434de 100644
--- a/hw/cpu/arm11mpcore.c
+++ b/hw/cpu/arm11mpcore.c
@@ -153,17 +153,14 @@ static void mpcore_priv_class_init(ObjectClass *klass, 
void *data)
 device_class_set_props(dc, mpcore_priv_properties);
 }
 
-static const TypeInfo mpcore_priv_info = {
-.name  = TYPE_ARM11MPCORE_PRIV,
-.parent= TYPE_SYS_BUS_DEVICE,
-.instance_size = sizeof(ARM11MPCorePriveState),
-.instance_init = mpcore_priv_initfn,
-.class_init= mpcore_priv_class_init,
+static const TypeInfo arm11mp_types[] = {
+{
+.name   = TYPE_ARM11MPCORE_PRIV,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size  = sizeof(ARM11MPCorePriveState),
+.instance_init  = mpcore_priv_initfn,
+.class_init = mpcore_priv_class_init,
+},
 };
 
-static void arm11mpcore_register_types(void)
-{
-type_register_static(_priv_info);
-}
-
-type_init(arm11mpcore_register_types)
+DEFINE_TYPES(arm11mp_types)
diff --git a/hw/cpu/realview_mpcore.c b/hw/cpu/realview_mpcore.c
index 7480b38d1a..b140888618 100644
--- a/hw/cpu/realview_mpcore.c
+++ b/hw/cpu/realview_mpcore.c
@@ -114,17 +114,14 @@ static void mpcore_rirq_class_init(ObjectClass *klass, 
void *data)
 dc->realize = realview_mpcore_realize;
 }
 
-static const TypeInfo mpcore_rirq_info = {
-.name  = TYPE_REALVIEW_MPCORE_RIRQ,
-.parent= TYPE_SYS_BUS_DEVICE,
-.instance_size = sizeof(mpcore_rirq_state),
-.instance_init = mpcore_rirq_init,
-.class_init= mpcore_rirq_class_init,
+static const TypeInfo realview_mpcore_types[] = {
+{
+.name   = TYPE_REALVIEW_MPCORE_RIRQ,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size  = sizeof(mpcore_rirq_state),
+.instance_init  = mpcore_rirq_init,
+.class_init = mpcore_rirq_class_init,
+},
 };
 
-static void realview_mpcore_register_types(void)
-{
-type_register_static(_rirq_info);
-}
-
-type_init(realview_mpcore_register_types)
+DEFINE_TYPES(realview_mpcore_types)
-- 
2.41.0




[PATCH 10/33] hw/cpu/arm: Introduce abstract CORTEX_MPCORE_PRIV QOM type

2023-12-12 Thread Philippe Mathieu-Daudé
This type will be common to A9MPCORE/A15MPCORE devices.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/cpu/cortex_mpcore.h | 21 +
 hw/cpu/cortex_mpcore.c | 22 ++
 hw/arm/Kconfig |  3 +++
 hw/cpu/meson.build |  1 +
 4 files changed, 47 insertions(+)
 create mode 100644 hw/cpu/cortex_mpcore.c

diff --git a/include/hw/cpu/cortex_mpcore.h b/include/hw/cpu/cortex_mpcore.h
index 9147f35c2a..c5dd7200d0 100644
--- a/include/hw/cpu/cortex_mpcore.h
+++ b/include/hw/cpu/cortex_mpcore.h
@@ -17,6 +17,27 @@
 #include "hw/timer/a9gtimer.h"
 #include "hw/timer/arm_mptimer.h"
 
+/*
+ * This is a model of the Arm Cortex-A MPCore family of hardware.
+ *
+ * The A7 and A15 MPCore contain:
+ *  up to 4 Cortex-A cores
+ *  a GIC
+ * The A9 MPCore additionally contains:
+ *  a System Control Unit
+ *  some timers and watchdogs
+ */
+#define TYPE_CORTEX_MPCORE_PRIV "cortex_mpcore_priv"
+OBJECT_DECLARE_TYPE(CortexMPPrivState, CortexMPPrivClass, CORTEX_MPCORE_PRIV)
+
+struct CortexMPPrivClass {
+SysBusDeviceClass parent_class;
+};
+
+struct CortexMPPrivState {
+SysBusDevice parent_obj;
+};
+
 #define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
 OBJECT_DECLARE_SIMPLE_TYPE(A9MPPrivState, A9MPCORE_PRIV)
 
diff --git a/hw/cpu/cortex_mpcore.c b/hw/cpu/cortex_mpcore.c
new file mode 100644
index 00..7d3796bd69
--- /dev/null
+++ b/hw/cpu/cortex_mpcore.c
@@ -0,0 +1,22 @@
+/*
+ * Cortex-MPCore internal peripheral emulation.
+ *
+ * Copyright (c) 2023 Linaro Limited.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/cpu/cortex_mpcore.h"
+
+static const TypeInfo cortex_mpcore_types[] = {
+{
+.name   = TYPE_CORTEX_MPCORE_PRIV,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size  = sizeof(CortexMPPrivState),
+.class_size = sizeof(CortexMPPrivClass),
+.abstract   = true,
+},
+};
+
+DEFINE_TYPES(cortex_mpcore_types)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 3ada335a24..3040342fcb 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -643,6 +643,9 @@ config ZAURUS
 select NAND
 select ECC
 
+config CORTEX_MPCORE
+bool
+
 config A9MPCORE
 bool
 select A9_GTIMER
diff --git a/hw/cpu/meson.build b/hw/cpu/meson.build
index 6d319947ca..8b376d6e7c 100644
--- a/hw/cpu/meson.build
+++ b/hw/cpu/meson.build
@@ -2,5 +2,6 @@ system_ss.add(files('core.c', 'cluster.c'))
 
 system_ss.add(when: 'CONFIG_ARM11MPCORE', if_true: files('arm11mpcore.c'))
 system_ss.add(when: 'CONFIG_REALVIEW', if_true: files('realview_mpcore.c'))
+specific_ss.add(when: 'CONFIG_CORTEX_MPCORE', if_true: 
files('cortex_mpcore.c'))
 specific_ss.add(when: 'CONFIG_A9MPCORE', if_true: files('a9mpcore.c'))
 specific_ss.add(when: 'CONFIG_A15MPCORE', if_true: files('a15mpcore.c'))
-- 
2.41.0




[PATCH 05/33] hw/cpu: Remove dead Kconfig

2023-12-12 Thread Philippe Mathieu-Daudé
ARM MPCore Kconfig are defined in hw/arm/Kconfig.
hw/cpu/Kconfig is never used, remove it.

Fixes: 82f5181777 ("kconfig: introduce kconfig files")
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/cpu/Kconfig | 8 
 1 file changed, 8 deletions(-)
 delete mode 100644 hw/cpu/Kconfig

diff --git a/hw/cpu/Kconfig b/hw/cpu/Kconfig
deleted file mode 100644
index 1767d028ac..00
--- a/hw/cpu/Kconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-config ARM11MPCORE
-bool
-
-config A9MPCORE
-bool
-
-config A15MPCORE
-bool
-- 
2.41.0




[PATCH 20/33] hw/cpu/arm: Consolidate check on max GIC spi supported

2023-12-12 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/cpu/cortex_mpcore.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/hw/cpu/cortex_mpcore.c b/hw/cpu/cortex_mpcore.c
index c9ba254818..75324268fa 100644
--- a/hw/cpu/cortex_mpcore.c
+++ b/hw/cpu/cortex_mpcore.c
@@ -43,6 +43,13 @@ static void cortex_mpcore_priv_realize(DeviceState *dev, 
Error **errp)
 CortexMPPrivClass *k = CORTEX_MPCORE_PRIV_GET_CLASS(dev);
 DeviceState *gicdev = DEVICE(>gic);
 
+if (s->gic_spi_num > k->gic_spi_max) {
+error_setg(errp,
+   "At most %u GIC SPI are supported (requested %u)",
+   k->gic_spi_max, s->gic_spi_num);
+return;
+}
+
 qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cores);
 qdev_prop_set_uint32(gicdev, "num-irq", s->gic_spi_num);
 if (k->gic_priority_bits) {
-- 
2.41.0




[PATCH 30/33] hw/arm/npcm7xx: Let the A9MPcore create/wire the CPU cores

2023-12-12 Thread Philippe Mathieu-Daudé
Set the properties on the mpcore object to let it create and
wire the CPU cores. Remove the redundant code.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/arm/npcm7xx.h |  1 -
 hw/arm/npcm7xx.c | 48 ++--
 2 files changed, 12 insertions(+), 37 deletions(-)

diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 7abbf85cbf..e0737fa4de 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -80,7 +80,6 @@ typedef struct NPCM7xxMachineClass {
 struct NPCM7xxState {
 DeviceState parent;
 
-ARMCPU  cpu[NPCM7XX_MAX_NUM_CPUS];
 A9MPPrivState   a9mpcore;
 
 MemoryRegionsram;
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 5b6e968fa9..1154a0f0a5 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -363,9 +363,11 @@ static struct arm_boot_info npcm7xx_binfo = {
 
 void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
 {
+CortexMPPrivState *mp = CORTEX_MPCORE_PRIV(>a9mpcore);
+
 npcm7xx_binfo.ram_size = machine->ram_size;
 
-arm_load_kernel(>cpu[0], machine, _binfo);
+arm_load_kernel(mp->cpu[0], machine, _binfo);
 }
 
 static void npcm7xx_init_fuses(NPCM7xxState *s)
@@ -400,11 +402,6 @@ static void npcm7xx_init(Object *obj)
 NPCM7xxState *s = NPCM7XX(obj);
 int i;
 
-for (i = 0; i < NPCM7XX_MAX_NUM_CPUS; i++) {
-object_initialize_child(obj, "cpu[*]", >cpu[i],
-ARM_CPU_TYPE_NAME("cortex-a9"));
-}
-
 object_initialize_child(obj, "a9mpcore", >a9mpcore, TYPE_A9MPCORE_PRIV);
 object_initialize_child(obj, "gcr", >gcr, TYPE_NPCM7XX_GCR);
 object_property_add_alias(obj, "power-on-straps", OBJECT(>gcr),
@@ -471,40 +468,19 @@ static void npcm7xx_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
-/* CPUs */
-for (i = 0; i < nc->num_cpus; i++) {
-object_property_set_int(OBJECT(>cpu[i]), "mp-affinity",
-arm_cpu_mp_affinity(i, NPCM7XX_MAX_NUM_CPUS),
-_abort);
-object_property_set_int(OBJECT(>cpu[i]), "reset-cbar",
-NPCM7XX_GIC_CPU_IF_ADDR, _abort);
-object_property_set_bool(OBJECT(>cpu[i]), "reset-hivecs", true,
- _abort);
-
-/* Disable security extensions. */
-object_property_set_bool(OBJECT(>cpu[i]), "has_el3", false,
- _abort);
-
-if (!qdev_realize(DEVICE(>cpu[i]), NULL, errp)) {
-return;
-}
-}
-
 /* A9MPCORE peripherals. Can only fail if we pass bad parameters here. */
-object_property_set_int(OBJECT(>a9mpcore), "num-cores", nc->num_cpus,
-_abort);
-object_property_set_int(OBJECT(>a9mpcore), "num-irq", NPCM7XX_NUM_IRQ,
-_abort);
+qdev_prop_set_uint32(DEVICE(>a9mpcore), "num-cores", nc->num_cpus);
+qdev_prop_set_string(DEVICE(>a9mpcore), "cpu-type",
+ ARM_CPU_TYPE_NAME("cortex-a9"));
+/* Disable security extensions. */
+qdev_prop_set_bit(DEVICE(>a9mpcore), "cpu-has-el3", false);
+qdev_prop_set_uint64(DEVICE(>a9mpcore), "cpu-reset-cbar",
+ NPCM7XX_GIC_CPU_IF_ADDR);
+qdev_prop_set_bit(DEVICE(>a9mpcore), "cpu-reset-hivecs", true);
+qdev_prop_set_uint32(DEVICE(>a9mpcore), "gic-spi-num", NPCM7XX_NUM_IRQ);
 sysbus_realize(SYS_BUS_DEVICE(>a9mpcore), _abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(>a9mpcore), 0, NPCM7XX_CPUP_BA);
 
-for (i = 0; i < nc->num_cpus; i++) {
-sysbus_connect_irq(SYS_BUS_DEVICE(>a9mpcore), i,
-   qdev_get_gpio_in(DEVICE(>cpu[i]), ARM_CPU_IRQ));
-sysbus_connect_irq(SYS_BUS_DEVICE(>a9mpcore), i + nc->num_cpus,
-   qdev_get_gpio_in(DEVICE(>cpu[i]), ARM_CPU_FIQ));
-}
-
 /* L2 cache controller */
 sysbus_create_simple("l2x0", NPCM7XX_L2C_BA, NULL);
 
-- 
2.41.0




[PATCH 19/33] hw/cpu/arm: Introduce TYPE_A7MPCORE_PRIV for Cortex-A7 MPCore

2023-12-12 Thread Philippe Mathieu-Daudé
For QEMU modelling, the only difference between the A15 and A7
MPCore is the latter can have up to 480 SPIs.

In particular, since commit b151de69f6 ("hw/arm: ast2600: Set
AST2600_MAX_IRQ to value from datasheet") the AST2600 machine
initializes its GIC with 256 SPIs, which is more than the 224
maximum of the A15.

Since the A7 was not available, few boards were using the A15.
Replace them by a A7 MPCore.

Signed-off-by: Philippe Mathieu-Daudé 
---
The comment in a7mp_priv_class_init() is a bit off.
---
 include/hw/cpu/cortex_mpcore.h |  2 ++
 hw/arm/aspeed_ast2600.c|  3 +--
 hw/arm/fsl-imx6ul.c|  3 +--
 hw/arm/fsl-imx7.c  |  3 +--
 hw/cpu/a15mpcore.c | 30 ++
 5 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/include/hw/cpu/cortex_mpcore.h b/include/hw/cpu/cortex_mpcore.h
index 7822d5cbc4..4e1aa9f7f7 100644
--- a/include/hw/cpu/cortex_mpcore.h
+++ b/include/hw/cpu/cortex_mpcore.h
@@ -118,4 +118,6 @@ struct A9MPPrivState {
 
 #define TYPE_A15MPCORE_PRIV "a15mpcore_priv"
 
+#define TYPE_A7MPCORE_PRIV "a7mpcore_priv"
+
 #endif
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index ca788e1cf0..88e2a23514 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -171,8 +171,7 @@ static void aspeed_soc_ast2600_init(Object *obj)
 object_property_add_alias(obj, "hw-prot-key", OBJECT(>scu),
   "hw-prot-key");
 
-object_initialize_child(obj, "a7mpcore", >a7mpcore,
-TYPE_A15MPCORE_PRIV);
+object_initialize_child(obj, "a7mpcore", >a7mpcore, TYPE_A7MPCORE_PRIV);
 
 object_initialize_child(obj, "rtc", >rtc, TYPE_ASPEED_RTC);
 
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
index 93908811c5..6e4343efaa 100644
--- a/hw/arm/fsl-imx6ul.c
+++ b/hw/arm/fsl-imx6ul.c
@@ -40,8 +40,7 @@ static void fsl_imx6ul_init(Object *obj)
 /*
  * A7MPCORE
  */
-object_initialize_child(obj, "a7mpcore", >a7mpcore,
-TYPE_A15MPCORE_PRIV);
+object_initialize_child(obj, "a7mpcore", >a7mpcore, TYPE_A7MPCORE_PRIV);
 
 /*
  * CCM
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index 8a3e9933c4..bd9266b8b5 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -48,8 +48,7 @@ static void fsl_imx7_init(Object *obj)
 /*
  * A7MPCORE
  */
-object_initialize_child(obj, "a7mpcore", >a7mpcore,
-TYPE_A15MPCORE_PRIV);
+object_initialize_child(obj, "a7mpcore", >a7mpcore, TYPE_A7MPCORE_PRIV);
 
 /*
  * GPIOs
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index 87b0786781..5f28a97adb 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -121,6 +121,30 @@ static void a15mp_priv_class_init(ObjectClass *klass, void 
*data)
 /* We currently have no saveable state */
 }
 
+static void a7mp_priv_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+CortexMPPrivClass *cc = CORTEX_MPCORE_PRIV_CLASS(klass);
+
+cc->container_size = 0x8000;
+
+cc->gic_class_name = gic_class_name();
+cc->gic_revision = 2;
+/*
+ * The Cortex-A7MP may have anything from 0 to 480 external interrupt
+ * IRQ lines (with another 32 internal). We default to 128+32, which
+ * is the number provided by the Cortex-A15MP test chip in the
+ * Versatile Express A15 development board.
+ * Other boards may differ and should set this property appropriately.
+ */
+cc->gic_spi_default = 160;
+cc->gic_spi_max = 480;
+
+device_class_set_parent_realize(dc, a15mp_priv_realize,
+>parent_realize);
+/* We currently have no saveable state */
+}
+
 static const TypeInfo a15mp_types[] = {
 {
 .name   = TYPE_A15MPCORE_PRIV,
@@ -128,6 +152,12 @@ static const TypeInfo a15mp_types[] = {
 .instance_size  = sizeof(CortexMPPrivState),
 .class_init = a15mp_priv_class_init,
 },
+{
+.name   = TYPE_A7MPCORE_PRIV,
+.parent = TYPE_CORTEX_MPCORE_PRIV,
+.instance_size  = sizeof(CortexMPPrivState),
+.class_init = a7mp_priv_class_init,
+},
 };
 
 DEFINE_TYPES(a15mp_types)
-- 
2.41.0




[PATCH 16/33] hw/cpu/arm: Handle GIC once in MPCore parent

2023-12-12 Thread Philippe Mathieu-Daudé
Move the GIC instance creation to the abstract QOM parent.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/cpu/cortex_mpcore.h | 31 +--
 hw/cpu/a15mpcore.c | 56 --
 hw/cpu/a9mpcore.c  | 43 +-
 hw/cpu/cortex_mpcore.c | 46 
 hw/arm/Kconfig |  3 +-
 5 files changed, 88 insertions(+), 91 deletions(-)

diff --git a/include/hw/cpu/cortex_mpcore.h b/include/hw/cpu/cortex_mpcore.h
index 96da713be9..4697fd47c7 100644
--- a/include/hw/cpu/cortex_mpcore.h
+++ b/include/hw/cpu/cortex_mpcore.h
@@ -34,6 +34,28 @@
  *have the exception level features present.
  *  + QOM property "gic-spi-num" sets the number of GIC Shared Peripheral
  *Interrupts.
+ * QEMU interface forwarded from the GIC:
+ *  + unnamed GPIO inputs: (where P is number of GIC SPIs, i.e. num-irq - 32)
+ *[0..P-1]  GIC SPIs
+ *[P..P+31] PPIs for CPU 0
+ *[P+32..P+63] PPIs for CPU 1
+ *...
+ *  + sysbus output IRQs: (in order; number will vary depending on number of
+ *cores)
+ *- IRQ for CPU 0
+ *- IRQ for CPU 1
+ *  ...
+ *- FIQ for CPU 0
+ *- FIQ for CPU 1
+ *  ...
+ *- VIRQ for CPU 0 (exists even if virt extensions not present)
+ *- VIRQ for CPU 1 (exists even if virt extensions not present)
+ *  ...
+ *- VFIQ for CPU 0 (exists even if virt extensions not present)
+ *- VFIQ for CPU 1 (exists even if virt extensions not present)
+ *  ...
+ *- maintenance IRQ for CPU i/f 0 (only if virt extensions present)
+ *- maintenance IRQ for CPU i/f 1 (only if virt extensions present)
  */
 #define TYPE_CORTEX_MPCORE_PRIV "cortex_mpcore_priv"
 OBJECT_DECLARE_TYPE(CortexMPPrivState, CortexMPPrivClass, CORTEX_MPCORE_PRIV)
@@ -41,8 +63,10 @@ OBJECT_DECLARE_TYPE(CortexMPPrivState, CortexMPPrivClass, 
CORTEX_MPCORE_PRIV)
 /**
  * CortexMPPrivClass:
  * @container_size - size of the device's MMIO region
+ * @gic_class_name - GIC QOM class name
  * @gic_spi_default - default number of GIC SPIs
  * @gic_spi_max - maximum number of GIC SPIs
+ * @gic_revision - revision of the GIC
  */
 struct CortexMPPrivClass {
 SysBusDeviceClass parent_class;
@@ -51,14 +75,18 @@ struct CortexMPPrivClass {
 
 uint64_t container_size;
 
+const char *gic_class_name;
 unsigned gic_spi_default;
 unsigned gic_spi_max;
+unsigned gic_revision;
+uint32_t gic_priority_bits;
 };
 
 struct CortexMPPrivState {
 SysBusDevice parent_obj;
 
 MemoryRegion container;
+GICState gic;
 
 /* Properties */
 uint32_t num_cores;
@@ -76,7 +104,6 @@ struct A9MPPrivState {
 CortexMPPrivState parent_obj;
 
 A9SCUState scu;
-GICState gic;
 A9GTimerState gtimer;
 ARMMPTimerState mptimer;
 ARMMPTimerState wdt;
@@ -87,8 +114,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(A15MPPrivState, A15MPCORE_PRIV)
 
 struct A15MPPrivState {
 CortexMPPrivState parent_obj;
-
-GICState gic;
 };
 
 #endif
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index 195355b589..ecd04b7af1 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -22,34 +22,15 @@
 #include "qapi/error.h"
 #include "qemu/module.h"
 #include "hw/cpu/cortex_mpcore.h"
-#include "hw/irq.h"
-#include "hw/qdev-properties.h"
-#include "sysemu/kvm.h"
-#include "kvm_arm.h"
-
-static void a15mp_priv_set_irq(void *opaque, int irq, int level)
-{
-A15MPPrivState *s = (A15MPPrivState *)opaque;
-
-qemu_set_irq(qdev_get_gpio_in(DEVICE(>gic), irq), level);
-}
-
-static void a15mp_priv_initfn(Object *obj)
-{
-A15MPPrivState *s = A15MPCORE_PRIV(obj);
-
-object_initialize_child(obj, "gic", >gic, gic_class_name());
-qdev_prop_set_uint32(DEVICE(>gic), "revision", 2);
-}
+#include "hw/core/cpu.h"
+#include "target/arm/cpu.h"
 
 static void a15mp_priv_realize(DeviceState *dev, Error **errp)
 {
 CortexMPPrivClass *cc = CORTEX_MPCORE_PRIV_GET_CLASS(dev);
-SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
-A15MPPrivState *s = A15MPCORE_PRIV(dev);
 CortexMPPrivState *c = CORTEX_MPCORE_PRIV(dev);
-DeviceState *gicdev;
-SysBusDevice *gicsbd;
+DeviceState *gicdev = DEVICE(>gic);
+SysBusDevice *gicsbd = SYS_BUS_DEVICE(>gic);
 Error *local_err = NULL;
 int i;
 
@@ -59,32 +40,6 @@ static void a15mp_priv_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
-gicdev = DEVICE(>gic);
-qdev_prop_set_uint32(gicdev, "num-cpu", c->num_cores);
-qdev_prop_set_uint32(gicdev, "num-irq", c->gic_spi_num);
-
-if (!kvm_irqchip_in_kernel()) {
-/* Make the GIC's TZ support match the CPUs. We assume that
- * either all the CPUs have TZ, or none do.
- */
-qdev_prop_set_bit(gicdev, "has-security-extensions",
-  c->cpu_has_el3);
-/* Similarly for virtualization support */
-qdev_prop_set_bit(gicdev, "has-virtualization-extensions",
-  

[PATCH 11/33] hw/cpu/arm: Have A9MPCORE/A15MPCORE inheritate common CORTEX_MPCORE_PRIV

2023-12-12 Thread Philippe Mathieu-Daudé
TYPE_CORTEX_MPCORE_PRIV becomes the common parent to
TYPE_A9MPCORE_PRIV and TYPE_A15MPCORE_PRIV.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/cpu/cortex_mpcore.h |  6 --
 hw/cpu/a15mpcore.c | 14 --
 hw/cpu/a9mpcore.c  | 13 +++--
 hw/arm/Kconfig |  2 ++
 4 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/include/hw/cpu/cortex_mpcore.h b/include/hw/cpu/cortex_mpcore.h
index c5dd7200d0..4084c6003a 100644
--- a/include/hw/cpu/cortex_mpcore.h
+++ b/include/hw/cpu/cortex_mpcore.h
@@ -32,6 +32,8 @@ OBJECT_DECLARE_TYPE(CortexMPPrivState, CortexMPPrivClass, 
CORTEX_MPCORE_PRIV)
 
 struct CortexMPPrivClass {
 SysBusDeviceClass parent_class;
+
+DeviceRealize parent_realize;
 };
 
 struct CortexMPPrivState {
@@ -42,7 +44,7 @@ struct CortexMPPrivState {
 OBJECT_DECLARE_SIMPLE_TYPE(A9MPPrivState, A9MPCORE_PRIV)
 
 struct A9MPPrivState {
-SysBusDevice parent_obj;
+CortexMPPrivState parent_obj;
 
 uint32_t num_cpu;
 MemoryRegion container;
@@ -59,7 +61,7 @@ struct A9MPPrivState {
 OBJECT_DECLARE_SIMPLE_TYPE(A15MPPrivState, A15MPCORE_PRIV)
 
 struct A15MPPrivState {
-SysBusDevice parent_obj;
+CortexMPPrivState parent_obj;
 
 uint32_t num_cpu;
 uint32_t num_irq;
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index 0f56c40b86..5a57145179 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -48,15 +48,23 @@ static void a15mp_priv_initfn(Object *obj)
 
 static void a15mp_priv_realize(DeviceState *dev, Error **errp)
 {
+CortexMPPrivClass *cc = CORTEX_MPCORE_PRIV_GET_CLASS(dev);
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 A15MPPrivState *s = A15MPCORE_PRIV(dev);
 DeviceState *gicdev;
 SysBusDevice *gicsbd;
+Error *local_err = NULL;
 int i;
 bool has_el3;
 bool has_el2 = false;
 Object *cpuobj;
 
+cc->parent_realize(dev, _err);
+if (local_err) {
+error_propagate(errp, local_err);
+return;
+}
+
 gicdev = DEVICE(>gic);
 qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
 qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
@@ -158,8 +166,10 @@ static Property a15mp_priv_properties[] = {
 static void a15mp_priv_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
+CortexMPPrivClass *cc = CORTEX_MPCORE_PRIV_CLASS(klass);
 
-dc->realize = a15mp_priv_realize;
+device_class_set_parent_realize(dc, a15mp_priv_realize,
+>parent_realize);
 device_class_set_props(dc, a15mp_priv_properties);
 /* We currently have no saveable state */
 }
@@ -167,7 +177,7 @@ static void a15mp_priv_class_init(ObjectClass *klass, void 
*data)
 static const TypeInfo a15mp_types[] = {
 {
 .name   = TYPE_A15MPCORE_PRIV,
-.parent = TYPE_SYS_BUS_DEVICE,
+.parent = TYPE_CORTEX_MPCORE_PRIV,
 .instance_size  = sizeof(A15MPPrivState),
 .instance_init  = a15mp_priv_initfn,
 .class_init = a15mp_priv_class_init,
diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
index e9cd71e92f..d59e49126b 100644
--- a/hw/cpu/a9mpcore.c
+++ b/hw/cpu/a9mpcore.c
@@ -46,11 +46,13 @@ static void a9mp_priv_initfn(Object *obj)
 
 static void a9mp_priv_realize(DeviceState *dev, Error **errp)
 {
+CortexMPPrivClass *cc = CORTEX_MPCORE_PRIV_GET_CLASS(dev);
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 A9MPPrivState *s = A9MPCORE_PRIV(dev);
 DeviceState *scudev, *gicdev, *gtimerdev, *mptimerdev, *wdtdev;
 SysBusDevice *scubusdev, *gicbusdev, *gtimerbusdev, *mptimerbusdev,
  *wdtbusdev;
+Error *local_err = NULL;
 int i;
 bool has_el3;
 CPUState *cpu0;
@@ -65,6 +67,12 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
 return;
 }
 
+cc->parent_realize(dev, _err);
+if (local_err) {
+error_propagate(errp, local_err);
+return;
+}
+
 scudev = DEVICE(>scu);
 qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
 if (!sysbus_realize(SYS_BUS_DEVICE(>scu), errp)) {
@@ -173,15 +181,16 @@ static Property a9mp_priv_properties[] = {
 static void a9mp_priv_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
+CortexMPPrivClass *cc = CORTEX_MPCORE_PRIV_CLASS(klass);
 
-dc->realize = a9mp_priv_realize;
+device_class_set_parent_realize(dc, a9mp_priv_realize, 
>parent_realize);
 device_class_set_props(dc, a9mp_priv_properties);
 }
 
 static const TypeInfo a9mp_types[] = {
 {
 .name   = TYPE_A9MPCORE_PRIV,
-.parent = TYPE_SYS_BUS_DEVICE,
+.parent = TYPE_CORTEX_MPCORE_PRIV,
 .instance_size  =  sizeof(A9MPPrivState),
 .instance_init  = a9mp_priv_initfn,
 .class_init = a9mp_priv_class_init,
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 3040342fcb..ec6e585797 100644
--- a/hw/arm/Kconfig

[PATCH 07/33] hw/cpu/arm: Alias 'num-cpu' property on TYPE_REALVIEW_MPCORE

2023-12-12 Thread Philippe Mathieu-Daudé
No need to duplicate and forward the 'num-cpu' property from
TYPE_ARM11MPCORE_PRIV to TYPE_REALVIEW_MPCORE, alias it with
QOM object_property_add_alias().

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/cpu/realview_mpcore.c | 9 +
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/hw/cpu/realview_mpcore.c b/hw/cpu/realview_mpcore.c
index 72c792eef1..7480b38d1a 100644
--- a/hw/cpu/realview_mpcore.c
+++ b/hw/cpu/realview_mpcore.c
@@ -14,7 +14,6 @@
 #include "hw/cpu/arm11mpcore.h"
 #include "hw/intc/realview_gic.h"
 #include "hw/irq.h"
-#include "hw/qdev-properties.h"
 #include "qom/object.h"
 
 #define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore"
@@ -68,7 +67,6 @@ static void realview_mpcore_realize(DeviceState *dev, Error 
**errp)
 int n;
 int i;
 
-qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
 if (!sysbus_realize(SYS_BUS_DEVICE(>priv), errp)) {
 return;
 }
@@ -100,6 +98,7 @@ static void mpcore_rirq_init(Object *obj)
 int i;
 
 object_initialize_child(obj, "a11priv", >priv, TYPE_ARM11MPCORE_PRIV);
+object_property_add_alias(obj, "num-cpu", OBJECT(>priv), "num-cpu");
 privbusdev = SYS_BUS_DEVICE(>priv);
 sysbus_init_mmio(sbd, sysbus_mmio_get_region(privbusdev, 0));
 
@@ -108,17 +107,11 @@ static void mpcore_rirq_init(Object *obj)
 }
 }
 
-static Property mpcore_rirq_properties[] = {
-DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
-DEFINE_PROP_END_OF_LIST(),
-};
-
 static void mpcore_rirq_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 
 dc->realize = realview_mpcore_realize;
-device_class_set_props(dc, mpcore_rirq_properties);
 }
 
 static const TypeInfo mpcore_rirq_info = {
-- 
2.41.0




[PATCH 15/33] hw/cpu/arm: Handle 'gic-irq' property once in MPCore parent

2023-12-12 Thread Philippe Mathieu-Daudé
Move the 'num-irq' property to the abstract QOM parent.
Rename it as 'gic-irq', keeping it aliased as 'num-irq'.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/cpu/cortex_mpcore.h | 13 +
 hw/cpu/a15mpcore.c | 28 +---
 hw/cpu/a9mpcore.c  | 28 +---
 hw/cpu/cortex_mpcore.c |  5 +
 4 files changed, 40 insertions(+), 34 deletions(-)

diff --git a/include/hw/cpu/cortex_mpcore.h b/include/hw/cpu/cortex_mpcore.h
index 387552468c..96da713be9 100644
--- a/include/hw/cpu/cortex_mpcore.h
+++ b/include/hw/cpu/cortex_mpcore.h
@@ -32,6 +32,8 @@
  *the cluster.
  *  + QOM properties "cpu-has-el3", "cpu-has-el2" which set whether the CPUs
  *have the exception level features present.
+ *  + QOM property "gic-spi-num" sets the number of GIC Shared Peripheral
+ *Interrupts.
  */
 #define TYPE_CORTEX_MPCORE_PRIV "cortex_mpcore_priv"
 OBJECT_DECLARE_TYPE(CortexMPPrivState, CortexMPPrivClass, CORTEX_MPCORE_PRIV)
@@ -39,6 +41,8 @@ OBJECT_DECLARE_TYPE(CortexMPPrivState, CortexMPPrivClass, 
CORTEX_MPCORE_PRIV)
 /**
  * CortexMPPrivClass:
  * @container_size - size of the device's MMIO region
+ * @gic_spi_default - default number of GIC SPIs
+ * @gic_spi_max - maximum number of GIC SPIs
  */
 struct CortexMPPrivClass {
 SysBusDeviceClass parent_class;
@@ -46,6 +50,9 @@ struct CortexMPPrivClass {
 DeviceRealize parent_realize;
 
 uint64_t container_size;
+
+unsigned gic_spi_default;
+unsigned gic_spi_max;
 };
 
 struct CortexMPPrivState {
@@ -58,6 +65,8 @@ struct CortexMPPrivState {
 
 bool cpu_has_el3;
 bool cpu_has_el2;
+
+uint32_t gic_spi_num;
 };
 
 #define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
@@ -66,8 +75,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(A9MPPrivState, A9MPCORE_PRIV)
 struct A9MPPrivState {
 CortexMPPrivState parent_obj;
 
-uint32_t num_irq;
-
 A9SCUState scu;
 GICState gic;
 A9GTimerState gtimer;
@@ -81,8 +88,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(A15MPPrivState, A15MPCORE_PRIV)
 struct A15MPPrivState {
 CortexMPPrivState parent_obj;
 
-uint32_t num_irq;
-
 GICState gic;
 };
 
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index a16544fdde..195355b589 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -61,7 +61,7 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
 
 gicdev = DEVICE(>gic);
 qdev_prop_set_uint32(gicdev, "num-cpu", c->num_cores);
-qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
+qdev_prop_set_uint32(gicdev, "num-irq", c->gic_spi_num);
 
 if (!kvm_irqchip_in_kernel()) {
 /* Make the GIC's TZ support match the CPUs. We assume that
@@ -83,14 +83,14 @@ static void a15mp_priv_realize(DeviceState *dev, Error 
**errp)
 sysbus_pass_irq(sbd, gicsbd);
 
 /* Pass through inbound GPIO lines to the GIC */
-qdev_init_gpio_in(dev, a15mp_priv_set_irq, s->num_irq - 32);
+qdev_init_gpio_in(dev, a15mp_priv_set_irq, c->gic_spi_num - 32);
 
 /* Wire the outputs from each CPU's generic timer to the
  * appropriate GIC PPI inputs
  */
 for (i = 0; i < c->num_cores; i++) {
 DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
-int ppibase = s->num_irq - 32 + i * 32;
+int ppibase = c->gic_spi_num - 32 + i * 32;
 int irq;
 /* Mapping from the output timer irq lines from the CPU to the
  * GIC PPI inputs used on the A15:
@@ -142,17 +142,6 @@ static void a15mp_priv_realize(DeviceState *dev, Error 
**errp)
 }
 }
 
-static Property a15mp_priv_properties[] = {
-/* The Cortex-A15MP may have anything from 0 to 224 external interrupt
- * IRQ lines (with another 32 internal). We default to 128+32, which
- * is the number provided by the Cortex-A15MP test chip in the
- * Versatile Express A15 development board.
- * Other boards may differ and should set this property appropriately.
- */
-DEFINE_PROP_UINT32("num-irq", A15MPPrivState, num_irq, 160),
-DEFINE_PROP_END_OF_LIST(),
-};
-
 static void a15mp_priv_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -160,9 +149,18 @@ static void a15mp_priv_class_init(ObjectClass *klass, void 
*data)
 
 cc->container_size = 0x8000;
 
+/*
+ * The Cortex-A15MP may have anything from 0 to 224 external interrupt
+ * IRQ lines (with another 32 internal). We default to 128+32, which
+ * is the number provided by the Cortex-A15MP test chip in the
+ * Versatile Express A15 development board.
+ * Other boards may differ and should set this property appropriately.
+ */
+cc->gic_spi_default = 160;
+cc->gic_spi_max = 224;
+
 device_class_set_parent_realize(dc, a15mp_priv_realize,
 >parent_realize);
-device_class_set_props(dc, a15mp_priv_properties);
 /* We currently have no saveable state */
 }
 
diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
index 

[PATCH 14/33] hw/cpu/arm: Handle 'has_el2/3' properties once in MPCore parent

2023-12-12 Thread Philippe Mathieu-Daudé
Move the 'has_el2' and 'has_el3' properties to the abstract
QOM parent.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/cpu/cortex_mpcore.h |  5 +
 hw/arm/exynos4210.c| 10 --
 hw/arm/vexpress.c  |  6 ++
 hw/arm/xilinx_zynq.c   |  6 ++
 hw/cpu/a15mpcore.c | 18 ++
 hw/cpu/a9mpcore.c  |  5 +
 hw/cpu/cortex_mpcore.c |  3 +++
 7 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/include/hw/cpu/cortex_mpcore.h b/include/hw/cpu/cortex_mpcore.h
index 0e7cca9e93..387552468c 100644
--- a/include/hw/cpu/cortex_mpcore.h
+++ b/include/hw/cpu/cortex_mpcore.h
@@ -30,6 +30,8 @@
  * QEMU interface:
  *  + QOM property "num-cores" which set the number of cores present in
  *the cluster.
+ *  + QOM properties "cpu-has-el3", "cpu-has-el2" which set whether the CPUs
+ *have the exception level features present.
  */
 #define TYPE_CORTEX_MPCORE_PRIV "cortex_mpcore_priv"
 OBJECT_DECLARE_TYPE(CortexMPPrivState, CortexMPPrivClass, CORTEX_MPCORE_PRIV)
@@ -53,6 +55,9 @@ struct CortexMPPrivState {
 
 /* Properties */
 uint32_t num_cores;
+
+bool cpu_has_el3;
+bool cpu_has_el2;
 };
 
 #define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index ea1364499d..7386a8fe57 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -548,7 +548,7 @@ static void exynos4210_realize(DeviceState *socdev, Error 
**errp)
 Exynos4210State *s = EXYNOS4210_SOC(socdev);
 MemoryRegion *system_mem = get_system_memory();
 SysBusDevice *busdev;
-DeviceState *dev, *uart[4], *pl330[3];
+DeviceState *dev, *mpdev, *uart[4], *pl330[3];
 int i, n;
 
 for (n = 0; n < EXYNOS4210_NCPUS; n++) {
@@ -582,7 +582,13 @@ static void exynos4210_realize(DeviceState *socdev, Error 
**errp)
 }
 
 /* Private memory region and Internal GIC */
-qdev_prop_set_uint32(DEVICE(>a9mpcore), "num-cores", EXYNOS4210_NCPUS);
+mpdev = DEVICE(>a9mpcore);
+qdev_prop_set_uint32(mpdev, "num-cores", EXYNOS4210_NCPUS);
+/*
+ * By default A9 CPUs have EL3 enabled.  This board does not currently
+ * support EL3 so the CPU EL3 property is disabled before realization.
+ */
+qdev_prop_set_bit(mpdev, "cpu-has-el3", false);
 busdev = SYS_BUS_DEVICE(>a9mpcore);
 sysbus_realize(busdev, _fatal);
 sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index a320d1c181..294b6f15f2 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -239,6 +239,12 @@ static void init_cpus(MachineState *ms, const char 
*cpu_type,
  * wires itself up to the CPU's generic_timer gpio out lines.
  */
 dev = qdev_new(privdev);
+if (!secure) {
+qdev_prop_set_bit(dev, "cpu-has-el3", false);
+}
+if (!virt) {
+qdev_prop_set_bit(dev, "cpu-has-el2", false);
+}
 qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
 busdev = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(busdev, _fatal);
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index fc9c927d09..28430dcfba 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -240,6 +240,12 @@ static void zynq_init(MachineState *machine)
 
 dev = qdev_new(TYPE_A9MPCORE_PRIV);
 qdev_prop_set_uint32(dev, "num-cpu", 1);
+/*
+ * By default A9 CPUs have EL3 enabled.  This board does not
+ * currently support EL3 so the CPU EL3 property is disabled before
+ * realization.
+ */
+qdev_prop_set_bit(dev, "cpu-has-el3", false);
 busdev = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(busdev, _fatal);
 sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE);
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index 16874426e1..a16544fdde 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -52,9 +52,6 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
 SysBusDevice *gicsbd;
 Error *local_err = NULL;
 int i;
-bool has_el3;
-bool has_el2 = false;
-Object *cpuobj;
 
 cc->parent_realize(dev, _err);
 if (local_err) {
@@ -70,14 +67,11 @@ static void a15mp_priv_realize(DeviceState *dev, Error 
**errp)
 /* Make the GIC's TZ support match the CPUs. We assume that
  * either all the CPUs have TZ, or none do.
  */
-cpuobj = OBJECT(qemu_get_cpu(0));
-has_el3 = object_property_find(cpuobj, "has_el3") &&
-object_property_get_bool(cpuobj, "has_el3", _abort);
-qdev_prop_set_bit(gicdev, "has-security-extensions", has_el3);
+qdev_prop_set_bit(gicdev, "has-security-extensions",
+  c->cpu_has_el3);
 /* Similarly for virtualization support */
-has_el2 = object_property_find(cpuobj, "has_el2") &&
-object_property_get_bool(cpuobj, "has_el2", _abort);
-qdev_prop_set_bit(gicdev, "has-virtualization-extensions", has_el2);

[PATCH 17/33] hw/cpu/arm: Document more properties of CORTEX_MPCORE_PRIV QOM type

2023-12-12 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/cpu/cortex_mpcore.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/hw/cpu/cortex_mpcore.h b/include/hw/cpu/cortex_mpcore.h
index 4697fd47c7..73627bc415 100644
--- a/include/hw/cpu/cortex_mpcore.h
+++ b/include/hw/cpu/cortex_mpcore.h
@@ -28,10 +28,17 @@
  *  some timers and watchdogs
  *
  * QEMU interface:
+ *  + QOM property "cluster-id" which set the cluster ID and its affinity.
  *  + QOM property "num-cores" which set the number of cores present in
  *the cluster.
+ *  + QOM property "cpu-type" is the CPU model typename.
  *  + QOM properties "cpu-has-el3", "cpu-has-el2" which set whether the CPUs
  *have the exception level features present.
+ *  + QOM properties "cpu-has-vfp-d32", "cpu-has-neon" which set whether the
+ *CPUs have the FPU features present.
+ *  + QOM property "cpu-freq-hz" is the frequency of each core
+ *  + QOM property "cpu-memory" is a MemoryRegion containing the devices
+ *provided by the board model.
  *  + QOM property "gic-spi-num" sets the number of GIC Shared Peripheral
  *Interrupts.
  * QEMU interface forwarded from the GIC:
-- 
2.41.0




[PATCH 04/33] hw/arm/fsl-imx7: Add a local 'gic' variable

2023-12-12 Thread Philippe Mathieu-Daudé
The A7MPCore forward the IRQs from its internal GIC.
To make the code clearer, add a 'gic' variable.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/fsl-imx7.c | 38 +-
 1 file changed, 17 insertions(+), 21 deletions(-)

diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index 474cfdc87c..a283dcb45f 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -163,6 +163,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
 {
 MachineState *ms = MACHINE(qdev_get_machine());
 FslIMX7State *s = FSL_IMX7(dev);
+DeviceState *gic;
 Object *o;
 int i;
 qemu_irq irq;
@@ -209,6 +210,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
 
 sysbus_realize(SYS_BUS_DEVICE(>a7mpcore), _abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(>a7mpcore), 0, FSL_IMX7_A7MPCORE_ADDR);
+gic = DEVICE(>a7mpcore);
 
 for (i = 0; i < smp_cpus; i++) {
 SysBusDevice *sbd = SYS_BUS_DEVICE(>a7mpcore);
@@ -252,8 +254,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
 sysbus_realize(SYS_BUS_DEVICE(>gpt[i]), _abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(>gpt[i]), 0, FSL_IMX7_GPTn_ADDR[i]);
 sysbus_connect_irq(SYS_BUS_DEVICE(>gpt[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX7_GPTn_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX7_GPTn_IRQ[i]));
 }
 
 /*
@@ -295,12 +296,10 @@ static void fsl_imx7_realize(DeviceState *dev, Error 
**errp)
 FSL_IMX7_GPIOn_ADDR[i]);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>gpio[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX7_GPIOn_LOW_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX7_GPIOn_LOW_IRQ[i]));
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>gpio[i]), 1,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX7_GPIOn_HIGH_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX7_GPIOn_HIGH_IRQ[i]));
 }
 
 /*
@@ -352,8 +351,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(>spi[i]), 0,
 FSL_IMX7_SPIn_ADDR[i]);
 sysbus_connect_irq(SYS_BUS_DEVICE(>spi[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX7_SPIn_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX7_SPIn_IRQ[i]));
 }
 
 /*
@@ -378,8 +376,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(>i2c[i]), 0, FSL_IMX7_I2Cn_ADDR[i]);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>i2c[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX7_I2Cn_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX7_I2Cn_IRQ[i]));
 }
 
 /*
@@ -413,7 +410,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
 
 sysbus_mmio_map(SYS_BUS_DEVICE(>uart[i]), 0, 
FSL_IMX7_UARTn_ADDR[i]);
 
-irq = qdev_get_gpio_in(DEVICE(>a7mpcore), FSL_IMX7_UARTn_IRQ[i]);
+irq = qdev_get_gpio_in(gic, FSL_IMX7_UARTn_IRQ[i]);
 sysbus_connect_irq(SYS_BUS_DEVICE(>uart[i]), 0, irq);
 }
 
@@ -451,9 +448,9 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
 
 sysbus_mmio_map(SYS_BUS_DEVICE(>eth[i]), 0, FSL_IMX7_ENETn_ADDR[i]);
 
-irq = qdev_get_gpio_in(DEVICE(>a7mpcore), FSL_IMX7_ENET_IRQ(i, 0));
+irq = qdev_get_gpio_in(gic, FSL_IMX7_ENET_IRQ(i, 0));
 sysbus_connect_irq(SYS_BUS_DEVICE(>eth[i]), 0, irq);
-irq = qdev_get_gpio_in(DEVICE(>a7mpcore), FSL_IMX7_ENET_IRQ(i, 3));
+irq = qdev_get_gpio_in(gic, FSL_IMX7_ENET_IRQ(i, 3));
 sysbus_connect_irq(SYS_BUS_DEVICE(>eth[i]), 1, irq);
 }
 
@@ -480,7 +477,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(>usdhc[i]), 0,
 FSL_IMX7_USDHCn_ADDR[i]);
 
-irq = qdev_get_gpio_in(DEVICE(>a7mpcore), FSL_IMX7_USDHCn_IRQ[i]);
+irq = qdev_get_gpio_in(gic, FSL_IMX7_USDHCn_IRQ[i]);
 sysbus_connect_irq(SYS_BUS_DEVICE(>usdhc[i]), 0, irq);
 }
 
@@ -519,8 +516,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
 
 sysbus_mmio_map(SYS_BUS_DEVICE(>wdt[i]), 0, FSL_IMX7_WDOGn_ADDR[i]);
 sysbus_connect_irq(SYS_BUS_DEVICE(>wdt[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX7_WDOGn_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX7_WDOGn_IRQ[i]));
 }
 
 /*
@@ -596,13 +592,13 @@ static void fsl_imx7_realize(DeviceState *dev, Error 
**errp)
 

[PATCH 13/33] hw/cpu/arm: Handle 'num_cores' property once in MPCore parent

2023-12-12 Thread Philippe Mathieu-Daudé
Move the 'num_cpu' property to the abstract QOM parent.
Rename it as 'num_cores', keeping it aliased as 'num_cpu'.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/cpu/cortex_mpcore.h |  9 +++--
 hw/arm/aspeed_ast2600.c|  2 +-
 hw/arm/exynos4210.c|  2 +-
 hw/arm/fsl-imx6.c  |  2 +-
 hw/arm/fsl-imx6ul.c|  2 +-
 hw/arm/fsl-imx7.c  |  2 +-
 hw/arm/npcm7xx.c   |  2 +-
 hw/arm/realview.c  |  2 +-
 hw/cpu/a15mpcore.c | 11 +--
 hw/cpu/a9mpcore.c  | 14 ++
 hw/cpu/arm11mpcore.c   |  3 ++-
 hw/cpu/cortex_mpcore.c | 17 +
 hw/cpu/realview_mpcore.c   |  3 ++-
 13 files changed, 46 insertions(+), 25 deletions(-)

diff --git a/include/hw/cpu/cortex_mpcore.h b/include/hw/cpu/cortex_mpcore.h
index 1d94c8769d..0e7cca9e93 100644
--- a/include/hw/cpu/cortex_mpcore.h
+++ b/include/hw/cpu/cortex_mpcore.h
@@ -26,6 +26,10 @@
  * The A9 MPCore additionally contains:
  *  a System Control Unit
  *  some timers and watchdogs
+ *
+ * QEMU interface:
+ *  + QOM property "num-cores" which set the number of cores present in
+ *the cluster.
  */
 #define TYPE_CORTEX_MPCORE_PRIV "cortex_mpcore_priv"
 OBJECT_DECLARE_TYPE(CortexMPPrivState, CortexMPPrivClass, CORTEX_MPCORE_PRIV)
@@ -46,6 +50,9 @@ struct CortexMPPrivState {
 SysBusDevice parent_obj;
 
 MemoryRegion container;
+
+/* Properties */
+uint32_t num_cores;
 };
 
 #define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
@@ -54,7 +61,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(A9MPPrivState, A9MPCORE_PRIV)
 struct A9MPPrivState {
 CortexMPPrivState parent_obj;
 
-uint32_t num_cpu;
 uint32_t num_irq;
 
 A9SCUState scu;
@@ -70,7 +76,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(A15MPPrivState, A15MPCORE_PRIV)
 struct A15MPPrivState {
 CortexMPPrivState parent_obj;
 
-uint32_t num_cpu;
 uint32_t num_irq;
 
 GICState gic;
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index b965fbab5e..ca788e1cf0 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -330,7 +330,7 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
 }
 
 /* A7MPCORE */
-object_property_set_int(OBJECT(>a7mpcore), "num-cpu", sc->num_cpus,
+object_property_set_int(OBJECT(>a7mpcore), "num-cores", sc->num_cpus,
 _abort);
 object_property_set_int(OBJECT(>a7mpcore), "num-irq",
 ROUND_UP(AST2600_MAX_IRQ + GIC_INTERNAL, 32),
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index 2e6423f74d..ea1364499d 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -582,7 +582,7 @@ static void exynos4210_realize(DeviceState *socdev, Error 
**errp)
 }
 
 /* Private memory region and Internal GIC */
-qdev_prop_set_uint32(DEVICE(>a9mpcore), "num-cpu", EXYNOS4210_NCPUS);
+qdev_prop_set_uint32(DEVICE(>a9mpcore), "num-cores", EXYNOS4210_NCPUS);
 busdev = SYS_BUS_DEVICE(>a9mpcore);
 sysbus_realize(busdev, _fatal);
 sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index f6edbd7465..65c7c1a0f9 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -138,7 +138,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 }
 }
 
-object_property_set_int(OBJECT(>a9mpcore), "num-cpu", smp_cpus,
+object_property_set_int(OBJECT(>a9mpcore), "num-cores", smp_cpus,
 _abort);
 
 object_property_set_int(OBJECT(>a9mpcore), "num-irq",
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
index 59032263cf..93908811c5 100644
--- a/hw/arm/fsl-imx6ul.c
+++ b/hw/arm/fsl-imx6ul.c
@@ -173,7 +173,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 /*
  * A7MPCORE
  */
-object_property_set_int(OBJECT(>a7mpcore), "num-cpu", 1, _abort);
+object_property_set_int(OBJECT(>a7mpcore), "num-cores", 1, 
_abort);
 object_property_set_int(OBJECT(>a7mpcore), "num-irq",
 FSL_IMX6UL_MAX_IRQ + GIC_INTERNAL, _abort);
 sysbus_realize(SYS_BUS_DEVICE(>a7mpcore), _abort);
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index a283dcb45f..8a3e9933c4 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -203,7 +203,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
 /*
  * A7MPCORE
  */
-object_property_set_int(OBJECT(>a7mpcore), "num-cpu", smp_cpus,
+object_property_set_int(OBJECT(>a7mpcore), "num-cores", smp_cpus,
 _abort);
 object_property_set_int(OBJECT(>a7mpcore), "num-irq",
 FSL_IMX7_MAX_IRQ + GIC_INTERNAL, _abort);
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 15ff21d047..5b6e968fa9 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -491,7 +491,7 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 }
 
 /* 

[PATCH 12/33] hw/cpu/arm: Create MPCore container in QOM parent

2023-12-12 Thread Philippe Mathieu-Daudé
Move the memory region container creation to the abstract QOM
parent. Children set the region size via the class 'container_size'
field.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/cpu/cortex_mpcore.h | 10 --
 hw/cpu/a15mpcore.c | 17 -
 hw/cpu/a9mpcore.c  | 18 +-
 hw/cpu/cortex_mpcore.c | 14 ++
 4 files changed, 39 insertions(+), 20 deletions(-)

diff --git a/include/hw/cpu/cortex_mpcore.h b/include/hw/cpu/cortex_mpcore.h
index 4084c6003a..1d94c8769d 100644
--- a/include/hw/cpu/cortex_mpcore.h
+++ b/include/hw/cpu/cortex_mpcore.h
@@ -30,14 +30,22 @@
 #define TYPE_CORTEX_MPCORE_PRIV "cortex_mpcore_priv"
 OBJECT_DECLARE_TYPE(CortexMPPrivState, CortexMPPrivClass, CORTEX_MPCORE_PRIV)
 
+/**
+ * CortexMPPrivClass:
+ * @container_size - size of the device's MMIO region
+ */
 struct CortexMPPrivClass {
 SysBusDeviceClass parent_class;
 
 DeviceRealize parent_realize;
+
+uint64_t container_size;
 };
 
 struct CortexMPPrivState {
 SysBusDevice parent_obj;
+
+MemoryRegion container;
 };
 
 #define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
@@ -47,7 +55,6 @@ struct A9MPPrivState {
 CortexMPPrivState parent_obj;
 
 uint32_t num_cpu;
-MemoryRegion container;
 uint32_t num_irq;
 
 A9SCUState scu;
@@ -65,7 +72,6 @@ struct A15MPPrivState {
 
 uint32_t num_cpu;
 uint32_t num_irq;
-MemoryRegion container;
 
 GICState gic;
 };
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index 5a57145179..128941eb50 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -36,12 +36,8 @@ static void a15mp_priv_set_irq(void *opaque, int irq, int 
level)
 
 static void a15mp_priv_initfn(Object *obj)
 {
-SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 A15MPPrivState *s = A15MPCORE_PRIV(obj);
 
-memory_region_init(>container, obj, "a15mp-priv-container", 0x8000);
-sysbus_init_mmio(sbd, >container);
-
 object_initialize_child(obj, "gic", >gic, gic_class_name());
 qdev_prop_set_uint32(DEVICE(>gic), "revision", 2);
 }
@@ -51,6 +47,7 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
 CortexMPPrivClass *cc = CORTEX_MPCORE_PRIV_GET_CLASS(dev);
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 A15MPPrivState *s = A15MPCORE_PRIV(dev);
+CortexMPPrivState *c = CORTEX_MPCORE_PRIV(dev);
 DeviceState *gicdev;
 SysBusDevice *gicsbd;
 Error *local_err = NULL;
@@ -133,20 +130,20 @@ static void a15mp_priv_realize(DeviceState *dev, Error 
**errp)
  *  0x5600-0x57ff -- GIC virtual interface control for CPU 3
  *  0x6000-0x7fff -- GIC virtual CPU interface
  */
-memory_region_add_subregion(>container, 0x1000,
+memory_region_add_subregion(>container, 0x1000,
 sysbus_mmio_get_region(gicsbd, 0));
-memory_region_add_subregion(>container, 0x2000,
+memory_region_add_subregion(>container, 0x2000,
 sysbus_mmio_get_region(gicsbd, 1));
 if (has_el2) {
-memory_region_add_subregion(>container, 0x4000,
+memory_region_add_subregion(>container, 0x4000,
 sysbus_mmio_get_region(gicsbd, 2));
-memory_region_add_subregion(>container, 0x6000,
+memory_region_add_subregion(>container, 0x6000,
 sysbus_mmio_get_region(gicsbd, 3));
 for (i = 0; i < s->num_cpu; i++) {
 hwaddr base = 0x5000 + i * 0x200;
 MemoryRegion *mr = sysbus_mmio_get_region(gicsbd,
   4 + s->num_cpu + i);
-memory_region_add_subregion(>container, base, mr);
+memory_region_add_subregion(>container, base, mr);
 }
 }
 }
@@ -168,6 +165,8 @@ static void a15mp_priv_class_init(ObjectClass *klass, void 
*data)
 DeviceClass *dc = DEVICE_CLASS(klass);
 CortexMPPrivClass *cc = CORTEX_MPCORE_PRIV_CLASS(klass);
 
+cc->container_size = 0x8000;
+
 device_class_set_parent_realize(dc, a15mp_priv_realize,
 >parent_realize);
 device_class_set_props(dc, a15mp_priv_properties);
diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
index d59e49126b..08346b0049 100644
--- a/hw/cpu/a9mpcore.c
+++ b/hw/cpu/a9mpcore.c
@@ -30,9 +30,6 @@ static void a9mp_priv_initfn(Object *obj)
 {
 A9MPPrivState *s = A9MPCORE_PRIV(obj);
 
-memory_region_init(>container, obj, "a9mp-priv-container", 0x2000);
-sysbus_init_mmio(SYS_BUS_DEVICE(obj), >container);
-
 object_initialize_child(obj, "scu", >scu, TYPE_A9_SCU);
 
 object_initialize_child(obj, "gic", >gic, TYPE_ARM_GIC);
@@ -47,6 +44,7 @@ static void a9mp_priv_initfn(Object *obj)
 static void a9mp_priv_realize(DeviceState *dev, Error **errp)
 {
 CortexMPPrivClass *cc = CORTEX_MPCORE_PRIV_GET_CLASS(dev);
+CortexMPPrivState *c = CORTEX_MPCORE_PRIV(dev);
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 

[PATCH 06/33] hw/cpu/arm: Rename 'busdev' -> 'gicsbd' in a15mp_priv_realize()

2023-12-12 Thread Philippe Mathieu-Daudé
'busdev' is the internal GIC as SysBus device.
Since we already have a 'gicdev' variable for the GIC as QDev,
rename 'busdev' as 'gicsbd' to make it clear we access the IRQ
lines from the GIC.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/cpu/a15mpcore.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index bfd8aa5644..a40f142128 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -51,7 +51,7 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 A15MPPrivState *s = A15MPCORE_PRIV(dev);
 DeviceState *gicdev;
-SysBusDevice *busdev;
+SysBusDevice *gicsbd;
 int i;
 bool has_el3;
 bool has_el2 = false;
@@ -78,10 +78,10 @@ static void a15mp_priv_realize(DeviceState *dev, Error 
**errp)
 if (!sysbus_realize(SYS_BUS_DEVICE(>gic), errp)) {
 return;
 }
-busdev = SYS_BUS_DEVICE(>gic);
+gicsbd = SYS_BUS_DEVICE(>gic);
 
 /* Pass through outbound IRQ lines from the GIC */
-sysbus_pass_irq(sbd, busdev);
+sysbus_pass_irq(sbd, gicsbd);
 
 /* Pass through inbound GPIO lines to the GIC */
 qdev_init_gpio_in(dev, a15mp_priv_set_irq, s->num_irq - 32);
@@ -126,17 +126,17 @@ static void a15mp_priv_realize(DeviceState *dev, Error 
**errp)
  *  0x6000-0x7fff -- GIC virtual CPU interface
  */
 memory_region_add_subregion(>container, 0x1000,
-sysbus_mmio_get_region(busdev, 0));
+sysbus_mmio_get_region(gicsbd, 0));
 memory_region_add_subregion(>container, 0x2000,
-sysbus_mmio_get_region(busdev, 1));
+sysbus_mmio_get_region(gicsbd, 1));
 if (has_el2) {
 memory_region_add_subregion(>container, 0x4000,
-sysbus_mmio_get_region(busdev, 2));
+sysbus_mmio_get_region(gicsbd, 2));
 memory_region_add_subregion(>container, 0x6000,
-sysbus_mmio_get_region(busdev, 3));
+sysbus_mmio_get_region(gicsbd, 3));
 for (i = 0; i < s->num_cpu; i++) {
 hwaddr base = 0x5000 + i * 0x200;
-MemoryRegion *mr = sysbus_mmio_get_region(busdev,
+MemoryRegion *mr = sysbus_mmio_get_region(gicsbd,
   4 + s->num_cpu + i);
 memory_region_add_subregion(>container, base, mr);
 }
-- 
2.41.0




Re: [PATCH] fix qemu build with xen-4.18.0

2023-12-12 Thread Stefan Hajnoczi
On Tue, 12 Dec 2023 at 11:02, Volodymyr Babchuk
 wrote:
>
>
> Hi Stefan,
>
> Stefan Hajnoczi  writes:
>
> > On Tue, 12 Dec 2023 at 10:36, Volodymyr Babchuk
> >  wrote:
> >>
> >> Hi Anthony
> >>
> >> Anthony PERARD  writes:
> >>
> >> > On Fri, Dec 08, 2023 at 02:49:27PM -0800, Stefano Stabellini wrote:
> >> >> On Fri, 8 Dec 2023, Daniel P. Berrangé wrote:
> >> >> > On Thu, Dec 07, 2023 at 11:12:48PM +, Michael Young wrote:
> >> >> > > Builds of qemu-8.2.0rc2 with xen-4.18.0 are currently failing
> >> >> > > with errors like
> >> >> > > ../hw/arm/xen_arm.c:74:5: error: ‘GUEST_VIRTIO_MMIO_SPI_LAST’ 
> >> >> > > undeclared (first use in this function)
> >> >> > >74 |(GUEST_VIRTIO_MMIO_SPI_LAST - 
> >> >> > > GUEST_VIRTIO_MMIO_SPI_FIRST)
> >> >> > >   | ^~
> >> >> > >
> >> >> > > as there is an incorrect comparision in include/hw/xen/xen_native.h
> >> >> > > which means that settings like GUEST_VIRTIO_MMIO_SPI_LAST
> >> >> > > aren't being defined for xen-4.18.0
> >> >> >
> >> >> > The conditions in arch-arm.h for xen 4.18 show:
> >> >> >
> >> >> > $ cppi arch-arm.h | grep -E '(#.*if)|MMIO'
> >> >> > #ifndef __XEN_PUBLIC_ARCH_ARM_H__
> >> >> > # if defined(__XEN__) || defined(__XEN_TOOLS__) || defined(__GNUC__)
> >> >> > # endif
> >> >> > # ifndef __ASSEMBLY__
> >> >> > #  if defined(__XEN__) || defined(__XEN_TOOLS__)
> >> >> > #   if defined(__GNUC__) && !defined(__STRICT_ANSI__)
> >> >> > #   endif
> >> >> > #  endif /* __XEN__ || __XEN_TOOLS__ */
> >> >> > # endif
> >> >> > # if defined(__XEN__) || defined(__XEN_TOOLS__)
> >> >> > #  define PSR_MODE_BIT  0x10U /* Set iff AArch32 */
> >> >> > /* Virtio MMIO mappings */
> >> >> > #  define GUEST_VIRTIO_MMIO_BASE   xen_mk_ullong(0x0200)
> >> >> > #  define GUEST_VIRTIO_MMIO_SIZE   xen_mk_ullong(0x0010)
> >> >> > #  define GUEST_VIRTIO_MMIO_SPI_FIRST   33
> >> >> > #  define GUEST_VIRTIO_MMIO_SPI_LAST43
> >> >> > # endif
> >> >> > # ifndef __ASSEMBLY__
> >> >> > # endif
> >> >> > #endif /*  __XEN_PUBLIC_ARCH_ARM_H__ */
> >> >> >
> >> >> > So the MMIO constants are available if __XEN__ or __XEN_TOOLS__
> >> >> > are defined. This is no different to the condition that was
> >> >> > present in Xen 4.17.
> >> >> >
> >> >> > What you didn't mention was that the Fedora build failure is
> >> >> > seen on an x86_64 host, when building the aarch64 target QEMU,
> >> >> > and I think this is the key issue.
> >> >>
> >> >> Hi Daniel, thanks for looking into it.
> >> >>
> >> >> - you are building on a x86_64 host
> >> >> - the target is aarch64
> >> >> - the target is the aarch64 Xen PVH machine (xen_arm.c)
> >> >>
> >> >> But is the resulting QEMU binary expected to be an x86 binary? Or are
> >> >> you cross compiling ARM binaries on a x86 host?
> >> >>
> >> >> In other word, is the resulting QEMU binary expected to run on ARM or
> >> >> x86?
> >> >>
> >> >>
> >> >> > Are we expecting to build Xen support for non-arch native QEMU
> >> >> > system binaries or not ?
> >> >>
> >> >> The ARM xenpvh machine (xen_arm.c) is meant to work with Xen on ARM, not
> >> >> Xen on x86.  So this is only expected to work if you are
> >> >> cross-compiling. But you can cross-compile both Xen and QEMU, and I am
> >> >> pretty sure that Yocto is able to build Xen, Xen userspace tools, and
> >> >> QEMU for Xen/ARM on an x86 host today.
> >> >>
> >> >>
> >> >> > The constants are defined in arch-arm.h, which is only included
> >> >> > under:
> >> >> >
> >> >> >   #if defined(__i386__) || defined(__x86_64__)
> >> >> >   #include "arch-x86/xen.h"
> >> >> >   #elif defined(__arm__) || defined (__aarch64__)
> >> >> >   #include "arch-arm.h"
> >> >> >   #else
> >> >> >   #error "Unsupported architecture"
> >> >> >   #endif
> >> >> >
> >> >> >
> >> >> > When we are building on an x86_64 host, we not going to get
> >> >> > arch-arm.h included, even if we're trying to build the aarch64
> >> >> > system emulator.
> >> >> >
> >> >> > I don't know how this is supposed to work ?
> >> >>
> >> >> It looks like a host vs. target architecture mismatch: the #if defined
> >> >> (__aarch64__) check should pass I think.
> >> >
> >> >
> >> > Building qemu with something like:
> >> > ./configure --enable-xen --cpu=x86_64
> >> > used to work. Can we fix that? It still works with v8.1.0.
> >> > At least, it works on x86, I never really try to build qemu for arm.
> >> > Notice that there's no "--target-list" on the configure command line.
> >> > I don't know if --cpu is useful here.
> >> >
> >> > Looks like the first commit where the build doesn't work is
> >> > 7899f6589b78 ("xen_arm: Add virtual PCIe host bridge support").
> >>
> >> I am currently trying to upstream this patch. It is in the QEMU mailing
> >> list but it was never accepted. It is not reviewed in fact. I'll take a
> >> look at it, but I don't understand how did you get in the first place.
> >
> > Hi Volodymyr,
> > Paolo Bonzini sent a pull request with similar code changes this
> > morning and 

[PATCH 01/33] hw/arm/boot: Propagate vCPU to arm_load_dtb()

2023-12-12 Thread Philippe Mathieu-Daudé
In heterogeneous setup the first vCPU might not be
the one expected, better pass it explicitly.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/arm/boot.h |  4 +++-
 hw/arm/boot.c | 11 ++-
 hw/arm/virt.c |  2 +-
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
index 80c492d742..b12bf61ca8 100644
--- a/include/hw/arm/boot.h
+++ b/include/hw/arm/boot.h
@@ -160,6 +160,7 @@ AddressSpace *arm_boot_address_space(ARMCPU *cpu,
  * @binfo:  struct describing the boot environment
  * @addr_limit: upper limit of the available memory area at @addr
  * @as: address space to load image to
+ * @cpu:ARM CPU object
  *
  * Load a device tree supplied by the machine or by the user  with the
  * '-dtb' command line option, and put it at offset @addr in target
@@ -176,7 +177,8 @@ AddressSpace *arm_boot_address_space(ARMCPU *cpu,
  * Note: Must not be called unless have_dtb(binfo) is true.
  */
 int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
- hwaddr addr_limit, AddressSpace *as, MachineState *ms);
+ hwaddr addr_limit, AddressSpace *as, MachineState *ms,
+ ARMCPU *cpu);
 
 /* Write a secure board setup routine with a dummy handler for SMCs */
 void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 84ea6a807a..334e4640fd 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -432,13 +432,12 @@ out:
 return ret;
 }
 
-static void fdt_add_psci_node(void *fdt)
+static void fdt_add_psci_node(void *fdt, ARMCPU *armcpu)
 {
 uint32_t cpu_suspend_fn;
 uint32_t cpu_off_fn;
 uint32_t cpu_on_fn;
 uint32_t migrate_fn;
-ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
 const char *psci_method;
 int64_t psci_conduit;
 int rc;
@@ -512,7 +511,8 @@ static void fdt_add_psci_node(void *fdt)
 }
 
 int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
- hwaddr addr_limit, AddressSpace *as, MachineState *ms)
+ hwaddr addr_limit, AddressSpace *as, MachineState *ms,
+ ARMCPU *cpu)
 {
 void *fdt = NULL;
 int size, rc, n = 0;
@@ -655,7 +655,7 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info 
*binfo,
 }
 }
 
-fdt_add_psci_node(fdt);
+fdt_add_psci_node(fdt, cpu);
 
 if (binfo->modify_dtb) {
 binfo->modify_dtb(binfo, fdt);
@@ -1321,7 +1321,8 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, 
struct arm_boot_info *info)
  * decided whether to enable PSCI and set the psci-conduit CPU properties.
  */
 if (!info->skip_dtb_autoload && have_dtb(info)) {
-if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as, ms) < 0) {
+if (arm_load_dtb(info->dtb_start, info, info->dtb_limit,
+ as, ms, cpu) < 0) {
 exit(1);
 }
 }
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index be2856c018..4a1d1550f5 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1678,7 +1678,7 @@ void virt_machine_done(Notifier *notifier, void *data)
vms->memmap[VIRT_PLATFORM_BUS].size,
vms->irqmap[VIRT_PLATFORM_BUS]);
 }
-if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as, ms) < 0) {
+if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as, ms, cpu) < 0) 
{
 exit(1);
 }
 
-- 
2.41.0




[PATCH 03/33] hw/arm/fsl-imx6ul: Add a local 'gic' variable

2023-12-12 Thread Philippe Mathieu-Daudé
The A7MPCore forward the IRQs from its internal GIC.
To make the code clearer, add a 'gic' variable.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/fsl-imx6ul.c | 38 ++
 1 file changed, 14 insertions(+), 24 deletions(-)

diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
index e37b69a5e1..59032263cf 100644
--- a/hw/arm/fsl-imx6ul.c
+++ b/hw/arm/fsl-imx6ul.c
@@ -156,6 +156,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 {
 MachineState *ms = MACHINE(qdev_get_machine());
 FslIMX6ULState *s = FSL_IMX6UL(dev);
+DeviceState *gic;
 int i;
 char name[NAME_SIZE];
 SysBusDevice *sbd;
@@ -177,6 +178,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 FSL_IMX6UL_MAX_IRQ + GIC_INTERNAL, _abort);
 sysbus_realize(SYS_BUS_DEVICE(>a7mpcore), _abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(>a7mpcore), 0, FSL_IMX6UL_A7MPCORE_ADDR);
+gic = DEVICE(>a7mpcore);
 
 sbd = SYS_BUS_DEVICE(>a7mpcore);
 d = DEVICE(>cpu);
@@ -213,8 +215,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 FSL_IMX6UL_GPTn_ADDR[i]);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>gpt[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX6UL_GPTn_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX6UL_GPTn_IRQ[i]));
 }
 
 /*
@@ -238,8 +239,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 FSL_IMX6UL_EPITn_ADDR[i]);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>epit[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX6UL_EPITn_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX6UL_EPITn_IRQ[i]));
 }
 
 /*
@@ -276,12 +276,10 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 FSL_IMX6UL_GPIOn_ADDR[i]);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>gpio[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX6UL_GPIOn_LOW_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX6UL_GPIOn_LOW_IRQ[i]));
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>gpio[i]), 1,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX6UL_GPIOn_HIGH_IRQ[i]));
+   qdev_get_gpio_in(gic, 
FSL_IMX6UL_GPIOn_HIGH_IRQ[i]));
 }
 
 /*
@@ -335,8 +333,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 FSL_IMX6UL_SPIn_ADDR[i]);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>spi[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX6UL_SPIn_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX6UL_SPIn_IRQ[i]));
 }
 
 /*
@@ -361,8 +358,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(>i2c[i]), 0, 
FSL_IMX6UL_I2Cn_ADDR[i]);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>i2c[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX6UL_I2Cn_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX6UL_I2Cn_IRQ[i]));
 }
 
 /*
@@ -399,8 +395,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 FSL_IMX6UL_UARTn_ADDR[i]);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>uart[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX6UL_UARTn_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX6UL_UARTn_IRQ[i]));
 }
 
 /*
@@ -449,12 +444,10 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 FSL_IMX6UL_ENETn_ADDR[i]);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>eth[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX6UL_ENETn_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX6UL_ENETn_IRQ[i]));
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>eth[i]), 1,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-FSL_IMX6UL_ENETn_TIMER_IRQ[i]));
+   qdev_get_gpio_in(gic, 
FSL_IMX6UL_ENETn_TIMER_IRQ[i]));
 }
 
 /*
@@ -490,8 +483,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(>usb[i]), 0,
 FSL_IMX6UL_USB02_USBn_ADDR[i]);
 sysbus_connect_irq(SYS_BUS_DEVICE(>usb[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a7mpcore),
-

[PATCH 02/33] hw/arm/fsl-imx6: Add a local 'gic' variable

2023-12-12 Thread Philippe Mathieu-Daudé
The A9MPCore forward the IRQs from its internal GIC.
To make the code clearer, add a 'gic' variable.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/fsl-imx6.c | 37 +
 1 file changed, 13 insertions(+), 24 deletions(-)

diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index 7dc42cbfe6..f6edbd7465 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -111,6 +111,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 uint16_t i;
 Error *err = NULL;
 unsigned int smp_cpus = ms->smp.cpus;
+DeviceState *gic = DEVICE(>a9mpcore);
 
 if (smp_cpus > FSL_IMX6_NUM_CPUS) {
 error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
@@ -186,8 +187,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 
 sysbus_mmio_map(SYS_BUS_DEVICE(>uart[i]), 0, serial_table[i].addr);
 sysbus_connect_irq(SYS_BUS_DEVICE(>uart[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a9mpcore),
-serial_table[i].irq));
+   qdev_get_gpio_in(gic, serial_table[i].irq));
 }
 
 s->gpt.ccm = IMX_CCM(>ccm);
@@ -198,8 +198,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 
 sysbus_mmio_map(SYS_BUS_DEVICE(>gpt), 0, FSL_IMX6_GPT_ADDR);
 sysbus_connect_irq(SYS_BUS_DEVICE(>gpt), 0,
-   qdev_get_gpio_in(DEVICE(>a9mpcore),
-FSL_IMX6_GPT_IRQ));
+   qdev_get_gpio_in(gic, FSL_IMX6_GPT_IRQ));
 
 /* Initialize all EPIT timers */
 for (i = 0; i < FSL_IMX6_NUM_EPITS; i++) {
@@ -219,8 +218,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 
 sysbus_mmio_map(SYS_BUS_DEVICE(>epit[i]), 0, epit_table[i].addr);
 sysbus_connect_irq(SYS_BUS_DEVICE(>epit[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a9mpcore),
-epit_table[i].irq));
+   qdev_get_gpio_in(gic, epit_table[i].irq));
 }
 
 /* Initialize all I2C */
@@ -240,8 +238,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 
 sysbus_mmio_map(SYS_BUS_DEVICE(>i2c[i]), 0, i2c_table[i].addr);
 sysbus_connect_irq(SYS_BUS_DEVICE(>i2c[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a9mpcore),
-i2c_table[i].irq));
+   qdev_get_gpio_in(gic, i2c_table[i].irq));
 }
 
 /* Initialize all GPIOs */
@@ -298,11 +295,9 @@ static void fsl_imx6_realize(DeviceState *dev, Error 
**errp)
 
 sysbus_mmio_map(SYS_BUS_DEVICE(>gpio[i]), 0, gpio_table[i].addr);
 sysbus_connect_irq(SYS_BUS_DEVICE(>gpio[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a9mpcore),
-gpio_table[i].irq_low));
+   qdev_get_gpio_in(gic, gpio_table[i].irq_low));
 sysbus_connect_irq(SYS_BUS_DEVICE(>gpio[i]), 1,
-   qdev_get_gpio_in(DEVICE(>a9mpcore),
-gpio_table[i].irq_high));
+   qdev_get_gpio_in(gic, gpio_table[i].irq_high));
 }
 
 /* Initialize all SDHC */
@@ -329,8 +324,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 }
 sysbus_mmio_map(SYS_BUS_DEVICE(>esdhc[i]), 0, esdhc_table[i].addr);
 sysbus_connect_irq(SYS_BUS_DEVICE(>esdhc[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a9mpcore),
-esdhc_table[i].irq));
+   qdev_get_gpio_in(gic, esdhc_table[i].irq));
 }
 
 /* USB */
@@ -351,8 +345,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(>usb[i]), 0,
 FSL_IMX6_USBOH3_USB_ADDR + i * 0x200);
 sysbus_connect_irq(SYS_BUS_DEVICE(>usb[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a9mpcore),
-FSL_IMX6_USBn_IRQ[i]));
+   qdev_get_gpio_in(gic, FSL_IMX6_USBn_IRQ[i]));
 }
 
 /* Initialize all ECSPI */
@@ -375,8 +368,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 
 sysbus_mmio_map(SYS_BUS_DEVICE(>spi[i]), 0, spi_table[i].addr);
 sysbus_connect_irq(SYS_BUS_DEVICE(>spi[i]), 0,
-   qdev_get_gpio_in(DEVICE(>a9mpcore),
-spi_table[i].irq));
+   qdev_get_gpio_in(gic, spi_table[i].irq));
 }
 
 object_property_set_uint(OBJECT(>eth), "phy-num", s->phy_num,
@@ -387,11 +379,9 @@ static void fsl_imx6_realize(DeviceState *dev, Error 
**errp)
 }
 sysbus_mmio_map(SYS_BUS_DEVICE(>eth), 0, FSL_IMX6_ENET_ADDR);
 sysbus_connect_irq(SYS_BUS_DEVICE(>eth), 0,
-   

[PATCH 00/33] hw/cpu/arm: Remove one use of qemu_get_cpu() in A7/A15 MPCore priv

2023-12-12 Thread Philippe Mathieu-Daudé
Hi,

When a MPCore cluster is used, the Cortex-A cores belong the the
cluster container, not to the board/soc layer. This series move
the creation of vCPUs to the MPCore private container.

Doing so we consolidate the QOM model, moving common code in a
central place (abstract MPCore parent).

This eventually allow removing one qemu_get_cpu() use, which we
want to remove in heterogeneous machines (machines using MPCore
are candidate for heterogeneous emulation).

Maybe these hw/cpu/arm/ files belong to hw/arm/...

Regards,

Phil.

Philippe Mathieu-Daudé (33):
  hw/arm/boot: Propagate vCPU to arm_load_dtb()
  hw/arm/fsl-imx6: Add a local 'gic' variable
  hw/arm/fsl-imx6ul: Add a local 'gic' variable
  hw/arm/fsl-imx7: Add a local 'gic' variable
  hw/cpu: Remove dead Kconfig
  hw/cpu/arm: Rename 'busdev' -> 'gicsbd' in a15mp_priv_realize()
  hw/cpu/arm: Alias 'num-cpu' property on TYPE_REALVIEW_MPCORE
  hw/cpu/arm: Declare CPU QOM types using DEFINE_TYPES() macro
  hw/cpu/arm: Merge {a9mpcore.h, a15mpcore.h} as cortex_mpcore.h
  hw/cpu/arm: Introduce abstract CORTEX_MPCORE_PRIV QOM type
  hw/cpu/arm: Have A9MPCORE/A15MPCORE inheritate common
CORTEX_MPCORE_PRIV
  hw/cpu/arm: Create MPCore container in QOM parent
  hw/cpu/arm: Handle 'num_cores' property once in MPCore parent
  hw/cpu/arm: Handle 'has_el2/3' properties once in MPCore parent
  hw/cpu/arm: Handle 'gic-irq' property once in MPCore parent
  hw/cpu/arm: Handle GIC once in MPCore parent
  hw/cpu/arm: Document more properties of CORTEX_MPCORE_PRIV QOM type
  hw/cpu/arm: Replace A15MPPrivState by CortexMPPrivState
  hw/cpu/arm: Introduce TYPE_A7MPCORE_PRIV for Cortex-A7 MPCore
  hw/cpu/arm: Consolidate check on max GIC spi supported
  hw/cpu/arm: Create CPUs once in MPCore parent
  hw/arm/aspeed_ast2600: Let the A7MPcore create/wire the CPU cores
  hw/arm/exynos4210: Let the A9MPcore create/wire the CPU cores
  hw/arm/fsl-imx6: Let the A9MPcore create/wire the CPU cores
  hw/arm/fsl-imx6ul: Let the A7MPcore create/wire the CPU cores
  hw/arm/fsl-imx7: Let the A7MPcore create/wire the CPU cores
  hw/arm/highbank: Let the A9/A15MPcore create/wire the CPU cores
  hw/arm/vexpress: Let the A9/A15MPcore create/wire the CPU cores
  hw/arm/xilinx_zynq: Let the A9MPcore create/wire the CPU cores
  hw/arm/npcm7xx: Let the A9MPcore create/wire the CPU cores
  hw/cpu/a9mpcore: Remove legacy code
  hw/cpu/arm: Remove 'num-cpu' property alias
  hw/cpu/arm: Remove use of qemu_get_cpu() in A7/A15 realize()

 MAINTAINERS|   3 +-
 include/hw/arm/aspeed_soc.h|   5 +-
 include/hw/arm/boot.h  |   4 +-
 include/hw/arm/exynos4210.h|   6 +-
 include/hw/arm/fsl-imx6.h  |   6 +-
 include/hw/arm/fsl-imx6ul.h|   8 +-
 include/hw/arm/fsl-imx7.h  |   8 +-
 include/hw/arm/npcm7xx.h   |   3 +-
 include/hw/cpu/a15mpcore.h |  44 ---
 include/hw/cpu/a9mpcore.h  |  39 ---
 include/hw/cpu/cortex_mpcore.h | 135 ++
 hw/arm/aspeed_ast2600.c|  61 --
 hw/arm/boot.c  |  11 +-
 hw/arm/exynos4210.c|  60 --
 hw/arm/exynos4_boards.c|   6 +-
 hw/arm/fsl-imx6.c  |  84 --
 hw/arm/fsl-imx6ul.c|  65 ---
 hw/arm/fsl-imx7.c  | 103 +
 hw/arm/highbank.c  |  56 ++---
 hw/arm/mcimx6ul-evk.c  |   3 +-
 hw/arm/mcimx7d-sabre.c |   3 +-
 hw/arm/npcm7xx.c   |  48 ++--
 hw/arm/realview.c  |   4 +-
 hw/arm/sabrelite.c |   4 +-
 hw/arm/vexpress.c  |  60 +++---
 hw/arm/virt.c  |   2 +-
 hw/arm/xilinx_zynq.c   |  30 ++---
 hw/cpu/a15mpcore.c | 179 +
 hw/cpu/a9mpcore.c  | 138 +-
 hw/cpu/arm11mpcore.c   |  23 ++--
 hw/cpu/cortex_mpcore.c | 202 +
 hw/cpu/realview_mpcore.c   |  30 ++---
 hw/arm/Kconfig |   8 +-
 hw/cpu/Kconfig |   8 --
 hw/cpu/meson.build |   1 +
 35 files changed, 689 insertions(+), 761 deletions(-)
 delete mode 100644 include/hw/cpu/a15mpcore.h
 delete mode 100644 include/hw/cpu/a9mpcore.h
 create mode 100644 include/hw/cpu/cortex_mpcore.h
 create mode 100644 hw/cpu/cortex_mpcore.c
 delete mode 100644 hw/cpu/Kconfig

-- 
2.41.0




[PATCH for-9.0] docs/devel/docs: Document .hx file syntax

2023-12-12 Thread Peter Maydell
We don't currently document the syntax of .hx files anywhere
except in a few comments at the top of individual .hx files.
We don't even have somewhere in the developer docs where we
could do this.

Add a new files docs/devel/docs.rst which can be a place to
document how our docs build process works. For the moment,
put in only a brief introductory paragraph and the documentation
of the .hx files. We could later add to this file by for
example describing how the QAPI-schema-to-docs process works,
or anything else that developers might need to know about
how to add documentation.

Make the .hx files refer to this doc file, and clean
up their header comments to be more accurate for the
usage in each file and less cut-n-pasted.

Signed-off-by: Peter Maydell 
---
My motivation here is that we're about to add support for
extending the SRST directive to specify a label so we
can hyperlink to a documentation fragment; this gives us
somewhere we can document the syntax for that.
---
 MAINTAINERS|  1 +
 docs/devel/docs.rst| 60 ++
 docs/devel/index-build.rst |  1 +
 hmp-commands-info.hx   | 10 +++
 hmp-commands.hx| 10 +++
 qemu-img-cmds.hx   |  2 ++
 qemu-options.hx|  2 ++
 7 files changed, 76 insertions(+), 10 deletions(-)
 create mode 100644 docs/devel/docs.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 695e0bd34fb..49b8ca9d1a8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4149,6 +4149,7 @@ F: docs/conf.py
 F: docs/*/conf.py
 F: docs/sphinx/
 F: docs/_templates/
+F: docs/devel/docs.rst
 
 Miscellaneous
 -
diff --git a/docs/devel/docs.rst b/docs/devel/docs.rst
new file mode 100644
index 000..7da067905b8
--- /dev/null
+++ b/docs/devel/docs.rst
@@ -0,0 +1,60 @@
+
+==
+QEMU Documentation
+==
+
+QEMU's documentation is written in reStructuredText format and
+built using the Sphinx documentation generator. We generate both
+the HTML manual and the manpages from the some documentation sources.
+
+hxtool and .hx files
+
+
+The documentation for QEMU command line options and Human Monitor Protocol
+(HMP) commands is written in files with the ``.hx`` suffix. These
+are processed in two ways:
+
+ * ``scripts/hxtool`` creates C header files from them, which are included
+   in QEMU to do things like handle the ``--help`` option output
+ * a Sphinx extension in ``docs/sphinx/hxtool.py`` generates rST output
+   to be included in the HTML or manpage documentation
+
+The syntax of these ``.hx`` files is simple. It is broadly an
+alternation of C code put into the C output and rST format text
+put into the documention. A few special directives are recognised;
+these are all-caps and must be at the beginning of the line.
+
+``HXCOMM`` is the comment marker. The line, including any arbitrary
+text after the marker, is discarded and appears neither in the C output
+nor the documentation output.
+
+``SRST`` starts a reStructuredText section. Following lines
+are put into the documentation verbatim, and discarded from the C output.
+
+``ERST`` ends the documentation section started with ``SRST``,
+and switches back to a C code section.
+
+``DEFHEADING()`` defines a heading that should appear in both the
+``--help`` output and in the documentation. This directive should
+be in the C code block. If there is a string inside the brackets,
+this is the heading to use. If this string is empty, it produces
+a blank line in the ``--help`` output and is ignored for the rST
+output.
+
+``ARCHHEADING()`` is a variant of ``DEFHEADING()`` which produces
+the heading only if the specified guest architecture was compiled
+into QEMU. This should be avoided in new documentation.
+
+Within C code sections, you should check the comments at the top
+of the file to see what the expected usage is, because this
+varies between files. For instance in ``qemu-options.hx`` we use
+the ``DEF()`` macro to define each option and specify its ``--help``
+text, but in ``hmp-commands.hx`` the C code sections are elements
+of an array of structs of type ``HMPCommand`` which define the
+name, behaviour and help text for each monitor command.
+
+In the file ``qemu-options.hx``, do not try to define a
+reStructuredText label within a documentation section. This file
+is included into two separate Sphinx documents, and some
+versions of Sphinx will complain about the duplicate label
+that results.
diff --git a/docs/devel/index-build.rst b/docs/devel/index-build.rst
index 57e8d39d985..90b406ca0ed 100644
--- a/docs/devel/index-build.rst
+++ b/docs/devel/index-build.rst
@@ -10,6 +10,7 @@ the basics if you are adding new files and targets to the 
build.
 
build-system
kconfig
+   docs
testing
acpi-bits
qtest
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index f5b37eb74ab..da120f82a32 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -1,8 +1,8 @@
-HXCOMM 

Re: [PATCH v2 08/20] util/dsa: Implement DSA task enqueue and dequeue.

2023-12-12 Thread Fabiano Rosas
Hao Xiang  writes:

> * Use a safe thread queue for DSA task enqueue/dequeue.
> * Implement DSA task submission.
> * Implement DSA batch task submission.
>
> Signed-off-by: Hao Xiang 
> ---
>  include/qemu/dsa.h |  35 
>  util/dsa.c | 196 +
>  2 files changed, 231 insertions(+)
>
> diff --git a/include/qemu/dsa.h b/include/qemu/dsa.h
> index 30246b507e..23f55185be 100644
> --- a/include/qemu/dsa.h
> +++ b/include/qemu/dsa.h
> @@ -12,6 +12,41 @@
>  #include 
>  #include "x86intrin.h"
>  
> +enum dsa_task_type {

Our coding style requires CamelCase for enums and typedef'ed structures.

> +DSA_TASK = 0,
> +DSA_BATCH_TASK
> +};
> +
> +enum dsa_task_status {
> +DSA_TASK_READY = 0,
> +DSA_TASK_PROCESSING,
> +DSA_TASK_COMPLETION
> +};
> +
> +typedef void (*buffer_zero_dsa_completion_fn)(void *);

We don't really need the "buffer_zero" mention in any of this
code. Simply dsa_batch_task or batch_task would suffice.

> +
> +typedef struct buffer_zero_batch_task {
> +struct dsa_hw_desc batch_descriptor;
> +struct dsa_hw_desc *descriptors;
> +struct dsa_completion_record batch_completion 
> __attribute__((aligned(32)));
> +struct dsa_completion_record *completions;
> +struct dsa_device_group *group;
> +struct dsa_device *device;
> +buffer_zero_dsa_completion_fn completion_callback;
> +QemuSemaphore sem_task_complete;
> +enum dsa_task_type task_type;
> +enum dsa_task_status status;
> +bool *results;
> +int batch_size;
> +QSIMPLEQ_ENTRY(buffer_zero_batch_task) entry;
> +} buffer_zero_batch_task;

I see data specific to this implementation and data coming from the
library, maybe these would be better organized in two separate
structures with the qemu-specific having a pointer to the generic
one. Looking ahead in the series, there seems to be migration data
coming into this as well.

> +
> +#else
> +
> +struct buffer_zero_batch_task {
> +bool *results;
> +};
> +
>  #endif
>  
>  /**
> diff --git a/util/dsa.c b/util/dsa.c
> index 8edaa892ec..f82282ce99 100644
> --- a/util/dsa.c
> +++ b/util/dsa.c
> @@ -245,6 +245,200 @@ dsa_device_group_get_next_device(struct 
> dsa_device_group *group)
>  return >dsa_devices[current];
>  }
>  
> +/**
> + * @brief Empties out the DSA task queue.
> + *
> + * @param group A pointer to the DSA device group.
> + */
> +static void
> +dsa_empty_task_queue(struct dsa_device_group *group)
> +{
> +qemu_mutex_lock(>task_queue_lock);
> +dsa_task_queue *task_queue = >task_queue;
> +while (!QSIMPLEQ_EMPTY(task_queue)) {
> +QSIMPLEQ_REMOVE_HEAD(task_queue, entry);
> +}
> +qemu_mutex_unlock(>task_queue_lock);
> +}
> +
> +/**
> + * @brief Adds a task to the DSA task queue.
> + *
> + * @param group A pointer to the DSA device group.
> + * @param context A pointer to the DSA task to enqueue.
> + *
> + * @return int Zero if successful, otherwise a proper error code.
> + */
> +static int
> +dsa_task_enqueue(struct dsa_device_group *group,
> + struct buffer_zero_batch_task *task)
> +{
> +dsa_task_queue *task_queue = >task_queue;
> +QemuMutex *task_queue_lock = >task_queue_lock;
> +QemuCond *task_queue_cond = >task_queue_cond;
> +
> +bool notify = false;
> +
> +qemu_mutex_lock(task_queue_lock);
> +
> +if (!group->running) {
> +fprintf(stderr, "DSA: Tried to queue task to stopped device 
> queue\n");
> +qemu_mutex_unlock(task_queue_lock);
> +return -1;
> +}
> +
> +// The queue is empty. This enqueue operation is a 0->1 transition.
> +if (QSIMPLEQ_EMPTY(task_queue))
> +notify = true;
> +
> +QSIMPLEQ_INSERT_TAIL(task_queue, task, entry);
> +
> +// We need to notify the waiter for 0->1 transitions.
> +if (notify)
> +qemu_cond_signal(task_queue_cond);
> +
> +qemu_mutex_unlock(task_queue_lock);
> +
> +return 0;
> +}
> +
> +/**
> + * @brief Takes a DSA task out of the task queue.
> + *
> + * @param group A pointer to the DSA device group.
> + * @return buffer_zero_batch_task* The DSA task being dequeued.
> + */
> +__attribute__((unused))
> +static struct buffer_zero_batch_task *
> +dsa_task_dequeue(struct dsa_device_group *group)
> +{
> +struct buffer_zero_batch_task *task = NULL;
> +dsa_task_queue *task_queue = >task_queue;
> +QemuMutex *task_queue_lock = >task_queue_lock;
> +QemuCond *task_queue_cond = >task_queue_cond;
> +
> +qemu_mutex_lock(task_queue_lock);
> +
> +while (true) {
> +if (!group->running)
> +goto exit;
> +task = QSIMPLEQ_FIRST(task_queue);
> +if (task != NULL) {
> +break;
> +}
> +qemu_cond_wait(task_queue_cond, task_queue_lock);
> +}
> +
> +QSIMPLEQ_REMOVE_HEAD(task_queue, entry);
> +
> +exit:
> +qemu_mutex_unlock(task_queue_lock);
> +return task;
> +}
> +
> +/**
> + * @brief Submits a DSA work item to the device work 

Re: [PATCH] fix qemu build with xen-4.18.0

2023-12-12 Thread Volodymyr Babchuk

Hi Stefan,

Stefan Hajnoczi  writes:

> On Tue, 12 Dec 2023 at 10:36, Volodymyr Babchuk
>  wrote:
>>
>> Hi Anthony
>>
>> Anthony PERARD  writes:
>>
>> > On Fri, Dec 08, 2023 at 02:49:27PM -0800, Stefano Stabellini wrote:
>> >> On Fri, 8 Dec 2023, Daniel P. Berrangé wrote:
>> >> > On Thu, Dec 07, 2023 at 11:12:48PM +, Michael Young wrote:
>> >> > > Builds of qemu-8.2.0rc2 with xen-4.18.0 are currently failing
>> >> > > with errors like
>> >> > > ../hw/arm/xen_arm.c:74:5: error: ‘GUEST_VIRTIO_MMIO_SPI_LAST’ 
>> >> > > undeclared (first use in this function)
>> >> > >74 |(GUEST_VIRTIO_MMIO_SPI_LAST - GUEST_VIRTIO_MMIO_SPI_FIRST)
>> >> > >   | ^~
>> >> > >
>> >> > > as there is an incorrect comparision in include/hw/xen/xen_native.h
>> >> > > which means that settings like GUEST_VIRTIO_MMIO_SPI_LAST
>> >> > > aren't being defined for xen-4.18.0
>> >> >
>> >> > The conditions in arch-arm.h for xen 4.18 show:
>> >> >
>> >> > $ cppi arch-arm.h | grep -E '(#.*if)|MMIO'
>> >> > #ifndef __XEN_PUBLIC_ARCH_ARM_H__
>> >> > # if defined(__XEN__) || defined(__XEN_TOOLS__) || defined(__GNUC__)
>> >> > # endif
>> >> > # ifndef __ASSEMBLY__
>> >> > #  if defined(__XEN__) || defined(__XEN_TOOLS__)
>> >> > #   if defined(__GNUC__) && !defined(__STRICT_ANSI__)
>> >> > #   endif
>> >> > #  endif /* __XEN__ || __XEN_TOOLS__ */
>> >> > # endif
>> >> > # if defined(__XEN__) || defined(__XEN_TOOLS__)
>> >> > #  define PSR_MODE_BIT  0x10U /* Set iff AArch32 */
>> >> > /* Virtio MMIO mappings */
>> >> > #  define GUEST_VIRTIO_MMIO_BASE   xen_mk_ullong(0x0200)
>> >> > #  define GUEST_VIRTIO_MMIO_SIZE   xen_mk_ullong(0x0010)
>> >> > #  define GUEST_VIRTIO_MMIO_SPI_FIRST   33
>> >> > #  define GUEST_VIRTIO_MMIO_SPI_LAST43
>> >> > # endif
>> >> > # ifndef __ASSEMBLY__
>> >> > # endif
>> >> > #endif /*  __XEN_PUBLIC_ARCH_ARM_H__ */
>> >> >
>> >> > So the MMIO constants are available if __XEN__ or __XEN_TOOLS__
>> >> > are defined. This is no different to the condition that was
>> >> > present in Xen 4.17.
>> >> >
>> >> > What you didn't mention was that the Fedora build failure is
>> >> > seen on an x86_64 host, when building the aarch64 target QEMU,
>> >> > and I think this is the key issue.
>> >>
>> >> Hi Daniel, thanks for looking into it.
>> >>
>> >> - you are building on a x86_64 host
>> >> - the target is aarch64
>> >> - the target is the aarch64 Xen PVH machine (xen_arm.c)
>> >>
>> >> But is the resulting QEMU binary expected to be an x86 binary? Or are
>> >> you cross compiling ARM binaries on a x86 host?
>> >>
>> >> In other word, is the resulting QEMU binary expected to run on ARM or
>> >> x86?
>> >>
>> >>
>> >> > Are we expecting to build Xen support for non-arch native QEMU
>> >> > system binaries or not ?
>> >>
>> >> The ARM xenpvh machine (xen_arm.c) is meant to work with Xen on ARM, not
>> >> Xen on x86.  So this is only expected to work if you are
>> >> cross-compiling. But you can cross-compile both Xen and QEMU, and I am
>> >> pretty sure that Yocto is able to build Xen, Xen userspace tools, and
>> >> QEMU for Xen/ARM on an x86 host today.
>> >>
>> >>
>> >> > The constants are defined in arch-arm.h, which is only included
>> >> > under:
>> >> >
>> >> >   #if defined(__i386__) || defined(__x86_64__)
>> >> >   #include "arch-x86/xen.h"
>> >> >   #elif defined(__arm__) || defined (__aarch64__)
>> >> >   #include "arch-arm.h"
>> >> >   #else
>> >> >   #error "Unsupported architecture"
>> >> >   #endif
>> >> >
>> >> >
>> >> > When we are building on an x86_64 host, we not going to get
>> >> > arch-arm.h included, even if we're trying to build the aarch64
>> >> > system emulator.
>> >> >
>> >> > I don't know how this is supposed to work ?
>> >>
>> >> It looks like a host vs. target architecture mismatch: the #if defined
>> >> (__aarch64__) check should pass I think.
>> >
>> >
>> > Building qemu with something like:
>> > ./configure --enable-xen --cpu=x86_64
>> > used to work. Can we fix that? It still works with v8.1.0.
>> > At least, it works on x86, I never really try to build qemu for arm.
>> > Notice that there's no "--target-list" on the configure command line.
>> > I don't know if --cpu is useful here.
>> >
>> > Looks like the first commit where the build doesn't work is
>> > 7899f6589b78 ("xen_arm: Add virtual PCIe host bridge support").
>>
>> I am currently trying to upstream this patch. It is in the QEMU mailing
>> list but it was never accepted. It is not reviewed in fact. I'll take a
>> look at it, but I don't understand how did you get in the first place.
>
> Hi Volodymyr,
> Paolo Bonzini sent a pull request with similar code changes this
> morning and I have merged it into the qemu.git/staging branch:
> https://urldefense.com/v3/__https://gitlab.com/qemu-project/qemu/-/commit/eaae59af4035770975b0ce9364b587223a909501__;!!GF_29dbcQIUBPA!yFgSxAEgXPjckF8piSt0T77bbeggSgwC-6-xDuZmzq4a8U7HEP8XxGnxwIhgA9iyFVie-fdVgAVA5wVipnewbLNp$
> [gitlab[.]com]
>
> If you 

Re: Adding MSI support for virtio-pci to QEMU as Xen backend on ARM

2023-12-12 Thread Alex Bennée
Stefano Stabellini  writes:

> +Stewart
>
> On Fri, 8 Dec 2023, Mykyta Poturai wrote:
>> Hello everyone,
>> 
>> I am currently working on adding MSI support to virtio-pci on ARM with Xen.
>
> Excellent!
>
>
>> As far as I understand QEMU Xen ARM machine that is used for
>> virtio-pci device emulation does not initialize any interrupt
>> controllers. And that makes it somewhat unclear what is the best
>> approach to adding the MSI support. So, I would appreciate some
>> thoughts on this.
>> To trigger the MSI interrupt in Xen guests we basically need to call a 
>> single DMOP, which I am also implementing.
>
> You should be able to call xen_inject_msi
>
>
>> So far, I have come up with 3 possible approaches:
>> 1. Hooking up the existing GIC code to the Xen Arm machine and extending it 
>> with the DMOP call.
>
> No, I would rather avoid this for a couple of reasons. In reality, the
> GIC is emulated by Xen, not QEMU. So letting QEMU think that QEMU is
> emulating a GIC is more error prone than the alternatives and also it
> would allocate resources needlessly.
>
>
>> 2. Writing some new barebones GIC implementation with only the required 
>> methods (something similar to xen_apic.c).
>> 3. Just hooking up the DMOP call to the existing PCI code based on 
>> xen_enabled() check.
>
> I would rather not introduce any more if (xen_enabled()) checks beyond
> the ones we already have unless it is the only option. So I would go
> with option 2). Even better if we could reuse xen_apic.c. xen_apic.c is
> just a stub, which is basically the same thing that we need here.

I guess the APIC part of the name is part of the historical baggage of
x86 - really it's just a xenpv-irq controller?

Anyway yeah I think just move it from hw/i386/xen to hw/xen and maybe
give it a new name with an alias to the old one we can deprecate over
time?

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro



Re: [PATCH] fix qemu build with xen-4.18.0

2023-12-12 Thread Anthony PERARD
On Tue, Dec 12, 2023 at 03:35:50PM +, Volodymyr Babchuk wrote:
> Hi Anthony
> 
> Anthony PERARD  writes:
> 
> > On Fri, Dec 08, 2023 at 02:49:27PM -0800, Stefano Stabellini wrote:
> >> On Fri, 8 Dec 2023, Daniel P. Berrangé wrote:
> >> > On Thu, Dec 07, 2023 at 11:12:48PM +, Michael Young wrote:
> >> > > Builds of qemu-8.2.0rc2 with xen-4.18.0 are currently failing
> >> > > with errors like
> >> > > ../hw/arm/xen_arm.c:74:5: error: ‘GUEST_VIRTIO_MMIO_SPI_LAST’ 
> >> > > undeclared (first use in this function)
> >> > >74 |(GUEST_VIRTIO_MMIO_SPI_LAST - GUEST_VIRTIO_MMIO_SPI_FIRST)
> >> > >   | ^~
> >> > > 
> >> > > as there is an incorrect comparision in include/hw/xen/xen_native.h
> >> > > which means that settings like GUEST_VIRTIO_MMIO_SPI_LAST
> >> > > aren't being defined for xen-4.18.0
> >> > 
> >> > The conditions in arch-arm.h for xen 4.18 show:
> >> > 
> >> > $ cppi arch-arm.h | grep -E '(#.*if)|MMIO'
> >> > #ifndef __XEN_PUBLIC_ARCH_ARM_H__
> >> > # if defined(__XEN__) || defined(__XEN_TOOLS__) || defined(__GNUC__)
> >> > # endif
> >> > # ifndef __ASSEMBLY__
> >> > #  if defined(__XEN__) || defined(__XEN_TOOLS__)
> >> > #   if defined(__GNUC__) && !defined(__STRICT_ANSI__)
> >> > #   endif
> >> > #  endif /* __XEN__ || __XEN_TOOLS__ */
> >> > # endif
> >> > # if defined(__XEN__) || defined(__XEN_TOOLS__)
> >> > #  define PSR_MODE_BIT  0x10U /* Set iff AArch32 */
> >> > /* Virtio MMIO mappings */
> >> > #  define GUEST_VIRTIO_MMIO_BASE   xen_mk_ullong(0x0200)
> >> > #  define GUEST_VIRTIO_MMIO_SIZE   xen_mk_ullong(0x0010)
> >> > #  define GUEST_VIRTIO_MMIO_SPI_FIRST   33
> >> > #  define GUEST_VIRTIO_MMIO_SPI_LAST43
> >> > # endif
> >> > # ifndef __ASSEMBLY__
> >> > # endif
> >> > #endif /*  __XEN_PUBLIC_ARCH_ARM_H__ */
> >> > 
> >> > So the MMIO constants are available if __XEN__ or __XEN_TOOLS__
> >> > are defined. This is no different to the condition that was
> >> > present in Xen 4.17.
> >> > 
> >> > What you didn't mention was that the Fedora build failure is
> >> > seen on an x86_64 host, when building the aarch64 target QEMU,
> >> > and I think this is the key issue.
> >> 
> >> Hi Daniel, thanks for looking into it.
> >> 
> >> - you are building on a x86_64 host
> >> - the target is aarch64
> >> - the target is the aarch64 Xen PVH machine (xen_arm.c)
> >> 
> >> But is the resulting QEMU binary expected to be an x86 binary? Or are
> >> you cross compiling ARM binaries on a x86 host?
> >> 
> >> In other word, is the resulting QEMU binary expected to run on ARM or
> >> x86?
> >> 
> >> 
> >> > Are we expecting to build Xen support for non-arch native QEMU
> >> > system binaries or not ?
> >> 
> >> The ARM xenpvh machine (xen_arm.c) is meant to work with Xen on ARM, not
> >> Xen on x86.  So this is only expected to work if you are
> >> cross-compiling. But you can cross-compile both Xen and QEMU, and I am
> >> pretty sure that Yocto is able to build Xen, Xen userspace tools, and
> >> QEMU for Xen/ARM on an x86 host today.
> >> 
> >> 
> >> > The constants are defined in arch-arm.h, which is only included
> >> > under:
> >> > 
> >> >   #if defined(__i386__) || defined(__x86_64__)
> >> >   #include "arch-x86/xen.h"
> >> >   #elif defined(__arm__) || defined (__aarch64__)
> >> >   #include "arch-arm.h"
> >> >   #else
> >> >   #error "Unsupported architecture"
> >> >   #endif
> >> > 
> >> > 
> >> > When we are building on an x86_64 host, we not going to get
> >> > arch-arm.h included, even if we're trying to build the aarch64
> >> > system emulator.
> >> > 
> >> > I don't know how this is supposed to work ?
> >> 
> >> It looks like a host vs. target architecture mismatch: the #if defined
> >> (__aarch64__) check should pass I think.
> >
> >
> > Building qemu with something like:
> > ./configure --enable-xen --cpu=x86_64
> > used to work. Can we fix that? It still works with v8.1.0.
> > At least, it works on x86, I never really try to build qemu for arm.
> > Notice that there's no "--target-list" on the configure command line.
> > I don't know if --cpu is useful here.
> >
> > Looks like the first commit where the build doesn't work is
> > 7899f6589b78 ("xen_arm: Add virtual PCIe host bridge support").
> 
> I am currently trying to upstream this patch. It is in the QEMU mailing
> list but it was never accepted. It is not reviewed in fact. I'll take a
> look at it, but I don't understand how did you get in the first place.

Sorry, I got the wrong commit pasted, I actually meant:
0c8ab1cddd6c ("xen_arm: Create virtio-mmio devices during initialization")

-- 
Anthony PERARD



Re: [PATCH] fix qemu build with xen-4.18.0

2023-12-12 Thread Stefan Hajnoczi
On Tue, 12 Dec 2023 at 10:36, Volodymyr Babchuk
 wrote:
>
> Hi Anthony
>
> Anthony PERARD  writes:
>
> > On Fri, Dec 08, 2023 at 02:49:27PM -0800, Stefano Stabellini wrote:
> >> On Fri, 8 Dec 2023, Daniel P. Berrangé wrote:
> >> > On Thu, Dec 07, 2023 at 11:12:48PM +, Michael Young wrote:
> >> > > Builds of qemu-8.2.0rc2 with xen-4.18.0 are currently failing
> >> > > with errors like
> >> > > ../hw/arm/xen_arm.c:74:5: error: ‘GUEST_VIRTIO_MMIO_SPI_LAST’ 
> >> > > undeclared (first use in this function)
> >> > >74 |(GUEST_VIRTIO_MMIO_SPI_LAST - GUEST_VIRTIO_MMIO_SPI_FIRST)
> >> > >   | ^~
> >> > >
> >> > > as there is an incorrect comparision in include/hw/xen/xen_native.h
> >> > > which means that settings like GUEST_VIRTIO_MMIO_SPI_LAST
> >> > > aren't being defined for xen-4.18.0
> >> >
> >> > The conditions in arch-arm.h for xen 4.18 show:
> >> >
> >> > $ cppi arch-arm.h | grep -E '(#.*if)|MMIO'
> >> > #ifndef __XEN_PUBLIC_ARCH_ARM_H__
> >> > # if defined(__XEN__) || defined(__XEN_TOOLS__) || defined(__GNUC__)
> >> > # endif
> >> > # ifndef __ASSEMBLY__
> >> > #  if defined(__XEN__) || defined(__XEN_TOOLS__)
> >> > #   if defined(__GNUC__) && !defined(__STRICT_ANSI__)
> >> > #   endif
> >> > #  endif /* __XEN__ || __XEN_TOOLS__ */
> >> > # endif
> >> > # if defined(__XEN__) || defined(__XEN_TOOLS__)
> >> > #  define PSR_MODE_BIT  0x10U /* Set iff AArch32 */
> >> > /* Virtio MMIO mappings */
> >> > #  define GUEST_VIRTIO_MMIO_BASE   xen_mk_ullong(0x0200)
> >> > #  define GUEST_VIRTIO_MMIO_SIZE   xen_mk_ullong(0x0010)
> >> > #  define GUEST_VIRTIO_MMIO_SPI_FIRST   33
> >> > #  define GUEST_VIRTIO_MMIO_SPI_LAST43
> >> > # endif
> >> > # ifndef __ASSEMBLY__
> >> > # endif
> >> > #endif /*  __XEN_PUBLIC_ARCH_ARM_H__ */
> >> >
> >> > So the MMIO constants are available if __XEN__ or __XEN_TOOLS__
> >> > are defined. This is no different to the condition that was
> >> > present in Xen 4.17.
> >> >
> >> > What you didn't mention was that the Fedora build failure is
> >> > seen on an x86_64 host, when building the aarch64 target QEMU,
> >> > and I think this is the key issue.
> >>
> >> Hi Daniel, thanks for looking into it.
> >>
> >> - you are building on a x86_64 host
> >> - the target is aarch64
> >> - the target is the aarch64 Xen PVH machine (xen_arm.c)
> >>
> >> But is the resulting QEMU binary expected to be an x86 binary? Or are
> >> you cross compiling ARM binaries on a x86 host?
> >>
> >> In other word, is the resulting QEMU binary expected to run on ARM or
> >> x86?
> >>
> >>
> >> > Are we expecting to build Xen support for non-arch native QEMU
> >> > system binaries or not ?
> >>
> >> The ARM xenpvh machine (xen_arm.c) is meant to work with Xen on ARM, not
> >> Xen on x86.  So this is only expected to work if you are
> >> cross-compiling. But you can cross-compile both Xen and QEMU, and I am
> >> pretty sure that Yocto is able to build Xen, Xen userspace tools, and
> >> QEMU for Xen/ARM on an x86 host today.
> >>
> >>
> >> > The constants are defined in arch-arm.h, which is only included
> >> > under:
> >> >
> >> >   #if defined(__i386__) || defined(__x86_64__)
> >> >   #include "arch-x86/xen.h"
> >> >   #elif defined(__arm__) || defined (__aarch64__)
> >> >   #include "arch-arm.h"
> >> >   #else
> >> >   #error "Unsupported architecture"
> >> >   #endif
> >> >
> >> >
> >> > When we are building on an x86_64 host, we not going to get
> >> > arch-arm.h included, even if we're trying to build the aarch64
> >> > system emulator.
> >> >
> >> > I don't know how this is supposed to work ?
> >>
> >> It looks like a host vs. target architecture mismatch: the #if defined
> >> (__aarch64__) check should pass I think.
> >
> >
> > Building qemu with something like:
> > ./configure --enable-xen --cpu=x86_64
> > used to work. Can we fix that? It still works with v8.1.0.
> > At least, it works on x86, I never really try to build qemu for arm.
> > Notice that there's no "--target-list" on the configure command line.
> > I don't know if --cpu is useful here.
> >
> > Looks like the first commit where the build doesn't work is
> > 7899f6589b78 ("xen_arm: Add virtual PCIe host bridge support").
>
> I am currently trying to upstream this patch. It is in the QEMU mailing
> list but it was never accepted. It is not reviewed in fact. I'll take a
> look at it, but I don't understand how did you get in the first place.

Hi Volodymyr,
Paolo Bonzini sent a pull request with similar code changes this
morning and I have merged it into the qemu.git/staging branch:
https://gitlab.com/qemu-project/qemu/-/commit/eaae59af4035770975b0ce9364b587223a909501

If you spot something that is not correct, please reply here.

Thanks!

Stefan

>
> --
> WBR, Volodymyr



  1   2   3   >