[PATCH 06/10] target/arm: Move arm_current_el() and arm_el_is_aa64() to internals.h

2025-03-06 Thread Peter Maydell
The functions arm_current_el() and arm_el_is_aa64() are used only in
target/arm and in hw/intc/arm_gicv3_cpuif.c.  They're functions that
query internal state of the CPU.  Move them out of cpu.h and into
internals.h.

This means we need to include internals.h in arm_gicv3_cpuif.c, but
this is justifiable because that file is implementing the GICv3 CPU
interface, which really is part of the CPU proper; we just ended up
implementing it in code in hw/intc/ for historical reasons.

The motivation for this move is that we'd like to change
arm_el_is_aa64() to add a condition that uses cpu_isar_feature();
but we don't want to include cpu-features.h in cpu.h.

Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h  | 66 --
 target/arm/internals.h| 67 +++
 hw/intc/arm_gicv3_cpuif.c |  1 +
 target/arm/arch_dump.c|  1 +
 4 files changed, 69 insertions(+), 66 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 16c9083be61..a779fd5ae94 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2633,39 +2633,6 @@ uint64_t arm_hcr_el2_eff_secstate(CPUARMState *env, 
ARMSecuritySpace space);
 uint64_t arm_hcr_el2_eff(CPUARMState *env);
 uint64_t arm_hcrx_el2_eff(CPUARMState *env);
 
-/* Return true if the specified exception level is running in AArch64 state. */
-static inline bool arm_el_is_aa64(CPUARMState *env, int el)
-{
-/* This isn't valid for EL0 (if we're in EL0, is_a64() is what you want,
- * and if we're not in EL0 then the state of EL0 isn't well defined.)
- */
-assert(el >= 1 && el <= 3);
-bool aa64 = arm_feature(env, ARM_FEATURE_AARCH64);
-
-/* The highest exception level is always at the maximum supported
- * register width, and then lower levels have a register width controlled
- * by bits in the SCR or HCR registers.
- */
-if (el == 3) {
-return aa64;
-}
-
-if (arm_feature(env, ARM_FEATURE_EL3) &&
-((env->cp15.scr_el3 & SCR_NS) || !(env->cp15.scr_el3 & SCR_EEL2))) {
-aa64 = aa64 && (env->cp15.scr_el3 & SCR_RW);
-}
-
-if (el == 2) {
-return aa64;
-}
-
-if (arm_is_el2_enabled(env)) {
-aa64 = aa64 && (env->cp15.hcr_el2 & HCR_RW);
-}
-
-return aa64;
-}
-
 /*
  * Function for determining whether guest cp register reads and writes should
  * access the secure or non-secure bank of a cp register.  When EL3 is
@@ -2697,39 +2664,6 @@ static inline bool arm_v7m_is_handler_mode(CPUARMState 
*env)
 return env->v7m.exception != 0;
 }
 
-/* Return the current Exception Level (as per ARMv8; note that this differs
- * from the ARMv7 Privilege Level).
- */
-static inline int arm_current_el(CPUARMState *env)
-{
-if (arm_feature(env, ARM_FEATURE_M)) {
-return arm_v7m_is_handler_mode(env) ||
-!(env->v7m.control[env->v7m.secure] & 1);
-}
-
-if (is_a64(env)) {
-return extract32(env->pstate, 2, 2);
-}
-
-switch (env->uncached_cpsr & 0x1f) {
-case ARM_CPU_MODE_USR:
-return 0;
-case ARM_CPU_MODE_HYP:
-return 2;
-case ARM_CPU_MODE_MON:
-return 3;
-default:
-if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
-/* If EL3 is 32-bit then all secure privileged modes run in
- * EL3
- */
-return 3;
-}
-
-return 1;
-}
-}
-
 /**
  * write_list_to_cpustate
  * @cpu: ARMCPU
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 70d1f88c20b..b3f732233f4 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -392,6 +392,73 @@ static inline FloatRoundMode arm_rmode_to_sf(ARMFPRounding 
rmode)
 return arm_rmode_to_sf_map[rmode];
 }
 
+/* Return true if the specified exception level is running in AArch64 state. */
+static inline bool arm_el_is_aa64(CPUARMState *env, int el)
+{
+/*
+ * This isn't valid for EL0 (if we're in EL0, is_a64() is what you want,
+ * and if we're not in EL0 then the state of EL0 isn't well defined.)
+ */
+assert(el >= 1 && el <= 3);
+bool aa64 = arm_feature(env, ARM_FEATURE_AARCH64);
+
+/*
+ * The highest exception level is always at the maximum supported
+ * register width, and then lower levels have a register width controlled
+ * by bits in the SCR or HCR registers.
+ */
+if (el == 3) {
+return aa64;
+}
+
+if (arm_feature(env, ARM_FEATURE_EL3) &&
+((env->cp15.scr_el3 & SCR_NS) || !(env->cp15.scr_el3 & SCR_EEL2))) {
+aa64 = aa64 && (env->cp15.scr_el3 & SCR_RW);
+}
+
+if (el == 2) {
+return aa64;
+}
+
+if (arm_is_el2_enabled(env)) {
+aa64 = aa64 && (env->cp15.hcr_el2 & HCR_RW);
+}
+
+return aa64;
+}
+
+/*
+ * Return the current Exception Level (as per ARMv8; note that this differs
+ * from the ARMv7 Privilege Level).
+ */
+static inline int arm_current_el(CPUARMState *env)
+{
+if (arm_feature(env, A

Re: [PATCH 01/10] target/arm: Move A32_BANKED_REG_{GET, SET} macros to cpregs.h

2025-03-06 Thread Richard Henderson

On 3/6/25 08:39, Peter Maydell wrote:

The A32_BANKED_REG_{GET,SET} macros are only used inside target/arm;
move their definitions to cpregs.h. There's no need to have them
defined in all the code that includes cpu.h.

Signed-off-by: Peter Maydell
---
  target/arm/cpregs.h | 28 
  target/arm/cpu.h| 27 ---
  2 files changed, 28 insertions(+), 27 deletions(-)


Reviewed-by: Richard Henderson 

r~



[PATCH] include/exec: Move TARGET_PAGE_{SIZE, MASK, BITS} to target_page.h

2025-03-06 Thread Richard Henderson
Re-use the TARGET_PAGE_BITS_VARY mechanism to define
TARGET_PAGE_SIZE and friends when not compiling per-target.
Inline qemu_target_page_{size,mask,bits} as they are now trivial.

Signed-off-by: Richard Henderson 
---

After this, we could in fact remove qemu_target_page_foo(), etc.
We certainly don't need to convert any more uses of TARGET_PAGE_FOO.

r~

---
 include/exec/cpu-all.h | 21 +-
 include/exec/poison.h  |  5 
 include/exec/target_page.h | 58 ++
 page-target.c  | 18 
 page-vary-target.c |  2 ++
 5 files changed, 55 insertions(+), 49 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 09f537d06f..8f7aebb088 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -105,26 +105,7 @@ static inline void stl_phys_notdirty(AddressSpace *as, 
hwaddr addr, uint32_t val
 
 /* page related stuff */
 #include "exec/cpu-defs.h"
-#ifdef TARGET_PAGE_BITS_VARY
-# include "exec/page-vary.h"
-extern const TargetPageBits target_page;
-# ifdef CONFIG_DEBUG_TCG
-#  define TARGET_PAGE_BITS   ({ assert(target_page.decided); \
-target_page.bits; })
-#  define TARGET_PAGE_MASK   ({ assert(target_page.decided); \
-(target_long)target_page.mask; })
-# else
-#  define TARGET_PAGE_BITS   target_page.bits
-#  define TARGET_PAGE_MASK   ((target_long)target_page.mask)
-# endif
-# define TARGET_PAGE_SIZE(-(int)TARGET_PAGE_MASK)
-#else
-# define TARGET_PAGE_BITS_MIN TARGET_PAGE_BITS
-# define TARGET_PAGE_SIZE(1 << TARGET_PAGE_BITS)
-# define TARGET_PAGE_MASK((target_long)-1 << TARGET_PAGE_BITS)
-#endif
-
-#define TARGET_PAGE_ALIGN(addr) ROUND_UP((addr), TARGET_PAGE_SIZE)
+#include "exec/target_page.h"
 
 CPUArchState *cpu_copy(CPUArchState *env);
 
diff --git a/include/exec/poison.h b/include/exec/poison.h
index f4283f693a..ce43a12965 100644
--- a/include/exec/poison.h
+++ b/include/exec/poison.h
@@ -44,11 +44,6 @@
 #pragma GCC poison TARGET_FMT_ld
 #pragma GCC poison TARGET_FMT_lu
 
-#pragma GCC poison TARGET_PAGE_SIZE
-#pragma GCC poison TARGET_PAGE_MASK
-#pragma GCC poison TARGET_PAGE_BITS
-#pragma GCC poison TARGET_PAGE_ALIGN
-
 #pragma GCC poison CPU_INTERRUPT_HARD
 #pragma GCC poison CPU_INTERRUPT_EXITTB
 #pragma GCC poison CPU_INTERRUPT_HALT
diff --git a/include/exec/target_page.h b/include/exec/target_page.h
index 98ffbb5c23..8e89e5cbe6 100644
--- a/include/exec/target_page.h
+++ b/include/exec/target_page.h
@@ -14,10 +14,56 @@
 #ifndef EXEC_TARGET_PAGE_H
 #define EXEC_TARGET_PAGE_H
 
-size_t qemu_target_page_size(void);
-int qemu_target_page_mask(void);
-int qemu_target_page_bits(void);
-int qemu_target_page_bits_min(void);
-
-size_t qemu_target_pages_to_MiB(size_t pages);
+/*
+ * If compiling per-target, get the real values.
+ * For generic code, reuse the mechanism for variable page size.
+ */
+#ifdef COMPILING_PER_TARGET
+#include "cpu-param.h"
+#include "exec/target_long.h"
+#define TARGET_PAGE_TYPE  target_long
+#else
+#define TARGET_PAGE_BITS_VARY
+#define TARGET_PAGE_TYPE  int
+#endif
+
+#ifdef TARGET_PAGE_BITS_VARY
+# include "exec/page-vary.h"
+extern const TargetPageBits target_page;
+# ifdef CONFIG_DEBUG_TCG
+#  define TARGET_PAGE_BITS   ({ assert(target_page.decided); \
+target_page.bits; })
+#  define TARGET_PAGE_MASK   ({ assert(target_page.decided); \
+(TARGET_PAGE_TYPE)target_page.mask; })
+# else
+#  define TARGET_PAGE_BITS   target_page.bits
+#  define TARGET_PAGE_MASK   ((TARGET_PAGE_TYPE)target_page.mask)
+# endif
+# define TARGET_PAGE_SIZE(-(int)TARGET_PAGE_MASK)
+#else
+# define TARGET_PAGE_BITS_MIN TARGET_PAGE_BITS
+# define TARGET_PAGE_SIZE(1 << TARGET_PAGE_BITS)
+# define TARGET_PAGE_MASK((TARGET_PAGE_TYPE)-1 << TARGET_PAGE_BITS)
+#endif
+
+#define TARGET_PAGE_ALIGN(addr) ROUND_UP((addr), TARGET_PAGE_SIZE)
+
+static inline size_t qemu_target_page_size(void)
+{
+return TARGET_PAGE_SIZE;
+}
+
+static inline int qemu_target_page_mask(void)
+{
+return TARGET_PAGE_MASK;
+}
+
+static inline int qemu_target_page_bits(void)
+{
+return TARGET_PAGE_BITS;
+}
+
+int qemu_target_page_bits_min(void);
+size_t qemu_target_pages_to_MiB(size_t pages);
+
 #endif
diff --git a/page-target.c b/page-target.c
index 82211c8593..321e43d06f 100644
--- a/page-target.c
+++ b/page-target.c
@@ -8,24 +8,6 @@
 
 #include "qemu/osdep.h"
 #include "exec/target_page.h"
-#include "exec/cpu-defs.h"
-#include "cpu.h"
-#include "exec/cpu-all.h"
-
-size_t qemu_target_page_size(void)
-{
-return TARGET_PAGE_SIZE;
-}
-
-int qemu_target_page_mask(void)
-{
-return TARGET_PAGE_MASK;
-}
-
-int qemu_target_page_bits(void)
-{
-return TARGET_PAGE_BITS;
-}
 
 int qemu_target_page_bits_min(void)
 {
diff --git a/page-vary-target.c b/page-vary-target.c
index 343b4adb95..1b4a9a10be 100644
--- a/page-vary-target.c
+++ b/page-vary-target.c
@@ -37,5 +3

Re: [PATCH] accel/tcg: Restrict CPU_TLB_DYN_*_BITS definitions to accel/tcg/

2025-03-06 Thread Richard Henderson

On 3/5/25 11:18, Philippe Mathieu-Daudé wrote:

CPU_TLB_DYN_*_BITS definitions are only used by accel/tcg/cputlb.c
and accel/tcg/translate-all.c. Move them to accel/tcg/tb-internal.h.

Signed-off-by: Philippe Mathieu-Daudé 
---
  accel/tcg/tb-internal.h | 27 +++
  include/exec/cpu-defs.h | 26 --
  2 files changed, 27 insertions(+), 26 deletions(-)


Reviewed-by: Richard Henderson 

r~



diff --git a/accel/tcg/tb-internal.h b/accel/tcg/tb-internal.h
index 90be61f296a..abd423fcf58 100644
--- a/accel/tcg/tb-internal.h
+++ b/accel/tcg/tb-internal.h
@@ -13,6 +13,33 @@
  #include "exec/exec-all.h"
  #include "exec/translation-block.h"
  
+#ifdef CONFIG_SOFTMMU

+
+#define CPU_TLB_DYN_MIN_BITS 6
+#define CPU_TLB_DYN_DEFAULT_BITS 8
+
+# if HOST_LONG_BITS == 32
+/* Make sure we do not require a double-word shift for the TLB load */
+#  define CPU_TLB_DYN_MAX_BITS (32 - TARGET_PAGE_BITS)
+# else /* HOST_LONG_BITS == 64 */
+/*
+ * Assuming TARGET_PAGE_BITS==12, with 2**22 entries we can cover 2**(22+12) ==
+ * 2**34 == 16G of address space. This is roughly what one would expect a
+ * TLB to cover in a modern (as of 2018) x86_64 CPU. For instance, Intel
+ * Skylake's Level-2 STLB has 16 1G entries.
+ * Also, make sure we do not size the TLB past the guest's address space.
+ */
+#  ifdef TARGET_PAGE_BITS_VARY
+#   define CPU_TLB_DYN_MAX_BITS  \
+MIN(22, TARGET_VIRT_ADDR_SPACE_BITS - TARGET_PAGE_BITS)
+#  else
+#   define CPU_TLB_DYN_MAX_BITS  \
+MIN_CONST(22, TARGET_VIRT_ADDR_SPACE_BITS - TARGET_PAGE_BITS)
+#  endif
+# endif
+
+#endif /* CONFIG_SOFTMMU */
+
  #ifdef CONFIG_USER_ONLY
  #include "user/page-protection.h"
  /*
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index ae18398fa99..9f955f53fde 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -46,30 +46,4 @@
  
  #include "exec/target_long.h"
  
-#if defined(CONFIG_SOFTMMU) && defined(CONFIG_TCG)

-#define CPU_TLB_DYN_MIN_BITS 6
-#define CPU_TLB_DYN_DEFAULT_BITS 8
-
-# if HOST_LONG_BITS == 32
-/* Make sure we do not require a double-word shift for the TLB load */
-#  define CPU_TLB_DYN_MAX_BITS (32 - TARGET_PAGE_BITS)
-# else /* HOST_LONG_BITS == 64 */
-/*
- * Assuming TARGET_PAGE_BITS==12, with 2**22 entries we can cover 2**(22+12) ==
- * 2**34 == 16G of address space. This is roughly what one would expect a
- * TLB to cover in a modern (as of 2018) x86_64 CPU. For instance, Intel
- * Skylake's Level-2 STLB has 16 1G entries.
- * Also, make sure we do not size the TLB past the guest's address space.
- */
-#  ifdef TARGET_PAGE_BITS_VARY
-#   define CPU_TLB_DYN_MAX_BITS  \
-MIN(22, TARGET_VIRT_ADDR_SPACE_BITS - TARGET_PAGE_BITS)
-#  else
-#   define CPU_TLB_DYN_MAX_BITS  \
-MIN_CONST(22, TARGET_VIRT_ADDR_SPACE_BITS - TARGET_PAGE_BITS)
-#  endif
-# endif
-
-#endif /* CONFIG_SOFTMMU && CONFIG_TCG */
-
  #endif





Re: [PATCH 10/10] target/arm: Forbid return to AArch32 when CPU is AArch64-only

2025-03-06 Thread Richard Henderson

On 3/6/25 08:39, Peter Maydell wrote:

In the Arm ARM, rule R_TYTWB states that returning to AArch32
is an illegal exception return if:
  * AArch32 is not supported at any exception level
  * the target EL is configured for AArch64 via SCR_EL3.RW
or HCR_EL2.RW or via CPU state at reset

We check the second of these, but not the first (which can only be
relevant for the case of a return to EL0, because if AArch32 is not
supported at one of the higher ELs then the RW bits will have an
effective value of 1 and the the "configured for AArch64" condition
will hold also).

Add the missing condition. This isn't currently a bug because
all our CPUs support AArch32 at EL0, but future CPUs we add
might be 64-bit only.

Signed-off-by: Peter Maydell
---
  target/arm/tcg/helper-a64.c | 5 +
  1 file changed, 5 insertions(+)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 04/10] linux-user/arm: Remove unused get_put_user macros

2025-03-06 Thread Richard Henderson

On 3/6/25 08:39, Peter Maydell wrote:

In linux-user/arm/cpu_loop.c we define a full set of get/put
macros for both code and data (since the endianness handling
is different between the two). However the only one we actually
use is get_user_code_u32(). Remove the rest.

We leave a comment noting how data-side accesses should be handled
for big-endian, because that's a subtle point and we just removed the
macros that were effectively documenting it.

Signed-off-by: Peter Maydell
---
  linux-user/arm/cpu_loop.c | 43 ---
  1 file changed, 4 insertions(+), 39 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 2/7] target/riscv: env->misa_mxl is a constant

2025-03-06 Thread Alistair Francis
On Thu, Mar 6, 2025 at 11:00 PM Paolo Bonzini  wrote:
>
> On 3/6/25 02:16, Alistair Francis wrote:
> > On Wed, Feb 19, 2025 at 3:01 AM Paolo Bonzini  wrote:
> >>
> >> There is nothing that overwrites env->misa_mxl, so it is a constant.  Do
> >
> > The idea is that misa_mxl can change, although that's not supported now.
>
> At run-time, or only at configuration time (before realize)?

Runtime, at least kind of

The RISC-V spec 1.12 and earlier allows MXL to change at runtime by
writing to misa.MXL. QEMU doesn't support this and AFAIK no hardware
does either, but it was something that we might support in the future
(hence the split).

The latest RISC-V priv spec has changed misa.MXL to be read only though.

So I guess although in theory it can be changed at runtime, we are
probably never going to support that now that it's deprecated.

Now that the latest priv spec has dropped the ability to write to
misa.MXL we will probably work towards just consolidating misa_mxl_max
and misa_mxl into a single value that is constant after realise.

>
> >> not let a corrupted migration stream change the value; changing misa_mxl
> >
> > Does this actually happen? If the migration data is corrupted won't we
> > have all sorts of strange issues?
>
> Generally migration data (just like disk image formats) is treated as
> security-sensitive, overriding any other considerations.  So you have to
> assume that the corruption is intentional, and sneaky enough to cause
> trouble.

I'm not convinced that this is the thing that we should be checking
for. If someone can corrupt the migration data for an attack there are
better things to change then the MXL

Alistair

>
> Paolo
>
> > Alistair
> >
> >> would have a snowball effect on, for example, the valid VM modes.
> >>
> >> Signed-off-by: Paolo Bonzini 
> >> ---
> >>   target/riscv/machine.c | 13 +
> >>   1 file changed, 13 insertions(+)
> >>
> >> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> >> index d8445244ab2..c3d8e7c4005 100644
> >> --- a/target/riscv/machine.c
> >> +++ b/target/riscv/machine.c
> >> @@ -375,6 +375,18 @@ static const VMStateDescription vmstate_ssp = {
> >>   }
> >>   };
> >>
> >> +static bool riscv_validate_misa_mxl(void *opaque, int version_id)
> >> +{
> >> +RISCVCPU *cpu = RISCV_CPU(opaque);
> >> +CPURISCVState *env = &cpu->env;
> >> +RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
> >> +uint32_t misa_mxl_saved = env->misa_mxl;
> >> +
> >> +/* Preserve misa_mxl even if the migration stream corrupted it  */
> >> +env->misa_mxl = mcc->misa_mxl_max;
> >> +return misa_mxl_saved == mcc->misa_mxl_max;
> >> +}
> >> +
> >>   const VMStateDescription vmstate_riscv_cpu = {
> >>   .name = "cpu",
> >>   .version_id = 10,
> >> @@ -394,6 +406,7 @@ const VMStateDescription vmstate_riscv_cpu = {
> >>   VMSTATE_UINTTL(env.priv_ver, RISCVCPU),
> >>   VMSTATE_UINTTL(env.vext_ver, RISCVCPU),
> >>   VMSTATE_UINT32(env.misa_mxl, RISCVCPU),
> >> +VMSTATE_VALIDATE("MXL must match", riscv_validate_misa_mxl),
> >>   VMSTATE_UINT32(env.misa_ext, RISCVCPU),
> >>   VMSTATE_UNUSED(4),
> >>   VMSTATE_UINT32(env.misa_ext_mask, RISCVCPU),
> >> --
> >> 2.48.1
> >>
> >>
> >
> >
>



[PATCH v6 03/29] hw/intc/aspeed: Introduce dynamic allocation for regs array

2025-03-06 Thread Jamin Lin via
Currently, the size of the "regs" array is 0x2000, which is too large. To save
code size and avoid mapping large unused gaps, will update it to only map the
useful set of registers. This update will support multiple sub-regions with
different sizes.

To address the redundant size issue, replace the static "regs" array with a
dynamically allocated "regs" memory.

Introduce a new "aspeed_intc_unrealize" function to free the allocated "regs"
memory.

Signed-off-by: Jamin Lin 
---
 include/hw/intc/aspeed_intc.h |  2 +-
 hw/intc/aspeed_intc.c | 12 +++-
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 03324f05ab..47ea0520b5 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -27,7 +27,7 @@ struct AspeedINTCState {
 MemoryRegion iomem;
 MemoryRegion iomem_container;
 
-uint32_t regs[ASPEED_INTC_NR_REGS];
+uint32_t *regs;
 OrIRQState orgates[ASPEED_INTC_NR_INTS];
 qemu_irq output_pins[ASPEED_INTC_NR_INTS];
 
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 465f41e4fd..558901570f 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -289,7 +289,7 @@ static void aspeed_intc_reset(DeviceState *dev)
 {
 AspeedINTCState *s = ASPEED_INTC(dev);
 
-memset(s->regs, 0, sizeof(s->regs));
+memset(s->regs, 0, ASPEED_INTC_NR_REGS << 2);
 memset(s->enable, 0, sizeof(s->enable));
 memset(s->mask, 0, sizeof(s->mask));
 memset(s->pending, 0, sizeof(s->pending));
@@ -307,6 +307,7 @@ static void aspeed_intc_realize(DeviceState *dev, Error 
**errp)
 
 sysbus_init_mmio(sbd, &s->iomem_container);
 
+s->regs = g_new(uint32_t, ASPEED_INTC_NR_REGS);
 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
   TYPE_ASPEED_INTC ".regs", ASPEED_INTC_NR_REGS << 2);
 
@@ -322,12 +323,21 @@ static void aspeed_intc_realize(DeviceState *dev, Error 
**errp)
 }
 }
 
+static void aspeed_intc_unrealize(DeviceState *dev)
+{
+AspeedINTCState *s = ASPEED_INTC(dev);
+
+g_free(s->regs);
+s->regs = NULL;
+}
+
 static void aspeed_intc_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 
 dc->desc = "ASPEED INTC Controller";
 dc->realize = aspeed_intc_realize;
+dc->unrealize = aspeed_intc_unrealize;
 device_class_set_legacy_reset(dc, aspeed_intc_reset);
 dc->vmsd = NULL;
 }
-- 
2.43.0




[PATCH v5 14/29] hw/intc/aspeed: Introduce AspeedINTCIRQ structure to save the irq index and register address

2025-03-06 Thread Jamin Lin via
The INTC controller supports GICINT128 to GICINT136, mapping 1:1 to input and
output IRQs 0 to 8. Previously, the formula "address & 0x0f00" was used to
derive the IRQ index numbers.

However, the INTC controller also supports GICINT192_201, mapping 1 input IRQ
pin to 10 output IRQ pins. The pin numbers for input and output are different.
It is difficult to use a formula to determine the index number of INTC model
supported input and output IRQs.

To simplify and improve readability, introduces the AspeedINTCIRQ structure to
save the input/output IRQ index and its enable/status register address.

Introduce the "aspeed_2700_intc_irqs" table to store IRQ information for INTC.
Introduce the "aspeed_intc_get_irq" function to retrieve the input/output IRQ
pin index from the provided status/enable register address.

Signed-off-by: Jamin Lin 
---
 include/hw/intc/aspeed_intc.h | 10 
 hw/intc/aspeed_intc.c | 87 +++
 2 files changed, 58 insertions(+), 39 deletions(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 41b1f82d73..fa92e9eef2 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -19,6 +19,14 @@ OBJECT_DECLARE_TYPE(AspeedINTCState, AspeedINTCClass, 
ASPEED_INTC)
 #define ASPEED_INTC_MAX_INPINS 9
 #define ASPEED_INTC_MAX_OUTPINS 9
 
+typedef struct AspeedINTCIRQ {
+int inpin_idx;
+int outpin_idx;
+int num_outpins;
+uint32_t enable_reg;
+uint32_t status_reg;
+} AspeedINTCIRQ;
+
 struct AspeedINTCState {
 /*< private >*/
 SysBusDevice parent_obj;
@@ -46,6 +54,8 @@ struct AspeedINTCClass {
 uint64_t reg_size;
 uint64_t reg_offset;
 const MemoryRegionOps *reg_ops;
+const AspeedINTCIRQ *irq_table;
+int irq_table_count;
 };
 
 #endif /* ASPEED_INTC_H */
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 5b0d15f463..0ac59745f6 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -40,7 +40,23 @@ REG32(GICINT135_STATUS, 0x704)
 REG32(GICINT136_EN, 0x800)
 REG32(GICINT136_STATUS, 0x804)
 
-#define GICINT_STATUS_BASE R_GICINT128_STATUS
+static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic,
+uint32_t reg)
+{
+int i;
+
+for (i = 0; i < aic->irq_table_count; i++) {
+if (aic->irq_table[i].enable_reg == reg ||
+aic->irq_table[i].status_reg == reg) {
+return &aic->irq_table[i];
+}
+}
+
+/*
+ * Invalid reg.
+ */
+g_assert_not_reached();
+}
 
 /*
  * Update the state of an interrupt controller pin by setting
@@ -54,17 +70,7 @@ static void aspeed_intc_update(AspeedINTCState *s, int 
inpin_idx,
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
 const char *name = object_get_typename(OBJECT(s));
 
-if (inpin_idx >= aic->num_inpins) {
-qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid input pin index: %d\n",
-  __func__, inpin_idx);
-return;
-}
-
-if (outpin_idx >= aic->num_outpins) {
-qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid output pin index: %d\n",
-  __func__, outpin_idx);
-return;
-}
+assert((outpin_idx < aic->num_outpins) && (inpin_idx < aic->num_inpins));
 
 trace_aspeed_intc_update_irq(name, inpin_idx, outpin_idx, level);
 qemu_set_irq(s->output_pins[outpin_idx], level);
@@ -81,21 +87,20 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 AspeedINTCState *s = (AspeedINTCState *)opaque;
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
 const char *name = object_get_typename(OBJECT(s));
-uint32_t status_reg = GICINT_STATUS_BASE + ((0x100 * irq) >> 2);
+const AspeedINTCIRQ *intc_irq;
+uint32_t status_reg;
 uint32_t select = 0;
 uint32_t enable;
 int outpin_idx;
 int inpin_idx;
 int i;
 
-outpin_idx = irq;
-inpin_idx = irq;
+assert(irq < aic->num_inpins);
 
-if (irq >= aic->num_inpins) {
-qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid input pin index: %d\n",
-  __func__, irq);
-return;
-}
+intc_irq = &aic->irq_table[irq];
+status_reg = intc_irq->status_reg;
+outpin_idx = intc_irq->outpin_idx;
+inpin_idx = intc_irq->inpin_idx;
 
 trace_aspeed_intc_set_irq(name, inpin_idx, level);
 enable = s->enable[inpin_idx];
@@ -146,21 +151,16 @@ static void aspeed_intc_enable_handler(AspeedINTCState 
*s, hwaddr offset,
 {
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
 const char *name = object_get_typename(OBJECT(s));
+const AspeedINTCIRQ *intc_irq;
 uint32_t reg = offset >> 2;
 uint32_t old_enable;
 uint32_t change;
 int inpin_idx;
-uint32_t irq;
 
-irq = (offset & 0x0f00) >> 8;
-inpin_idx = irq;
+intc_irq = aspeed_intc_get_irq(aic, reg);
+inpin_idx = intc_irq->inpin_idx;
 
-if (inpin_idx >= aic->num_inpins) {
-

[PATCH] tests/functional/test_virtio_balloon: Only use KVM for running this test

2025-03-06 Thread Thomas Huth
The virtio_balloon test is currently hanging for unknown reasons
when being run on the shared gitlab CI runners (which don't provide
KVM, thus it's running in TCG mode there). All other functional tests
that use the same asset (the Fedora 31 kernel) have already been
marked to work only with KVM in the past, so those other tests are
skipped on the shared gitlab CI runners. As long as the problem isn't
fully understood and fixed, let's do the same with the virtio_balloon
test to avoid that the CI is failing here.

Signed-off-by: Thomas Huth 
---
 tests/functional/test_virtio_balloon.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/functional/test_virtio_balloon.py 
b/tests/functional/test_virtio_balloon.py
index 082bf08c4e8..5877b6c408c 100755
--- a/tests/functional/test_virtio_balloon.py
+++ b/tests/functional/test_virtio_balloon.py
@@ -110,6 +110,7 @@ def assert_running_stats(self, then):
 
 def test_virtio_balloon_stats(self):
 self.set_machine('q35')
+self.require_accelerator("kvm")
 kernel_path = self.ASSET_KERNEL.fetch()
 initrd_path = self.ASSET_INITRD.fetch()
 diskimage_path = self.ASSET_DISKIMAGE.fetch()
@@ -122,7 +123,7 @@ def test_virtio_balloon_stats(self):
 # reset, we can reliably catch the clean stats again in BIOS
 # phase before the guest OS launches
 self.vm.add_args("-boot", "menu=on")
-self.vm.add_args("-machine", "q35,accel=kvm:tcg")
+self.vm.add_args("-accel", "kvm")
 self.vm.add_args("-device", "virtio-balloon,id=balloon")
 self.vm.add_args('-drive',
  f'file={diskimage_path},if=none,id=drv0,snapshot=on')
-- 
2.48.1




[PATCH v6 13/29] hw/intc/aspeed: Refactor INTC to support separate input and output pin indices

2025-03-06 Thread Jamin Lin via
Refactors the INTC to distinguish between input and output pin indices,
improving interrupt handling clarity and accuracy.

Updated the functions to handle both input and output pin indices.
Added detailed logging for input and output pin indices in trace events.

These changes ensure that the INTC controller can handle multiple input and
output pins, improving support for the AST2700 A1.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/intc/aspeed_intc.c | 97 +++
 hw/intc/trace-events  | 12 +++---
 2 files changed, 67 insertions(+), 42 deletions(-)

diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 6f37afc17e..1cbee0e17a 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -42,20 +42,32 @@ REG32(GICINT136_STATUS, 0x804)
 
 #define GICINT_STATUS_BASE R_GICINT128_STATUS
 
-static void aspeed_intc_update(AspeedINTCState *s, int irq, int level)
+/*
+ * Update the state of an interrupt controller pin by setting
+ * the specified output pin to the given level.
+ * The input pin index should be between 0 and the number of input pins.
+ * The output pin index should be between 0 and the number of output pins.
+ */
+static void aspeed_intc_update(AspeedINTCState *s, int inpin_idx,
+   int outpin_idx, int level)
 {
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
 const char *name = object_get_typename(OBJECT(s));
 
-if (irq >= aic->num_inpins) {
-qemu_log_mask(LOG_GUEST_ERROR,
-  "%s: Invalid input pin index: %d\n",
-  __func__, irq);
+if (inpin_idx >= aic->num_inpins) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid input pin index: %d\n",
+  __func__, inpin_idx);
 return;
 }
 
-trace_aspeed_intc_update_irq(name, irq, level);
-qemu_set_irq(s->output_pins[irq], level);
+if (outpin_idx >= aic->num_outpins) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid output pin index: %d\n",
+  __func__, outpin_idx);
+return;
+}
+
+trace_aspeed_intc_update_irq(name, inpin_idx, outpin_idx, level);
+qemu_set_irq(s->output_pins[outpin_idx], level);
 }
 
 /*
@@ -72,23 +84,28 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 uint32_t status_reg = GICINT_STATUS_BASE + ((0x100 * irq) >> 2);
 uint32_t select = 0;
 uint32_t enable;
+int outpin_idx;
+int inpin_idx;
 int i;
 
+outpin_idx = irq;
+inpin_idx = irq;
+
 if (irq >= aic->num_inpins) {
 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid input pin index: %d\n",
   __func__, irq);
 return;
 }
 
-trace_aspeed_intc_set_irq(name, irq, level);
-enable = s->enable[irq];
+trace_aspeed_intc_set_irq(name, inpin_idx, level);
+enable = s->enable[inpin_idx];
 
 if (!level) {
 return;
 }
 
 for (i = 0; i < aic->num_lines; i++) {
-if (s->orgates[irq].levels[i]) {
+if (s->orgates[inpin_idx].levels[i]) {
 if (enable & BIT(i)) {
 select |= BIT(i);
 }
@@ -101,7 +118,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 
 trace_aspeed_intc_select(name, select);
 
-if (s->mask[irq] || s->regs[status_reg]) {
+if (s->mask[inpin_idx] || s->regs[status_reg]) {
 /*
  * a. mask is not 0 means in ISR mode
  * sources interrupt routine are executing.
@@ -110,16 +127,17 @@ static void aspeed_intc_set_irq(void *opaque, int irq, 
int level)
  *
  * save source interrupt to pending variable.
  */
-s->pending[irq] |= select;
-trace_aspeed_intc_pending_irq(name, irq, s->pending[irq]);
+s->pending[inpin_idx] |= select;
+trace_aspeed_intc_pending_irq(name, inpin_idx, s->pending[inpin_idx]);
 } else {
 /*
  * notify firmware which source interrupt are coming
  * by setting status register
  */
 s->regs[status_reg] = select;
-trace_aspeed_intc_trigger_irq(name, irq, s->regs[status_reg]);
-aspeed_intc_update(s, irq, 1);
+trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
+  s->regs[status_reg]);
+aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
 }
 }
 
@@ -131,14 +149,16 @@ static void aspeed_intc_enable_handler(AspeedINTCState 
*s, hwaddr offset,
 uint32_t reg = offset >> 2;
 uint32_t old_enable;
 uint32_t change;
+int inpin_idx;
 uint32_t irq;
 
 irq = (offset & 0x0f00) >> 8;
+inpin_idx = irq;
 
-if (irq >= aic->num_inpins) {
+if (inpin_idx >= aic->num_inpins) {
 qemu_log_mask(LOG_GUEST_ERROR,
   "%s: Invalid input pin index: %d\n",
-  __func__, irq);
+  __func__, inpin_idx);
 return;
 }
 
@@ -149,17 +169,17 @@ static

[PATCH v6 14/29] hw/intc/aspeed: Introduce AspeedINTCIRQ structure to save the irq index and register address

2025-03-06 Thread Jamin Lin via
The INTC controller supports GICINT128 to GICINT136, mapping 1:1 to input and
output IRQs 0 to 8. Previously, the formula "address & 0x0f00" was used to
derive the IRQ index numbers.

However, the INTC controller also supports GICINT192_201, mapping 1 input IRQ
pin to 10 output IRQ pins. The pin numbers for input and output are different.
It is difficult to use a formula to determine the index number of INTC model
supported input and output IRQs.

To simplify and improve readability, introduces the AspeedINTCIRQ structure to
save the input/output IRQ index and its enable/status register address.

Introduce the "aspeed_2700_intc_irqs" table to store IRQ information for INTC.
Introduce the "aspeed_intc_get_irq" function to retrieve the input/output IRQ
pin index from the provided status/enable register address.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 include/hw/intc/aspeed_intc.h | 10 
 hw/intc/aspeed_intc.c | 87 +++
 2 files changed, 58 insertions(+), 39 deletions(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 2a22e30846..e6c3a27264 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -19,6 +19,14 @@ OBJECT_DECLARE_TYPE(AspeedINTCState, AspeedINTCClass, 
ASPEED_INTC)
 #define ASPEED_INTC_MAX_INPINS 9
 #define ASPEED_INTC_MAX_OUTPINS 9
 
+typedef struct AspeedINTCIRQ {
+int inpin_idx;
+int outpin_idx;
+int num_outpins;
+uint32_t enable_reg;
+uint32_t status_reg;
+} AspeedINTCIRQ;
+
 struct AspeedINTCState {
 /*< private >*/
 SysBusDevice parent_obj;
@@ -46,6 +54,8 @@ struct AspeedINTCClass {
 uint64_t nr_regs;
 uint64_t reg_offset;
 const MemoryRegionOps *reg_ops;
+const AspeedINTCIRQ *irq_table;
+int irq_table_count;
 };
 
 #endif /* ASPEED_INTC_H */
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 1cbee0e17a..be24516ec9 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -40,7 +40,23 @@ REG32(GICINT135_STATUS, 0x704)
 REG32(GICINT136_EN, 0x800)
 REG32(GICINT136_STATUS, 0x804)
 
-#define GICINT_STATUS_BASE R_GICINT128_STATUS
+static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic,
+uint32_t reg)
+{
+int i;
+
+for (i = 0; i < aic->irq_table_count; i++) {
+if (aic->irq_table[i].enable_reg == reg ||
+aic->irq_table[i].status_reg == reg) {
+return &aic->irq_table[i];
+}
+}
+
+/*
+ * Invalid reg.
+ */
+g_assert_not_reached();
+}
 
 /*
  * Update the state of an interrupt controller pin by setting
@@ -54,17 +70,7 @@ static void aspeed_intc_update(AspeedINTCState *s, int 
inpin_idx,
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
 const char *name = object_get_typename(OBJECT(s));
 
-if (inpin_idx >= aic->num_inpins) {
-qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid input pin index: %d\n",
-  __func__, inpin_idx);
-return;
-}
-
-if (outpin_idx >= aic->num_outpins) {
-qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid output pin index: %d\n",
-  __func__, outpin_idx);
-return;
-}
+assert((outpin_idx < aic->num_outpins) && (inpin_idx < aic->num_inpins));
 
 trace_aspeed_intc_update_irq(name, inpin_idx, outpin_idx, level);
 qemu_set_irq(s->output_pins[outpin_idx], level);
@@ -81,21 +87,20 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 AspeedINTCState *s = (AspeedINTCState *)opaque;
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
 const char *name = object_get_typename(OBJECT(s));
-uint32_t status_reg = GICINT_STATUS_BASE + ((0x100 * irq) >> 2);
+const AspeedINTCIRQ *intc_irq;
+uint32_t status_reg;
 uint32_t select = 0;
 uint32_t enable;
 int outpin_idx;
 int inpin_idx;
 int i;
 
-outpin_idx = irq;
-inpin_idx = irq;
+assert(irq < aic->num_inpins);
 
-if (irq >= aic->num_inpins) {
-qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid input pin index: %d\n",
-  __func__, irq);
-return;
-}
+intc_irq = &aic->irq_table[irq];
+status_reg = intc_irq->status_reg;
+outpin_idx = intc_irq->outpin_idx;
+inpin_idx = intc_irq->inpin_idx;
 
 trace_aspeed_intc_set_irq(name, inpin_idx, level);
 enable = s->enable[inpin_idx];
@@ -146,21 +151,16 @@ static void aspeed_intc_enable_handler(AspeedINTCState 
*s, hwaddr offset,
 {
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
 const char *name = object_get_typename(OBJECT(s));
+const AspeedINTCIRQ *intc_irq;
 uint32_t reg = offset >> 2;
 uint32_t old_enable;
 uint32_t change;
 int inpin_idx;
-uint32_t irq;
 
-irq = (offset & 0x0f00) >> 8;
-inpin_idx = irq;
+intc_irq = aspeed_intc_get_irq(aic, reg);
+inpin_idx = intc_irq->inpin_idx;
 
-if (inpin_i

Re: [PATCH 12/57] docs/qapi-domain: add :since: directive option

2025-03-06 Thread Markus Armbruster
John Snow  writes:

> Add a little special markup for registering "Since:" information. Adding
> it as an option instead of generic content lets us hoist the information
> into the Signature bar, optionally put it in the index, etc.
>
> Signed-off-by: John Snow 
> ---
>  docs/sphinx/qapi_domain.py | 29 +++--
>  1 file changed, 27 insertions(+), 2 deletions(-)
>
> diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py
> index 6168c23936f..9919dacd4e6 100644
> --- a/docs/sphinx/qapi_domain.py
> +++ b/docs/sphinx/qapi_domain.py
> @@ -4,6 +4,7 @@
>  
>  from __future__ import annotations
>  
> +import re
>  from typing import (
>  TYPE_CHECKING,
>  AbstractSet,
> @@ -104,6 +105,18 @@ def process_link(
>  return title, target
>  
>  
> +def since_validator(param: str) -> str:
> +"""
> +Validate the `:since: X.Y` option field.
> +"""
> +match = re.match(r"[0-9]+\.[0-9]+", param)

This accepts arbitrary crap after the version.  Example:
"9.2.50v9.2.0-2253-ge8a0110293" is fine.  Intentional?

> +if not match:
> +raise ValueError(
> +f":since: requires a version number in X.Y format; not {param!r}"
> +)
> +return param

Schema validation is the frontend's job.  Ideally, a backend doesn't
report any errors.  The backends generating C don't.  A backend
generating docs has to: all the reST processing happens there, and
therefore reST errors can only be diagnosed there.  Since "no errors"
purity is impossible for this backend, we can be pragmatic about sinning
a bit more.

Still, I think this one should rather go into the doc comment parser.

This is not a demand.  We can always clean it up later.

> +
> +
>  # Alias for the return of handle_signature(), which is used in several 
> places.
>  # (In the Python domain, this is Tuple[str, str] instead.)
>  Signature = str
> @@ -124,6 +137,8 @@ class QAPIObject(ObjectDescription[Signature]):
>  {
>  # Borrowed from the Python domain:
>  "module": directives.unchanged,  # Override contextual module 
> name
> +# These are QAPI originals:
> +"since": since_validator,
>  }
>  )
>  
> @@ -135,9 +150,19 @@ def get_signature_prefix(self) -> List[nodes.Node]:
>  SpaceNode(" "),
>  ]
>  
> -def get_signature_suffix(self) -> list[nodes.Node]:
> +def get_signature_suffix(self) -> List[nodes.Node]:
>  """Returns a suffix to put after the object name in the signature."""
> -return []
> +ret: List[nodes.Node] = []
> +
> +if "since" in self.options:
> +ret += [
> +SpaceNode(" "),
> +addnodes.desc_sig_element(
> +"", f"(Since: {self.options['since']})"
> +),
> +]
> +
> +return ret
>  
>  def handle_signature(self, sig: str, signode: desc_signature) -> 
> Signature:
>  """




[PATCH] util/loongarch64: Add clang compiler support

2025-03-06 Thread Bibo Mao
Float register name f0 - f31 is not recognized with clang compiler
with LoongArch64 target, its name should be $f0 - $f31. It is ok
for both gcc and clang compiler.

Signed-off-by: Bibo Mao 
---
 host/include/loongarch64/host/bufferiszero.c.inc | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/host/include/loongarch64/host/bufferiszero.c.inc 
b/host/include/loongarch64/host/bufferiszero.c.inc
index 69891eac80..bb2598fdc3 100644
--- a/host/include/loongarch64/host/bufferiszero.c.inc
+++ b/host/include/loongarch64/host/bufferiszero.c.inc
@@ -61,7 +61,8 @@ static bool buffer_is_zero_lsx(const void *buf, size_t len)
 "2:"
 : "=&r"(ret), "+r"(p)
 : "r"(buf), "r"(e), "r"(l)
-: "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "fcc0");
+: "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8",
+  "$fcc0");
 
 return ret;
 }
@@ -119,7 +120,8 @@ static bool buffer_is_zero_lasx(const void *buf, size_t len)
 "3:"
 : "=&r"(ret), "+r"(p)
 : "r"(buf), "r"(e), "r"(l)
-: "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "fcc0");
+: "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8",
+  "$fcc0");
 
 return ret;
 }

base-commit: 661c2e1ab29cd9c4d268ae3f44712e8d421c0e56
-- 
2.39.3




Re: [PATCH v2 02/10] target/i386: disable PERFCORE when "-pmu" is configured

2025-03-06 Thread Zhao Liu
> 1. Remove "kvm_enabled() && IS_AMD_CPU(env)" since the bit is reserved by
> Intel.
> 
> 2. Add your Reviewed-by.

Yes, this is exactly what I mean!

Regards,
Zhao




Re: [PATCH v3 00/10] vfio/igd: Decoupling quirks with legacy mode

2025-03-06 Thread Corvin Köhne
On Thu, 2025-03-06 at 15:49 -0700, Alex Williamson wrote:
> On Fri,  7 Mar 2025 02:01:20 +0800
> Tomita Moeko  wrote:
> 
> > This patchset intends to decouple existing quirks from legacy mode.
> > Currently all quirks depends on legacy mode (except x-igd-opregion),
> > which includes following conditions:
> > * Machine type is i440fx
> > * IGD device is at guest BDF 00:02.0
> > * VBIOS in ROM BAR or file
> > * VGA IO/MMIO ranges are claimed by IGD
> > * OpRegion
> > * Same LPC bridge and Host bridge VID/DID/SVID/SSID as host
> > 
> > If one of the condition is not met, the quirks will not be applied.
> > However, for recent generations, espcially Gen 11+ devices that removed
> > VBIOS support, not all the conditions are required. For example, on EFI-
> > based systems, VBIOS ROM is unnecessary, and VGA ranges are not used.
> > 
> > To have better support on newer UEFI-based VMs, this patchset makes the
> > quirks independent of legacy mode. The BDSM and GGC register quirks are
> > applied to all supported IGD devices, new x-igd-lpc option for the LPC
> > bridge / Host bridge ID quirk is introduced for possible Q35 support.
> > It also prepares for supporting IGD passthrough when it is not primary
> > display later (kernel change will be merged in 6.15).
> > 
> > To maintain backward compatbility with exising configuration, legacy
> > mode will automatically be enabled when:
> > * Machine type is i440fx
> > * IGD device is at guest BDF 00:02.0
> > If the legacy mode behavior is unwanted, option x-igd-legacy-mode=off
> > is provided for users to disable it. Setting x-igd-legacy-mode=on checks
> > if the condition above are met, and set up all the required quirks.
> > 
> > The default value is x-igd-legacy-mode=auto. When the above conditions
> > are all met, it acts as before and continues on any error. Otherwise it
> > is equivalent to x-igd-legacy-mode=off.
> > 
> > When x-igd-legacy-mode is set to on or off, QEMU will fail immediately
> > on error.
> > 
> > The first 2 patches of this patchset was taken from a previous one,
> > details can be found at:
> > https://lore.kernel.org/all/20250124191245.12464-1-tomitamo...@gmail.com/
> > 
> > This patchest was mainly tested on Alder Lake UHD770, with Debian 12
> > (kernel 6.1), Windows 11 (driver 32.0.101.6458) and Intel GOP driver
> > 17.0.1081.
> > 
> > Due to I caught COVID these days, I am unable to deliver the proposed
> > documentation update before QEMU 10.0 soft-freeze next week. Please help
> > decide whether to make this patch series in 10.0 or next release.
> > 
> > Changelog:
> > v3:
> > * Use OnOffAuto for x-igd-legacy-mode option, default is auto, to keep
> >   current behavior.
> > * Added a new patch to solve the possible KVMGT/GVT-g fail.
> > Link:
> > https://lore.kernel.org/all/20250303175220.74917-1-tomitamo...@gmail.com/
> 
> See comment on 07/ but otherwise works for me with GVT-d and GVT-g on
> my i7-7700:
> 
> Reviewed-by: Alex Williamson 
> Tested-by: Alex Williamson 
> 

Reviewed-by: Corvin Köhne 



signature.asc
Description: This is a digitally signed message part


Re: [PATCH v6 03/29] hw/intc/aspeed: Introduce dynamic allocation for regs array

2025-03-06 Thread Cédric Le Goater

On 3/7/25 04:59, Jamin Lin wrote:

Currently, the size of the "regs" array is 0x2000, which is too large. To save
code size and avoid mapping large unused gaps, will update it to only map the
useful set of registers. This update will support multiple sub-regions with
different sizes.

To address the redundant size issue, replace the static "regs" array with a
dynamically allocated "regs" memory.

Introduce a new "aspeed_intc_unrealize" function to free the allocated "regs"
memory.

Signed-off-by: Jamin Lin 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  include/hw/intc/aspeed_intc.h |  2 +-
  hw/intc/aspeed_intc.c | 12 +++-
  2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 03324f05ab..47ea0520b5 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -27,7 +27,7 @@ struct AspeedINTCState {
  MemoryRegion iomem;
  MemoryRegion iomem_container;
  
-uint32_t regs[ASPEED_INTC_NR_REGS];

+uint32_t *regs;
  OrIRQState orgates[ASPEED_INTC_NR_INTS];
  qemu_irq output_pins[ASPEED_INTC_NR_INTS];
  
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c

index 465f41e4fd..558901570f 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -289,7 +289,7 @@ static void aspeed_intc_reset(DeviceState *dev)
  {
  AspeedINTCState *s = ASPEED_INTC(dev);
  
-memset(s->regs, 0, sizeof(s->regs));

+memset(s->regs, 0, ASPEED_INTC_NR_REGS << 2);
  memset(s->enable, 0, sizeof(s->enable));
  memset(s->mask, 0, sizeof(s->mask));
  memset(s->pending, 0, sizeof(s->pending));
@@ -307,6 +307,7 @@ static void aspeed_intc_realize(DeviceState *dev, Error 
**errp)
  
  sysbus_init_mmio(sbd, &s->iomem_container);
  
+s->regs = g_new(uint32_t, ASPEED_INTC_NR_REGS);

  memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
TYPE_ASPEED_INTC ".regs", ASPEED_INTC_NR_REGS << 2);
  
@@ -322,12 +323,21 @@ static void aspeed_intc_realize(DeviceState *dev, Error **errp)

  }
  }
  
+static void aspeed_intc_unrealize(DeviceState *dev)

+{
+AspeedINTCState *s = ASPEED_INTC(dev);
+
+g_free(s->regs);
+s->regs = NULL;
+}
+
  static void aspeed_intc_class_init(ObjectClass *klass, void *data)
  {
  DeviceClass *dc = DEVICE_CLASS(klass);
  
  dc->desc = "ASPEED INTC Controller";

  dc->realize = aspeed_intc_realize;
+dc->unrealize = aspeed_intc_unrealize;
  device_class_set_legacy_reset(dc, aspeed_intc_reset);
  dc->vmsd = NULL;
  }





[PULL 26/54] target/microblaze: Explode MO_TExx -> MO_TE | MO_xx

2025-03-06 Thread Philippe Mathieu-Daudé
Extract the implicit MO_TE definition in order to replace
it by runtime variable in the next commit.

Mechanical change using:

  $ for n in UW UL UQ UO SW SL SQ; do \
  sed -i -e "s/MO_TE$n/MO_TE | MO_$n/" \
   $(git grep -l MO_TE$n target/microblaze); \
done

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-Id: <20241105130431.22564-14-phi...@linaro.org>
---
 target/microblaze/translate.c | 36 +--
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index 24005f05b21..86efabb83b5 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -780,13 +780,13 @@ static bool trans_lbui(DisasContext *dc, arg_typeb *arg)
 static bool trans_lhu(DisasContext *dc, arg_typea *arg)
 {
 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
-return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
+return do_load(dc, arg->rd, addr, MO_TE | MO_UW, dc->mem_index, false);
 }
 
 static bool trans_lhur(DisasContext *dc, arg_typea *arg)
 {
 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
-return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, true);
+return do_load(dc, arg->rd, addr, MO_TE | MO_UW, dc->mem_index, true);
 }
 
 static bool trans_lhuea(DisasContext *dc, arg_typea *arg)
@@ -798,26 +798,26 @@ static bool trans_lhuea(DisasContext *dc, arg_typea *arg)
 return true;
 #else
 TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
-return do_load(dc, arg->rd, addr, MO_TEUW, MMU_NOMMU_IDX, false);
+return do_load(dc, arg->rd, addr, MO_TE | MO_UW, MMU_NOMMU_IDX, false);
 #endif
 }
 
 static bool trans_lhui(DisasContext *dc, arg_typeb *arg)
 {
 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
-return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
+return do_load(dc, arg->rd, addr, MO_TE | MO_UW, dc->mem_index, false);
 }
 
 static bool trans_lw(DisasContext *dc, arg_typea *arg)
 {
 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
-return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
+return do_load(dc, arg->rd, addr, MO_TE | MO_UL, dc->mem_index, false);
 }
 
 static bool trans_lwr(DisasContext *dc, arg_typea *arg)
 {
 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
-return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, true);
+return do_load(dc, arg->rd, addr, MO_TE | MO_UL, dc->mem_index, true);
 }
 
 static bool trans_lwea(DisasContext *dc, arg_typea *arg)
@@ -829,14 +829,14 @@ static bool trans_lwea(DisasContext *dc, arg_typea *arg)
 return true;
 #else
 TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
-return do_load(dc, arg->rd, addr, MO_TEUL, MMU_NOMMU_IDX, false);
+return do_load(dc, arg->rd, addr, MO_TE | MO_UL, MMU_NOMMU_IDX, false);
 #endif
 }
 
 static bool trans_lwi(DisasContext *dc, arg_typeb *arg)
 {
 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
-return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
+return do_load(dc, arg->rd, addr, MO_TE | MO_UL, dc->mem_index, false);
 }
 
 static bool trans_lwx(DisasContext *dc, arg_typea *arg)
@@ -846,7 +846,7 @@ static bool trans_lwx(DisasContext *dc, arg_typea *arg)
 /* lwx does not throw unaligned access errors, so force alignment */
 tcg_gen_andi_tl(addr, addr, ~3);
 
-tcg_gen_qemu_ld_i32(cpu_res_val, addr, dc->mem_index, MO_TEUL);
+tcg_gen_qemu_ld_i32(cpu_res_val, addr, dc->mem_index, MO_TE | MO_UL);
 tcg_gen_mov_tl(cpu_res_addr, addr);
 
 if (arg->rd) {
@@ -930,13 +930,13 @@ static bool trans_sbi(DisasContext *dc, arg_typeb *arg)
 static bool trans_sh(DisasContext *dc, arg_typea *arg)
 {
 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
-return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
+return do_store(dc, arg->rd, addr, MO_TE | MO_UW, dc->mem_index, false);
 }
 
 static bool trans_shr(DisasContext *dc, arg_typea *arg)
 {
 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
-return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, true);
+return do_store(dc, arg->rd, addr, MO_TE | MO_UW, dc->mem_index, true);
 }
 
 static bool trans_shea(DisasContext *dc, arg_typea *arg)
@@ -948,26 +948,26 @@ static bool trans_shea(DisasContext *dc, arg_typea *arg)
 return true;
 #else
 TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
-return do_store(dc, arg->rd, addr, MO_TEUW, MMU_NOMMU_IDX, false);
+return do_store(dc, arg->rd, addr, MO_TE | MO_UW, MMU_NOMMU_IDX, false);
 #endif
 }
 
 static bool trans_shi(DisasContext *dc, arg_typeb *arg)
 {
 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
-return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
+return do_store(dc, arg->rd, addr, MO_TE | MO_UW, dc->mem_index, 

[PULL 1/2] target/loongarch: fix 'make check-functional' failed

2025-03-06 Thread Song Gao
 some tlb instructions get  the tlb_ps from tlb->misc but the
 value may has been initialized to 0,just check the tlb_ps skip
 the function and write a log.

Signed-off-by: Song Gao 
Reviewed-by: Bibo Mao 
Message-Id: <20250305063311.830674-2-gaos...@loongson.cn>
---
 target/loongarch/tcg/tlb_helper.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/target/loongarch/tcg/tlb_helper.c 
b/target/loongarch/tcg/tlb_helper.c
index a323606e5a..27c729b5b5 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -123,7 +123,11 @@ static void invalidate_tlb_entry(CPULoongArchState *env, 
int index)
 uint8_t tlb_v0 = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, V);
 uint8_t tlb_v1 = FIELD_EX64(tlb->tlb_entry1, TLBENTRY, V);
 uint64_t tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN);
+uint8_t tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E);
 
+if (!tlb_e) {
+return;
+}
 if (index >= LOONGARCH_STLB) {
 tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
 } else {
@@ -427,7 +431,11 @@ void helper_invtlb_page_asid(CPULoongArchState *env, 
target_ulong info,
 uint16_t tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
 uint64_t vpn, tlb_vppn;
 uint8_t tlb_ps, compare_shift;
+uint8_t tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E);
 
+if (!tlb_e) {
+continue;
+}
 if (i >= LOONGARCH_STLB) {
 tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
 } else {
@@ -456,7 +464,11 @@ void helper_invtlb_page_asid_or_g(CPULoongArchState *env,
 uint16_t tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
 uint64_t vpn, tlb_vppn;
 uint8_t tlb_ps, compare_shift;
+uint8_t tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E);
 
+if (!tlb_e) {
+continue;
+}
 if (i >= LOONGARCH_STLB) {
 tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
 } else {
-- 
2.34.1




[PULL 0/2] loongarch tcg queue

2025-03-06 Thread Song Gao
The following changes since commit e8a01102936286e012ed0f00bd7f3b7474d415c9:

  Merge tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu into 
staging (2025-03-05 21:58:23 +0800)

are available in the Git repository at:

  https://gitlab.com/gaosong/qemu.git tags/pull-loongarch-20250307

for you to fetch changes up to d882c284a3d4472d827e49a7357198b611900b08:

  target/loongarch: check tlb_ps (2025-03-07 10:15:08 +0800)


 pull-loongarch-tcg-20250307


Song Gao (2):
  target/loongarch: fix 'make check-functional' failed
  target/loongarch: check tlb_ps

 target/loongarch/cpu.c | 11 +--
 target/loongarch/helper.h  |  1 +
 target/loongarch/internals.h   |  2 ++
 target/loongarch/tcg/csr_helper.c  | 26 ++--
 .../tcg/insn_trans/trans_privileged.c.inc  |  1 +
 target/loongarch/tcg/tlb_helper.c  | 35 --
 6 files changed, 68 insertions(+), 8 deletions(-)




[PULL 2/2] target/loongarch: check tlb_ps

2025-03-06 Thread Song Gao
For LoongArch th min tlb_ps is 12(4KB), for TLB code,
the tlb_ps may be 0,this may case UndefinedBehavior
Add a check-tlb_ps fuction to check tlb_ps,
to make sure the tlb_ps is avalablie. we check tlb_ps
when get the tlb_ps from tlb->misc or CSR bits.
1. cpu reset
   set CSR_PWCL.PTBASE and CSR_STLBPS.PS bits a default value
   from CSR_PRCFG2;
2. tlb instructions.
   some tlb instructions get  the tlb_ps from tlb->misc but the
   value may  has been initialized to 0. we need just check the tlb_ps
   skip the function and write a guest log.
3. csrwr instructions.
   to make sure CSR_PWCL.PTBASE and CSR_STLBPS.PS bits are avalable,
   cheke theses bits and set a default value from CSR_PRCFG2.

Signed-off-by: Song Gao 
Reviewed-by: Bibo Mao 
Message-Id: <20250305063311.830674-3-gaos...@loongson.cn>
---
 target/loongarch/cpu.c| 11 +---
 target/loongarch/helper.h |  1 +
 target/loongarch/internals.h  |  2 ++
 target/loongarch/tcg/csr_helper.c | 26 ---
 .../tcg/insn_trans/trans_privileged.c.inc |  1 +
 target/loongarch/tcg/tlb_helper.c | 23 ++--
 6 files changed, 56 insertions(+), 8 deletions(-)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index ac514a15fb..0486853048 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -544,6 +544,7 @@ static void loongarch_max_initfn(Object *obj)
 
 static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
 {
+uint8_t tlb_ps;
 CPUState *cs = CPU(obj);
 LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(obj);
 CPULoongArchState *env = cpu_env(cs);
@@ -592,13 +593,17 @@ static void loongarch_cpu_reset_hold(Object *obj, 
ResetType type)
  */
 env->CSR_PGDH = 0;
 env->CSR_PGDL = 0;
-env->CSR_PWCL = 0;
 env->CSR_PWCH = 0;
-env->CSR_STLBPS = 0;
 env->CSR_EENTRY = 0;
 env->CSR_TLBRENTRY = 0;
 env->CSR_MERRENTRY = 0;
-
+/* set CSR_PWCL.PTBASE and CSR_STLBPS.PS bits from CSR_PRCFG2 */
+if (env->CSR_PRCFG2 == 0) {
+env->CSR_PRCFG2 = 0x3f000;
+}
+tlb_ps = ctz32(env->CSR_PRCFG2);
+env->CSR_STLBPS = FIELD_DP64(env->CSR_STLBPS, CSR_STLBPS, PS, tlb_ps);
+env->CSR_PWCL = FIELD_DP64(env->CSR_PWCL, CSR_PWCL, PTBASE, tlb_ps);
 for (n = 0; n < 4; n++) {
 env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV0, 0);
 env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV1, 0);
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 943517b5f2..1d5cb0198c 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -100,6 +100,7 @@ DEF_HELPER_1(rdtime_d, i64, env)
 DEF_HELPER_1(csrrd_pgd, i64, env)
 DEF_HELPER_1(csrrd_cpuid, i64, env)
 DEF_HELPER_1(csrrd_tval, i64, env)
+DEF_HELPER_2(csrwr_stlbps, i64, env, tl)
 DEF_HELPER_2(csrwr_estat, i64, env, tl)
 DEF_HELPER_2(csrwr_asid, i64, env, tl)
 DEF_HELPER_2(csrwr_tcfg, i64, env, tl)
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 7b254c5f49..1cd959a766 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -43,6 +43,8 @@ enum {
 TLBRET_PE = 7,
 };
 
+bool check_ps(CPULoongArchState *ent, int ps);
+
 extern const VMStateDescription vmstate_loongarch_cpu;
 
 void loongarch_cpu_set_irq(void *opaque, int irq, int level);
diff --git a/target/loongarch/tcg/csr_helper.c 
b/target/loongarch/tcg/csr_helper.c
index 6c95be9910..289d89266e 100644
--- a/target/loongarch/tcg/csr_helper.c
+++ b/target/loongarch/tcg/csr_helper.c
@@ -17,6 +17,22 @@
 #include "hw/irq.h"
 #include "cpu-csr.h"
 
+target_ulong helper_csrwr_stlbps(CPULoongArchState *env, target_ulong val)
+{
+int64_t old_v = env->CSR_STLBPS;
+
+/*
+ * The real hardware only supports the min tlb_ps is 12
+ * tlb_ps=0 may cause undefined-behavior.
+ */
+uint8_t tlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS);
+if (!check_ps(env, tlb_ps)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "Attempted set ps %d\n", tlb_ps);
+}
+return old_v;
+}
+
 target_ulong helper_csrrd_pgd(CPULoongArchState *env)
 {
 int64_t v;
@@ -99,7 +115,7 @@ target_ulong helper_csrwr_ticlr(CPULoongArchState *env, 
target_ulong val)
 
 target_ulong helper_csrwr_pwcl(CPULoongArchState *env, target_ulong val)
 {
-int shift;
+int shift, ptbase;
 int64_t old_v = env->CSR_PWCL;
 
 /*
@@ -107,12 +123,16 @@ target_ulong helper_csrwr_pwcl(CPULoongArchState *env, 
target_ulong val)
  * treated as illegal.
  */
 shift = FIELD_EX64(val, CSR_PWCL, PTEWIDTH);
+ptbase = FIELD_EX64(val, CSR_PWCL, PTBASE);
 if (shift) {
 qemu_log_mask(LOG_GUEST_ERROR,
   "Attempted set pte width with %d bit\n", 64 << shift);
 val = FIELD_DP64(val, CSR_PWCL, PTEWIDTH, 0);
 }
-
-env->CSR_PWCL = val;
+if (!check_ps(env, ptbase)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ 

Re: [PATCH v2 2/2] target/riscv: fixes a bug against `ssamoswap` behavior in M-mode

2025-03-06 Thread Alistair Francis
On Thu, Mar 6, 2025 at 4:47 PM Deepak Gupta  wrote:
>
> Commit f06bfe3dc38c ("target/riscv: implement zicfiss instructions") adds
> `ssamoswap` instruction. `ssamoswap` takes the code-point from existing
> reserved encoding (and not a zimop like other shadow stack instructions).
> If shadow stack is not enabled (via xenvcfg.SSE) and effective priv is
> less than M then `ssamoswap` must result in an illegal instruction
> exception. However if effective priv is M, then `ssamoswap` results in
> store/AMO access fault. See Section "22.2.3. Shadow Stack Memory
> Protection" of priv spec.
>
> Fixes: f06bfe3dc38c ("target/riscv: implement zicfiss instructions")
>
> Reported-by: Ved Shanbhogue 
> Signed-off-by: Deepak Gupta 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/insn_trans/trans_rvzicfiss.c.inc | 17 +
>  1 file changed, 17 insertions(+)
>
> diff --git a/target/riscv/insn_trans/trans_rvzicfiss.c.inc 
> b/target/riscv/insn_trans/trans_rvzicfiss.c.inc
> index e3ebc4977c..b0096adcd0 100644
> --- a/target/riscv/insn_trans/trans_rvzicfiss.c.inc
> +++ b/target/riscv/insn_trans/trans_rvzicfiss.c.inc
> @@ -15,6 +15,13 @@
>   * You should have received a copy of the GNU General Public License along 
> with
>   * this program.  If not, see .
>   */
> +
> +#define REQUIRE_ZICFISS(ctx) do {\
> +if (!ctx->cfg_ptr->ext_zicfiss) {\
> +return false;\
> +}\
> +} while (0)
> +
>  static bool trans_sspopchk(DisasContext *ctx, arg_sspopchk *a)
>  {
>  if (!ctx->bcfi_enabled) {
> @@ -77,6 +84,11 @@ static bool trans_ssrdp(DisasContext *ctx, arg_ssrdp *a)
>  static bool trans_ssamoswap_w(DisasContext *ctx, arg_amoswap_w *a)
>  {
>  REQUIRE_A_OR_ZAAMO(ctx);
> +REQUIRE_ZICFISS(ctx);
> +if (ctx->priv == PRV_M) {
> +generate_exception(ctx, RISCV_EXCP_STORE_AMO_ACCESS_FAULT);
> +}
> +
>  if (!ctx->bcfi_enabled) {
>  return false;
>  }
> @@ -97,6 +109,11 @@ static bool trans_ssamoswap_d(DisasContext *ctx, 
> arg_amoswap_w *a)
>  {
>  REQUIRE_64BIT(ctx);
>  REQUIRE_A_OR_ZAAMO(ctx);
> +REQUIRE_ZICFISS(ctx);
> +if (ctx->priv == PRV_M) {
> +generate_exception(ctx, RISCV_EXCP_STORE_AMO_ACCESS_FAULT);
> +}
> +
>  if (!ctx->bcfi_enabled) {
>  return false;
>  }
> --
> 2.34.1
>
>



[PATCH v6 10/29] hw/intc/aspeed: Support different memory region ops

2025-03-06 Thread Jamin Lin via
The previous implementation set the "aspeed_intc_ops" struct, containing read
and write callbacks, to be used when I/O is performed on the INTC region.
Both "aspeed_intc_read" and "aspeed_intc_write" callback functions were used
for INTC (CPU Die).

To support the INTCIO (IO Die) model, introduces a new "reg_ops" class
attribute. This allows setting different memory region operations to support
different INTC models.

Will introduce "aspeed_intcio_read" and "aspeed_intcio_write" callback
functions are used for INTCIO.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 include/hw/intc/aspeed_intc.h | 1 +
 hw/intc/aspeed_intc.c | 5 -
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 208e764c4a..3433277d87 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -43,6 +43,7 @@ struct AspeedINTCClass {
 uint64_t mem_size;
 uint64_t nr_regs;
 uint64_t reg_offset;
+const MemoryRegionOps *reg_ops;
 };
 
 #endif /* ASPEED_INTC_H */
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index d06e697ecc..d8ee6e1c04 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -332,7 +332,7 @@ static void aspeed_intc_realize(DeviceState *dev, Error 
**errp)
 sysbus_init_mmio(sbd, &s->iomem_container);
 
 s->regs = g_new(uint32_t, aic->nr_regs);
-memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
+memory_region_init_io(&s->iomem, OBJECT(s), aic->reg_ops, s,
   TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2);
 
 memory_region_add_subregion(&s->iomem_container, aic->reg_offset,
@@ -359,12 +359,15 @@ static void aspeed_intc_unrealize(DeviceState *dev)
 static void aspeed_intc_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
+AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
 
 dc->desc = "ASPEED INTC Controller";
 dc->realize = aspeed_intc_realize;
 dc->unrealize = aspeed_intc_unrealize;
 device_class_set_legacy_reset(dc, aspeed_intc_reset);
 dc->vmsd = NULL;
+
+aic->reg_ops = &aspeed_intc_ops;
 }
 
 static const TypeInfo aspeed_intc_info = {
-- 
2.43.0




[PATCH v6 01/29] hw/intc/aspeed: Support setting different memory size

2025-03-06 Thread Jamin Lin via
According to the AST2700 datasheet, the INTC(CPU DIE) controller has 16KB
(0x4000) of register space, and the INTCIO (I/O DIE) controller has 1KB (0x400)
of register space.

Introduced a new class attribute "mem_size" to set different memory sizes for
the INTC models in AST2700.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 include/hw/intc/aspeed_intc.h | 3 +++
 hw/intc/aspeed_intc.c | 9 -
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 18cb43476c..03324f05ab 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -25,6 +25,8 @@ struct AspeedINTCState {
 
 /*< public >*/
 MemoryRegion iomem;
+MemoryRegion iomem_container;
+
 uint32_t regs[ASPEED_INTC_NR_REGS];
 OrIRQState orgates[ASPEED_INTC_NR_INTS];
 qemu_irq output_pins[ASPEED_INTC_NR_INTS];
@@ -39,6 +41,7 @@ struct AspeedINTCClass {
 
 uint32_t num_lines;
 uint32_t num_ints;
+uint64_t mem_size;
 };
 
 #endif /* ASPEED_INTC_H */
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 126b711b94..033b574c1e 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -302,10 +302,16 @@ static void aspeed_intc_realize(DeviceState *dev, Error 
**errp)
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
 int i;
 
+memory_region_init(&s->iomem_container, OBJECT(s),
+TYPE_ASPEED_INTC ".container", aic->mem_size);
+
+sysbus_init_mmio(sbd, &s->iomem_container);
+
 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
   TYPE_ASPEED_INTC ".regs", ASPEED_INTC_NR_REGS << 2);
 
-sysbus_init_mmio(sbd, &s->iomem);
+memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem);
+
 qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints);
 
 for (i = 0; i < aic->num_ints; i++) {
@@ -344,6 +350,7 @@ static void aspeed_2700_intc_class_init(ObjectClass *klass, 
void *data)
 dc->desc = "ASPEED 2700 INTC Controller";
 aic->num_lines = 32;
 aic->num_ints = 9;
+aic->mem_size = 0x4000;
 }
 
 static const TypeInfo aspeed_2700_intc_info = {
-- 
2.43.0




[PATCH v6 05/29] hw/intc/aspeed: Reduce regs array size by adding a register sub-region

2025-03-06 Thread Jamin Lin via
Currently, the size of the "regs" array is 0x2000, which is too large. So far,
it only uses "GICINT128 to `GICINT134", and the offsets from 0 to 0x1000 are
unused. To save code size and avoid mapping large unused gaps, update to only
map the useful set of registers:

INTC register [0x1000 – 0x1804]

Update "reg_size" to 0x808. Introduce a new class attribute "reg_offset" to set
the start offset of a "INTC" sub-region. Set the "reg_offset" to 0x1000 for INTC
registers.

Signed-off-by: Jamin Lin 
---
 include/hw/intc/aspeed_intc.h |  1 +
 hw/intc/aspeed_intc.c | 50 ---
 2 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index ec4936b3f4..208e764c4a 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -42,6 +42,7 @@ struct AspeedINTCClass {
 uint32_t num_ints;
 uint64_t mem_size;
 uint64_t nr_regs;
+uint64_t reg_offset;
 };
 
 #endif /* ASPEED_INTC_H */
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 134922e46f..d684b4bb4f 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -14,25 +14,31 @@
 #include "hw/registerfields.h"
 #include "qapi/error.h"
 
-/* INTC Registers */
-REG32(GICINT128_EN, 0x1000)
-REG32(GICINT128_STATUS, 0x1004)
-REG32(GICINT129_EN, 0x1100)
-REG32(GICINT129_STATUS, 0x1104)
-REG32(GICINT130_EN, 0x1200)
-REG32(GICINT130_STATUS, 0x1204)
-REG32(GICINT131_EN, 0x1300)
-REG32(GICINT131_STATUS, 0x1304)
-REG32(GICINT132_EN, 0x1400)
-REG32(GICINT132_STATUS, 0x1404)
-REG32(GICINT133_EN, 0x1500)
-REG32(GICINT133_STATUS, 0x1504)
-REG32(GICINT134_EN, 0x1600)
-REG32(GICINT134_STATUS, 0x1604)
-REG32(GICINT135_EN, 0x1700)
-REG32(GICINT135_STATUS, 0x1704)
-REG32(GICINT136_EN, 0x1800)
-REG32(GICINT136_STATUS, 0x1804)
+/*
+ * INTC Registers
+ *
+ * values below are offset by - 0x1000 from datasheet
+ * because its memory region is start at 0x1000
+ *
+ */
+REG32(GICINT128_EN, 0x000)
+REG32(GICINT128_STATUS, 0x004)
+REG32(GICINT129_EN, 0x100)
+REG32(GICINT129_STATUS, 0x104)
+REG32(GICINT130_EN, 0x200)
+REG32(GICINT130_STATUS, 0x204)
+REG32(GICINT131_EN, 0x300)
+REG32(GICINT131_STATUS, 0x304)
+REG32(GICINT132_EN, 0x400)
+REG32(GICINT132_STATUS, 0x404)
+REG32(GICINT133_EN, 0x500)
+REG32(GICINT133_STATUS, 0x504)
+REG32(GICINT134_EN, 0x600)
+REG32(GICINT134_STATUS, 0x604)
+REG32(GICINT135_EN, 0x700)
+REG32(GICINT135_STATUS, 0x704)
+REG32(GICINT136_EN, 0x800)
+REG32(GICINT136_STATUS, 0x804)
 
 #define GICINT_STATUS_BASE R_GICINT128_STATUS
 
@@ -298,7 +304,8 @@ static void aspeed_intc_realize(DeviceState *dev, Error 
**errp)
 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
   TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2);
 
-memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem);
+memory_region_add_subregion(&s->iomem_container, aic->reg_offset,
+&s->iomem);
 
 qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints);
 
@@ -348,7 +355,8 @@ static void aspeed_2700_intc_class_init(ObjectClass *klass, 
void *data)
 aic->num_lines = 32;
 aic->num_ints = 9;
 aic->mem_size = 0x4000;
-aic->nr_regs = 0x2000 >> 2;
+aic->nr_regs = 0x808 >> 2;
+aic->reg_offset = 0x1000;
 }
 
 static const TypeInfo aspeed_2700_intc_info = {
-- 
2.43.0




[PATCH v6 21/29] hw/arm/aspeed_ast27x0: Support two levels of INTC controllers for AST2700 A1

2025-03-06 Thread Jamin Lin via
The design of INTC controllers has significantly changed in AST2700 A1.

There are a total of 480 interrupt sources in AST2700 A1. For interrupt numbers
from 0 to 127, they can route directly to PSP, SSP, and TSP. Due to the
limitation of interrupt numbers of processors, the interrupts are merged every
32 sources for interrupt numbers greater than 127.

There are two levels of interrupt controllers, INTC(CPUD Die) and INTCIO
(IO Die). The interrupt sources of INTC are the interrupt numbers from INTC_0 to
INTC_127 and interrupts from INTCIO. The interrupt sources of INTCIO are the
interrupt numbers greater than INTC_127. INTC_IO controls the interrupts
INTC_128 to INTC_319 only.

Currently, only GIC 192 to 201 are supported, and their source interrupts are
from INTCIO and connected to INTC at input pin 0 and output pins 0 to 9 for
GIC 192-201.

The design of the orgates for GICINT 196 is as follows:
It has interrupt sources ranging from 0 to 31, with its output pin connected to
INTCIO "T0 GICINT_196". The output pin is then connected to INTC "GIC_192_201"
at bit 4, and its bit 4 output should be connected to GIC 196.
The design of INTC GIC_192_201 have 10 output pins, mapped as following:
Bit 0 -> GIC 192
Bit 1 -> GIC 193
Bit 2 -> GIC 194
Bit 3 -> GIC 195
Bit 4 -> GIC 196

To support both AST2700 A1 and A0, INTC input pins 1 to 9 and output pins
10 to 18 remain to support GIC 128-136, which source interrupts from INTC.
These will be removed if we decide not to support AST2700 A0 in the future.

|---|
|   AST2700 A1 Design   
|
|   To GICINT196
|
|   
|
|   ETH1|---||--|   
 |--|   |
|  >|0  || INTCIO   |   
 |  orgates[0]  |   |
|   ETH2|  4|   
orgates[0]-->|inpin[0]>outpin[0]|--->| 0|   |
|  >|1 5|   
orgates[1]-->|inpin[1]>outpin[1]|--->| 1|   |
|   ETH3|  6|   
orgates[2]-->|inpin[2]>outpin[2]|--->| 2|   |
|  >|219|   
orgates[3]-->|inpin[3]>outpin[3]|--->| 3  OR[0:9]   |-| |
|   UART0   | 
20|-->orgates[4]-->|inpin[4]>outpin[4]|--->| 4| 
| |
|  >|721|   
orgates[5]-->|inpin[5]>outpin[5]|--->| 5| | |
|   UART1   | 22|   
orgates[6]-->|inpin[6]>outpin[6]|--->| 6| | |
|  >|823|   
orgates[7]-->|inpin[7]>outpin[7]|--->| 7| | |
|   UART2   | 24|   
orgates[8]-->|inpin[8]>outpin[8]|--->| 8| | |
|  >|925|   
orgates[9]-->|inpin[9]>outpin[9]|--->| 9| | |
|   UART3   | 26||--|   
 |--| | |
|  -|10   27|   
  | |
|   UART5   | 28|   
  | |
|  >|11   29|   
  | |
|   UART6   |   |   
  | |
|  >|12   30| 
|---| |
|   UART7   | 31| | 
|
|  >|13 | | 
|
|   UART8   |  OR[0:31] | ||--| 
  |--|  |
|  >|14 | ||INTC  | 
  | GIC  |  |
|   UART9   |   | ||inpin[0:0]->outpin[0] 
|-->|192   |  |
|  >|15 | ||inpin[0:1]->outpin[1] 
|-->|193   |  |
|   UART10  |   | ||inpin[0:2]->outpin[2] 
|-->|194   |  |
|  >|16 | ||inpin[0:3]->outpin[3] 
|-->|195   |  |
|   UART11  |   | |--> |inpin[0:4]->outpin[4] 
|-->|196   |  |
|  >|17 |  |inpin[0:5]->outpin[5] 
|-->|197   |  |
|   UART12  |   |  |inpin[0:

[PATCH v6 23/29] hw/arm/aspeed: Add Machine Support for AST2700 A1

2025-03-06 Thread Jamin Lin via
Introduce "aspeed_machine_ast2700a1_evb_class_init" to initialize the
AST2700 A1 EVB.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/arm/aspeed.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 18f7c450da..82f42582fa 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1693,6 +1693,26 @@ static void 
aspeed_machine_ast2700a0_evb_class_init(ObjectClass *oc, void *data)
 mc->default_ram_size = 1 * GiB;
 aspeed_machine_class_init_cpus_defaults(mc);
 }
+
+static void aspeed_machine_ast2700a1_evb_class_init(ObjectClass *oc, void 
*data)
+{
+MachineClass *mc = MACHINE_CLASS(oc);
+AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
+
+mc->desc = "Aspeed AST2700 A1 EVB (Cortex-A35)";
+amc->soc_name  = "ast2700-a1";
+amc->hw_strap1 = AST2700_EVB_HW_STRAP1;
+amc->hw_strap2 = AST2700_EVB_HW_STRAP2;
+amc->fmc_model = "w25q01jvq";
+amc->spi_model = "w25q512jv";
+amc->num_cs= 2;
+amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON | ASPEED_MAC2_ON;
+amc->uart_default = ASPEED_DEV_UART12;
+amc->i2c_init  = ast2700_evb_i2c_init;
+mc->auto_create_sdcard = true;
+mc->default_ram_size = 1 * GiB;
+aspeed_machine_class_init_cpus_defaults(mc);
+}
 #endif
 
 static void aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass *oc,
@@ -1821,6 +1841,10 @@ static const TypeInfo aspeed_machine_types[] = {
 .name  = MACHINE_TYPE_NAME("ast2700a0-evb"),
 .parent= TYPE_ASPEED_MACHINE,
 .class_init= aspeed_machine_ast2700a0_evb_class_init,
+}, {
+.name  = MACHINE_TYPE_NAME("ast2700a1-evb"),
+.parent= TYPE_ASPEED_MACHINE,
+.class_init= aspeed_machine_ast2700a1_evb_class_init,
 #endif
 }, {
 .name  = TYPE_ASPEED_MACHINE,
-- 
2.43.0




[PATCH v6 29/29] docs/specs: Add aspeed-intc

2025-03-06 Thread Jamin Lin via
Add AST2700 INTC design guidance and its block diagram.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 docs/specs/aspeed-intc.rst | 136 +
 docs/specs/index.rst   |   1 +
 2 files changed, 137 insertions(+)
 create mode 100644 docs/specs/aspeed-intc.rst

diff --git a/docs/specs/aspeed-intc.rst b/docs/specs/aspeed-intc.rst
new file mode 100644
index 00..9cefd7f37f
--- /dev/null
+++ b/docs/specs/aspeed-intc.rst
@@ -0,0 +1,136 @@
+===
+ASPEED Interrupt Controller
+===
+
+AST2700
+---
+There are a total of 480 interrupt sources in AST2700. Due to the limitation of
+interrupt numbers of processors, the interrupts are merged every 32 sources for
+interrupt numbers greater than 127.
+
+There are two levels of interrupt controllers, INTC (CPU Die) and INTCIO
+(I/O Die).
+
+Interrupt Mapping
+-
+- INTC: Handles interrupt sources 0 - 127 and integrates signals from INTCIO.
+- INTCIO: Handles interrupt sources 128 - 319 independently.
+
+QEMU Support
+
+Currently, only GIC 192 to 201 are supported, and their source interrupts are
+from INTCIO and connected to INTC at input pin 0 and output pins 0 to 9 for
+GIC 192-201.
+
+Design for GICINT 196
+-
+The orgate has interrupt sources ranging from 0 to 31, with its output pin
+connected to INTCIO "T0 GICINT_196". The output pin is then connected to INTC
+"GIC_192_201" at bit 4, and its bit 4 output pin is connected to GIC 196.
+
+INTC GIC_192_201 Output Pin Mapping
+---
+The design of INTC GIC_192_201 have 10 output pins, mapped as following:
+
+  
+Bit   GIC
+  
+0 192
+1 193
+2 194
+3 195
+4 196
+5 197
+6 198
+7 199
+8 200
+9 201
+  
+
+AST2700 A0
+--
+It has only one INTC controller, and currently, only GIC 128-136 is supported.
+To support both AST2700 A1 and AST2700 A0, there are 10 OR gates in the INTC,
+with gates 1 to 9 supporting GIC 128-136.
+
+Design for GICINT 132
+-
+The orgate has interrupt sources ranging from 0 to 31, with its output pin
+connected to INTC. The output pin is then connected to GIC 132.
+
+Block Diagram of GICINT 196 for AST2700 A1 and GICINT 132 for AST2700 A0
+
+
+.. code-block::
+
+   
|---|
+   |   AST2700 A1 Design   
|
+   |   To GICINT196
|
+   |   
|
+   |   ETH1|---||--|   
 |--|   |
+   |  >|0  || INTCIO   |   
 |  orgates[0]  |   |
+   |   ETH2|  4|   
orgates[0]-->|inpin[0]>outpin[0]|--->| 0|   |
+   |  >|1 5|   
orgates[1]-->|inpin[1]>outpin[1]|--->| 1|   |
+   |   ETH3|  6|   
orgates[2]-->|inpin[2]>outpin[2]|--->| 2|   |
+   |  >|219|   
orgates[3]-->|inpin[3]>outpin[3]|--->| 3  OR[0:9]   |-| |
+   |   UART0   | 
20|-->orgates[4]-->|inpin[4]>outpin[4]|--->| 4| 
| |
+   |  >|721|   
orgates[5]-->|inpin[5]>outpin[5]|--->| 5| | |
+   |   UART1   | 22|   
orgates[6]-->|inpin[6]>outpin[6]|--->| 6| | |
+   |  >|823|   
orgates[7]-->|inpin[7]>outpin[7]|--->| 7| | |
+   |   UART2   | 24|   
orgates[8]-->|inpin[8]>outpin[8]|--->| 8| | |
+   |  >|925|   
orgates[9]-->|inpin[9]>outpin[9]|--->| 9| | |
+   |   UART3   | 26||--|   
 |--| | |
+   |  -|10   27|   
  | |
+   |   UART5   | 28|   
  | |
+   |  >|11   29|   
  | |
+   |   UART6   |   |   
  | |
+   |  >|12   30| 
|---| |
+   |   UART7   | 31| | 
|
+

[PATCH v6 19/29] hw/arm/aspeed_ast27x0.c Support AST2700 A1 GIC Interrupt Mapping

2025-03-06 Thread Jamin Lin via
Currently, these IRQ tables support from GIC 128 - 136 for AST2700 A0.
These IRQ tables can be reused for AST2700 A1 from GIC 192 - 197.
Updates the interrupt mapping to include support for AST2700 A1 by extending
the existing mappings to the new GIC range.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/arm/aspeed_ast27x0.c | 77 ++---
 1 file changed, 50 insertions(+), 27 deletions(-)

diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index 2d24361daa..343fe87921 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -120,21 +120,27 @@ static const int aspeed_soc_ast2700a0_irqmap[] = {
 };
 
 /* GICINT 128 */
-static const int aspeed_soc_ast2700_gic128_intcmap[] = {
+/* GICINT 192 */
+static const int ast2700_gic128_gic192_intcmap[] = {
 [ASPEED_DEV_LPC]   = 0,
 [ASPEED_DEV_IBT]   = 2,
 [ASPEED_DEV_KCS]   = 4,
 };
 
+/* GICINT 129 */
+/* GICINT 193 */
+
 /* GICINT 130 */
-static const int aspeed_soc_ast2700_gic130_intcmap[] = {
+/* GICINT 194 */
+static const int ast2700_gic130_gic194_intcmap[] = {
 [ASPEED_DEV_I2C]= 0,
 [ASPEED_DEV_ADC]= 16,
 [ASPEED_DEV_GPIO]   = 18,
 };
 
 /* GICINT 131 */
-static const int aspeed_soc_ast2700_gic131_intcmap[] = {
+/* GICINT 195 */
+static const int ast2700_gic131_gic195_intcmap[] = {
 [ASPEED_DEV_I3C]   = 0,
 [ASPEED_DEV_WDT]   = 16,
 [ASPEED_DEV_FMC]   = 25,
@@ -142,7 +148,8 @@ static const int aspeed_soc_ast2700_gic131_intcmap[] = {
 };
 
 /* GICINT 132 */
-static const int aspeed_soc_ast2700_gic132_intcmap[] = {
+/* GICINT 196 */
+static const int ast2700_gic132_gic196_intcmap[] = {
 [ASPEED_DEV_ETH1]  = 0,
 [ASPEED_DEV_ETH2]  = 1,
 [ASPEED_DEV_ETH3]  = 2,
@@ -161,24 +168,26 @@ static const int aspeed_soc_ast2700_gic132_intcmap[] = {
 };
 
 /* GICINT 133 */
-static const int aspeed_soc_ast2700_gic133_intcmap[] = {
+/* GICINT 197 */
+static const int ast2700_gic133_gic197_intcmap[] = {
 [ASPEED_DEV_SDHCI] = 1,
 [ASPEED_DEV_PECI]  = 4,
 };
 
 /* GICINT 128 ~ 136 */
+/* GICINT 192 ~ 201 */
 struct gic_intc_irq_info {
 int irq;
 const int *ptr;
 };
 
-static const struct gic_intc_irq_info aspeed_soc_ast2700_gic_intcmap[] = {
-{128,  aspeed_soc_ast2700_gic128_intcmap},
+static const struct gic_intc_irq_info ast2700_gic_intcmap[] = {
+{128,  ast2700_gic128_gic192_intcmap},
 {129,  NULL},
-{130,  aspeed_soc_ast2700_gic130_intcmap},
-{131,  aspeed_soc_ast2700_gic131_intcmap},
-{132,  aspeed_soc_ast2700_gic132_intcmap},
-{133,  aspeed_soc_ast2700_gic133_intcmap},
+{130,  ast2700_gic130_gic194_intcmap},
+{131,  ast2700_gic131_gic195_intcmap},
+{132,  ast2700_gic132_gic196_intcmap},
+{133,  ast2700_gic133_gic197_intcmap},
 {134,  NULL},
 {135,  NULL},
 {136,  NULL},
@@ -190,11 +199,11 @@ static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState 
*s, int dev)
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 int i;
 
-for (i = 0; i < ARRAY_SIZE(aspeed_soc_ast2700_gic_intcmap); i++) {
-if (sc->irqmap[dev] == aspeed_soc_ast2700_gic_intcmap[i].irq) {
-assert(aspeed_soc_ast2700_gic_intcmap[i].ptr);
+for (i = 0; i < ARRAY_SIZE(ast2700_gic_intcmap); i++) {
+if (sc->irqmap[dev] == ast2700_gic_intcmap[i].irq) {
+assert(ast2700_gic_intcmap[i].ptr);
 return qdev_get_gpio_in(DEVICE(&a->intc.orgates[i]),
-aspeed_soc_ast2700_gic_intcmap[i].ptr[dev]);
+ast2700_gic_intcmap[i].ptr[dev]);
 }
 }
 
@@ -208,16 +217,17 @@ static qemu_irq 
aspeed_soc_ast2700_get_irq_index(AspeedSoCState *s, int dev,
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 int i;
 
-for (i = 0; i < ARRAY_SIZE(aspeed_soc_ast2700_gic_intcmap); i++) {
-if (sc->irqmap[dev] == aspeed_soc_ast2700_gic_intcmap[i].irq) {
-assert(aspeed_soc_ast2700_gic_intcmap[i].ptr);
+for (i = 0; i < ARRAY_SIZE(ast2700_gic_intcmap); i++) {
+if (sc->irqmap[dev] == ast2700_gic_intcmap[i].irq) {
+assert(ast2700_gic_intcmap[i].ptr);
 return qdev_get_gpio_in(DEVICE(&a->intc.orgates[i]),
-aspeed_soc_ast2700_gic_intcmap[i].ptr[dev] + index);
+ast2700_gic_intcmap[i].ptr[dev] + index);
 }
 }
 
 /*
- * Invalid orgate index, device irq should be 128 to 136.
+ * Invalid OR gate index, device IRQ should be between 128 to 136
+ * and 192 to 201.
  */
 g_assert_not_reached();
 }
@@ -530,17 +540,18 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, 
Error **errp)
 aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc), 0,
 sc->memmap[ASPEED_DEV_INTC]);
 
-/* source orgates -> INTC */
+/* irq sources -> orgates -> INTC */
 for (i = 0; i < ic->num_inpins; i++) {
 qdev_connect_gpio_out(DEVICE(&a->intc.orga

[PATCH v6 17/29] hw/intc/aspeed: Add Support for AST2700 INTCIO Controller

2025-03-06 Thread Jamin Lin via
Introduce a new ast2700 INTCIO class to support AST2700 INTCIO.
Added new register definitions for INTCIO, including enable and status
registers for IRQs GICINT192 through GICINT197.
Created a dedicated IRQ array for INTCIO, supporting six input pins and six
output pins, aligning with the newly defined registers.
Implemented "aspeed_intcio_read" and "aspeed_intcio_write" to handle
INTCIO-specific register access.

 To GICINT196   
 |

   ETH1|---||--|
  >|0  || INTCIO   |
   ETH2|  4|   orgates[0]-->|inpin[0]>outpin[0]|
  >|1 5|   orgates[1]-->|inpin[1]>outpin[1]|
   ETH3|  6|   orgates[2]-->|inpin[2]>outpin[2]|
  >|219|   orgates[3]-->|inpin[3]>outpin[3]|
   UART0   | 20|-->orgates[4]-->|inpin[4]>outpin[4]|
  >|721|   orgates[5]-->|inpin[5]>outpin[5]|
   UART1   | 22||--|
  >|823|
   UART2   | 24|
  >|925|
   UART3   | 26|
  -|10   27|
   UART5   | 28|
  >|11   29|
   UART6   |   |
  >|12   30|
   UART7   | 31|
  >|13 |
   UART8   |  OR[0:31] |
  >|14 |
   UART9   |   |
  >|15 |
   UART10  |   |
  >|16 |
   UART11  |   |
  >|17 |
   UART12  |   |
  >|18 |
   |---|

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 include/hw/intc/aspeed_intc.h |   1 +
 hw/intc/aspeed_intc.c | 112 ++
 2 files changed, 113 insertions(+)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 85df8c6be9..3727ba24be 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -14,6 +14,7 @@
 
 #define TYPE_ASPEED_INTC "aspeed.intc"
 #define TYPE_ASPEED_2700_INTC TYPE_ASPEED_INTC "-ast2700"
+#define TYPE_ASPEED_2700_INTCIO TYPE_ASPEED_INTC "io-ast2700"
 OBJECT_DECLARE_TYPE(AspeedINTCState, AspeedINTCClass, ASPEED_INTC)
 
 #define ASPEED_INTC_MAX_INPINS 10
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index f2ca9237ea..3fd417084f 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -42,6 +42,26 @@ REG32(GICINT136_STATUS, 0x804)
 REG32(GICINT192_201_EN, 0xB00)
 REG32(GICINT192_201_STATUS, 0xB04)
 
+/*
+ * INTCIO Registers
+ *
+ * values below are offset by - 0x100 from datasheet
+ * because its memory region is start at 0x100
+ *
+ */
+REG32(GICINT192_EN, 0x00)
+REG32(GICINT192_STATUS, 0x04)
+REG32(GICINT193_EN, 0x10)
+REG32(GICINT193_STATUS, 0x14)
+REG32(GICINT194_EN, 0x20)
+REG32(GICINT194_STATUS, 0x24)
+REG32(GICINT195_EN, 0x30)
+REG32(GICINT195_STATUS, 0x34)
+REG32(GICINT196_EN, 0x40)
+REG32(GICINT196_STATUS, 0x44)
+REG32(GICINT197_EN, 0x50)
+REG32(GICINT197_STATUS, 0x54)
+
 static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic,
 uint32_t reg)
 {
@@ -432,6 +452,55 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, 
uint64_t data,
 return;
 }
 
+static uint64_t aspeed_intcio_read(void *opaque, hwaddr offset,
+   unsigned int size)
+{
+AspeedINTCState *s = ASPEED_INTC(opaque);
+const char *name = object_get_typename(OBJECT(s));
+uint32_t reg = offset >> 2;
+uint32_t value = 0;
+
+value = s->regs[reg];
+trace_aspeed_intc_read(name, offset, size, value);
+
+return value;
+}
+
+static void aspeed_intcio_write(void *opaque, hwaddr offset, uint64_t data,
+unsigned size)
+{
+AspeedINTCState *s = ASPEED_INTC(opaque);
+const char *name = object_get_typename(OBJECT(s));
+uint32_t reg = offset >> 2;
+
+trace_aspeed_intc_write(name, offset, size, data);
+
+switch (reg) {
+case R_GICINT192_EN:
+case R_GICINT193_EN:
+case R_GICINT194_EN:
+case R_GICINT195_EN:
+case R_GICINT196_EN:
+case R_GICINT197_EN:
+aspeed_intc_enable_handler(s, offset, data);
+break;
+case R_GICINT192_STATUS:
+case R_GICINT193_STATUS:
+case R_GICINT194_STATUS:
+case R_GICINT195_STATUS:
+case R_GICINT196_STATUS:
+case R_GICINT197_STATUS:
+aspeed_intc_status_handler(s, offset, data);
+break;
+default:
+s->regs[reg] = data;
+break;
+}
+
+return;
+}
+
+
 static const MemoryRegionOps aspeed_intc_ops = {
 .read = aspeed

[PATCH v6 16/29] hw/intc/aspeed: Add Support for Multi-Output IRQ Handling

2025-03-06 Thread Jamin Lin via
This update introduces support for handling multi-output IRQs in the AST2700
interrupt controller (INTC), specifically for GICINT192_201. GICINT192_201 maps
1:10 to input IRQ 0 and output IRQs 0 to 9. Each status bit corresponds to a
specific IRQ.

Implemented "aspeed_intc_set_irq_handler_multi_outpins" to handle IRQs with
multiple output pins. Introduced "aspeed_intc_status_handler_multi_outpins"
for managing status registers associated with multi-output IRQs.

Added new IRQ definitions for GICINT192_201 in INTC.
Adjusted the IRQ array to accommodate 10 input pins and 19 output pins,
aligning with the new GICINT192_201 mappings.

   |--|
   |INTC  |
   |inpin[0:0]->outpin[0] |
   |inpin[0:1]->outpin[1] |
   |inpin[0:2]->outpin[2] |
   |inpin[0:3]->outpin[3] |
orgates[0]---> |inpin[0:4]->outpin[4] |
   |inpin[0:5]->outpin[5] |
   |inpin[0:6]->outpin[6] |
   |inpin[0:7]->outpin[7] |
   |inpin[0:8]->outpin[8] |
   |inpin[0:9]->outpin[9] |
   |  |
 orgates[1]--> |inpin[1]--->outpin[10]|
 orgates[2]--> |inpin[2]--->outpin[11]|
 orgates[3]--> |inpin[3]--->outpin[12]|
 orgates[4]--> |inpin[4]--->outpin[13]|
 orgates[5]--> |inpin[5]--->outpin[14]|
 orgates[6]--> |inpin[6]--->outpin[15]|
 orgates[7]--> |inpin[7]--->outpin[16]|
 orgates[8]--> |inpin[8]--->outpin[17]|
 orgates[9]--> |inpin[9]--->outpin[18]|
   |--|

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 include/hw/intc/aspeed_intc.h |   4 +-
 hw/intc/aspeed_intc.c | 149 ++
 hw/intc/trace-events  |   1 +
 3 files changed, 137 insertions(+), 17 deletions(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index e6c3a27264..85df8c6be9 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -16,8 +16,8 @@
 #define TYPE_ASPEED_2700_INTC TYPE_ASPEED_INTC "-ast2700"
 OBJECT_DECLARE_TYPE(AspeedINTCState, AspeedINTCClass, ASPEED_INTC)
 
-#define ASPEED_INTC_MAX_INPINS 9
-#define ASPEED_INTC_MAX_OUTPINS 9
+#define ASPEED_INTC_MAX_INPINS 10
+#define ASPEED_INTC_MAX_OUTPINS 19
 
 typedef struct AspeedINTCIRQ {
 int inpin_idx;
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 3aa97add8b..f2ca9237ea 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -39,6 +39,8 @@ REG32(GICINT135_EN, 0x700)
 REG32(GICINT135_STATUS, 0x704)
 REG32(GICINT136_EN, 0x800)
 REG32(GICINT136_STATUS, 0x804)
+REG32(GICINT192_201_EN, 0xB00)
+REG32(GICINT192_201_STATUS, 0xB04)
 
 static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic,
 uint32_t reg)
@@ -112,9 +114,55 @@ static void aspeed_intc_set_irq_handler(AspeedINTCState *s,
 }
 }
 
+static void aspeed_intc_set_irq_handler_multi_outpins(AspeedINTCState *s,
+ const AspeedINTCIRQ *intc_irq, uint32_t 
select)
+{
+const char *name = object_get_typename(OBJECT(s));
+uint32_t status_reg;
+int num_outpins;
+int outpin_idx;
+int inpin_idx;
+int i;
+
+num_outpins = intc_irq->num_outpins;
+status_reg = intc_irq->status_reg;
+outpin_idx = intc_irq->outpin_idx;
+inpin_idx = intc_irq->inpin_idx;
+
+for (i = 0; i < num_outpins; i++) {
+if (select & BIT(i)) {
+if (s->mask[inpin_idx] & BIT(i) ||
+s->regs[status_reg] & BIT(i)) {
+/*
+ * a. mask bit is not 0 means in ISR mode sources interrupt
+ * routine are executing.
+ * b. status bit is not 0 means previous source interrupt
+ * does not be executed, yet.
+ *
+ * save source interrupt to pending bit.
+ */
+ s->pending[inpin_idx] |= BIT(i);
+ trace_aspeed_intc_pending_irq(name, inpin_idx,
+   s->pending[inpin_idx]);
+} else {
+/*
+ * notify firmware which source interrupt are coming
+ * by setting status bit
+ */
+s->regs[status_reg] |= BIT(i);
+trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx + i,
+  s->regs[status_reg]);
+aspeed_intc_update(s, inpin_idx, outpin_idx + i, 1);
+}
+}
+}
+}
+
 /*
- * GICINT128 to GICINT136 map 1:1 to input and output IRQs 0 to 8.

Re: [PATCH] pci-ids.rst: Add Red Hat pci-id for AMD IOMMU device

2025-03-06 Thread Suthikulpanit, Suravee




On 3/5/2025 1:52 PM, Michael S. Tsirkin wrote:

On Tue, Mar 04, 2025 at 06:37:47PM +, Suravee Suthikulpanit wrote:

The QEMU-emulated AMD IOMMU PCI device is implemented based on the AMD I/O
Virtualization Technology (IOMMU) Specification [1]. The PCI id for this
device is platform-specific.

Currently, the QEMU-emulated AMD IOMMU device is using AMD vendor id and
undefined device id.

undefined?


Therefore, change the vendor id to Red Hat and request a new QEMU-specific
device id.

Won't the drivers fail to load then?


[1]https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/ 
specifications/48882_IOMMU.pdf

what is this link teaching us? It's a 300 page document. Where to look
in there?


What I am trying to say is that all AMD IOMMU implementations must 
adhere to this specification including the QEMU-emulated AMD IOMMU. 
Unlike cpu emulation, we don't need to exactly mimic a particular 
hardware implementation.


QEMU-emulated AMD IOMMU device can have its own set of features that it 
supports. Going forward, we might even have QEMU-specific feature / 
behavior. So, we should not be using an existing PCI ID.


Thanks,
Suravee



Re: [PATCH v3 00/10] vfio/igd: Decoupling quirks with legacy mode

2025-03-06 Thread Alex Williamson
On Fri,  7 Mar 2025 02:01:20 +0800
Tomita Moeko  wrote:

> This patchset intends to decouple existing quirks from legacy mode.
> Currently all quirks depends on legacy mode (except x-igd-opregion),
> which includes following conditions:
> * Machine type is i440fx
> * IGD device is at guest BDF 00:02.0
> * VBIOS in ROM BAR or file
> * VGA IO/MMIO ranges are claimed by IGD
> * OpRegion
> * Same LPC bridge and Host bridge VID/DID/SVID/SSID as host
> 
> If one of the condition is not met, the quirks will not be applied.
> However, for recent generations, espcially Gen 11+ devices that removed
> VBIOS support, not all the conditions are required. For example, on EFI-
> based systems, VBIOS ROM is unnecessary, and VGA ranges are not used.
> 
> To have better support on newer UEFI-based VMs, this patchset makes the
> quirks independent of legacy mode. The BDSM and GGC register quirks are
> applied to all supported IGD devices, new x-igd-lpc option for the LPC
> bridge / Host bridge ID quirk is introduced for possible Q35 support.
> It also prepares for supporting IGD passthrough when it is not primary
> display later (kernel change will be merged in 6.15).
> 
> To maintain backward compatbility with exising configuration, legacy
> mode will automatically be enabled when:
> * Machine type is i440fx
> * IGD device is at guest BDF 00:02.0
> If the legacy mode behavior is unwanted, option x-igd-legacy-mode=off
> is provided for users to disable it. Setting x-igd-legacy-mode=on checks
> if the condition above are met, and set up all the required quirks.
> 
> The default value is x-igd-legacy-mode=auto. When the above conditions
> are all met, it acts as before and continues on any error. Otherwise it
> is equivalent to x-igd-legacy-mode=off.
> 
> When x-igd-legacy-mode is set to on or off, QEMU will fail immediately
> on error.
> 
> The first 2 patches of this patchset was taken from a previous one,
> details can be found at:
> https://lore.kernel.org/all/20250124191245.12464-1-tomitamo...@gmail.com/
> 
> This patchest was mainly tested on Alder Lake UHD770, with Debian 12
> (kernel 6.1), Windows 11 (driver 32.0.101.6458) and Intel GOP driver
> 17.0.1081.
> 
> Due to I caught COVID these days, I am unable to deliver the proposed
> documentation update before QEMU 10.0 soft-freeze next week. Please help
> decide whether to make this patch series in 10.0 or next release.
> 
> Changelog:
> v3:
> * Use OnOffAuto for x-igd-legacy-mode option, default is auto, to keep
>   current behavior.
> * Added a new patch to solve the possible KVMGT/GVT-g fail.
> Link: 
> https://lore.kernel.org/all/20250303175220.74917-1-tomitamo...@gmail.com/

See comment on 07/ but otherwise works for me with GVT-d and GVT-g on
my i7-7700:

Reviewed-by: Alex Williamson 
Tested-by: Alex Williamson 




Re: [PATCH 04/57] docs/sphinx: add compat.py module and nested_parse helper

2025-03-06 Thread Markus Armbruster
John Snow  writes:

> Create a compat module that handles sphinx cross-version compatibility
> issues. For the inaugural function, add a nested_parse() helper that
> handles differences in line number tracking for nested directive body
> parsing.
>
> Spoilers: there are more cross-version hacks to come throughout the
> series.
>
> Signed-off-by: John Snow 
> ---
>  docs/sphinx/compat.py | 33 +
>  1 file changed, 33 insertions(+)
>  create mode 100644 docs/sphinx/compat.py
>
> diff --git a/docs/sphinx/compat.py b/docs/sphinx/compat.py
> new file mode 100644
> index 000..792aca10e39
> --- /dev/null
> +++ b/docs/sphinx/compat.py
> @@ -0,0 +1,33 @@
> +"""
> +Sphinx cross-version compatibility goop
> +"""
> +
> +from docutils.nodes import Element
> +
> +from sphinx.util.docutils import SphinxDirective, switch_source_input
> +from sphinx.util.nodes import nested_parse_with_titles
> +
> +
> +def nested_parse(directive: SphinxDirective, content_node: Element) -> None:
> +"""
> +This helper preserves error parsing context across sphinx versions.
> +"""
> +
> +# necessary so that the child nodes get the right source/line set
> +content_node.document = directive.state.document
> +
> +try:
> +# Modern sphinx (6.2.0+) supports proper offsetting for
> +# nested parse error context management
> +nested_parse_with_titles(
> +directive.state,
> +directive.content,
> +content_node,
> +content_offset=directive.content_offset,
> +)
> +except TypeError:
> +# No content_offset argument. Fall back to SSI method.
> +with switch_source_input(directive.state, directive.content):
> +nested_parse_with_titles(
> +directive.state, directive.content, content_node
> +)

The function wraps around sphinx.util.nodes.nested_parse_with_titles().
Would calling it nested_parse_with_titles() reduce readers' cognitive
load at call sites?

Please do not misinterpret my question as a demand.  It's really just a
question :)




Re: [qemu-web PATCH] Announce Google Summer of Code 2025

2025-03-06 Thread Thomas Huth

On 06/03/2025 13.46, Stefan Hajnoczi wrote:

Let people know that QEMU is participating in Google Summer of Code so
that they can apply for an internship this summer.


Thanks, looks good, applied now:

 https://www.qemu.org/2025/03/06/gsoc-2025/

 Thomas




Re: [PATCH 15/57] docs/qapi-domain: add "Errors:" field lists

2025-03-06 Thread Markus Armbruster
John Snow  writes:

> ``:error: descr`` can now be used to document error conditions. The
> format of the description is not defined here; so the ability to name
> specific types is left to the document writer.
>
> Signed-off-by: John Snow 

By convention, the description is a bullet list, but we don't enforce
that in software.  Observation, not a suggestion to start enforcing it
now.




Re: [PATCH 13/57] docs/qapi-domain: add "Arguments:" field lists

2025-03-06 Thread Markus Armbruster
John Snow  writes:

> This adds special rendering for Sphinx's typed field lists.
>
> This patch does not add any QAPI-aware markup, rendering, or
> cross-referencing for the type names, yet. That feature requires a
> subclass to TypedField which will happen in its own commit quite a bit
> later in this series; after all the basic fields and objects have been
> established first.
>
> The syntax for this field is:
>
> :arg type name: description
>description cont'd
>
> You can omit the type or the description, but you cannot omit the name
> -- if you do so, it degenerates into a "normal field list" entry, and
> probably isn't what you want.

Exuse my nitpicking...  "cannot omit" suggests omission is a hard error.
The text after "--" suggests it isn't, it gives you something that
"probably isn't what you want".  Which way does it actually behave?

>
> Signed-off-by: John Snow 




[PATCH v6 07/29] hw/intc/aspeed: Add object type name to trace events for better debugging

2025-03-06 Thread Jamin Lin via
Currently, these trace events only refer to INTC. To simplify the INTC model,
both INTC(CPU Die) and INTCIO(IO Die) will share the same helper functions.

However, it is difficult to recognize whether these trace events are comes from
INTC or INTCIO. To make these trace events more readable, adds object type name
to the INTC trace events.
Update trace events to include the "name" field for better identification.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/intc/aspeed_intc.c | 32 +++-
 hw/intc/trace-events  | 24 
 2 files changed, 31 insertions(+), 25 deletions(-)

diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index b58a7ee712..d06e697ecc 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -45,6 +45,7 @@ REG32(GICINT136_STATUS, 0x804)
 static void aspeed_intc_update(AspeedINTCState *s, int irq, int level)
 {
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+const char *name = object_get_typename(OBJECT(s));
 
 if (irq >= aic->num_ints) {
 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
@@ -52,7 +53,7 @@ static void aspeed_intc_update(AspeedINTCState *s, int irq, 
int level)
 return;
 }
 
-trace_aspeed_intc_update_irq(irq, level);
+trace_aspeed_intc_update_irq(name, irq, level);
 qemu_set_irq(s->output_pins[irq], level);
 }
 
@@ -66,6 +67,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 {
 AspeedINTCState *s = (AspeedINTCState *)opaque;
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+const char *name = object_get_typename(OBJECT(s));
 uint32_t status_reg = GICINT_STATUS_BASE + ((0x100 * irq) >> 2);
 uint32_t select = 0;
 uint32_t enable;
@@ -77,7 +79,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 return;
 }
 
-trace_aspeed_intc_set_irq(irq, level);
+trace_aspeed_intc_set_irq(name, irq, level);
 enable = s->enable[irq];
 
 if (!level) {
@@ -96,7 +98,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 return;
 }
 
-trace_aspeed_intc_select(select);
+trace_aspeed_intc_select(name, select);
 
 if (s->mask[irq] || s->regs[status_reg]) {
 /*
@@ -108,14 +110,14 @@ static void aspeed_intc_set_irq(void *opaque, int irq, 
int level)
  * save source interrupt to pending variable.
  */
 s->pending[irq] |= select;
-trace_aspeed_intc_pending_irq(irq, s->pending[irq]);
+trace_aspeed_intc_pending_irq(name, irq, s->pending[irq]);
 } else {
 /*
  * notify firmware which source interrupt are coming
  * by setting status register
  */
 s->regs[status_reg] = select;
-trace_aspeed_intc_trigger_irq(irq, s->regs[status_reg]);
+trace_aspeed_intc_trigger_irq(name, irq, s->regs[status_reg]);
 aspeed_intc_update(s, irq, 1);
 }
 }
@@ -124,6 +126,7 @@ static void aspeed_intc_enable_handler(AspeedINTCState *s, 
hwaddr offset,
uint64_t data)
 {
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+const char *name = object_get_typename(OBJECT(s));
 uint32_t reg = offset >> 2;
 uint32_t old_enable;
 uint32_t change;
@@ -154,7 +157,7 @@ static void aspeed_intc_enable_handler(AspeedINTCState *s, 
hwaddr offset,
 
 /* enable new source interrupt */
 if (old_enable != s->enable[irq]) {
-trace_aspeed_intc_enable(s->enable[irq]);
+trace_aspeed_intc_enable(name, s->enable[irq]);
 s->regs[reg] = data;
 return;
 }
@@ -163,10 +166,10 @@ static void aspeed_intc_enable_handler(AspeedINTCState 
*s, hwaddr offset,
 change = s->regs[reg] ^ data;
 if (change & data) {
 s->mask[irq] &= ~change;
-trace_aspeed_intc_unmask(change, s->mask[irq]);
+trace_aspeed_intc_unmask(name, change, s->mask[irq]);
 } else {
 s->mask[irq] |= change;
-trace_aspeed_intc_mask(change, s->mask[irq]);
+trace_aspeed_intc_mask(name, change, s->mask[irq]);
 }
 
 s->regs[reg] = data;
@@ -176,6 +179,7 @@ static void aspeed_intc_status_handler(AspeedINTCState *s, 
hwaddr offset,
uint64_t data)
 {
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+const char *name = object_get_typename(OBJECT(s));
 uint32_t reg = offset >> 2;
 uint32_t irq;
 
@@ -207,7 +211,7 @@ static void aspeed_intc_status_handler(AspeedINTCState *s, 
hwaddr offset,
 
 /* All source ISR execution are done */
 if (!s->regs[reg]) {
-trace_aspeed_intc_all_isr_done(irq);
+trace_aspeed_intc_all_isr_done(name, irq);
 if (s->pending[irq]) {
 /*
  * handle pending source interrupt
@@ -216,11 +220,11 @@ static void aspeed_intc_status_handler(AspeedINTCState 
*s, hwaddr offset,
  */
 s->regs[reg] 

RE: [PATCH v6 00/29] Support AST2700 A1

2025-03-06 Thread Steven Lee
> -Original Message-
> From: Cédric Le Goater 
> Sent: Friday, March 7, 2025 3:44 PM
> To: Jamin Lin ; Peter Maydell
> ; Steven Lee ; Troy
> Lee ; Andrew Jeffery ;
> Joel Stanley ; open list:All patches CC here
> ; open list:ASPEED BMCs
> 
> Cc: Troy Lee 
> Subject: Re: [PATCH v6 00/29] Support AST2700 A1
> 
> On 3/7/25 08:36, Jamin Lin wrote:
> > Hi Cedric,
> >
> >> Subject: Re: [PATCH v6 00/29] Support AST2700 A1
> >>
> >> On 3/7/25 04:59, Jamin Lin wrote:
> >>> v1:
> >>>1. Refactor INTC model to support both INTC0 and INTC1.
> >>>2. Support AST2700 A1.
> >>>3. Create ast2700a0-evb machine.
> >>>
> >>> v2:
> >>> To streamline the review process, split the following patch series 
> >>> into
> >>> three parts.
> >>>
> >>
> https://patchwork.kernel.org/project/qemu-devel/cover/20250121070424.24
> 6
> >> 5942-1-jamin_...@aspeedtech.com/
> >>> This patch series focuses on cleaning up the INTC model to
> >>> facilitate future support for the INTC_IO model.
> >>>
> >>> v3:
> >>>1. Update and add functional test for AST2700
> >>>2. Add AST2700 INTC design guidance and its block diagram.
> >>>3. Retaining the INTC naming and introducing a new INTCIO model to
> >> support the AST2700 A1.
> >>>4. Create ast2700a1-evb machine and rename ast2700a0-evb
> machine
> >>>5. Fix silicon revision issue and support AST2700 A1.
> >>>
> >>> v4:
> >>>1. rework functional test for AST2700
> >>>2. the initial machine "ast2700-evb" is aliased to "ast2700a0-evb.
> >>>3. intc: Reduce regs array size by adding a register sub-region
> >>>4. intc: split patch for Support setting different register sizes
> >>>5. update ast2700a1-evb machine parent to TYPE_ASPEED_MACHINE
> >>>
> >>> v5:
> >>>1. Rename status_addr and addr to status_reg and reg for clarity
> >>>2. Introduce dynamic allocation for regs array
> >>>3. Sort the memmap table by mapping address
> >>>4. ast27x0.c split patch for Support two levels of INTC controllers for
> >> AST2700 A1
> >>>5. tests/functional/aspped split patch for Introduce
> start_ast2700_test API
> >>>6. keep variable naming for reviewer suggestion.
> >>>7. Add reviewer suggestion and split patch to make more readable.
> >>>
> >>> v6:
> >>> 1. rename reg_size to nr_regs
> >>> 2. Fix clean regs size
> >>> 3. replace g_malloc with g_new
> >>>
> >>> With the patch applied, QEMU now supports two machines for running
> >> AST2700 SoCs:
> >>> ast2700a0-evb: Designed for AST2700 A0
> >>> ast2700a1-evb: Designed for AST2700 A1
> >>>
> >>> Test information
> >>> 1. QEMU version:
> >>
> https://github.com/qemu/qemu/commit/50d38b8921837827ea397d4b20c8b
> c
> >> 5efe186e53
> >>> 2. ASPEED SDK v09.05 pre-built image
> >>>
> https://github.com/AspeedTech-BMC/openbmc/releases/tag/v09.05
> >>>  ast2700-default-obmc.tar.gz (AST2700 A1)
> >>>
> >>
> https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.05/a
> st
> >> 2700-default-obmc.tar.gz
> >>>  ast2700-a0-default-obmc.tar.gz (AST2700 A0)
> >>>
> >>
> https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.05/a
> st
> >> 2700-a0-default-obmc.tar.gz
> >>>
> >>> This patch series depends on the following patch series:
> >>>
> >>
> https://patchwork.kernel.org/project/qemu-devel/cover/20250304064710.21
> 2
> >> 8993-1-jamin_...@aspeedtech.com/
> >>>
> >>
> https://patchwork.kernel.org/project/qemu-devel/cover/20250225075622.30
> 5
> >> 515-1-jamin_...@aspeedtech.com/
> >>>
> >>> Jamin Lin (29):
> >>> hw/intc/aspeed: Support setting different memory size
> >>> hw/intc/aspeed: Rename status_addr and addr to status_reg and
> reg for
> >>>   clarity
> >>> hw/intc/aspeed: Introduce dynamic allocation for regs array
> >>> hw/intc/aspeed: Support setting different register size
> >>> hw/intc/aspeed: Reduce regs array size by adding a register
> sub-region
> >>> hw/intc/aspeed: Introduce helper functions for enable and status
> >>>   registers
> >>> hw/intc/aspeed: Add object type name to trace events for better
> >>>   debugging
> >>> hw/arm/aspeed: Rename IRQ table and machine name for AST2700
> A0
> >>> hw/arm/aspeed_ast27x0: Sort the IRQ table by IRQ number
> >>> hw/intc/aspeed: Support different memory region ops
> >>> hw/intc/aspeed: Rename num_ints to num_inpins for clarity
> >>> hw/intc/aspeed: Add support for multiple output pins in INTC
> >>> hw/intc/aspeed: Refactor INTC to support separate input and output
> pin
> >>>   indices
> >>> hw/intc/aspeed: Introduce AspeedINTCIRQ structure to save the irq
> >>>   index and register address
> >>> hw/intc/aspeed: Introduce IRQ handler function to reduce code
> >>>   duplication
> >>> hw/intc/aspeed: Add Support for Multi-Output IRQ Handling
> >>> hw/intc/aspeed: Add Support for AST2700 INTCIO Controller
> >>> hw/misc/aspeed_scu: Add Support for AST2700/AST2750 A1 Silicon
> >>>   Revisions
> >

Re: [PATCH] include/exec: Move TARGET_PAGE_{SIZE,MASK,BITS} to target_page.h

2025-03-06 Thread Richard Henderson

On 3/6/25 15:41, Richard Henderson wrote:

diff --git a/page-vary-target.c b/page-vary-target.c
index 343b4adb95..1b4a9a10be 100644
--- a/page-vary-target.c
+++ b/page-vary-target.c
@@ -37,5 +37,7 @@ void finalize_target_page_bits(void)
  {
  #ifdef TARGET_PAGE_BITS_VARY
  finalize_target_page_bits_common(TARGET_PAGE_BITS_MIN);
+#else
+finalize_target_page_bits_common(TARGET_PAGE_BITS);
  #endif
  }


Actually, the ifdef here should be removed.
TARGET_PAGE_BITS_MIN is always correct.

r~



Re: [PATCH] pci-ids.rst: Add Red Hat pci-id for AMD IOMMU device

2025-03-06 Thread Suthikulpanit, Suravee



On 3/6/2025 3:58 PM, Daniel P. Berrangé wrote:

On Thu, Mar 06, 2025 at 09:11:53AM +0200, Yan Vugenfirer wrote:

On Wed, Mar 5, 2025 at 8:54 AM Michael S. Tsirkin  wrote:


On Tue, Mar 04, 2025 at 06:37:47PM +, Suravee Suthikulpanit wrote:

The QEMU-emulated AMD IOMMU PCI device is implemented based on the AMD

I/O

Virtualization Technology (IOMMU) Specification [1]. The PCI id for this
device is platform-specific.

Currently, the QEMU-emulated AMD IOMMU device is using AMD vendor id and
undefined device id.


undefined?


Currently, QEMU is using vendor ID "1022" and device ID "0".




Therefore, change the vendor id to Red Hat and request a new

QEMU-specific

device id.


Won't the drivers fail to load then?



Windows will not identify the device (it is a dummy device, without driver)
and SVVP certifications will fail as a result.
I suggest using ID that is already present in Windows machine.inf:
VEN_1002&DEV_5A23


  Ven:  Advanced Micro Devices, Inc. [AMD/ATI]
  Dev: RD890S/RD990 I/O Memory Management Unit (IOMMU)


VEN_1022&DEV_1419


  Vendor:  Advanced Micro Devices, Inc. [AMD]
  Dev: Family 15h (Models 10h-1fh) I/O Memory Management Unit

Is our implementation semantically a match for the functionality
in either of those real hardware devices ?

We shouldn't use an existing hardware dev ID unless we intend to
emulate its functionality as a precise match.


I agree. We should not use the "fake" ID unless we know for sure that 
the QEMU device is a match from the list of supported features and 
behavior (which might be implementation-specific on different 
platforms). Currently, this is not an exact match.


Linux does not care much about the PCI vendor/device ids since it uses 
the information in the IVRS table to probe for the device. Features are 
determined using the information in:

  * MMIO Offset 0030h IOMMU Extended Feature Register
  * MMIO Offset 01A0h IOMMU Extended Feature 2 Register

However, we can't guarantee how other OSes might be using these 
information for probing / loading drivers.


Thanks,
Suravee



[PATCH v6 15/29] hw/intc/aspeed: Introduce IRQ handler function to reduce code duplication

2025-03-06 Thread Jamin Lin via
The behavior of the INTC set IRQ is almost identical between INTC and INTCIO.
To reduce duplicated code, introduce the "aspeed_intc_set_irq_handler" function
to handle both INTC and INTCIO IRQ behavior. No functional change.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/intc/aspeed_intc.c | 70 ---
 1 file changed, 39 insertions(+), 31 deletions(-)

diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index be24516ec9..3aa97add8b 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -76,11 +76,45 @@ static void aspeed_intc_update(AspeedINTCState *s, int 
inpin_idx,
 qemu_set_irq(s->output_pins[outpin_idx], level);
 }
 
+static void aspeed_intc_set_irq_handler(AspeedINTCState *s,
+const AspeedINTCIRQ *intc_irq,
+uint32_t select)
+{
+const char *name = object_get_typename(OBJECT(s));
+uint32_t status_reg;
+int outpin_idx;
+int inpin_idx;
+
+status_reg = intc_irq->status_reg;
+outpin_idx = intc_irq->outpin_idx;
+inpin_idx = intc_irq->inpin_idx;
+
+if (s->mask[inpin_idx] || s->regs[status_reg]) {
+/*
+ * a. mask is not 0 means in ISR mode
+ * sources interrupt routine are executing.
+ * b. status register value is not 0 means previous
+ * source interrupt does not be executed, yet.
+ *
+ * save source interrupt to pending variable.
+ */
+s->pending[inpin_idx] |= select;
+trace_aspeed_intc_pending_irq(name, inpin_idx, s->pending[inpin_idx]);
+} else {
+/*
+ * notify firmware which source interrupt are coming
+ * by setting status register
+ */
+s->regs[status_reg] = select;
+trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
+  s->regs[status_reg]);
+aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
+}
+}
+
 /*
- * The address of GICINT128 to GICINT136 are from 0x1000 to 0x1804.
- * Utilize "address & 0x0f00" to get the irq and irq output pin index
- * The value of irq should be 0 to num_inpins.
- * The irq 0 indicates GICINT128, irq 1 indicates GICINT129 and so on.
+ * GICINT128 to GICINT136 map 1:1 to input and output IRQs 0 to 8.
+ * The value of input IRQ should be between 0 and the number of inputs.
  */
 static void aspeed_intc_set_irq(void *opaque, int irq, int level)
 {
@@ -88,20 +122,15 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
 const char *name = object_get_typename(OBJECT(s));
 const AspeedINTCIRQ *intc_irq;
-uint32_t status_reg;
 uint32_t select = 0;
 uint32_t enable;
-int outpin_idx;
 int inpin_idx;
 int i;
 
 assert(irq < aic->num_inpins);
 
 intc_irq = &aic->irq_table[irq];
-status_reg = intc_irq->status_reg;
-outpin_idx = intc_irq->outpin_idx;
 inpin_idx = intc_irq->inpin_idx;
-
 trace_aspeed_intc_set_irq(name, inpin_idx, level);
 enable = s->enable[inpin_idx];
 
@@ -122,28 +151,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 }
 
 trace_aspeed_intc_select(name, select);
-
-if (s->mask[inpin_idx] || s->regs[status_reg]) {
-/*
- * a. mask is not 0 means in ISR mode
- * sources interrupt routine are executing.
- * b. status register value is not 0 means previous
- * source interrupt does not be executed, yet.
- *
- * save source interrupt to pending variable.
- */
-s->pending[inpin_idx] |= select;
-trace_aspeed_intc_pending_irq(name, inpin_idx, s->pending[inpin_idx]);
-} else {
-/*
- * notify firmware which source interrupt are coming
- * by setting status register
- */
-s->regs[status_reg] = select;
-trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
-  s->regs[status_reg]);
-aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
-}
+aspeed_intc_set_irq_handler(s, intc_irq, select);
 }
 
 static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset,
-- 
2.43.0




[PATCH v6 20/29] hw/arm/aspeed_ast27x0: Define an Array of AspeedINTCState with Two Instances

2025-03-06 Thread Jamin Lin via
Updated Aspeed27x0SoCState to include an intc[2] array instead of a single
AspeedINTCState instance. Modified aspeed_soc_ast2700_get_irq and
aspeed_soc_ast2700_get_irq_index to correctly reference the corresponding
interrupt controller instance and OR gate index.

Currently, only GIC 192 to 201 are supported, and their source interrupts are
from INTCIO and connected to INTC at input pin 0 and output pins 0 to 9 for
GIC 192-201.

To support both AST2700 A1 and A0, INTC input pins 1 to 9 and output pins
10 to 18 remain to support GIC 128-136, which source interrupts from INTC.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 include/hw/arm/aspeed_soc.h |  2 +-
 hw/arm/aspeed_ast27x0.c | 58 +
 2 files changed, 40 insertions(+), 20 deletions(-)

diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 689f52dae8..1ac99269ae 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -128,7 +128,7 @@ struct Aspeed27x0SoCState {
 AspeedSoCState parent;
 
 ARMCPU cpu[ASPEED_CPUS_NUM];
-AspeedINTCState intc;
+AspeedINTCState intc[2];
 GICv3State gic;
 MemoryRegion dram_empty;
 };
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index 343fe87921..90545215e2 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -178,32 +178,48 @@ static const int ast2700_gic133_gic197_intcmap[] = {
 /* GICINT 192 ~ 201 */
 struct gic_intc_irq_info {
 int irq;
+int intc_idx;
+int orgate_idx;
 const int *ptr;
 };
 
 static const struct gic_intc_irq_info ast2700_gic_intcmap[] = {
-{128,  ast2700_gic128_gic192_intcmap},
-{129,  NULL},
-{130,  ast2700_gic130_gic194_intcmap},
-{131,  ast2700_gic131_gic195_intcmap},
-{132,  ast2700_gic132_gic196_intcmap},
-{133,  ast2700_gic133_gic197_intcmap},
-{134,  NULL},
-{135,  NULL},
-{136,  NULL},
+{192, 1, 0, ast2700_gic128_gic192_intcmap},
+{193, 1, 1, NULL},
+{194, 1, 2, ast2700_gic130_gic194_intcmap},
+{195, 1, 3, ast2700_gic131_gic195_intcmap},
+{196, 1, 4, ast2700_gic132_gic196_intcmap},
+{197, 1, 5, ast2700_gic133_gic197_intcmap},
+{198, 1, 6, NULL},
+{199, 1, 7, NULL},
+{200, 1, 8, NULL},
+{201, 1, 9, NULL},
+{128, 0, 1, ast2700_gic128_gic192_intcmap},
+{129, 0, 2, NULL},
+{130, 0, 3, ast2700_gic130_gic194_intcmap},
+{131, 0, 4, ast2700_gic131_gic195_intcmap},
+{132, 0, 5, ast2700_gic132_gic196_intcmap},
+{133, 0, 6, ast2700_gic133_gic197_intcmap},
+{134, 0, 7, NULL},
+{135, 0, 8, NULL},
+{136, 0, 9, NULL},
 };
 
 static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int dev)
 {
 Aspeed27x0SoCState *a = ASPEED27X0_SOC(s);
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+int or_idx;
+int idx;
 int i;
 
 for (i = 0; i < ARRAY_SIZE(ast2700_gic_intcmap); i++) {
 if (sc->irqmap[dev] == ast2700_gic_intcmap[i].irq) {
 assert(ast2700_gic_intcmap[i].ptr);
-return qdev_get_gpio_in(DEVICE(&a->intc.orgates[i]),
-ast2700_gic_intcmap[i].ptr[dev]);
+or_idx = ast2700_gic_intcmap[i].orgate_idx;
+idx = ast2700_gic_intcmap[i].intc_idx;
+return qdev_get_gpio_in(DEVICE(&a->intc[idx].orgates[or_idx]),
+ast2700_gic_intcmap[i].ptr[dev]);
 }
 }
 
@@ -215,12 +231,16 @@ static qemu_irq 
aspeed_soc_ast2700_get_irq_index(AspeedSoCState *s, int dev,
 {
 Aspeed27x0SoCState *a = ASPEED27X0_SOC(s);
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+int or_idx;
+int idx;
 int i;
 
 for (i = 0; i < ARRAY_SIZE(ast2700_gic_intcmap); i++) {
 if (sc->irqmap[dev] == ast2700_gic_intcmap[i].irq) {
 assert(ast2700_gic_intcmap[i].ptr);
-return qdev_get_gpio_in(DEVICE(&a->intc.orgates[i]),
+or_idx = ast2700_gic_intcmap[i].orgate_idx;
+idx = ast2700_gic_intcmap[i].intc_idx;
+return qdev_get_gpio_in(DEVICE(&a->intc[idx].orgates[or_idx]),
 ast2700_gic_intcmap[i].ptr[dev] + index);
 }
 }
@@ -390,7 +410,7 @@ static void aspeed_soc_ast2700_init(Object *obj)
 
 object_initialize_child(obj, "sli", &s->sli, TYPE_ASPEED_2700_SLI);
 object_initialize_child(obj, "sliio", &s->sliio, TYPE_ASPEED_2700_SLIIO);
-object_initialize_child(obj, "intc", &a->intc, TYPE_ASPEED_2700_INTC);
+object_initialize_child(obj, "intc", &a->intc[0], TYPE_ASPEED_2700_INTC);
 
 snprintf(typename, sizeof(typename), "aspeed.adc-%s", socname);
 object_initialize_child(obj, "adc", &s->adc, typename);
@@ -502,7 +522,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, 
Error **errp)
 Aspeed27x0SoCState *a = ASPEED27X0_SOC(dev);
 AspeedSoCState *s = ASPEED_SOC(dev);
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
-AspeedINTCClass *ic = ASPEED_INTC_GET_CLASS(&a->intc)

[PATCH v6 12/29] hw/intc/aspeed: Add support for multiple output pins in INTC

2025-03-06 Thread Jamin Lin via
Added support for multiple output pins in the INTC controller to
accommodate the AST2700 A1.

Introduced "num_outpins" to represent the number of output pins. Updated the
IRQ handling logic to initialize and connect output pins separately from input
pins. Modified the "aspeed_soc_ast2700_realize" function to connect source
orgates to INTC and INTC to GIC128 - GIC136. Updated the "aspeed_intc_realize"
function to initialize output pins.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 include/hw/intc/aspeed_intc.h | 5 +++--
 hw/arm/aspeed_ast27x0.c   | 6 +-
 hw/intc/aspeed_intc.c | 4 
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 58be5b3e13..2a22e30846 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -16,8 +16,8 @@
 #define TYPE_ASPEED_2700_INTC TYPE_ASPEED_INTC "-ast2700"
 OBJECT_DECLARE_TYPE(AspeedINTCState, AspeedINTCClass, ASPEED_INTC)
 
-#define ASPEED_INTC_NR_INTS 9
 #define ASPEED_INTC_MAX_INPINS 9
+#define ASPEED_INTC_MAX_OUTPINS 9
 
 struct AspeedINTCState {
 /*< private >*/
@@ -29,7 +29,7 @@ struct AspeedINTCState {
 
 uint32_t *regs;
 OrIRQState orgates[ASPEED_INTC_MAX_INPINS];
-qemu_irq output_pins[ASPEED_INTC_NR_INTS];
+qemu_irq output_pins[ASPEED_INTC_MAX_OUTPINS];
 
 uint32_t enable[ASPEED_INTC_MAX_INPINS];
 uint32_t mask[ASPEED_INTC_MAX_INPINS];
@@ -41,6 +41,7 @@ struct AspeedINTCClass {
 
 uint32_t num_lines;
 uint32_t num_inpins;
+uint32_t num_outpins;
 uint64_t mem_size;
 uint64_t nr_regs;
 uint64_t reg_offset;
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index 01a8e1d6b4..2d24361daa 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -530,10 +530,14 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, 
Error **errp)
 aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc), 0,
 sc->memmap[ASPEED_DEV_INTC]);
 
-/* GICINT orgates -> INTC -> GIC */
+/* source orgates -> INTC */
 for (i = 0; i < ic->num_inpins; i++) {
 qdev_connect_gpio_out(DEVICE(&a->intc.orgates[i]), 0,
 qdev_get_gpio_in(DEVICE(&a->intc), i));
+}
+
+/* INTC -> GIC128 - GIC136 */
+for (i = 0; i < ic->num_outpins; i++) {
 sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc), i,
qdev_get_gpio_in(DEVICE(&a->gic),
 aspeed_soc_ast2700_gic_intcmap[i].irq));
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 217fda6fe0..6f37afc17e 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -347,6 +347,9 @@ static void aspeed_intc_realize(DeviceState *dev, Error 
**errp)
 if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) {
 return;
 }
+}
+
+for (i = 0; i < aic->num_outpins; i++) {
 sysbus_init_irq(sbd, &s->output_pins[i]);
 }
 }
@@ -391,6 +394,7 @@ static void aspeed_2700_intc_class_init(ObjectClass *klass, 
void *data)
 dc->desc = "ASPEED 2700 INTC Controller";
 aic->num_lines = 32;
 aic->num_inpins = 9;
+aic->num_outpins = 9;
 aic->mem_size = 0x4000;
 aic->nr_regs = 0x808 >> 2;
 aic->reg_offset = 0x1000;
-- 
2.43.0




[PATCH v6 25/29] tests/functional/aspeed: Introduce start_ast2700_test API

2025-03-06 Thread Jamin Lin via
Added a new method "start_ast2700_test" to the "AST2x00MachineSDK" class and
this method centralizes the logic for starting the AST2700 test, making it
reusable for different test cases.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 tests/functional/test_aarch64_aspeed.py | 29 +
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/tests/functional/test_aarch64_aspeed.py 
b/tests/functional/test_aarch64_aspeed.py
index 9595498ace..e1ad7fd470 100755
--- a/tests/functional/test_aarch64_aspeed.py
+++ b/tests/functional/test_aarch64_aspeed.py
@@ -31,33 +31,29 @@ def do_test_aarch64_aspeed_sdk_start(self, image):
 
'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.03/ast2700-default-obmc.tar.gz',
 '91225f50d255e2905ba8d8e0c80b71b9d157c3609770c7a740cd786370d85a77')
 
-def test_aarch64_ast2700_evb_sdk_v09_03(self):
-self.set_machine('ast2700-evb')
-
-self.archive_extract(self.ASSET_SDK_V903_AST2700)
-
+def start_ast2700_test(self, name):
 num_cpu = 4
-uboot_size = os.path.getsize(self.scratch_file('ast2700-default',
+uboot_size = os.path.getsize(self.scratch_file(name,
'u-boot-nodtb.bin'))
 uboot_dtb_load_addr = hex(0x4 + uboot_size)
 
 load_images_list = [
 {
 'addr': '0x4',
-'file': self.scratch_file('ast2700-default',
+'file': self.scratch_file(name,
   'u-boot-nodtb.bin')
 },
 {
 'addr': str(uboot_dtb_load_addr),
-'file': self.scratch_file('ast2700-default', 'u-boot.dtb')
+'file': self.scratch_file(name, 'u-boot.dtb')
 },
 {
 'addr': '0x43000',
-'file': self.scratch_file('ast2700-default', 'bl31.bin')
+'file': self.scratch_file(name, 'bl31.bin')
 },
 {
 'addr': '0x43008',
-'file': self.scratch_file('ast2700-default', 'optee',
+'file': self.scratch_file(name, 'optee',
   'tee-raw.bin')
 }
 ]
@@ -76,13 +72,12 @@ def test_aarch64_ast2700_evb_sdk_v09_03(self):
 self.vm.add_args('-device',
  
'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test')
 self.do_test_aarch64_aspeed_sdk_start(
-self.scratch_file('ast2700-default', 'image-bmc'))
+self.scratch_file(name, 'image-bmc'))
 
-wait_for_console_pattern(self, 'ast2700-default login:')
+wait_for_console_pattern(self, f'{name} login:')
 
 exec_command_and_wait_for_pattern(self, 'root', 'Password:')
-exec_command_and_wait_for_pattern(self,
-'0penBmc', 'root@ast2700-default:~#')
+exec_command_and_wait_for_pattern(self, '0penBmc', f'root@{name}:~#')
 
 exec_command_and_wait_for_pattern(self,
 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device ',
@@ -94,6 +89,12 @@ def test_aarch64_ast2700_evb_sdk_v09_03(self):
 exec_command_and_wait_for_pattern(self,
 'cat /sys/class/hwmon/hwmon20/temp1_input', '18000')
 
+def test_aarch64_ast2700_evb_sdk_v09_03(self):
+self.set_machine('ast2700-evb')
+
+self.archive_extract(self.ASSET_SDK_V903_AST2700)
+self.start_ast2700_test('ast2700-default')
+
 
 if __name__ == '__main__':
 QemuSystemTest.main()
-- 
2.43.0




Re: [PATCH v2 01/10] target/i386: disable PerfMonV2 when PERFCORE unavailable

2025-03-06 Thread Sandipan Das
On 3/3/2025 3:30 AM, Dongli Zhang wrote:
> When the PERFCORE is disabled with "-cpu host,-perfctr-core", it is
> reflected in in guest dmesg.
> 
> [0.285136] Performance Events: AMD PMU driver.
> 
> However, the guest CPUID indicates the PerfMonV2 is still available.
> 
> CPU:
>Extended Performance Monitoring and Debugging (0x8022):
>   AMD performance monitoring V2 = true
>   AMD LBR V2= false
>   AMD LBR stack & PMC freezing  = false
>   number of core perf ctrs  = 0x6 (6)
>   number of LBR stack entries   = 0x0 (0)
>   number of avail Northbridge perf ctrs = 0x0 (0)
>   number of available UMC PMCs  = 0x0 (0)
>   active UMCs bitmask   = 0x0
> 
> Disable PerfMonV2 in CPUID when PERFCORE is disabled.
> 
> Suggested-by: Zhao Liu 
> Fixes: 209b0ac12074 ("target/i386: Add PerfMonV2 feature bit")
> Signed-off-by: Dongli Zhang 
> ---
> Changed since v1:
>   - Use feature_dependencies (suggested by Zhao Liu).
> 
>  target/i386/cpu.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 72ab147e85..b6d6167910 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -1805,6 +1805,10 @@ static FeatureDep feature_dependencies[] = {
>  .from = { FEAT_7_1_EDX, CPUID_7_1_EDX_AVX10 },
>  .to = { FEAT_24_0_EBX,  ~0ull },
>  },
> +{
> +.from = { FEAT_8000_0001_ECX,   CPUID_EXT3_PERFCORE },
> +.to = { FEAT_8000_0022_EAX, CPUID_8000_0022_EAX_PERFMON_V2 },
> +},
>  };
>  
>  typedef struct X86RegisterInfo32 {


Reviewed-by: Sandipan Das 




Re: [PULL 0/4] NBD patches through 2025-03-05

2025-03-06 Thread Stefan Hajnoczi
Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/10.0 for any 
user-visible changes.


signature.asc
Description: PGP signature


Re: [PULL 00/54] Accelerators & CPU patches

2025-03-06 Thread Stefan Hajnoczi
Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/10.0 for any 
user-visible changes.


signature.asc
Description: PGP signature


Re: [PULL 0/1] Block patches

2025-03-06 Thread Stefan Hajnoczi
Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/10.0 for any 
user-visible changes.


signature.asc
Description: PGP signature


Re: [PULL 00/42] vfio queue

2025-03-06 Thread Stefan Hajnoczi
Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/10.0 for any 
user-visible changes.


signature.asc
Description: PGP signature


Re: [PATCH v2 03/10] [DO NOT MERGE] kvm: Introduce kvm_arch_pre_create_vcpu()

2025-03-06 Thread Zhao Liu
> I didn't know if I would need to wait until this patch is merged into
> mainline QEMU. That's why I didn't add my signed-off.

No problem if Xiaoyao is okay with it (copyright of patches need to
honor the original author & signed-off). IMO, if your series is accepted
first, it also helps to reduce the size of the TDX series, and it helps
the subsequent PMU development (like mediated PMU). Conversely, it's
also not a big deal; you can simply rebase and remove this patch at that
time.

Even I'm thinking that my KVM PMU filter should perhaps base on your work.

> I will add in v3 and remove "DO NOT MERGE" if the patch isn't in QEMU when
> I am sending out v3.

Okay.

Thanks,
Zhao




Re: [PATCH v6 00/29] Support AST2700 A1

2025-03-06 Thread Cédric Le Goater

On 3/7/25 04:59, Jamin Lin wrote:

v1:
  1. Refactor INTC model to support both INTC0 and INTC1.
  2. Support AST2700 A1.
  3. Create ast2700a0-evb machine.
  
v2:

   To streamline the review process, split the following patch series into
   three parts.
   
https://patchwork.kernel.org/project/qemu-devel/cover/20250121070424.2465942-1-jamin_...@aspeedtech.com/
   This patch series focuses on cleaning up the INTC model to
   facilitate future support for the INTC_IO model.

v3:
  1. Update and add functional test for AST2700
  2. Add AST2700 INTC design guidance and its block diagram.
  3. Retaining the INTC naming and introducing a new INTCIO model to support 
the AST2700 A1.
  4. Create ast2700a1-evb machine and rename ast2700a0-evb machine
  5. Fix silicon revision issue and support AST2700 A1.

v4:
  1. rework functional test for AST2700
  2. the initial machine "ast2700-evb" is aliased to "ast2700a0-evb.
  3. intc: Reduce regs array size by adding a register sub-region
  4. intc: split patch for Support setting different register sizes
  5. update ast2700a1-evb machine parent to TYPE_ASPEED_MACHINE

v5:
  1. Rename status_addr and addr to status_reg and reg for clarity
  2. Introduce dynamic allocation for regs array
  3. Sort the memmap table by mapping address
  4. ast27x0.c split patch for Support two levels of INTC controllers for 
AST2700 A1
  5. tests/functional/aspped split patch for Introduce start_ast2700_test API
  6. keep variable naming for reviewer suggestion.
  7. Add reviewer suggestion and split patch to make more readable.
  
v6:

   1. rename reg_size to nr_regs
   2. Fix clean regs size
   3. replace g_malloc with g_new

With the patch applied, QEMU now supports two machines for running AST2700 SoCs:
ast2700a0-evb: Designed for AST2700 A0
ast2700a1-evb: Designed for AST2700 A1

Test information
1. QEMU version: 
https://github.com/qemu/qemu/commit/50d38b8921837827ea397d4b20c8bc5efe186e53
2. ASPEED SDK v09.05 pre-built image
https://github.com/AspeedTech-BMC/openbmc/releases/tag/v09.05
ast2700-default-obmc.tar.gz (AST2700 A1)

https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.05/ast2700-default-obmc.tar.gz
ast2700-a0-default-obmc.tar.gz (AST2700 A0)

https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.05/ast2700-a0-default-obmc.tar.gz

This patch series depends on the following patch series:

https://patchwork.kernel.org/project/qemu-devel/cover/20250304064710.2128993-1-jamin_...@aspeedtech.com/
https://patchwork.kernel.org/project/qemu-devel/cover/20250225075622.305515-1-jamin_...@aspeedtech.com/

Jamin Lin (29):
   hw/intc/aspeed: Support setting different memory size
   hw/intc/aspeed: Rename status_addr and addr to status_reg and reg for
 clarity
   hw/intc/aspeed: Introduce dynamic allocation for regs array
   hw/intc/aspeed: Support setting different register size
   hw/intc/aspeed: Reduce regs array size by adding a register sub-region
   hw/intc/aspeed: Introduce helper functions for enable and status
 registers
   hw/intc/aspeed: Add object type name to trace events for better
 debugging
   hw/arm/aspeed: Rename IRQ table and machine name for AST2700 A0
   hw/arm/aspeed_ast27x0: Sort the IRQ table by IRQ number
   hw/intc/aspeed: Support different memory region ops
   hw/intc/aspeed: Rename num_ints to num_inpins for clarity
   hw/intc/aspeed: Add support for multiple output pins in INTC
   hw/intc/aspeed: Refactor INTC to support separate input and output pin
 indices
   hw/intc/aspeed: Introduce AspeedINTCIRQ structure to save the irq
 index and register address
   hw/intc/aspeed: Introduce IRQ handler function to reduce code
 duplication
   hw/intc/aspeed: Add Support for Multi-Output IRQ Handling
   hw/intc/aspeed: Add Support for AST2700 INTCIO Controller
   hw/misc/aspeed_scu: Add Support for AST2700/AST2750 A1 Silicon
 Revisions
   hw/arm/aspeed_ast27x0.c Support AST2700 A1 GIC Interrupt Mapping
   hw/arm/aspeed_ast27x0: Define an Array of AspeedINTCState with Two
 Instances
   hw/arm/aspeed_ast27x0: Support two levels of INTC controllers for
 AST2700 A1
   hw/arm/aspeed_ast27x0: Add SoC Support for AST2700 A1
   hw/arm/aspeed: Add Machine Support for AST2700 A1
   hw/arm/aspeed_ast27x0: Sort the memmap table by mapping address
   tests/functional/aspeed: Introduce start_ast2700_test API
   tests/functional/aspeed: Update temperature hwmon path
   tests/functional/aspeed: Update test ASPEED SDK v09.05
   tests/functional/aspeed: Add test case for AST2700 A1
   docs/specs: Add aspeed-intc

  docs/specs/aspeed-intc.rst  | 136 +
  docs/specs/index.rst|   1 +
  include/hw/arm/aspeed_soc.h |   3 +-
  include/hw/intc/aspeed_intc.h   |  36 +-
  include/hw/misc/aspeed_scu.h|   2 +
  hw/arm/aspeed.c |  33 +-
  hw/arm/aspeed_ast27x0.c | 329 
  hw/intc/aspeed_intc.c 

[qemu-web PATCH] Announce Google Summer of Code 2025

2025-03-06 Thread Stefan Hajnoczi
Let people know that QEMU is participating in Google Summer of Code so
that they can apply for an internship this summer.

Signed-off-by: Stefan Hajnoczi 
---
 _posts/2025-03-06-gsoc-2025.md | 40 ++
 1 file changed, 40 insertions(+)
 create mode 100644 _posts/2025-03-06-gsoc-2025.md

diff --git a/_posts/2025-03-06-gsoc-2025.md b/_posts/2025-03-06-gsoc-2025.md
new file mode 100644
index 000..5c7352f
--- /dev/null
+++ b/_posts/2025-03-06-gsoc-2025.md
@@ -0,0 +1,40 @@
+---
+layout: post
+title:  "Announcing QEMU Google Summer of Code 2025 internships"
+date:   2025-03-06 07:00:00 +
+categories: [internships, gsoc]
+---
+QEMU is participating in [Google Summer of
+Code](https://summerofcode.withgoogle.com/) again this year! Google Summer of 
Code
+is an open source internship program that offers paid remote work
+opportunities for contributing to open source. Internships run May through
+August, so if you have time and want to experience open source development,
+read on to find out how you can apply.
+
+Each intern is paired with one or more mentors, experienced QEMU contributors
+who support them during the internship. Code developed by the intern is
+submitted through the same open source development process that all QEMU
+contributions follow. This gives interns experience with contributing to open
+source software. Some interns then choose to pursue a career in open source
+software after completing their internship.
+
+## Find out if you are eligible
+Information on who can apply for Google Summer of Code is
+[here](https://developers.google.com/open-source/gsoc/faq#what_are_the_eligibility_requirements_for_participation).
+
+## Select a project idea
+Look through the the [list of QEMU project
+ideas](https://wiki.qemu.org/Google_Summer_of_Code_2025) and see if there is
+something you are interested in working on. Once you have found a project idea
+you want to apply for, email the mentor for that project idea to ask any
+questions you may have and discuss the idea further.
+
+## Submit your application
+You can [apply for Google Summer of Code](https://summerofcode.withgoogle.com/)
+from March 24th to April 8th.
+
+Good luck with your applications!
+
+If you have questions about applying for QEMU GSoC, please email
+[Stefan Hajnoczi](mailto:stefa...@gmail.com) or ask on the [#qemu-gsoc IRC
+channel](https://webchat.oftc.net/?channels=qemu-gsoc).
-- 
2.48.1




Re: [PATCH v2 08/10] target/i386/kvm: reset AMD PMU registers during VM reset

2025-03-06 Thread Sandipan Das
On 3/3/2025 3:30 AM, Dongli Zhang wrote:
> QEMU uses the kvm_get_msrs() function to save Intel PMU registers from KVM
> and kvm_put_msrs() to restore them to KVM. However, there is no support for
> AMD PMU registers. Currently, has_pmu_version and num_pmu_gp_counters are
> initialized based on cpuid(0xa), which does not apply to AMD processors.
> For AMD CPUs, prior to PerfMonV2, the number of general-purpose registers
> is determined based on the CPU version.
> 
> To address this issue, we need to add support for AMD PMU registers.
> Without this support, the following problems can arise:
> 
> 1. If the VM is reset (e.g., via QEMU system_reset or VM kdump/kexec) while
> running "perf top", the PMU registers are not disabled properly.
> 
> 2. Despite x86_cpu_reset() resetting many registers to zero, kvm_put_msrs()
> does not handle AMD PMU registers, causing some PMU events to remain
> enabled in KVM.
> 
> 3. The KVM kvm_pmc_speculative_in_use() function consistently returns true,
> preventing the reclamation of these events. Consequently, the
> kvm_pmc->perf_event remains active.
> 
> 4. After a reboot, the VM kernel may report the following error:
> 
> [0.092011] Performance Events: Fam17h+ core perfctr, Broken BIOS 
> detected, complain to your hardware vendor.
> [0.092023] [Firmware Bug]: the BIOS has corrupted hw-PMU resources (MSR 
> c0010200 is 530076)
> 
> 5. In the worst case, the active kvm_pmc->perf_event may inject unknown
> NMIs randomly into the VM kernel:
> 
> [...] Uhhuh. NMI received for unknown reason 30 on CPU 0.
> 
> To resolve these issues, we propose resetting AMD PMU registers during the
> VM reset process.
> 
> Signed-off-by: Dongli Zhang 
> ---
> Changed since v1:
>   - Modify "MSR_K7_EVNTSEL0 + 3" and "MSR_K7_PERFCTR0 + 3" by using
> AMD64_NUM_COUNTERS (suggested by Sandipan Das).
>   - Use "AMD64_NUM_COUNTERS_CORE * 2 - 1", not "MSR_F15H_PERF_CTL0 + 0xb".
> (suggested by Sandipan Das).
>   - Switch back to "-pmu" instead of using a global "pmu-cap-disabled".
>   - Don't initialize PMU info if kvm.enable_pmu=N.
> 
>  target/i386/cpu.h |   8 ++
>  target/i386/kvm/kvm.c | 173 +-
>  2 files changed, 177 insertions(+), 4 deletions(-)
> 
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index c67b42d34f..319600672b 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -490,6 +490,14 @@ typedef enum X86Seg {
>  #define MSR_CORE_PERF_GLOBAL_CTRL   0x38f
>  #define MSR_CORE_PERF_GLOBAL_OVF_CTRL   0x390
>  
> +#define MSR_K7_EVNTSEL0 0xc001
> +#define MSR_K7_PERFCTR0 0xc0010004
> +#define MSR_F15H_PERF_CTL0  0xc0010200
> +#define MSR_F15H_PERF_CTR0  0xc0010201
> +
> +#define AMD64_NUM_COUNTERS  4
> +#define AMD64_NUM_COUNTERS_CORE 6
> +
>  #define MSR_MC0_CTL 0x400
>  #define MSR_MC0_STATUS  0x401
>  #define MSR_MC0_ADDR0x402
> diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
> index efba3ae7a4..d4be8a0d2e 100644
> --- a/target/i386/kvm/kvm.c
> +++ b/target/i386/kvm/kvm.c
> @@ -2069,7 +2069,7 @@ int kvm_arch_pre_create_vcpu(CPUState *cpu, Error 
> **errp)
>  return 0;
>  }
>  
> -static void kvm_init_pmu_info(CPUX86State *env)
> +static void kvm_init_pmu_info_intel(CPUX86State *env)
>  {
>  uint32_t eax, edx;
>  uint32_t unused;
> @@ -2106,6 +2106,94 @@ static void kvm_init_pmu_info(CPUX86State *env)
>  }
>  }
>  
> +static void kvm_init_pmu_info_amd(CPUX86State *env)
> +{
> +uint32_t unused;
> +int64_t family;
> +uint32_t ecx;
> +
> +has_pmu_version = 0;
> +
> +/*
> + * To determine the CPU family, the following code is derived from
> + * x86_cpuid_version_get_family().
> + */
> +family = (env->cpuid_version >> 8) & 0xf;
> +if (family == 0xf) {
> +family += (env->cpuid_version >> 20) & 0xff;
> +}
> +
> +/*
> + * Performance-monitoring supported from K7 and later.
> + */
> +if (family < 6) {
> +return;
> +}
> +
> +has_pmu_version = 1;
> +
> +cpu_x86_cpuid(env, 0x8001, 0, &unused, &unused, &ecx, &unused);
> +
> +if (!(ecx & CPUID_EXT3_PERFCORE)) {
> +num_pmu_gp_counters = AMD64_NUM_COUNTERS;
> +return;
> +}
> +
> +num_pmu_gp_counters = AMD64_NUM_COUNTERS_CORE;
> +}
> +
> +static bool is_same_vendor(CPUX86State *env)
> +{
> +static uint32_t host_cpuid_vendor1;
> +static uint32_t host_cpuid_vendor2;
> +static uint32_t host_cpuid_vendor3;
> +
> +host_cpuid(0x0, 0, NULL, &host_cpuid_vendor1, &host_cpuid_vendor3,
> +   &host_cpuid_vendor2);
> +
> +return env->cpuid_vendor1 == host_cpuid_vendor1 &&
> +   env->cpuid_vendor2 == host_cpuid_vendor2 &&
> +   env->cpuid_vendor3 == host_cpuid_vendor3;
> +}
> +
> +static void kvm_init_pmu_info(CPUState *cs)
> +{
> +X86CPU *cpu = X86_CPU(cs);
> +

[PATCH v6 08/29] hw/arm/aspeed: Rename IRQ table and machine name for AST2700 A0

2025-03-06 Thread Jamin Lin via
Currently, AST2700 SoC only supports A0. To support AST2700 A1, rename its IRQ
table and machine name.

To follow the machine deprecation rule, the initial machine "ast2700-evb" is
aliased to "ast2700a0-evb." In the future, we will alias "ast2700-evb" to new
SoCs, such as "ast2700a1-evb."

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/arm/aspeed.c | 9 +
 hw/arm/aspeed_ast27x0.c | 8 
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index c6c18596d6..18f7c450da 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1673,12 +1673,13 @@ static void ast2700_evb_i2c_init(AspeedMachineState 
*bmc)
 TYPE_TMP105, 0x4d);
 }
 
-static void aspeed_machine_ast2700_evb_class_init(ObjectClass *oc, void *data)
+static void aspeed_machine_ast2700a0_evb_class_init(ObjectClass *oc, void 
*data)
 {
 MachineClass *mc = MACHINE_CLASS(oc);
 AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
 
-mc->desc = "Aspeed AST2700 EVB (Cortex-A35)";
+mc->alias = "ast2700-evb";
+mc->desc = "Aspeed AST2700 A0 EVB (Cortex-A35)";
 amc->soc_name  = "ast2700-a0";
 amc->hw_strap1 = AST2700_EVB_HW_STRAP1;
 amc->hw_strap2 = AST2700_EVB_HW_STRAP2;
@@ -1817,9 +1818,9 @@ static const TypeInfo aspeed_machine_types[] = {
 .class_init = aspeed_minibmc_machine_ast1030_evb_class_init,
 #ifdef TARGET_AARCH64
 }, {
-.name  = MACHINE_TYPE_NAME("ast2700-evb"),
+.name  = MACHINE_TYPE_NAME("ast2700a0-evb"),
 .parent= TYPE_ASPEED_MACHINE,
-.class_init= aspeed_machine_ast2700_evb_class_init,
+.class_init= aspeed_machine_ast2700a0_evb_class_init,
 #endif
 }, {
 .name  = TYPE_ASPEED_MACHINE,
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index 10e1358166..de79724446 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -73,7 +73,7 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = {
 #define AST2700_MAX_IRQ 256
 
 /* Shared Peripheral Interrupt values below are offset by -32 from datasheet */
-static const int aspeed_soc_ast2700_irqmap[] = {
+static const int aspeed_soc_ast2700a0_irqmap[] = {
 [ASPEED_DEV_UART0] = 132,
 [ASPEED_DEV_UART1] = 132,
 [ASPEED_DEV_UART2] = 132,
@@ -762,7 +762,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, 
Error **errp)
 create_unimplemented_device("ast2700.io", 0x0, 0x400);
 }
 
-static void aspeed_soc_ast2700_class_init(ObjectClass *oc, void *data)
+static void aspeed_soc_ast2700a0_class_init(ObjectClass *oc, void *data)
 {
 static const char * const valid_cpu_types[] = {
 ARM_CPU_TYPE_NAME("cortex-a35"),
@@ -785,7 +785,7 @@ static void aspeed_soc_ast2700_class_init(ObjectClass *oc, 
void *data)
 sc->uarts_num= 13;
 sc->num_cpus = 4;
 sc->uarts_base   = ASPEED_DEV_UART0;
-sc->irqmap   = aspeed_soc_ast2700_irqmap;
+sc->irqmap   = aspeed_soc_ast2700a0_irqmap;
 sc->memmap   = aspeed_soc_ast2700_memmap;
 sc->get_irq  = aspeed_soc_ast2700_get_irq;
 }
@@ -800,7 +800,7 @@ static const TypeInfo aspeed_soc_ast27x0_types[] = {
 .name   = "ast2700-a0",
 .parent = TYPE_ASPEED27X0_SOC,
 .instance_init  = aspeed_soc_ast2700_init,
-.class_init = aspeed_soc_ast2700_class_init,
+.class_init = aspeed_soc_ast2700a0_class_init,
 },
 };
 
-- 
2.43.0




[PATCH v6 09/29] hw/arm/aspeed_ast27x0: Sort the IRQ table by IRQ number

2025-03-06 Thread Jamin Lin via
To improve readability, sort the IRQ table by IRQ number.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/arm/aspeed_ast27x0.c | 50 -
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index de79724446..abd1f6b741 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -74,27 +74,13 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = {
 
 /* Shared Peripheral Interrupt values below are offset by -32 from datasheet */
 static const int aspeed_soc_ast2700a0_irqmap[] = {
-[ASPEED_DEV_UART0] = 132,
-[ASPEED_DEV_UART1] = 132,
-[ASPEED_DEV_UART2] = 132,
-[ASPEED_DEV_UART3] = 132,
-[ASPEED_DEV_UART4] = 8,
-[ASPEED_DEV_UART5] = 132,
-[ASPEED_DEV_UART6] = 132,
-[ASPEED_DEV_UART7] = 132,
-[ASPEED_DEV_UART8] = 132,
-[ASPEED_DEV_UART9] = 132,
-[ASPEED_DEV_UART10]= 132,
-[ASPEED_DEV_UART11]= 132,
-[ASPEED_DEV_UART12]= 132,
-[ASPEED_DEV_FMC]   = 131,
 [ASPEED_DEV_SDMC]  = 0,
-[ASPEED_DEV_SCU]   = 12,
-[ASPEED_DEV_ADC]   = 130,
+[ASPEED_DEV_HACE]  = 4,
 [ASPEED_DEV_XDMA]  = 5,
-[ASPEED_DEV_EMMC]  = 15,
-[ASPEED_DEV_GPIO]  = 130,
+[ASPEED_DEV_UART4] = 8,
+[ASPEED_DEV_SCU]   = 12,
 [ASPEED_DEV_RTC]   = 13,
+[ASPEED_DEV_EMMC]  = 15,
 [ASPEED_DEV_TIMER1]= 16,
 [ASPEED_DEV_TIMER2]= 17,
 [ASPEED_DEV_TIMER3]= 18,
@@ -103,19 +89,33 @@ static const int aspeed_soc_ast2700a0_irqmap[] = {
 [ASPEED_DEV_TIMER6]= 21,
 [ASPEED_DEV_TIMER7]= 22,
 [ASPEED_DEV_TIMER8]= 23,
-[ASPEED_DEV_WDT]   = 131,
-[ASPEED_DEV_PWM]   = 131,
+[ASPEED_DEV_DP]= 28,
 [ASPEED_DEV_LPC]   = 128,
 [ASPEED_DEV_IBT]   = 128,
+[ASPEED_DEV_KCS]   = 128,
+[ASPEED_DEV_ADC]   = 130,
+[ASPEED_DEV_GPIO]  = 130,
 [ASPEED_DEV_I2C]   = 130,
-[ASPEED_DEV_PECI]  = 133,
+[ASPEED_DEV_FMC]   = 131,
+[ASPEED_DEV_WDT]   = 131,
+[ASPEED_DEV_PWM]   = 131,
+[ASPEED_DEV_I3C]   = 131,
+[ASPEED_DEV_UART0] = 132,
+[ASPEED_DEV_UART1] = 132,
+[ASPEED_DEV_UART2] = 132,
+[ASPEED_DEV_UART3] = 132,
+[ASPEED_DEV_UART5] = 132,
+[ASPEED_DEV_UART6] = 132,
+[ASPEED_DEV_UART7] = 132,
+[ASPEED_DEV_UART8] = 132,
+[ASPEED_DEV_UART9] = 132,
+[ASPEED_DEV_UART10]= 132,
+[ASPEED_DEV_UART11]= 132,
+[ASPEED_DEV_UART12]= 132,
 [ASPEED_DEV_ETH1]  = 132,
 [ASPEED_DEV_ETH2]  = 132,
 [ASPEED_DEV_ETH3]  = 132,
-[ASPEED_DEV_HACE]  = 4,
-[ASPEED_DEV_KCS]   = 128,
-[ASPEED_DEV_DP]= 28,
-[ASPEED_DEV_I3C]   = 131,
+[ASPEED_DEV_PECI]  = 133,
 [ASPEED_DEV_SDHCI] = 133,
 };
 
-- 
2.43.0




Re: [v5,1/6] hw/misc/aspeed_scu: Skipping dram_init in u-boot

2025-03-06 Thread Cédric Le Goater

Hello,

On 3/6/25 19:05, Nabih Estefan wrote:

Hi Cédric,

We have a custom machine and a custom image using the AST27x0 A0. I ran
some of our internal tests using these patches. They even fixed some of the
errors we’d been seeing recently!

I’m also working on testing through the A1 patches, will reply to those soon.


I pushed them on the aspeed-next branch.

https://github.com/legoater/qemu/commits/aspeed-next/

and should send a PR around the week-end.

Thanks,

C.





Re: [PATCH v6 05/29] hw/intc/aspeed: Reduce regs array size by adding a register sub-region

2025-03-06 Thread Cédric Le Goater

On 3/7/25 04:59, Jamin Lin wrote:

Currently, the size of the "regs" array is 0x2000, which is too large. So far,
it only uses "GICINT128 to `GICINT134", and the offsets from 0 to 0x1000 are
unused. To save code size and avoid mapping large unused gaps, update to only
map the useful set of registers:

INTC register [0x1000 – 0x1804]

Update "reg_size" to 0x808. Introduce a new class attribute "reg_offset" to set
the start offset of a "INTC" sub-region. Set the "reg_offset" to 0x1000 for INTC
registers.

Signed-off-by: Jamin Lin 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  include/hw/intc/aspeed_intc.h |  1 +
  hw/intc/aspeed_intc.c | 50 ---
  2 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index ec4936b3f4..208e764c4a 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -42,6 +42,7 @@ struct AspeedINTCClass {
  uint32_t num_ints;
  uint64_t mem_size;
  uint64_t nr_regs;
+uint64_t reg_offset;
  };
  
  #endif /* ASPEED_INTC_H */

diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 134922e46f..d684b4bb4f 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -14,25 +14,31 @@
  #include "hw/registerfields.h"
  #include "qapi/error.h"
  
-/* INTC Registers */

-REG32(GICINT128_EN, 0x1000)
-REG32(GICINT128_STATUS, 0x1004)
-REG32(GICINT129_EN, 0x1100)
-REG32(GICINT129_STATUS, 0x1104)
-REG32(GICINT130_EN, 0x1200)
-REG32(GICINT130_STATUS, 0x1204)
-REG32(GICINT131_EN, 0x1300)
-REG32(GICINT131_STATUS, 0x1304)
-REG32(GICINT132_EN, 0x1400)
-REG32(GICINT132_STATUS, 0x1404)
-REG32(GICINT133_EN, 0x1500)
-REG32(GICINT133_STATUS, 0x1504)
-REG32(GICINT134_EN, 0x1600)
-REG32(GICINT134_STATUS, 0x1604)
-REG32(GICINT135_EN, 0x1700)
-REG32(GICINT135_STATUS, 0x1704)
-REG32(GICINT136_EN, 0x1800)
-REG32(GICINT136_STATUS, 0x1804)
+/*
+ * INTC Registers
+ *
+ * values below are offset by - 0x1000 from datasheet
+ * because its memory region is start at 0x1000
+ *
+ */
+REG32(GICINT128_EN, 0x000)
+REG32(GICINT128_STATUS, 0x004)
+REG32(GICINT129_EN, 0x100)
+REG32(GICINT129_STATUS, 0x104)
+REG32(GICINT130_EN, 0x200)
+REG32(GICINT130_STATUS, 0x204)
+REG32(GICINT131_EN, 0x300)
+REG32(GICINT131_STATUS, 0x304)
+REG32(GICINT132_EN, 0x400)
+REG32(GICINT132_STATUS, 0x404)
+REG32(GICINT133_EN, 0x500)
+REG32(GICINT133_STATUS, 0x504)
+REG32(GICINT134_EN, 0x600)
+REG32(GICINT134_STATUS, 0x604)
+REG32(GICINT135_EN, 0x700)
+REG32(GICINT135_STATUS, 0x704)
+REG32(GICINT136_EN, 0x800)
+REG32(GICINT136_STATUS, 0x804)
  
  #define GICINT_STATUS_BASE R_GICINT128_STATUS
  
@@ -298,7 +304,8 @@ static void aspeed_intc_realize(DeviceState *dev, Error **errp)

  memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2);
  
-memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem);

+memory_region_add_subregion(&s->iomem_container, aic->reg_offset,
+&s->iomem);
  
  qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints);
  
@@ -348,7 +355,8 @@ static void aspeed_2700_intc_class_init(ObjectClass *klass, void *data)

  aic->num_lines = 32;
  aic->num_ints = 9;
  aic->mem_size = 0x4000;
-aic->nr_regs = 0x2000 >> 2;
+aic->nr_regs = 0x808 >> 2;
+aic->reg_offset = 0x1000;
  }
  
  static const TypeInfo aspeed_2700_intc_info = {





[PATCH 6/7] hw/hyperv/balloon: common balloon compilation units

2025-03-06 Thread Pierrick Bouvier
Signed-off-by: Pierrick Bouvier 
---
 hw/hyperv/meson.build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/hyperv/meson.build b/hw/hyperv/meson.build
index a9f2045a9af..5acd709bdd5 100644
--- a/hw/hyperv/meson.build
+++ b/hw/hyperv/meson.build
@@ -2,5 +2,5 @@ specific_ss.add(when: 'CONFIG_HYPERV', if_true: 
files('hyperv.c'))
 specific_ss.add(when: 'CONFIG_HYPERV_TESTDEV', if_true: 
files('hyperv_testdev.c'))
 system_ss.add(when: 'CONFIG_VMBUS', if_true: files('vmbus.c'))
 system_ss.add(when: 'CONFIG_SYNDBG', if_true: files('syndbg.c'))
-specific_ss.add(when: 'CONFIG_HV_BALLOON', if_true: files('hv-balloon.c', 
'hv-balloon-page_range_tree.c', 'hv-balloon-our_range_memslots.c'))
+system_ss.add(when: 'CONFIG_HV_BALLOON', if_true: files('hv-balloon.c', 
'hv-balloon-page_range_tree.c', 'hv-balloon-our_range_memslots.c'))
 system_ss.add(when: 'CONFIG_HV_BALLOON', if_false: files('hv-balloon-stub.c'))
-- 
2.39.5




Re: [PATCH 11/57] docs/qapi-domain: add qapi:command directive

2025-03-06 Thread Markus Armbruster
John Snow  writes:

> This commit adds a stubbed version of QAPICommand that utilizes the
> QAPIObject class, the qapi:command directive, the :qapi:cmd:
> cross-reference role, and the "command" object type in the QAPI object
> registry.
>
> This commit also adds the aforementioned generic QAPIObject class for
> use in documenting various QAPI entities in the Sphinx ecosystem.
>
> They don't do anything *particularly* interesting yet, but that will
> come in forthcoming commits.
>
> Note: some versions of mypy get a little confused over the difference
> between class and instance variables; because sphinx's ObjectDescription
> does not declare option_spec as a ClassVar (even though it's obvious
> that it is), mypy may produce this error:
>
> qapi-domain.py:125: error: Cannot override instance variable (previously
> declared on base class "ObjectDescription") with class variable [misc]
>
> I can't control that; so silence the error with a pragma.

Is this still accurate?  qapi-domain.py line 125 is a comment.  I can't
see the pragma.

> Signed-off-by: John Snow 
> ---
>  docs/sphinx/qapi_domain.py | 146 -
>  1 file changed, 144 insertions(+), 2 deletions(-)
>
> diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py
> index 104bae709f3..6168c23936f 100644
> --- a/docs/sphinx/qapi_domain.py
> +++ b/docs/sphinx/qapi_domain.py
> @@ -21,9 +21,10 @@
>  from docutils import nodes
>  from docutils.parsers.rst import directives
>  
> -from compat import nested_parse
> +from compat import KeywordNode, SpaceNode, nested_parse
>  from sphinx import addnodes
> -from sphinx.addnodes import pending_xref
> +from sphinx.addnodes import desc_signature, pending_xref
> +from sphinx.directives import ObjectDescription
>  from sphinx.domains import (
>  Domain,
>  Index,
> @@ -103,6 +104,144 @@ def process_link(
>  return title, target
>  
>  
> +# Alias for the return of handle_signature(), which is used in several 
> places.
> +# (In the Python domain, this is Tuple[str, str] instead.)
> +Signature = str
> +
> +
> +class QAPIObject(ObjectDescription[Signature]):
> +"""
> +Description of a generic QAPI object.
> +
> +It's not used directly, but is instead subclassed by specific directives.
> +"""
> +
> +# Inherit some standard options from Sphinx's ObjectDescription
> +option_spec: OptionSpec = (  # type:ignore[misc]
> +ObjectDescription.option_spec.copy()
> +)
> +option_spec.update(
> +{
> +# Borrowed from the Python domain:

This is line 125 mentioned above.

> +"module": directives.unchanged,  # Override contextual module 
> name
> +}
> +)

[...]




[PATCH v6 06/29] hw/intc/aspeed: Introduce helper functions for enable and status registers

2025-03-06 Thread Jamin Lin via
The behavior of the enable and status registers is almost identical between
INTC(CPU Die) and INTCIO(IO Die). To reduce duplicated code, adds
"aspeed_intc_enable_handler" functions to handle enable register write
behavior and "aspeed_intc_status_handler" functions to handle status
register write behavior. No functional change.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/intc/aspeed_intc.c | 191 --
 1 file changed, 108 insertions(+), 83 deletions(-)

diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index d684b4bb4f..b58a7ee712 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -120,6 +120,112 @@ static void aspeed_intc_set_irq(void *opaque, int irq, 
int level)
 }
 }
 
+static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset,
+   uint64_t data)
+{
+AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+uint32_t reg = offset >> 2;
+uint32_t old_enable;
+uint32_t change;
+uint32_t irq;
+
+irq = (offset & 0x0f00) >> 8;
+
+if (irq >= aic->num_ints) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
+  __func__, irq);
+return;
+}
+
+/*
+ * The enable registers are used to enable source interrupts.
+ * They also handle masking and unmasking of source interrupts
+ * during the execution of the source ISR.
+ */
+
+/* disable all source interrupt */
+if (!data && !s->enable[irq]) {
+s->regs[reg] = data;
+return;
+}
+
+old_enable = s->enable[irq];
+s->enable[irq] |= data;
+
+/* enable new source interrupt */
+if (old_enable != s->enable[irq]) {
+trace_aspeed_intc_enable(s->enable[irq]);
+s->regs[reg] = data;
+return;
+}
+
+/* mask and unmask source interrupt */
+change = s->regs[reg] ^ data;
+if (change & data) {
+s->mask[irq] &= ~change;
+trace_aspeed_intc_unmask(change, s->mask[irq]);
+} else {
+s->mask[irq] |= change;
+trace_aspeed_intc_mask(change, s->mask[irq]);
+}
+
+s->regs[reg] = data;
+}
+
+static void aspeed_intc_status_handler(AspeedINTCState *s, hwaddr offset,
+   uint64_t data)
+{
+AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+uint32_t reg = offset >> 2;
+uint32_t irq;
+
+if (!data) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__);
+return;
+}
+
+irq = (offset & 0x0f00) >> 8;
+
+if (irq >= aic->num_ints) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
+  __func__, irq);
+return;
+}
+
+/* clear status */
+s->regs[reg] &= ~data;
+
+/*
+ * These status registers are used for notify sources ISR are executed.
+ * If one source ISR is executed, it will clear one bit.
+ * If it clear all bits, it means to initialize this register status
+ * rather than sources ISR are executed.
+ */
+if (data == 0x) {
+return;
+}
+
+/* All source ISR execution are done */
+if (!s->regs[reg]) {
+trace_aspeed_intc_all_isr_done(irq);
+if (s->pending[irq]) {
+/*
+ * handle pending source interrupt
+ * notify firmware which source interrupt are pending
+ * by setting status register
+ */
+s->regs[reg] = s->pending[irq];
+s->pending[irq] = 0;
+trace_aspeed_intc_trigger_irq(irq, s->regs[reg]);
+aspeed_intc_update(s, irq, 1);
+} else {
+/* clear irq */
+trace_aspeed_intc_clear_irq(irq, 0);
+aspeed_intc_update(s, irq, 0);
+}
+}
+}
+
 static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int 
size)
 {
 AspeedINTCState *s = ASPEED_INTC(opaque);
@@ -136,11 +242,7 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, 
uint64_t data,
 unsigned size)
 {
 AspeedINTCState *s = ASPEED_INTC(opaque);
-AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
 uint32_t reg = offset >> 2;
-uint32_t old_enable;
-uint32_t change;
-uint32_t irq;
 
 trace_aspeed_intc_write(offset, size, data);
 
@@ -154,45 +256,7 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, 
uint64_t data,
 case R_GICINT134_EN:
 case R_GICINT135_EN:
 case R_GICINT136_EN:
-irq = (offset & 0x0f00) >> 8;
-
-if (irq >= aic->num_ints) {
-qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: 
%d\n",
-  __func__, irq);
-return;
-}
-
-/*
- * These registers are used for enable sources interrupt and
- * mask and unmask source interrupt while executing source ISR.
- */
-
-/* disable all sourc

[PATCH v6 26/29] tests/functional/aspeed: Update temperature hwmon path

2025-03-06 Thread Jamin Lin via
Modified the temperature hwmon path to use a wildcard to handle different SDK
versions: "cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input".

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 tests/functional/test_aarch64_aspeed.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/functional/test_aarch64_aspeed.py 
b/tests/functional/test_aarch64_aspeed.py
index e1ad7fd470..07b0c7c1fd 100755
--- a/tests/functional/test_aarch64_aspeed.py
+++ b/tests/functional/test_aarch64_aspeed.py
@@ -83,11 +83,11 @@ def start_ast2700_test(self, name):
 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device ',
 'i2c i2c-1: new_device: Instantiated device lm75 at 0x4d');
 exec_command_and_wait_for_pattern(self,
-'cat /sys/class/hwmon/hwmon20/temp1_input', '0')
+'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '0')
 self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
 property='temperature', value=18000)
 exec_command_and_wait_for_pattern(self,
-'cat /sys/class/hwmon/hwmon20/temp1_input', '18000')
+'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', 
'18000')
 
 def test_aarch64_ast2700_evb_sdk_v09_03(self):
 self.set_machine('ast2700-evb')
-- 
2.43.0




RE: [PATCH v5 04/29] hw/intc/aspeed: Support setting different register size

2025-03-06 Thread Jamin Lin
Hi Cedric,

> Subject: Re: [PATCH v5 04/29] hw/intc/aspeed: Support setting different
> register size
> 
> On 3/6/25 11:38, Jamin Lin wrote:
> > Currently, the size of the regs array is 0x2000, which is too large.
> > So far, it only use GICINT128 - GICINT134, and the offsets from 0 to 0x1000
> are unused.
> > To save code size, introduce a new class attribute "reg_size" to set
> > the different register sizes for the INTC models in AST2700 and add a
> > regs sub-region in the memory container.
> >
> > Signed-off-by: Jamin Lin 
> > ---
> >   include/hw/intc/aspeed_intc.h |  2 +-
> >   hw/intc/aspeed_intc.c | 22 +-
> >   2 files changed, 6 insertions(+), 18 deletions(-)
> >
> > diff --git a/include/hw/intc/aspeed_intc.h
> > b/include/hw/intc/aspeed_intc.h index 47ea0520b5..17cd889e0d 100644
> > --- a/include/hw/intc/aspeed_intc.h
> > +++ b/include/hw/intc/aspeed_intc.h
> > @@ -16,7 +16,6 @@
> >   #define TYPE_ASPEED_2700_INTC TYPE_ASPEED_INTC "-ast2700"
> >   OBJECT_DECLARE_TYPE(AspeedINTCState, AspeedINTCClass,
> ASPEED_INTC)
> >
> > -#define ASPEED_INTC_NR_REGS (0x2000 >> 2)
> >   #define ASPEED_INTC_NR_INTS 9
> >
> >   struct AspeedINTCState {
> > @@ -42,6 +41,7 @@ struct AspeedINTCClass {
> >   uint32_t num_lines;
> >   uint32_t num_ints;
> >   uint64_t mem_size;
> > +uint64_t reg_size;
> 
> The '_size' prefix describing a number of registers is confusing.
> 'nr_regs' would be better.
> 
Will do

Thanks for your suggestion and review.
Jamin
> 
> Thanks,
> 
> C.
> 
> 
> 
> >   };
> >
> >   #endif /* ASPEED_INTC_H */
> > diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c index
> > feb2c52441..1c3dc3fce0 100644
> > --- a/hw/intc/aspeed_intc.c
> > +++ b/hw/intc/aspeed_intc.c
> > @@ -120,13 +120,6 @@ static uint64_t aspeed_intc_read(void *opaque,
> hwaddr offset, unsigned int size)
> >   uint32_t reg = offset >> 2;
> >   uint32_t value = 0;
> >
> > -if (reg >= ASPEED_INTC_NR_REGS) {
> > -qemu_log_mask(LOG_GUEST_ERROR,
> > -  "%s: Out-of-bounds read at offset 0x%"
> HWADDR_PRIx "\n",
> > -  __func__, offset);
> > -return 0;
> > -}
> > -
> >   value = s->regs[reg];
> >   trace_aspeed_intc_read(offset, size, value);
> >
> > @@ -143,13 +136,6 @@ static void aspeed_intc_write(void *opaque,
> hwaddr offset, uint64_t data,
> >   uint32_t change;
> >   uint32_t irq;
> >
> > -if (reg >= ASPEED_INTC_NR_REGS) {
> > -qemu_log_mask(LOG_GUEST_ERROR,
> > -  "%s: Out-of-bounds write at offset 0x%"
> HWADDR_PRIx "\n",
> > -  __func__, offset);
> > -return;
> > -}
> > -
> >   trace_aspeed_intc_write(offset, size, data);
> >
> >   switch (reg) {
> > @@ -288,8 +274,9 @@ static void aspeed_intc_instance_init(Object *obj)
> >   static void aspeed_intc_reset(DeviceState *dev)
> >   {
> >   AspeedINTCState *s = ASPEED_INTC(dev);
> > +AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
> >
> > -memset(s->regs, 0, ASPEED_INTC_NR_REGS);
> > +memset(s->regs, 0, aic->reg_size);
> >   memset(s->enable, 0, sizeof(s->enable));
> >   memset(s->mask, 0, sizeof(s->mask));
> >   memset(s->pending, 0, sizeof(s->pending)); @@ -307,9 +294,9 @@
> > static void aspeed_intc_realize(DeviceState *dev, Error **errp)
> >
> >   sysbus_init_mmio(sbd, &s->iomem_container);
> >
> > -s->regs = g_malloc0(ASPEED_INTC_NR_REGS);
> > +s->regs = g_malloc0(aic->reg_size);
> >   memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops,
> s,
> > -  TYPE_ASPEED_INTC ".regs",
> ASPEED_INTC_NR_REGS << 2);
> > +  TYPE_ASPEED_INTC ".regs", aic->reg_size
> <<
> > + 2);
> >
> >   memory_region_add_subregion(&s->iomem_container, 0x0,
> > &s->iomem);
> >
> > @@ -361,6 +348,7 @@ static void aspeed_2700_intc_class_init(ObjectClass
> *klass, void *data)
> >   aic->num_lines = 32;
> >   aic->num_ints = 9;
> >   aic->mem_size = 0x4000;
> > +aic->reg_size = 0x2000 >> 2;
> >   }
> >
> >   static const TypeInfo aspeed_2700_intc_info = {



[PATCH v6 04/29] hw/intc/aspeed: Support setting different register size

2025-03-06 Thread Jamin Lin via
Currently, the size of the regs array is 0x2000, which is too large. So far,
it only use GICINT128 - GICINT134, and the offsets from 0 to 0x1000 are unused.
To save code size, introduce a new class attribute "reg_size" to set the
different register sizes for the INTC models in AST2700 and add a regs
sub-region in the memory container.

Signed-off-by: Jamin Lin 
---
 include/hw/intc/aspeed_intc.h |  2 +-
 hw/intc/aspeed_intc.c | 22 +-
 2 files changed, 6 insertions(+), 18 deletions(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 47ea0520b5..ec4936b3f4 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -16,7 +16,6 @@
 #define TYPE_ASPEED_2700_INTC TYPE_ASPEED_INTC "-ast2700"
 OBJECT_DECLARE_TYPE(AspeedINTCState, AspeedINTCClass, ASPEED_INTC)
 
-#define ASPEED_INTC_NR_REGS (0x2000 >> 2)
 #define ASPEED_INTC_NR_INTS 9
 
 struct AspeedINTCState {
@@ -42,6 +41,7 @@ struct AspeedINTCClass {
 uint32_t num_lines;
 uint32_t num_ints;
 uint64_t mem_size;
+uint64_t nr_regs;
 };
 
 #endif /* ASPEED_INTC_H */
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 558901570f..134922e46f 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -120,13 +120,6 @@ static uint64_t aspeed_intc_read(void *opaque, hwaddr 
offset, unsigned int size)
 uint32_t reg = offset >> 2;
 uint32_t value = 0;
 
-if (reg >= ASPEED_INTC_NR_REGS) {
-qemu_log_mask(LOG_GUEST_ERROR,
-  "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
-  __func__, offset);
-return 0;
-}
-
 value = s->regs[reg];
 trace_aspeed_intc_read(offset, size, value);
 
@@ -143,13 +136,6 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, 
uint64_t data,
 uint32_t change;
 uint32_t irq;
 
-if (reg >= ASPEED_INTC_NR_REGS) {
-qemu_log_mask(LOG_GUEST_ERROR,
-  "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
-  __func__, offset);
-return;
-}
-
 trace_aspeed_intc_write(offset, size, data);
 
 switch (reg) {
@@ -288,8 +274,9 @@ static void aspeed_intc_instance_init(Object *obj)
 static void aspeed_intc_reset(DeviceState *dev)
 {
 AspeedINTCState *s = ASPEED_INTC(dev);
+AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
 
-memset(s->regs, 0, ASPEED_INTC_NR_REGS << 2);
+memset(s->regs, 0, aic->nr_regs << 2);
 memset(s->enable, 0, sizeof(s->enable));
 memset(s->mask, 0, sizeof(s->mask));
 memset(s->pending, 0, sizeof(s->pending));
@@ -307,9 +294,9 @@ static void aspeed_intc_realize(DeviceState *dev, Error 
**errp)
 
 sysbus_init_mmio(sbd, &s->iomem_container);
 
-s->regs = g_new(uint32_t, ASPEED_INTC_NR_REGS);
+s->regs = g_new(uint32_t, aic->nr_regs);
 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
-  TYPE_ASPEED_INTC ".regs", ASPEED_INTC_NR_REGS << 2);
+  TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2);
 
 memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem);
 
@@ -361,6 +348,7 @@ static void aspeed_2700_intc_class_init(ObjectClass *klass, 
void *data)
 aic->num_lines = 32;
 aic->num_ints = 9;
 aic->mem_size = 0x4000;
+aic->nr_regs = 0x2000 >> 2;
 }
 
 static const TypeInfo aspeed_2700_intc_info = {
-- 
2.43.0




Re: [PATCH] include/exec: Move TARGET_PAGE_{SIZE,MASK,BITS} to target_page.h

2025-03-06 Thread Pierrick Bouvier

On 3/6/25 15:41, Richard Henderson wrote:

Re-use the TARGET_PAGE_BITS_VARY mechanism to define
TARGET_PAGE_SIZE and friends when not compiling per-target.
Inline qemu_target_page_{size,mask,bits} as they are now trivial.

Signed-off-by: Richard Henderson 
---

After this, we could in fact remove qemu_target_page_foo(), etc.
We certainly don't need to convert any more uses of TARGET_PAGE_FOO.

r~

---
  include/exec/cpu-all.h | 21 +-
  include/exec/poison.h  |  5 
  include/exec/target_page.h | 58 ++
  page-target.c  | 18 
  page-vary-target.c |  2 ++
  5 files changed, 55 insertions(+), 49 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 09f537d06f..8f7aebb088 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -105,26 +105,7 @@ static inline void stl_phys_notdirty(AddressSpace *as, 
hwaddr addr, uint32_t val
  
  /* page related stuff */

  #include "exec/cpu-defs.h"
-#ifdef TARGET_PAGE_BITS_VARY
-# include "exec/page-vary.h"
-extern const TargetPageBits target_page;
-# ifdef CONFIG_DEBUG_TCG
-#  define TARGET_PAGE_BITS   ({ assert(target_page.decided); \
-target_page.bits; })
-#  define TARGET_PAGE_MASK   ({ assert(target_page.decided); \
-(target_long)target_page.mask; })
-# else
-#  define TARGET_PAGE_BITS   target_page.bits
-#  define TARGET_PAGE_MASK   ((target_long)target_page.mask)
-# endif
-# define TARGET_PAGE_SIZE(-(int)TARGET_PAGE_MASK)
-#else
-# define TARGET_PAGE_BITS_MIN TARGET_PAGE_BITS
-# define TARGET_PAGE_SIZE(1 << TARGET_PAGE_BITS)
-# define TARGET_PAGE_MASK((target_long)-1 << TARGET_PAGE_BITS)
-#endif
-
-#define TARGET_PAGE_ALIGN(addr) ROUND_UP((addr), TARGET_PAGE_SIZE)
+#include "exec/target_page.h"
  
  CPUArchState *cpu_copy(CPUArchState *env);
  
diff --git a/include/exec/poison.h b/include/exec/poison.h

index f4283f693a..ce43a12965 100644
--- a/include/exec/poison.h
+++ b/include/exec/poison.h
@@ -44,11 +44,6 @@
  #pragma GCC poison TARGET_FMT_ld
  #pragma GCC poison TARGET_FMT_lu
  
-#pragma GCC poison TARGET_PAGE_SIZE

-#pragma GCC poison TARGET_PAGE_MASK
-#pragma GCC poison TARGET_PAGE_BITS
-#pragma GCC poison TARGET_PAGE_ALIGN
-
  #pragma GCC poison CPU_INTERRUPT_HARD
  #pragma GCC poison CPU_INTERRUPT_EXITTB
  #pragma GCC poison CPU_INTERRUPT_HALT
diff --git a/include/exec/target_page.h b/include/exec/target_page.h
index 98ffbb5c23..8e89e5cbe6 100644
--- a/include/exec/target_page.h
+++ b/include/exec/target_page.h
@@ -14,10 +14,56 @@
  #ifndef EXEC_TARGET_PAGE_H
  #define EXEC_TARGET_PAGE_H
  
-size_t qemu_target_page_size(void);

-int qemu_target_page_mask(void);
-int qemu_target_page_bits(void);
-int qemu_target_page_bits_min(void);
-
-size_t qemu_target_pages_to_MiB(size_t pages);
+/*
+ * If compiling per-target, get the real values.
+ * For generic code, reuse the mechanism for variable page size.
+ */
+#ifdef COMPILING_PER_TARGET
+#include "cpu-param.h"
+#include "exec/target_long.h"
+#define TARGET_PAGE_TYPE  target_long
+#else
+#define TARGET_PAGE_BITS_VARY
+#define TARGET_PAGE_TYPE  int
+#endif
+
+#ifdef TARGET_PAGE_BITS_VARY
+# include "exec/page-vary.h"
+extern const TargetPageBits target_page;
+# ifdef CONFIG_DEBUG_TCG
+#  define TARGET_PAGE_BITS   ({ assert(target_page.decided); \
+target_page.bits; })
+#  define TARGET_PAGE_MASK   ({ assert(target_page.decided); \
+(TARGET_PAGE_TYPE)target_page.mask; })
+# else
+#  define TARGET_PAGE_BITS   target_page.bits
+#  define TARGET_PAGE_MASK   ((TARGET_PAGE_TYPE)target_page.mask)
+# endif
+# define TARGET_PAGE_SIZE(-(int)TARGET_PAGE_MASK)
+#else
+# define TARGET_PAGE_BITS_MIN TARGET_PAGE_BITS
+# define TARGET_PAGE_SIZE(1 << TARGET_PAGE_BITS)
+# define TARGET_PAGE_MASK((TARGET_PAGE_TYPE)-1 << TARGET_PAGE_BITS)
+#endif
+
+#define TARGET_PAGE_ALIGN(addr) ROUND_UP((addr), TARGET_PAGE_SIZE)
+
+static inline size_t qemu_target_page_size(void)
+{
+return TARGET_PAGE_SIZE;
+}
+
+static inline int qemu_target_page_mask(void)
+{
+return TARGET_PAGE_MASK;
+}
+
+static inline int qemu_target_page_bits(void)
+{
+return TARGET_PAGE_BITS;
+}
+
+int qemu_target_page_bits_min(void);
+size_t qemu_target_pages_to_MiB(size_t pages);
+
  #endif
diff --git a/page-target.c b/page-target.c
index 82211c8593..321e43d06f 100644
--- a/page-target.c
+++ b/page-target.c
@@ -8,24 +8,6 @@
  
  #include "qemu/osdep.h"

  #include "exec/target_page.h"
-#include "exec/cpu-defs.h"
-#include "cpu.h"
-#include "exec/cpu-all.h"
-
-size_t qemu_target_page_size(void)
-{
-return TARGET_PAGE_SIZE;
-}
-
-int qemu_target_page_mask(void)
-{
-return TARGET_PAGE_MASK;
-}
-
-int qemu_target_page_bits(void)
-{
-return TARGET_PAGE_BITS;
-}
  
  int qemu_target_page_bits_min(void)

  {
diff --git a/page-vary-target.c b/page-vary-target.c
index 343b4adb95..1

Re: [PATCH v2 2/2] target/riscv: fixes a bug against `ssamoswap` behavior in M-mode

2025-03-06 Thread Alistair Francis
On Thu, Mar 6, 2025 at 4:47 PM Deepak Gupta  wrote:
>
> Commit f06bfe3dc38c ("target/riscv: implement zicfiss instructions") adds
> `ssamoswap` instruction. `ssamoswap` takes the code-point from existing
> reserved encoding (and not a zimop like other shadow stack instructions).
> If shadow stack is not enabled (via xenvcfg.SSE) and effective priv is
> less than M then `ssamoswap` must result in an illegal instruction
> exception. However if effective priv is M, then `ssamoswap` results in
> store/AMO access fault. See Section "22.2.3. Shadow Stack Memory
> Protection" of priv spec.
>
> Fixes: f06bfe3dc38c ("target/riscv: implement zicfiss instructions")
>
> Reported-by: Ved Shanbhogue 
> Signed-off-by: Deepak Gupta 

Thanks!

Applied to riscv-to-apply.next

Please use a cover letter for a multi-patch series in the future

Alistair

> ---
>  target/riscv/insn_trans/trans_rvzicfiss.c.inc | 17 +
>  1 file changed, 17 insertions(+)
>
> diff --git a/target/riscv/insn_trans/trans_rvzicfiss.c.inc 
> b/target/riscv/insn_trans/trans_rvzicfiss.c.inc
> index e3ebc4977c..b0096adcd0 100644
> --- a/target/riscv/insn_trans/trans_rvzicfiss.c.inc
> +++ b/target/riscv/insn_trans/trans_rvzicfiss.c.inc
> @@ -15,6 +15,13 @@
>   * You should have received a copy of the GNU General Public License along 
> with
>   * this program.  If not, see .
>   */
> +
> +#define REQUIRE_ZICFISS(ctx) do {\
> +if (!ctx->cfg_ptr->ext_zicfiss) {\
> +return false;\
> +}\
> +} while (0)
> +
>  static bool trans_sspopchk(DisasContext *ctx, arg_sspopchk *a)
>  {
>  if (!ctx->bcfi_enabled) {
> @@ -77,6 +84,11 @@ static bool trans_ssrdp(DisasContext *ctx, arg_ssrdp *a)
>  static bool trans_ssamoswap_w(DisasContext *ctx, arg_amoswap_w *a)
>  {
>  REQUIRE_A_OR_ZAAMO(ctx);
> +REQUIRE_ZICFISS(ctx);
> +if (ctx->priv == PRV_M) {
> +generate_exception(ctx, RISCV_EXCP_STORE_AMO_ACCESS_FAULT);
> +}
> +
>  if (!ctx->bcfi_enabled) {
>  return false;
>  }
> @@ -97,6 +109,11 @@ static bool trans_ssamoswap_d(DisasContext *ctx, 
> arg_amoswap_w *a)
>  {
>  REQUIRE_64BIT(ctx);
>  REQUIRE_A_OR_ZAAMO(ctx);
> +REQUIRE_ZICFISS(ctx);
> +if (ctx->priv == PRV_M) {
> +generate_exception(ctx, RISCV_EXCP_STORE_AMO_ACCESS_FAULT);
> +}
> +
>  if (!ctx->bcfi_enabled) {
>  return false;
>  }
> --
> 2.34.1
>
>



RE: [PATCH v5 03/29] hw/intc/aspeed: Introduce dynamic allocation for regs array

2025-03-06 Thread Jamin Lin
Hi Cedric

> Subject: Re: [PATCH v5 03/29] hw/intc/aspeed: Introduce dynamic allocation
> for regs array
> 
> On 3/6/25 11:38, Jamin Lin wrote:
> > Currently, the size of the "regs" array is 0x2000, which is too large.
> > To save code size and avoid mapping large unused gaps, will update it
> > to only map the useful set of registers. This update will support
> > multiple sub-regions with different sizes.
> >
> > To address the redundant size issue, replace the static "regs" array
> > with a dynamically allocated "regs" memory.
> >
> > Introduce a new "aspeed_intc_unrealize" function to free the allocated 
> > "regs"
> > memory.
> >
> > Signed-off-by: Jamin Lin 
> > ---
> >   include/hw/intc/aspeed_intc.h |  2 +-
> >   hw/intc/aspeed_intc.c | 12 +++-
> >   2 files changed, 12 insertions(+), 2 deletions(-)
> >
> > diff --git a/include/hw/intc/aspeed_intc.h
> > b/include/hw/intc/aspeed_intc.h index 03324f05ab..47ea0520b5 100644
> > --- a/include/hw/intc/aspeed_intc.h
> > +++ b/include/hw/intc/aspeed_intc.h
> > @@ -27,7 +27,7 @@ struct AspeedINTCState {
> >   MemoryRegion iomem;
> >   MemoryRegion iomem_container;
> >
> > -uint32_t regs[ASPEED_INTC_NR_REGS];
> > +uint32_t *regs;
> >   OrIRQState orgates[ASPEED_INTC_NR_INTS];
> >   qemu_irq output_pins[ASPEED_INTC_NR_INTS];
> >
> > diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c index
> > 465f41e4fd..feb2c52441 100644
> > --- a/hw/intc/aspeed_intc.c
> > +++ b/hw/intc/aspeed_intc.c
> > @@ -289,7 +289,7 @@ static void aspeed_intc_reset(DeviceState *dev)
> >   {
> >   AspeedINTCState *s = ASPEED_INTC(dev);
> >
> > -memset(s->regs, 0, sizeof(s->regs));
> > +memset(s->regs, 0, ASPEED_INTC_NR_REGS);
> 
> this is not the same size. s->regs is larger than ASPEED_INTC_NR_REGS.
Will fix it.
> 
> >   memset(s->enable, 0, sizeof(s->enable));
> >   memset(s->mask, 0, sizeof(s->mask));
> >   memset(s->pending, 0, sizeof(s->pending)); @@ -307,6 +307,7 @@
> > static void aspeed_intc_realize(DeviceState *dev, Error **errp)
> >
> >   sysbus_init_mmio(sbd, &s->iomem_container);
> >
> > +s->regs = g_malloc0(ASPEED_INTC_NR_REGS);
> 
> please use g_new()

Will do

Thanks for review and suggestion.
Jamin
> 
> 
> Thanks,
> 
> C.
> 
> 
> >   memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops,
> s,
> > TYPE_ASPEED_INTC ".regs",
> > ASPEED_INTC_NR_REGS << 2);
> >
> > @@ -322,12 +323,21 @@ static void aspeed_intc_realize(DeviceState *dev,
> Error **errp)
> >   }
> >   }
> >
> > +static void aspeed_intc_unrealize(DeviceState *dev) {
> > +AspeedINTCState *s = ASPEED_INTC(dev);
> > +
> > +g_free(s->regs);
> > +s->regs = NULL;
> > +}
> > +
> >   static void aspeed_intc_class_init(ObjectClass *klass, void *data)
> >   {
> >   DeviceClass *dc = DEVICE_CLASS(klass);
> >
> >   dc->desc = "ASPEED INTC Controller";
> >   dc->realize = aspeed_intc_realize;
> > +dc->unrealize = aspeed_intc_unrealize;
> >   device_class_set_legacy_reset(dc, aspeed_intc_reset);
> >   dc->vmsd = NULL;
> >   }



Re: [PATCH v5 01/29] hw/intc/aspeed: Support setting different memory size

2025-03-06 Thread Cédric Le Goater

On 3/6/25 11:38, Jamin Lin wrote:

According to the AST2700 datasheet, the INTC(CPU DIE) controller has 16KB
(0x4000) of register space, and the INTCIO (I/O DIE) controller has 1KB (0x400)
of register space.

Introduced a new class attribute "mem_size" to set different memory sizes for
the INTC models in AST2700.

Signed-off-by: Jamin Lin 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  include/hw/intc/aspeed_intc.h | 3 +++
  hw/intc/aspeed_intc.c | 9 -
  2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 18cb43476c..03324f05ab 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -25,6 +25,8 @@ struct AspeedINTCState {
  
  /*< public >*/

  MemoryRegion iomem;
+MemoryRegion iomem_container;
+
  uint32_t regs[ASPEED_INTC_NR_REGS];
  OrIRQState orgates[ASPEED_INTC_NR_INTS];
  qemu_irq output_pins[ASPEED_INTC_NR_INTS];
@@ -39,6 +41,7 @@ struct AspeedINTCClass {
  
  uint32_t num_lines;

  uint32_t num_ints;
+uint64_t mem_size;
  };
  
  #endif /* ASPEED_INTC_H */

diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 126b711b94..033b574c1e 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -302,10 +302,16 @@ static void aspeed_intc_realize(DeviceState *dev, Error 
**errp)
  AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
  int i;
  
+memory_region_init(&s->iomem_container, OBJECT(s),

+TYPE_ASPEED_INTC ".container", aic->mem_size);
+
+sysbus_init_mmio(sbd, &s->iomem_container);
+
  memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
TYPE_ASPEED_INTC ".regs", ASPEED_INTC_NR_REGS << 2);
  
-sysbus_init_mmio(sbd, &s->iomem);

+memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem);
+
  qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints);
  
  for (i = 0; i < aic->num_ints; i++) {

@@ -344,6 +350,7 @@ static void aspeed_2700_intc_class_init(ObjectClass *klass, 
void *data)
  dc->desc = "ASPEED 2700 INTC Controller";
  aic->num_lines = 32;
  aic->num_ints = 9;
+aic->mem_size = 0x4000;
  }
  
  static const TypeInfo aspeed_2700_intc_info = {





[PATCH 3/5] hw/intc/loongarch_extioi: Replace legacy reset callback with new api

2025-03-06 Thread Bibo Mao
Replace legacy reset callback register device_class_set_legacy_reset()
with new function resettable_class_set_parent_phases(). With new API,
it will call reset callback of parent object and then itself.

Signed-off-by: Bibo Mao 
---
 hw/intc/loongarch_extioi.c | 12 
 include/hw/intc/loongarch_extioi.h |  1 +
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
index a51a215e6e..0fecc62a09 100644
--- a/hw/intc/loongarch_extioi.c
+++ b/hw/intc/loongarch_extioi.c
@@ -377,11 +377,13 @@ static void loongarch_extioi_unrealize(DeviceState *dev)
 g_free(s->cpu);
 }
 
-static void loongarch_extioi_reset(DeviceState *d)
+static void loongarch_extioi_reset_hold(Object *obj, ResetType type)
 {
-LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(d);
+LoongArchExtIOIClass *lec = LOONGARCH_EXTIOI_GET_CLASS(obj);
 
-s->status = 0;
+if (lec->parent_phases.hold) {
+lec->parent_phases.hold(obj, type);
+}
 }
 
 static int vmstate_extioi_post_load(void *opaque, int version_id)
@@ -406,12 +408,14 @@ static void loongarch_extioi_class_init(ObjectClass 
*klass, void *data)
 DeviceClass *dc = DEVICE_CLASS(klass);
 LoongArchExtIOIClass *lec = LOONGARCH_EXTIOI_CLASS(klass);
 LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
 
 device_class_set_parent_realize(dc, loongarch_extioi_realize,
 &lec->parent_realize);
 device_class_set_parent_unrealize(dc, loongarch_extioi_unrealize,
   &lec->parent_unrealize);
-device_class_set_legacy_reset(dc, loongarch_extioi_reset);
+resettable_class_set_parent_phases(rc, NULL, loongarch_extioi_reset_hold,
+   NULL, &lec->parent_phases);
 lecc->post_load = vmstate_extioi_post_load;
 }
 
diff --git a/include/hw/intc/loongarch_extioi.h 
b/include/hw/intc/loongarch_extioi.h
index 351f18afcf..4a6ae903e9 100644
--- a/include/hw/intc/loongarch_extioi.h
+++ b/include/hw/intc/loongarch_extioi.h
@@ -22,6 +22,7 @@ struct LoongArchExtIOIClass {
 
 DeviceRealize parent_realize;
 DeviceUnrealize parent_unrealize;
+ResettablePhases parent_phases;
 };
 
 #endif /* LOONGARCH_EXTIOI_H */
-- 
2.39.3




[PATCH 2/5] hw/intc/loongarch_extioi: Add reset support

2025-03-06 Thread Bibo Mao
Add reset support with extioi irqchip, and register reset callback
support with new API resettable_class_set_parent_phases(). Clear
internal HW registers and SW state when virt machine resets.

Signed-off-by: Bibo Mao 
---
 hw/intc/loongarch_extioi_common.c | 41 +++
 include/hw/intc/loongarch_extioi_common.h |  1 +
 2 files changed, 42 insertions(+)

diff --git a/hw/intc/loongarch_extioi_common.c 
b/hw/intc/loongarch_extioi_common.c
index ff3974f2a1..3a9d8c8657 100644
--- a/hw/intc/loongarch_extioi_common.c
+++ b/hw/intc/loongarch_extioi_common.c
@@ -108,6 +108,43 @@ static void loongarch_extioi_common_realize(DeviceState 
*dev, Error **errp)
 }
 }
 
+static void loongarch_extioi_common_reset_hold(Object *obj, ResetType type)
+{
+LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_GET_CLASS(obj);
+LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(obj);
+ExtIOICore *core;
+int i;
+
+if (lecc->parent_phases.hold) {
+lecc->parent_phases.hold(obj, type);
+}
+
+/* Clear HW registers for the board */
+memset(s->nodetype, 0, sizeof(s->nodetype));
+memset(s->bounce, 0, sizeof(s->bounce));
+memset(s->isr, 0, sizeof(s->isr));
+memset(s->enable, 0, sizeof(s->enable));
+memset(s->ipmap, 0, sizeof(s->ipmap));
+memset(s->coremap, 0, sizeof(s->coremap));
+memset(s->sw_pending, 0, sizeof(s->sw_pending));
+memset(s->sw_ipmap, 0, sizeof(s->sw_ipmap));
+memset(s->sw_coremap, 0, sizeof(s->sw_coremap));
+
+for (i = 0; i < s->num_cpu; i++) {
+core = s->cpu + i;
+/* EXTIOI with targeted CPU available however not present */
+if (!core->cpu) {
+continue;
+}
+
+/* Clear HW registers for CPUs */
+memset(core->coreisr, 0, sizeof(core->coreisr));
+memset(core->sw_isr, 0, sizeof(core->sw_isr));
+}
+
+s->status = 0;
+}
+
 static int loongarch_extioi_common_pre_save(void *opaque)
 {
 LoongArchExtIOICommonState *s = (LoongArchExtIOICommonState *)opaque;
@@ -179,9 +216,13 @@ static void loongarch_extioi_common_class_init(ObjectClass 
*klass, void *data)
 DeviceClass *dc = DEVICE_CLASS(klass);
 LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_CLASS(klass);
 HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
 
 device_class_set_parent_realize(dc, loongarch_extioi_common_realize,
 &lecc->parent_realize);
+resettable_class_set_parent_phases(rc, NULL,
+   loongarch_extioi_common_reset_hold,
+   NULL, &lecc->parent_phases);
 device_class_set_props(dc, extioi_properties);
 dc->vmsd = &vmstate_loongarch_extioi;
 hc->plug = loongarch_extioi_cpu_plug;
diff --git a/include/hw/intc/loongarch_extioi_common.h 
b/include/hw/intc/loongarch_extioi_common.h
index 22d7880977..735bfee80a 100644
--- a/include/hw/intc/loongarch_extioi_common.h
+++ b/include/hw/intc/loongarch_extioi_common.h
@@ -94,6 +94,7 @@ struct LoongArchExtIOICommonClass {
 SysBusDeviceClass parent_class;
 
 DeviceRealize parent_realize;
+ResettablePhases parent_phases;
 int (*pre_save)(void *s);
 int (*post_load)(void *s, int version_id);
 };
-- 
2.39.3




[PATCH 0/5] hw/intc: Add reset support for LoongArch irqchips

2025-03-06 Thread Bibo Mao
Here add reset support with LoongArch irqchips, including pch pic, ipi
and extioi interrupt controllers. For ipi irqchip, reset interface is
missing. For extioi irqchip, legacy reset callback is replaced with
new API and internal HW/SW states are cleared also. For pch pic irqchip,
legacy reset callback is replaced with new API.

Bibo Mao (5):
  hw/intc/loongarch_ipi: Add reset support
  hw/intc/loongarch_extioi: Add reset support
  hw/intc/loongarch_extioi: Replace legacy reset callback with new api
  hw/intc/loongarch_pch: Add reset support
  hw/intc/loongarch_pch: Replace legacy reset callback with new api

 hw/intc/loongarch_extioi.c| 12 ---
 hw/intc/loongarch_extioi_common.c | 41 +++
 hw/intc/loongarch_ipi.c   | 29 
 hw/intc/loongarch_pch_pic.c   | 26 +-
 hw/intc/loongarch_pic_common.c| 25 ++
 include/hw/intc/loongarch_extioi.h|  1 +
 include/hw/intc/loongarch_extioi_common.h |  1 +
 include/hw/intc/loongarch_ipi.h   |  1 +
 include/hw/intc/loongarch_pch_pic.h   |  1 +
 include/hw/intc/loongarch_pic_common.h|  1 +
 10 files changed, 116 insertions(+), 22 deletions(-)


base-commit: e8a01102936286e012ed0f00bd7f3b7474d415c9
-- 
2.39.3




Re: [PATCH qemu v2 2/3] hw/s390x: add SCLP event type CPI

2025-03-06 Thread shalini

On 2025-03-05 19:04, Thomas Huth wrote:

On 24/02/2025 13.04, Shalini Chellathurai Saroja wrote:

Implement the SCLP event type Control-Program Identification
(CPI) in QEMU. This event is used to send CPI identifiers,
which provide information about the guest OS to the host.

Save the information obtained from the SCLP CPI event to the
QOM along with the timestamp in which the data was received.

Example:
virsh # qemu-monitor-command vm --pretty '{
"execute":"qom-get","arguments": {
"path": "/machine", "property": "s390-control-program_id"}}'


I guess it should be a "-" instead of a "_" between "program" and "id"?


Hello Thomas,

Thank you very much for the review. Yes, that is correct. I will change 
it.


[...]


diff --git a/hw/s390x/sclpcpi.c b/hw/s390x/sclpcpi.c
new file mode 100644
index 00..f2830d2d57
--- /dev/null
+++ b/hw/s390x/sclpcpi.c
@@ -0,0 +1,105 @@
+/*


scripts/checkpatch.pl recently learnt a new check to mandate SPDX
license tags now for new files ... so please add one here now!



ok.

[...]

+static int write_event_data(SCLPEvent *event, EventBufferHeader 
*evt_buf_hdr)

+{
+ControlProgramIdMsg *cpi = container_of(evt_buf_hdr, 
ControlProgramIdMsg,

+ebh);
+S390CcwMachineState *ms = S390_CCW_MACHINE(qdev_get_machine());
+
+ascii_put(ms->cpi.system_type, (char *)cpi->data.system_type, 8);
+ascii_put(ms->cpi.system_name, (char *)cpi->data.system_name, 8);
+ascii_put(ms->cpi.sysplex_name, (char *)cpi->data.sysplex_name, 
8);

+ms->cpi.system_level = be64_to_cpu(cpi->data.system_level);


Can we be confident that system_level is always properly aligned?
Otherwise it's maybe better to use ldq_be_p() instead?


ok, I will use ldq_be_p() instead.



 Thomas


--
Mit freundlichen Grüßen / Kind regards
Shalini Chellathurai Saroja
Software Developer
Linux on IBM Z & KVM Development
IBM Deutschland Research & Development GmbH
Dept 1419, Schoenaicher Str. 220, 71032 Boeblingen
Vorsitzender des Aufsichtsrats: Wolfgang Wendt
Geschäftsführung: David Faller
Sitz der Gesellschaft: Böblingen / Registergericht: Amtsgericht 
Stuttgart, HRB 243294




[qemu-web PATCH] download/windows: Drop link to 32-bit builds, add aarch64 instead

2025-03-06 Thread Thomas Huth
QEMU does not support 32-bit Windows anymore, so we should not
tempt the users to download old builds.
OTOH, there is now interest in Windows build on arm computers instead
(see e.g. https://gitlab.com/qemu-project/qemu/-/issues/2850 ), so
let's add a link to these builds instead.

Signed-off-by: Thomas Huth 
---
 _download/windows.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/_download/windows.md b/_download/windows.md
index 8ce3f0d..f97d216 100644
--- a/_download/windows.md
+++ b/_download/windows.md
@@ -1,6 +1,6 @@
-Stefan Weil provides binaries and installers for
-both [32-bit](https://qemu.weilnetz.de/w32/) and
-[64-bit](https://qemu.weilnetz.de/w64/) Windows.
+Stefan Weil provides 64-bit binaries and installers for Windows on
+both [x86](https://qemu.weilnetz.de/w64/) and
+[arm](https://qemu.weilnetz.de/aarch64/) computers.
 
 **MSYS2:**
 
-- 
2.48.1




Re: [PATCH qemu v2 2/3] hw/s390x: add SCLP event type CPI

2025-03-06 Thread shalini

On 2025-03-05 20:00, Nina Schoetterl-Glausch wrote:

On Wed, 2025-03-05 at 19:04 +0100, Thomas Huth wrote:

[...]


> +
> +static int write_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr)
> +{
> +ControlProgramIdMsg *cpi = container_of(evt_buf_hdr, ControlProgramIdMsg,
> +ebh);
> +S390CcwMachineState *ms = S390_CCW_MACHINE(qdev_get_machine());
> +
> +ascii_put(ms->cpi.system_type, (char *)cpi->data.system_type, 8);
> +ascii_put(ms->cpi.system_name, (char *)cpi->data.system_name, 8);
> +ascii_put(ms->cpi.sysplex_name, (char *)cpi->data.sysplex_name, 8);
> +ms->cpi.system_level = be64_to_cpu(cpi->data.system_level);

Can we be confident that system_level is always properly aligned?


It has offset 40 from the start of a heap allocation, so yes, but it is 
far

from obvious so I wouldn't mind ldq_be_p.



ok, I will use ldc_be_p() instead, thank you Nina.


Otherwise it's maybe better to use ldq_be_p() instead?

  Thomas




--
Mit freundlichen Grüßen / Kind regards
Shalini Chellathurai Saroja
Software Developer
Linux on IBM Z & KVM Development
IBM Deutschland Research & Development GmbH
Dept 1419, Schoenaicher Str. 220, 71032 Boeblingen
Vorsitzender des Aufsichtsrats: Wolfgang Wendt
Geschäftsführung: David Faller
Sitz der Gesellschaft: Böblingen / Registergericht: Amtsgericht 
Stuttgart, HRB 243294




Re: [PATCH] hw/display/qxl-render.c: fix qxl_unpack_chunks() chunk size calculation

2025-03-06 Thread Michael Tokarev

A friendly ping?
This one probably should go to qemu-stable too.

Thanks,

/mjt

21.02.2025 16:48, Michael Tokarev wrote:

In case of multiple chunks, code in qxl_unpack_chunks() takes size of the
wrong (next in the chain) chunk, instead of using current chunk size.
This leads to wrong number of bytes being copied, and to crashes if next
chunk size is larger than the current one.

Based on the code by Gao Yong.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1628
Signed-off-by: Michael Tokarev 
---
  hw/display/qxl-render.c | 11 ++-
  1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
index eda6d3de37..c6a9ac1da1 100644
--- a/hw/display/qxl-render.c
+++ b/hw/display/qxl-render.c
@@ -222,6 +222,7 @@ static void qxl_unpack_chunks(void *dest, size_t size, 
PCIQXLDevice *qxl,
  uint32_t max_chunks = 32;
  size_t offset = 0;
  size_t bytes;
+QXLPHYSICAL next_chunk_phys = 0;
  
  for (;;) {

  bytes = MIN(size - offset, chunk->data_size);
@@ -230,7 +231,15 @@ static void qxl_unpack_chunks(void *dest, size_t size, 
PCIQXLDevice *qxl,
  if (offset == size) {
  return;
  }
-chunk = qxl_phys2virt(qxl, chunk->next_chunk, group_id,
+next_chunk_phys = chunk->next_chunk;
+/* fist time, only get the next chunk's data size */
+chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id,
+  sizeof(QXLDataChunk));
+if (!chunk) {
+return;
+}
+/* second time, check data size and get data */
+chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id,
sizeof(QXLDataChunk) + chunk->data_size);
  if (!chunk) {
  return;





[PULL 03/10] qapi/introspect: Use @dataclass to simplify

2025-03-06 Thread Markus Armbruster
A TODO comment in class Annotated reminds us to simplify it once we
can use @dataclass, new in Python 3.7.  We have that now, so do it.

There's a similar comment in scripts/qapi/source.py, but I can't
figure out how to use @dataclass there.  Left for another day.

Signed-off-by: Markus Armbruster 
Message-ID: <20250227080757.3978333-4-arm...@redhat.com>
Reviewed-by: Daniel P. Berrangé 
---
 scripts/qapi/introspect.py | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index 42e5185c7c..89ee5d5f17 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -11,6 +11,7 @@
 See the COPYING file in the top-level directory.
 """
 
+from dataclasses import dataclass
 from typing import (
 Any,
 Dict,
@@ -79,19 +80,16 @@
 _ValueT = TypeVar('_ValueT', bound=_Value)
 
 
+@dataclass
 class Annotated(Generic[_ValueT]):
 """
 Annotated generally contains a SchemaInfo-like type (as a dict),
 But it also used to wrap comments/ifconds around scalar leaf values,
 for the benefit of features and enums.
 """
-# TODO: Remove after Python 3.7 adds @dataclass:
-# pylint: disable=too-few-public-methods
-def __init__(self, value: _ValueT, ifcond: QAPISchemaIfCond,
- comment: Optional[str] = None):
-self.value = value
-self.comment: Optional[str] = comment
-self.ifcond = ifcond
+value: _ValueT
+ifcond: QAPISchemaIfCond
+comment: Optional[str] = None
 
 
 def _tree_to_qlit(obj: JSONValue,
-- 
2.48.1




Re: [RFC PATCH 2/4] hw/arm/raspi: Replace TARGET_AARCH64 by legacy_binary_is_64bit()

2025-03-06 Thread Thomas Huth

On 05/03/2025 20.07, Philippe Mathieu-Daudé wrote:

On 5/3/25 19:35, Thomas Huth wrote:

On 05/03/2025 19.12, Cédric Le Goater wrote:

On 3/5/25 18:40, Thomas Huth wrote:

On 05/03/2025 17.12, Philippe Mathieu-Daudé wrote:

For legacy ARM binaries, legacy_binary_is_64bit() is
equivalent of the compile time TARGET_AARCH64 definition.

Use it as TypeInfo::registerable() callback to dynamically
add Aarch64 specific types in qemu-system-aarch64 binary,
removing the need of TARGET_AARCH64 #ifdef'ry.

Signed-off-by: Philippe Mathieu-Daudé 
---
  hw/arm/bcm2836.c | 6 ++
  hw/arm/raspi.c   | 7 +++
  2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index 95e16806fa1..88a32e5fc20 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -12,6 +12,7 @@
  #include "qemu/osdep.h"
  #include "qapi/error.h"
  #include "qemu/module.h"
+#include "qemu/legacy_binary_info.h"
  #include "hw/arm/bcm2836.h"
  #include "hw/arm/raspi_platform.h"
  #include "hw/sysbus.h"
@@ -195,7 +196,6 @@ static void bcm2836_class_init(ObjectClass *oc, 
void *data)

  dc->realize = bcm2836_realize;
  };
-#ifdef TARGET_AARCH64
  static void bcm2837_class_init(ObjectClass *oc, void *data)
  {
  DeviceClass *dc = DEVICE_CLASS(oc);
@@ -208,7 +208,6 @@ static void bcm2837_class_init(ObjectClass *oc, 
void *data)

  bc->clusterid = 0x0;
  dc->realize = bcm2836_realize;
  };
-#endif
  static const TypeInfo bcm283x_types[] = {
  {
@@ -219,12 +218,11 @@ static const TypeInfo bcm283x_types[] = {
  .name   = TYPE_BCM2836,
  .parent = TYPE_BCM283X,
  .class_init = bcm2836_class_init,
-#ifdef TARGET_AARCH64
  }, {
  .name   = TYPE_BCM2837,
  .parent = TYPE_BCM283X,
+    .registerable   = legacy_binary_is_64bit,
  .class_init = bcm2837_class_init,
-#endif
  }, {
  .name   = TYPE_BCM283X,
  .parent = TYPE_BCM283X_BASE,
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index dce35ca11aa..f7e647a9cbf 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -15,6 +15,7 @@
  #include "qemu/osdep.h"
  #include "qemu/units.h"
  #include "qemu/cutils.h"
+#include "qemu/legacy_binary_info.h"
  #include "qapi/error.h"
  #include "hw/arm/boot.h"
  #include "hw/arm/bcm2836.h"
@@ -367,7 +368,6 @@ static void raspi2b_machine_class_init(ObjectClass 
*oc, void *data)

  raspi_machine_class_init(mc, rmc->board_rev);
  };
-#ifdef TARGET_AARCH64
  static void raspi3ap_machine_class_init(ObjectClass *oc, void *data)
  {
  MachineClass *mc = MACHINE_CLASS(oc);
@@ -387,7 +387,6 @@ static void raspi3b_machine_class_init(ObjectClass 
*oc, void *data)

  rmc->board_rev = 0xa02082;
  raspi_machine_class_init(mc, rmc->board_rev);
  };
-#endif /* TARGET_AARCH64 */
  static const TypeInfo raspi_machine_types[] = {
  {
@@ -402,16 +401,16 @@ static const TypeInfo raspi_machine_types[] = {
  .name   = MACHINE_TYPE_NAME("raspi2b"),
  .parent = TYPE_RASPI_MACHINE,
  .class_init = raspi2b_machine_class_init,
-#ifdef TARGET_AARCH64
  }, {
  .name   = MACHINE_TYPE_NAME("raspi3ap"),
  .parent = TYPE_RASPI_MACHINE,
+    .registerable   = legacy_binary_is_64bit,
  .class_init = raspi3ap_machine_class_init,
  }, {
  .name   = MACHINE_TYPE_NAME("raspi3b"),
  .parent = TYPE_RASPI_MACHINE,
+    .registerable   = legacy_binary_is_64bit,
  .class_init = raspi3b_machine_class_init,
-#endif
  }, {
  .name   = TYPE_RASPI_MACHINE,
  .parent = TYPE_RASPI_BASE_MACHINE,


Uh, this (together with patch 1) looks very cumbersome. Why don't you 
simply split the array into two, one for 32-bit and one for 64-bit, and 
then use a simply "if (legacy_binary_is_64bit())" in the type_init 
function instead?


Sounds like a good idea.

So we would have DEFINE_TYPES() and DEFINE_TYPES64() macros ?


Either that - or simply use type_init() directly here for the time being.


As Pierrick noted on private chat, my approach doesn't scale, I should
use smth in the lines of:

     }, {
     .name   = MACHINE_TYPE_NAME("raspi2b"),
     .parent = TYPE_RASPI_MACHINE,
     .registerable   = qemu_binary_has_target_arm,
     .class_init = raspi2b_machine_class_init,
     }, {
     .name   = MACHINE_TYPE_NAME("raspi3ap"),
     .parent = TYPE_RASPI_MACHINE,
     .registerable   = qemu_binary_has_target_aarch64,
     .class_init = raspi3ap_machine_class_init,
     }, {

Having:

bool qemu_binary_has_target_arm(void)
{
     return qemu_arch_available(QEMU_ARCH_ARM);
}

Now back to Thomas suggestion, we could define 2 TypeInfo arrays,
but I foresee lot of code churn when devices has to be made
available on different setup combinations; so with that in mind
the QOM registera

Re: [RFC PATCH 2/4] hw/arm/raspi: Replace TARGET_AARCH64 by legacy_binary_is_64bit()

2025-03-06 Thread Peter Maydell
On Thu, 6 Mar 2025 at 09:21, Daniel P. Berrangé  wrote:
>
> On Wed, Mar 05, 2025 at 05:12:46PM +0100, Philippe Mathieu-Daudé wrote:
> > For legacy ARM binaries, legacy_binary_is_64bit() is
> > equivalent of the compile time TARGET_AARCH64 definition.
> >
> > Use it as TypeInfo::registerable() callback to dynamically
> > add Aarch64 specific types in qemu-system-aarch64 binary,
> > removing the need of TARGET_AARCH64 #ifdef'ry.
> >
> > Signed-off-by: Philippe Mathieu-Daudé 
> > ---
> >  hw/arm/bcm2836.c | 6 ++
> >  hw/arm/raspi.c   | 7 +++
> >  2 files changed, 5 insertions(+), 8 deletions(-)
> >
> > diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
> > index 95e16806fa1..88a32e5fc20 100644
> > --- a/hw/arm/bcm2836.c
> > +++ b/hw/arm/bcm2836.c
>
>
> > @@ -219,12 +218,11 @@ static const TypeInfo bcm283x_types[] = {
> >  .name   = TYPE_BCM2836,
> >  .parent = TYPE_BCM283X,
> >  .class_init = bcm2836_class_init,
> > -#ifdef TARGET_AARCH64
> >  }, {
> >  .name   = TYPE_BCM2837,
> >  .parent = TYPE_BCM283X,
> > +.registerable   = legacy_binary_is_64bit,
> >  .class_init = bcm2837_class_init,
> > -#endif
> >  }, {
> >  .name   = TYPE_BCM283X,
> >  .parent = TYPE_BCM283X_BASE,
>
> So historically we have a subset of machines that are only exposed in
> the qemu-system-aarch64 binary, and not qemu-system-arm.
>
> You're attempting to build a single binary to cover both 32 & 64 bit
> arm, so need to be able to filter what machines are available to
> create when the symlink indicates invokation of the 32-bit binary.

What machines are there that we don't want to provide, though?
We don't provide for instance raspi4b in today's qemu-system-arm,
but that's because it wouldn't work there: qemu-system-arm
doesn't have the 64-bit CPUs. But if we have a single binary
that has both 32 and 64 bit arm in it, then the 64-bit CPUs
will be in that combined binary. Do we actually need to explicitly
forbid the user from saying 'qemu-system-arm -M raspi4b' when
qemu-system-arm is a symlink and the command would work fine
if it wasn't forbidden?

I had assumed that the motivation here was that we'd like to
be able to build this C file only once. Currently we have to
build it once for the aarch64 target and once for the arm target;
to avoid that we would need to determine "does the binary I'm
in have the AArch64 CPU types this type depends on" at runtime,
not at compile time (which is what the ifdef is doing, effectively).

thanks
-- PMM



[PATCH 0/7] hw/hyperv: remove duplication compilation units

2025-03-06 Thread Pierrick Bouvier
Work towards having a single binary, by removing duplicated object files.

hw/hyperv/hyperv.c was excluded at this time, because it depends on target
dependent symbols:
- from system/kvm.h
- kvm_check_extension
- kvm_vm_ioctl
- from exec/cpu-all.h | memory_ldst_phys.h.inc
- ldq_phys

Pierrick Bouvier (7):
  hw/hyperv/hv-balloon-stub: common compilation unit
  hw/hyperv/hyperv.h: header cleanup
  hw/hyperv/vmbus: common compilation unit
  hw/hyperv/hyperv-proto: move SYNDBG definition from target/i386
  hw/hyperv/syndbg: common compilation unit
  hw/hyperv/balloon: common balloon compilation units
  hw/hyperv/hyperv_testdev: common compilation unit

 include/hw/hyperv/hyperv-proto.h | 12 
 include/hw/hyperv/hyperv.h   |  4 ++-
 target/i386/kvm/hyperv-proto.h   | 12 
 hw/hyperv/syndbg.c   |  7 +++--
 hw/hyperv/vmbus.c| 50 
 hw/hyperv/meson.build|  9 +++---
 6 files changed, 49 insertions(+), 45 deletions(-)

-- 
2.39.5




[PULL 09/10] qdev: Improve a few more PropertyInfo @description members

2025-03-06 Thread Markus Armbruster
Signed-off-by: Markus Armbruster 
Message-ID: <20250227085601.4140852-7-arm...@redhat.com>
Reviewed-by: Daniel P. Berrangé 
---
 hw/block/xen-block.c | 2 +-
 hw/core/qdev-properties-system.c | 2 +-
 hw/core/qdev-properties.c| 1 +
 hw/s390x/ccw-device.c| 4 ++--
 target/sparc/cpu.c   | 1 +
 5 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
index 7c9d1b658c..2098286b5f 100644
--- a/hw/block/xen-block.c
+++ b/hw/block/xen-block.c
@@ -662,7 +662,7 @@ invalid:
  */
 static const PropertyInfo xen_block_prop_vdev = {
 .type  = "str",
-.description = "Virtual Disk specifier: d*p*/xvd*/hd*/sd*",
+.description = "Virtual Disk specifier (d*p*/xvd*/hd*/sd*)",
 .get = xen_block_get_vdev,
 .set = xen_block_set_vdev,
 };
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index 6d7dcf368d..a7dde73c29 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -985,7 +985,7 @@ inval:
 
 const PropertyInfo qdev_prop_pci_host_devaddr = {
 .type = "str",
-.description = "Address (bus/device/function) of "
+.description = "Address (bus:device.function) of "
"the host device, example: 04:10.0",
 .get = get_pci_host_devaddr,
 .set = set_pci_host_devaddr,
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 5a801057db..c04df3b337 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -247,6 +247,7 @@ static void set_bool(Object *obj, Visitor *v, const char 
*name, void *opaque,
 
 const PropertyInfo qdev_prop_bool = {
 .type  = "bool",
+.description = "on/off",
 .get   = get_bool,
 .set   = set_bool,
 .set_default_value = set_default_value_bool,
diff --git a/hw/s390x/ccw-device.c b/hw/s390x/ccw-device.c
index 1d4b8ea35c..1ea9934f6c 100644
--- a/hw/s390x/ccw-device.c
+++ b/hw/s390x/ccw-device.c
@@ -75,8 +75,8 @@ static void ccw_device_set_loadparm(Object *obj, Visitor *v,
 
 const PropertyInfo ccw_loadparm = {
 .type  = "str",
-.description = "Up to 8 chars in set of [A-Za-z0-9. ] to pass"
-" to the guest loader/kernel",
+.description = "Up to 8 chars in set of [A-Za-z0-9. ] to select"
+" a guest kernel",
 .get = ccw_device_get_loadparm,
 .set = ccw_device_set_loadparm,
 };
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index c8ea35be76..f0613f8a8e 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -939,6 +939,7 @@ static void sparc_set_nwindows(Object *obj, Visitor *v, 
const char *name,
 
 static const PropertyInfo qdev_prop_nwindows = {
 .type  = "int",
+.description = "Number of register windows",
 .get   = sparc_get_nwindows,
 .set   = sparc_set_nwindows,
 };
-- 
2.48.1




[PULL 05/10] qdev: Change qdev_prop_pci_devfn member @name from "int32" to "str"

2025-03-06 Thread Markus Armbruster
Properties using qdev_prop_pci_devfn initially accepted a string of
the form "DEV.FN" or "DEV" where DEV and FN are in hexadecimal.
Member @name was "pci-devfn" initially.

Commit b403298adb5 (qdev: make the non-legacy pci address property
accept an integer) changed them to additionally accept integers: bits
3..7 are DEV, and bits 0..2 are FN.  This is inaccessible externally
in device_add so far.

The commit also changed @name to "int32", and set member @legacy-name
to "pci-devfn".  Together, this kept QMP command
device-list-properties unaffected: it used @name only when
@legacy_name was null.

Commit 07d09c58dbb (qmp: Print descriptions of object properties)
quietly dumbed that down to use @name always, and the next commit
18b91a3e082q (qdev: Drop legacy_name from qdev properties) dropped
member @legacy_name.  This changed the value of @type reported by QMP
command device-list-properties from "pci-devfn" to "int32".

But "int32" is misleading: device_add actually wants QAPI type "str".
So change @name to that.

Signed-off-by: Markus Armbruster 
Message-ID: <20250227085601.4140852-3-arm...@redhat.com>
Reviewed-by: Daniel P. Berrangé 
---
 hw/core/qdev-properties-system.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index a91551a5ee..f2b6136d0a 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -882,7 +882,7 @@ static int print_pci_devfn(Object *obj, const Property 
*prop, char *dest,
 }
 
 const PropertyInfo qdev_prop_pci_devfn = {
-.name  = "int32",
+.name  = "str",
 .description = "Slot and optional function number, example: 06.0 or 06",
 .print = print_pci_devfn,
 .get   = qdev_propinfo_get_int32,
-- 
2.48.1




[PULL 08/10] qdev: Improve PropertyInfo member @description for enum properties

2025-03-06 Thread Markus Armbruster
Consistently use format "DESCRIPTION (VALUE/VALUE...)".

Signed-off-by: Markus Armbruster 
Message-ID: <20250227085601.4140852-6-arm...@redhat.com>
Reviewed-by: Daniel P. Berrangé 
---
 hw/core/qdev-properties-system.c | 26 +++---
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index 0ac1485d54..6d7dcf368d 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -603,6 +603,7 @@ QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
 
 const PropertyInfo qdev_prop_losttickpolicy = {
 .type  = "LostTickPolicy",
+.description = "Policy for handling lost ticks (discard/delay/slew)",
 .enum_table  = &LostTickPolicy_lookup,
 .get   = qdev_propinfo_get_enum,
 .set   = qdev_propinfo_set_losttickpolicy,
@@ -642,8 +643,7 @@ QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int));
 
 const PropertyInfo qdev_prop_blockdev_on_error = {
 .type = "BlockdevOnError",
-.description = "Error handling policy, "
-   "report/ignore/enospc/stop/auto",
+.description = "Error handling policy (report/ignore/enospc/stop/auto)",
 .enum_table = &BlockdevOnError_lookup,
 .get = qdev_propinfo_get_enum,
 .set = qdev_propinfo_set_enum,
@@ -656,8 +656,8 @@ QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != 
sizeof(int));
 
 const PropertyInfo qdev_prop_bios_chs_trans = {
 .type = "BiosAtaTranslation",
-.description = "Logical CHS translation algorithm, "
-   "auto/none/lba/large/rechs",
+.description = "Logical CHS translation algorithm "
+   " (auto/none/lba/large/rechs)",
 .enum_table = &BiosAtaTranslation_lookup,
 .get = qdev_propinfo_get_enum,
 .set = qdev_propinfo_set_enum,
@@ -668,8 +668,7 @@ const PropertyInfo qdev_prop_bios_chs_trans = {
 
 const PropertyInfo qdev_prop_fdc_drive_type = {
 .type = "FloppyDriveType",
-.description = "FDC drive type, "
-   "144/288/120/none/auto",
+.description = "Floppy drive type (144/288/120/none/auto)",
 .enum_table = &FloppyDriveType_lookup,
 .get = qdev_propinfo_get_enum,
 .set = qdev_propinfo_set_enum,
@@ -680,8 +679,8 @@ const PropertyInfo qdev_prop_fdc_drive_type = {
 
 const PropertyInfo qdev_prop_multifd_compression = {
 .type = "MultiFDCompression",
-.description = "multifd_compression values, "
-   "none/zlib/zstd/qpl/uadk/qatzip",
+.description = "multifd_compression values"
+   " (none/zlib/zstd/qpl/uadk/qatzip)",
 .enum_table = &MultiFDCompression_lookup,
 .get = qdev_propinfo_get_enum,
 .set = qdev_propinfo_set_enum,
@@ -694,8 +693,7 @@ QEMU_BUILD_BUG_ON(sizeof(MigMode) != sizeof(int));
 
 const PropertyInfo qdev_prop_mig_mode = {
 .type = "MigMode",
-.description = "mig_mode values, "
-   "normal,cpr-reboot",
+.description = "Migration mode (normal/cpr-reboot)",
 .enum_table = &MigMode_lookup,
 .get = qdev_propinfo_get_enum,
 .set = qdev_propinfo_set_enum,
@@ -708,8 +706,7 @@ QEMU_BUILD_BUG_ON(sizeof(GranuleMode) != sizeof(int));
 
 const PropertyInfo qdev_prop_granule_mode = {
 .type = "GranuleMode",
-.description = "granule_mode values, "
-   "4k, 8k, 16k, 64k, host",
+.description = "Granule page size (4k/8k/16k/64k/host)",
 .enum_table = &GranuleMode_lookup,
 .get = qdev_propinfo_get_enum,
 .set = qdev_propinfo_set_enum,
@@ -718,8 +715,7 @@ const PropertyInfo qdev_prop_granule_mode = {
 
 const PropertyInfo qdev_prop_zero_page_detection = {
 .type = "ZeroPageDetection",
-.description = "zero_page_detection values, "
-   "none,legacy,multifd",
+.description = "Zero page detection (none/legacy/multifd)",
 .enum_table = &ZeroPageDetection_lookup,
 .get = qdev_propinfo_get_enum,
 .set = qdev_propinfo_set_enum,
@@ -1232,7 +1228,7 @@ QEMU_BUILD_BUG_ON(sizeof(S390CpuEntitlement) != 
sizeof(int));
 
 const PropertyInfo qdev_prop_cpus390entitlement = {
 .type  = "S390CpuEntitlement",
-.description = "low/medium (default)/high",
+.description = "auto/low/medium/high (default medium)",
 .enum_table  = &S390CpuEntitlement_lookup,
 .get   = qdev_propinfo_get_enum,
 .set   = qdev_propinfo_set_enum,
-- 
2.48.1




[PULL 10/10] docs/devel/qapi-code-gen: Discourage use of 'prefix'

2025-03-06 Thread Markus Armbruster
QAPI's 'prefix' feature can make the connection between enumeration
type and its constants less than obvious.  It's best used with
restraint.  Commit 7bbadc60b5..64f5e9db77 eliminated most uses.
Discourage new ones.

Signed-off-by: Markus Armbruster 
Message-ID: <20250228134335.132278-1-arm...@redhat.com>
Reviewed-by: Daniel P. Berrangé 
---
 docs/devel/qapi-code-gen.rst | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst
index 9fa94251b0..f9cfe8721f 100644
--- a/docs/devel/qapi-code-gen.rst
+++ b/docs/devel/qapi-code-gen.rst
@@ -229,7 +229,8 @@ These are of the form PREFIX_NAME, where PREFIX is derived 
from the
 enumeration type's name, and NAME from the value's name.  For the
 example above, the generator maps 'MyEnum' to MY_ENUM and 'value1' to
 VALUE1, resulting in the enumeration constant MY_ENUM_VALUE1.  The
-optional 'prefix' member overrides PREFIX.
+optional 'prefix' member overrides PREFIX.  This is rarely necessary,
+and should be used with restraint.
 
 The generated C enumeration constants have values 0, 1, ..., N-1 (in
 QAPI schema order), where N is the number of values.  There is an
-- 
2.48.1




Re: [BUG, RFC] cpr-transfer: qxl guest driver crashes after migration

2025-03-06 Thread Denis V. Lunev

On 3/5/25 22:19, Steven Sistare wrote:

On 3/5/2025 11:50 AM, Andrey Drobyshev wrote:

On 3/4/25 9:05 PM, Steven Sistare wrote:

On 2/28/2025 1:37 PM, Andrey Drobyshev wrote:

On 2/28/25 8:35 PM, Andrey Drobyshev wrote:

On 2/28/25 8:20 PM, Steven Sistare wrote:

On 2/28/2025 1:13 PM, Steven Sistare wrote:

On 2/28/2025 12:39 PM, Andrey Drobyshev wrote:

Hi all,

We've been experimenting with cpr-transfer migration mode recently
and
have discovered the following issue with the guest QXL driver:

Run migration source:

EMULATOR=/path/to/emulator
ROOTFS=/path/to/image
QMPSOCK=/var/run/alma8qmp-src.sock

$EMULATOR -enable-kvm \
   -machine q35 \
   -cpu host -smp 2 -m 2G \
   -object 
memory-backend-file,id=ram0,size=2G,mem-path=/dev/shm/

ram0,share=on\
   -machine memory-backend=ram0 \
   -machine aux-ram-share=on \
   -drive file=$ROOTFS,media=disk,if=virtio \
   -qmp unix:$QMPSOCK,server=on,wait=off \
   -nographic \
   -device qxl-vga


Run migration target:

EMULATOR=/path/to/emulator
ROOTFS=/path/to/image
QMPSOCK=/var/run/alma8qmp-dst.sock
$EMULATOR -enable-kvm \
   -machine q35 \
   -cpu host -smp 2 -m 2G \
   -object 
memory-backend-file,id=ram0,size=2G,mem-path=/dev/shm/

ram0,share=on\
   -machine memory-backend=ram0 \
   -machine aux-ram-share=on \
   -drive file=$ROOTFS,media=disk,if=virtio \
   -qmp unix:$QMPSOCK,server=on,wait=off \
   -nographic \
   -device qxl-vga \
   -incoming tcp:0:4 \
   -incoming '{"channel-type": "cpr", "addr": { "transport":
"socket", "type": "unix", "path": "/var/run/alma8cpr-dst.sock"}}'



Launch the migration:

QMPSHELL=/root/src/qemu/master/scripts/qmp/qmp-shell
QMPSOCK=/var/run/alma8qmp-src.sock

$QMPSHELL -p $QMPSOCK <

Then, after a while, QXL guest driver on target crashes spewing 
the

following messages:

[   73.962002] [TTM] Buffer eviction failed
[   73.962072] qxl :00:02.0: object_init failed for (3149824,
0x0001)
[   73.962081] [drm:qxl_alloc_bo_reserved [qxl]] *ERROR* 
failed to

allocate VRAM BO


That seems to be a known kernel QXL driver bug:

https://lore.kernel.org/all/20220907094423.93581-1-
min_h...@163.com/T/
https://lore.kernel.org/lkml/ztgydqrlk6wx_...@eldamar.lan/

(the latter discussion contains that reproduce script which 
speeds up

the crash in the guest):

#!/bin/bash

chvt 3

for j in $(seq 80); do
   echo "$(date) starting round $j"
   if [ "$(journalctl --boot | grep "failed to 
allocate VRAM

BO")" != "" ]; then
   echo "bug was reproduced after $j tries"
   exit 1
   fi
   for i in $(seq 100); do
   dmesg > /dev/tty3
   done
done

echo "bug could not be reproduced"
exit 0


The bug itself seems to remain unfixed, as I was able to reproduce
that
with Fedora 41 guest, as well as AlmaLinux 8 guest. However our
cpr-transfer code also seems to be buggy as it triggers the 
crash -

without the cpr-transfer migration the above reproduce doesn't
lead to
crash on the source VM.

I suspect that, as cpr-transfer doesn't migrate the guest 
memory, but

rather passes it through the memory backend object, our code might
somehow corrupt the VRAM.  However, I wasn't able to trace the
corruption so far.

Could somebody help the investigation and take a look into 
this?  Any

suggestions would be appreciated.  Thanks!


Possibly some memory region created by qxl is not being preserved.
Try adding these traces to see what is preserved:

-trace enable='*cpr*'
-trace enable='*ram_alloc*'


Also try adding this patch to see if it flags any ram blocks as not
compatible with cpr.  A message is printed at migration start time.
https://lore.kernel.org/qemu-devel/1740667681-257312-1-git-send-
email-
steven.sist...@oracle.com/

- Steve



With the traces enabled + the "migration: ram block cpr blockers" 
patch

applied:

Source:

cpr_find_fd pc.bios, id 0 returns -1
cpr_save_fd pc.bios, id 0, fd 22
qemu_ram_alloc_shared pc.bios size 262144 max_size 262144 fd 22 host
0x7fec18e0
cpr_find_fd pc.rom, id 0 returns -1
cpr_save_fd pc.rom, id 0, fd 23
qemu_ram_alloc_shared pc.rom size 131072 max_size 131072 fd 23 host
0x7fec18c0
cpr_find_fd :00:01.0/e1000e.rom, id 0 returns -1
cpr_save_fd :00:01.0/e1000e.rom, id 0, fd 24
qemu_ram_alloc_shared :00:01.0/e1000e.rom size 262144 max_size
262144 fd 24 host 0x7fec18a0
cpr_find_fd :00:02.0/vga.vram, id 0 returns -1
cpr_save_fd :00:02.0/vga.vram, id 0, fd 25
qemu_ram_alloc_shared :00:02.0/vga.vram size 67108864 max_size
67108864 fd 25 host 0x7feb77e0
cpr_find_fd :00:02.0/qxl.vrom, id 0 returns -1
cpr_save_fd :00:02.0/qxl.vrom, id 0, fd 27
qemu_ram_alloc_shared :00:02.0/qxl.vrom size 8192 max_size 8192
fd 27 host 0x7fec1880
cpr_find_fd :00:02.0/qxl.vram, id 0 returns -1
cpr_save_fd :00:02.0/qxl.vram, id 0, fd 28
qemu_ram_alloc_shared :00:02.0/qxl.vram size 67108864 max_size
67108864

Re: [PATCH v6 30/36] vfio/migration: Multifd device state transfer support - send side

2025-03-06 Thread Cédric Le Goater

On 3/6/25 11:15, Maciej S. Szmigiero wrote:

On 6.03.2025 07:47, Avihai Horon wrote:


On 05/03/2025 0:03, Maciej S. Szmigiero wrote:

External email: Use caution opening links or attachments


From: "Maciej S. Szmigiero" 

Implement the multifd device state transfer via additional per-device
thread inside save_live_complete_precopy_thread handler.

Switch between doing the data transfer in the new handler and doing it
in the old save_state handler depending if VFIO multifd transfer is enabled
or not.

Signed-off-by: Maciej S. Szmigiero 
---
  hw/vfio/migration-multifd.c   | 142 ++
  hw/vfio/migration-multifd.h   |   6 ++
  hw/vfio/migration.c   |  22 --
  hw/vfio/trace-events  |   2 +
  include/hw/vfio/vfio-common.h |   6 ++
  5 files changed, 172 insertions(+), 6 deletions(-)

diff --git a/hw/vfio/migration-multifd.c b/hw/vfio/migration-multifd.c
index 1d81233c755f..bfb9a72fa450 100644
--- a/hw/vfio/migration-multifd.c
+++ b/hw/vfio/migration-multifd.c
@@ -496,6 +496,148 @@ bool vfio_multifd_setup(VFIODevice *vbasedev, bool 
alloc_multifd, Error **errp)
  return true;
  }

+void vfio_multifd_emit_dummy_eos(VFIODevice *vbasedev, QEMUFile *f)
+{
+    assert(vfio_multifd_transfer_enabled(vbasedev));
+
+    /*
+ * Emit dummy NOP data on the main migration channel since the actual
+ * device state transfer is done via multifd channels.
+ */
+    qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE);
+}
+
+static bool
+vfio_save_complete_precopy_thread_config_state(VFIODevice *vbasedev,
+   char *idstr,
+   uint32_t instance_id,
+   uint32_t idx,
+   Error **errp)
+{
+    g_autoptr(QIOChannelBuffer) bioc = NULL;
+    g_autoptr(QEMUFile) f = NULL;
+    int ret;
+    g_autofree VFIODeviceStatePacket *packet = NULL;
+    size_t packet_len;
+
+    bioc = qio_channel_buffer_new(0);
+    qio_channel_set_name(QIO_CHANNEL(bioc), "vfio-device-config-save");
+
+    f = qemu_file_new_output(QIO_CHANNEL(bioc));
+
+    if (vfio_save_device_config_state(f, vbasedev, errp)) {
+    return false;
+    }
+
+    ret = qemu_fflush(f);
+    if (ret) {
+    error_setg(errp, "%s: save config state flush failed: %d",
+   vbasedev->name, ret);
+    return false;
+    }
+
+    packet_len = sizeof(*packet) + bioc->usage;
+    packet = g_malloc0(packet_len);
+    packet->version = VFIO_DEVICE_STATE_PACKET_VER_CURRENT;
+    packet->idx = idx;
+    packet->flags = VFIO_DEVICE_STATE_CONFIG_STATE;


The packet is sent on the wire.
Shouldn't we use cpu_to_be32() for version, idx and flags? Also below in 
vfio_multifd_save_complete_precopy_thread().
And then use be32_to_cpu() in patch #26 when receiving the packet?


Is it even possible to migrate to a host with different endianess here?

Also AFAIK big endian hosts barely exist today, is any of them even 
VFIO-capable?


s390x is VFIO capable. VFIO PCI migration is not supported on these.

Thanks,

C.






[PATCH v5 07/29] hw/intc/aspeed: Add object type name to trace events for better debugging

2025-03-06 Thread Jamin Lin via
Currently, these trace events only refer to INTC. To simplify the INTC model,
both INTC(CPU Die) and INTCIO(IO Die) will share the same helper functions.

However, it is difficult to recognize whether these trace events are comes from
INTC or INTCIO. To make these trace events more readable, adds object type name
to the INTC trace events.
Update trace events to include the "name" field for better identification.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/intc/aspeed_intc.c | 32 +++-
 hw/intc/trace-events  | 24 
 2 files changed, 31 insertions(+), 25 deletions(-)

diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 11bda9d42a..9852094953 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -45,6 +45,7 @@ REG32(GICINT136_STATUS, 0x804)
 static void aspeed_intc_update(AspeedINTCState *s, int irq, int level)
 {
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+const char *name = object_get_typename(OBJECT(s));
 
 if (irq >= aic->num_ints) {
 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
@@ -52,7 +53,7 @@ static void aspeed_intc_update(AspeedINTCState *s, int irq, 
int level)
 return;
 }
 
-trace_aspeed_intc_update_irq(irq, level);
+trace_aspeed_intc_update_irq(name, irq, level);
 qemu_set_irq(s->output_pins[irq], level);
 }
 
@@ -66,6 +67,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 {
 AspeedINTCState *s = (AspeedINTCState *)opaque;
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+const char *name = object_get_typename(OBJECT(s));
 uint32_t status_reg = GICINT_STATUS_BASE + ((0x100 * irq) >> 2);
 uint32_t select = 0;
 uint32_t enable;
@@ -77,7 +79,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 return;
 }
 
-trace_aspeed_intc_set_irq(irq, level);
+trace_aspeed_intc_set_irq(name, irq, level);
 enable = s->enable[irq];
 
 if (!level) {
@@ -96,7 +98,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 return;
 }
 
-trace_aspeed_intc_select(select);
+trace_aspeed_intc_select(name, select);
 
 if (s->mask[irq] || s->regs[status_reg]) {
 /*
@@ -108,14 +110,14 @@ static void aspeed_intc_set_irq(void *opaque, int irq, 
int level)
  * save source interrupt to pending variable.
  */
 s->pending[irq] |= select;
-trace_aspeed_intc_pending_irq(irq, s->pending[irq]);
+trace_aspeed_intc_pending_irq(name, irq, s->pending[irq]);
 } else {
 /*
  * notify firmware which source interrupt are coming
  * by setting status register
  */
 s->regs[status_reg] = select;
-trace_aspeed_intc_trigger_irq(irq, s->regs[status_reg]);
+trace_aspeed_intc_trigger_irq(name, irq, s->regs[status_reg]);
 aspeed_intc_update(s, irq, 1);
 }
 }
@@ -124,6 +126,7 @@ static void aspeed_intc_enable_handler(AspeedINTCState *s, 
hwaddr offset,
uint64_t data)
 {
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+const char *name = object_get_typename(OBJECT(s));
 uint32_t reg = offset >> 2;
 uint32_t old_enable;
 uint32_t change;
@@ -154,7 +157,7 @@ static void aspeed_intc_enable_handler(AspeedINTCState *s, 
hwaddr offset,
 
 /* enable new source interrupt */
 if (old_enable != s->enable[irq]) {
-trace_aspeed_intc_enable(s->enable[irq]);
+trace_aspeed_intc_enable(name, s->enable[irq]);
 s->regs[reg] = data;
 return;
 }
@@ -163,10 +166,10 @@ static void aspeed_intc_enable_handler(AspeedINTCState 
*s, hwaddr offset,
 change = s->regs[reg] ^ data;
 if (change & data) {
 s->mask[irq] &= ~change;
-trace_aspeed_intc_unmask(change, s->mask[irq]);
+trace_aspeed_intc_unmask(name, change, s->mask[irq]);
 } else {
 s->mask[irq] |= change;
-trace_aspeed_intc_mask(change, s->mask[irq]);
+trace_aspeed_intc_mask(name, change, s->mask[irq]);
 }
 
 s->regs[reg] = data;
@@ -176,6 +179,7 @@ static void aspeed_intc_status_handler(AspeedINTCState *s, 
hwaddr offset,
uint64_t data)
 {
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
+const char *name = object_get_typename(OBJECT(s));
 uint32_t reg = offset >> 2;
 uint32_t irq;
 
@@ -207,7 +211,7 @@ static void aspeed_intc_status_handler(AspeedINTCState *s, 
hwaddr offset,
 
 /* All source ISR execution are done */
 if (!s->regs[reg]) {
-trace_aspeed_intc_all_isr_done(irq);
+trace_aspeed_intc_all_isr_done(name, irq);
 if (s->pending[irq]) {
 /*
  * handle pending source interrupt
@@ -216,11 +220,11 @@ static void aspeed_intc_status_handler(AspeedINTCState 
*s, hwaddr offset,
  */
 s->regs[reg] 

[PATCH v5 05/29] hw/intc/aspeed: Reduce regs array size by adding a register sub-region

2025-03-06 Thread Jamin Lin via
Currently, the size of the "regs" array is 0x2000, which is too large. So far,
it only uses "GICINT128 to `GICINT134", and the offsets from 0 to 0x1000 are
unused. To save code size and avoid mapping large unused gaps, update to only
map the useful set of registers:

INTC register [0x1000 – 0x1804]

Update "reg_size" to 0x808. Introduce a new class attribute "reg_offset" to set
the start offset of a "INTC" sub-region. Set the "reg_offset" to 0x1000 for INTC
registers.

Signed-off-by: Jamin Lin 
---
 include/hw/intc/aspeed_intc.h |  1 +
 hw/intc/aspeed_intc.c | 50 ---
 2 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 17cd889e0d..d72a5b4ab1 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -42,6 +42,7 @@ struct AspeedINTCClass {
 uint32_t num_ints;
 uint64_t mem_size;
 uint64_t reg_size;
+uint64_t reg_offset;
 };
 
 #endif /* ASPEED_INTC_H */
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 1c3dc3fce0..fad351449b 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -14,25 +14,31 @@
 #include "hw/registerfields.h"
 #include "qapi/error.h"
 
-/* INTC Registers */
-REG32(GICINT128_EN, 0x1000)
-REG32(GICINT128_STATUS, 0x1004)
-REG32(GICINT129_EN, 0x1100)
-REG32(GICINT129_STATUS, 0x1104)
-REG32(GICINT130_EN, 0x1200)
-REG32(GICINT130_STATUS, 0x1204)
-REG32(GICINT131_EN, 0x1300)
-REG32(GICINT131_STATUS, 0x1304)
-REG32(GICINT132_EN, 0x1400)
-REG32(GICINT132_STATUS, 0x1404)
-REG32(GICINT133_EN, 0x1500)
-REG32(GICINT133_STATUS, 0x1504)
-REG32(GICINT134_EN, 0x1600)
-REG32(GICINT134_STATUS, 0x1604)
-REG32(GICINT135_EN, 0x1700)
-REG32(GICINT135_STATUS, 0x1704)
-REG32(GICINT136_EN, 0x1800)
-REG32(GICINT136_STATUS, 0x1804)
+/*
+ * INTC Registers
+ *
+ * values below are offset by - 0x1000 from datasheet
+ * because its memory region is start at 0x1000
+ *
+ */
+REG32(GICINT128_EN, 0x000)
+REG32(GICINT128_STATUS, 0x004)
+REG32(GICINT129_EN, 0x100)
+REG32(GICINT129_STATUS, 0x104)
+REG32(GICINT130_EN, 0x200)
+REG32(GICINT130_STATUS, 0x204)
+REG32(GICINT131_EN, 0x300)
+REG32(GICINT131_STATUS, 0x304)
+REG32(GICINT132_EN, 0x400)
+REG32(GICINT132_STATUS, 0x404)
+REG32(GICINT133_EN, 0x500)
+REG32(GICINT133_STATUS, 0x504)
+REG32(GICINT134_EN, 0x600)
+REG32(GICINT134_STATUS, 0x604)
+REG32(GICINT135_EN, 0x700)
+REG32(GICINT135_STATUS, 0x704)
+REG32(GICINT136_EN, 0x800)
+REG32(GICINT136_STATUS, 0x804)
 
 #define GICINT_STATUS_BASE R_GICINT128_STATUS
 
@@ -298,7 +304,8 @@ static void aspeed_intc_realize(DeviceState *dev, Error 
**errp)
 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
   TYPE_ASPEED_INTC ".regs", aic->reg_size << 2);
 
-memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem);
+memory_region_add_subregion(&s->iomem_container, aic->reg_offset,
+&s->iomem);
 
 qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints);
 
@@ -348,7 +355,8 @@ static void aspeed_2700_intc_class_init(ObjectClass *klass, 
void *data)
 aic->num_lines = 32;
 aic->num_ints = 9;
 aic->mem_size = 0x4000;
-aic->reg_size = 0x2000 >> 2;
+aic->reg_size = 0x808 >> 2;
+aic->reg_offset = 0x1000;
 }
 
 static const TypeInfo aspeed_2700_intc_info = {
-- 
2.43.0




[PATCH v5 04/29] hw/intc/aspeed: Support setting different register size

2025-03-06 Thread Jamin Lin via
Currently, the size of the regs array is 0x2000, which is too large. So far,
it only use GICINT128 - GICINT134, and the offsets from 0 to 0x1000 are unused.
To save code size, introduce a new class attribute "reg_size" to set the
different register sizes for the INTC models in AST2700 and add a regs
sub-region in the memory container.

Signed-off-by: Jamin Lin 
---
 include/hw/intc/aspeed_intc.h |  2 +-
 hw/intc/aspeed_intc.c | 22 +-
 2 files changed, 6 insertions(+), 18 deletions(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 47ea0520b5..17cd889e0d 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -16,7 +16,6 @@
 #define TYPE_ASPEED_2700_INTC TYPE_ASPEED_INTC "-ast2700"
 OBJECT_DECLARE_TYPE(AspeedINTCState, AspeedINTCClass, ASPEED_INTC)
 
-#define ASPEED_INTC_NR_REGS (0x2000 >> 2)
 #define ASPEED_INTC_NR_INTS 9
 
 struct AspeedINTCState {
@@ -42,6 +41,7 @@ struct AspeedINTCClass {
 uint32_t num_lines;
 uint32_t num_ints;
 uint64_t mem_size;
+uint64_t reg_size;
 };
 
 #endif /* ASPEED_INTC_H */
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index feb2c52441..1c3dc3fce0 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -120,13 +120,6 @@ static uint64_t aspeed_intc_read(void *opaque, hwaddr 
offset, unsigned int size)
 uint32_t reg = offset >> 2;
 uint32_t value = 0;
 
-if (reg >= ASPEED_INTC_NR_REGS) {
-qemu_log_mask(LOG_GUEST_ERROR,
-  "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
-  __func__, offset);
-return 0;
-}
-
 value = s->regs[reg];
 trace_aspeed_intc_read(offset, size, value);
 
@@ -143,13 +136,6 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, 
uint64_t data,
 uint32_t change;
 uint32_t irq;
 
-if (reg >= ASPEED_INTC_NR_REGS) {
-qemu_log_mask(LOG_GUEST_ERROR,
-  "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
-  __func__, offset);
-return;
-}
-
 trace_aspeed_intc_write(offset, size, data);
 
 switch (reg) {
@@ -288,8 +274,9 @@ static void aspeed_intc_instance_init(Object *obj)
 static void aspeed_intc_reset(DeviceState *dev)
 {
 AspeedINTCState *s = ASPEED_INTC(dev);
+AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
 
-memset(s->regs, 0, ASPEED_INTC_NR_REGS);
+memset(s->regs, 0, aic->reg_size);
 memset(s->enable, 0, sizeof(s->enable));
 memset(s->mask, 0, sizeof(s->mask));
 memset(s->pending, 0, sizeof(s->pending));
@@ -307,9 +294,9 @@ static void aspeed_intc_realize(DeviceState *dev, Error 
**errp)
 
 sysbus_init_mmio(sbd, &s->iomem_container);
 
-s->regs = g_malloc0(ASPEED_INTC_NR_REGS);
+s->regs = g_malloc0(aic->reg_size);
 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
-  TYPE_ASPEED_INTC ".regs", ASPEED_INTC_NR_REGS << 2);
+  TYPE_ASPEED_INTC ".regs", aic->reg_size << 2);
 
 memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem);
 
@@ -361,6 +348,7 @@ static void aspeed_2700_intc_class_init(ObjectClass *klass, 
void *data)
 aic->num_lines = 32;
 aic->num_ints = 9;
 aic->mem_size = 0x4000;
+aic->reg_size = 0x2000 >> 2;
 }
 
 static const TypeInfo aspeed_2700_intc_info = {
-- 
2.43.0




[PATCH v5 25/29] tests/functional/aspeed: Introduce start_ast2700_test API

2025-03-06 Thread Jamin Lin via
Added a new method "start_ast2700_test" to the "AST2x00MachineSDK" class and
this method centralizes the logic for starting the AST2700 test, making it
reusable for different test cases.

Signed-off-by: Jamin Lin 
---
 tests/functional/test_aarch64_aspeed.py | 29 +
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/tests/functional/test_aarch64_aspeed.py 
b/tests/functional/test_aarch64_aspeed.py
index 9595498ace..e1ad7fd470 100755
--- a/tests/functional/test_aarch64_aspeed.py
+++ b/tests/functional/test_aarch64_aspeed.py
@@ -31,33 +31,29 @@ def do_test_aarch64_aspeed_sdk_start(self, image):
 
'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.03/ast2700-default-obmc.tar.gz',
 '91225f50d255e2905ba8d8e0c80b71b9d157c3609770c7a740cd786370d85a77')
 
-def test_aarch64_ast2700_evb_sdk_v09_03(self):
-self.set_machine('ast2700-evb')
-
-self.archive_extract(self.ASSET_SDK_V903_AST2700)
-
+def start_ast2700_test(self, name):
 num_cpu = 4
-uboot_size = os.path.getsize(self.scratch_file('ast2700-default',
+uboot_size = os.path.getsize(self.scratch_file(name,
'u-boot-nodtb.bin'))
 uboot_dtb_load_addr = hex(0x4 + uboot_size)
 
 load_images_list = [
 {
 'addr': '0x4',
-'file': self.scratch_file('ast2700-default',
+'file': self.scratch_file(name,
   'u-boot-nodtb.bin')
 },
 {
 'addr': str(uboot_dtb_load_addr),
-'file': self.scratch_file('ast2700-default', 'u-boot.dtb')
+'file': self.scratch_file(name, 'u-boot.dtb')
 },
 {
 'addr': '0x43000',
-'file': self.scratch_file('ast2700-default', 'bl31.bin')
+'file': self.scratch_file(name, 'bl31.bin')
 },
 {
 'addr': '0x43008',
-'file': self.scratch_file('ast2700-default', 'optee',
+'file': self.scratch_file(name, 'optee',
   'tee-raw.bin')
 }
 ]
@@ -76,13 +72,12 @@ def test_aarch64_ast2700_evb_sdk_v09_03(self):
 self.vm.add_args('-device',
  
'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test')
 self.do_test_aarch64_aspeed_sdk_start(
-self.scratch_file('ast2700-default', 'image-bmc'))
+self.scratch_file(name, 'image-bmc'))
 
-wait_for_console_pattern(self, 'ast2700-default login:')
+wait_for_console_pattern(self, f'{name} login:')
 
 exec_command_and_wait_for_pattern(self, 'root', 'Password:')
-exec_command_and_wait_for_pattern(self,
-'0penBmc', 'root@ast2700-default:~#')
+exec_command_and_wait_for_pattern(self, '0penBmc', f'root@{name}:~#')
 
 exec_command_and_wait_for_pattern(self,
 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device ',
@@ -94,6 +89,12 @@ def test_aarch64_ast2700_evb_sdk_v09_03(self):
 exec_command_and_wait_for_pattern(self,
 'cat /sys/class/hwmon/hwmon20/temp1_input', '18000')
 
+def test_aarch64_ast2700_evb_sdk_v09_03(self):
+self.set_machine('ast2700-evb')
+
+self.archive_extract(self.ASSET_SDK_V903_AST2700)
+self.start_ast2700_test('ast2700-default')
+
 
 if __name__ == '__main__':
 QemuSystemTest.main()
-- 
2.43.0




[PATCH v5 12/29] hw/intc/aspeed: Add support for multiple output pins in INTC

2025-03-06 Thread Jamin Lin via
Added support for multiple output pins in the INTC controller to
accommodate the AST2700 A1.

Introduced "num_outpins" to represent the number of output pins. Updated the
IRQ handling logic to initialize and connect output pins separately from input
pins. Modified the "aspeed_soc_ast2700_realize" function to connect source
orgates to INTC and INTC to GIC128 - GIC136. Updated the "aspeed_intc_realize"
function to initialize output pins.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 include/hw/intc/aspeed_intc.h | 5 +++--
 hw/arm/aspeed_ast27x0.c   | 6 +-
 hw/intc/aspeed_intc.c | 4 
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index bb634d2b4a..41b1f82d73 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -16,8 +16,8 @@
 #define TYPE_ASPEED_2700_INTC TYPE_ASPEED_INTC "-ast2700"
 OBJECT_DECLARE_TYPE(AspeedINTCState, AspeedINTCClass, ASPEED_INTC)
 
-#define ASPEED_INTC_NR_INTS 9
 #define ASPEED_INTC_MAX_INPINS 9
+#define ASPEED_INTC_MAX_OUTPINS 9
 
 struct AspeedINTCState {
 /*< private >*/
@@ -29,7 +29,7 @@ struct AspeedINTCState {
 
 uint32_t *regs;
 OrIRQState orgates[ASPEED_INTC_MAX_INPINS];
-qemu_irq output_pins[ASPEED_INTC_NR_INTS];
+qemu_irq output_pins[ASPEED_INTC_MAX_OUTPINS];
 
 uint32_t enable[ASPEED_INTC_MAX_INPINS];
 uint32_t mask[ASPEED_INTC_MAX_INPINS];
@@ -41,6 +41,7 @@ struct AspeedINTCClass {
 
 uint32_t num_lines;
 uint32_t num_inpins;
+uint32_t num_outpins;
 uint64_t mem_size;
 uint64_t reg_size;
 uint64_t reg_offset;
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index 01a8e1d6b4..2d24361daa 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -530,10 +530,14 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, 
Error **errp)
 aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc), 0,
 sc->memmap[ASPEED_DEV_INTC]);
 
-/* GICINT orgates -> INTC -> GIC */
+/* source orgates -> INTC */
 for (i = 0; i < ic->num_inpins; i++) {
 qdev_connect_gpio_out(DEVICE(&a->intc.orgates[i]), 0,
 qdev_get_gpio_in(DEVICE(&a->intc), i));
+}
+
+/* INTC -> GIC128 - GIC136 */
+for (i = 0; i < ic->num_outpins; i++) {
 sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc), i,
qdev_get_gpio_in(DEVICE(&a->gic),
 aspeed_soc_ast2700_gic_intcmap[i].irq));
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index f062db5b72..4ce2904e0b 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -347,6 +347,9 @@ static void aspeed_intc_realize(DeviceState *dev, Error 
**errp)
 if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) {
 return;
 }
+}
+
+for (i = 0; i < aic->num_outpins; i++) {
 sysbus_init_irq(sbd, &s->output_pins[i]);
 }
 }
@@ -391,6 +394,7 @@ static void aspeed_2700_intc_class_init(ObjectClass *klass, 
void *data)
 dc->desc = "ASPEED 2700 INTC Controller";
 aic->num_lines = 32;
 aic->num_inpins = 9;
+aic->num_outpins = 9;
 aic->mem_size = 0x4000;
 aic->reg_size = 0x808 >> 2;
 aic->reg_offset = 0x1000;
-- 
2.43.0




[PATCH v5 29/29] docs/specs: Add aspeed-intc

2025-03-06 Thread Jamin Lin via
Add AST2700 INTC design guidance and its block diagram.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 docs/specs/aspeed-intc.rst | 136 +
 docs/specs/index.rst   |   1 +
 2 files changed, 137 insertions(+)
 create mode 100644 docs/specs/aspeed-intc.rst

diff --git a/docs/specs/aspeed-intc.rst b/docs/specs/aspeed-intc.rst
new file mode 100644
index 00..9cefd7f37f
--- /dev/null
+++ b/docs/specs/aspeed-intc.rst
@@ -0,0 +1,136 @@
+===
+ASPEED Interrupt Controller
+===
+
+AST2700
+---
+There are a total of 480 interrupt sources in AST2700. Due to the limitation of
+interrupt numbers of processors, the interrupts are merged every 32 sources for
+interrupt numbers greater than 127.
+
+There are two levels of interrupt controllers, INTC (CPU Die) and INTCIO
+(I/O Die).
+
+Interrupt Mapping
+-
+- INTC: Handles interrupt sources 0 - 127 and integrates signals from INTCIO.
+- INTCIO: Handles interrupt sources 128 - 319 independently.
+
+QEMU Support
+
+Currently, only GIC 192 to 201 are supported, and their source interrupts are
+from INTCIO and connected to INTC at input pin 0 and output pins 0 to 9 for
+GIC 192-201.
+
+Design for GICINT 196
+-
+The orgate has interrupt sources ranging from 0 to 31, with its output pin
+connected to INTCIO "T0 GICINT_196". The output pin is then connected to INTC
+"GIC_192_201" at bit 4, and its bit 4 output pin is connected to GIC 196.
+
+INTC GIC_192_201 Output Pin Mapping
+---
+The design of INTC GIC_192_201 have 10 output pins, mapped as following:
+
+  
+Bit   GIC
+  
+0 192
+1 193
+2 194
+3 195
+4 196
+5 197
+6 198
+7 199
+8 200
+9 201
+  
+
+AST2700 A0
+--
+It has only one INTC controller, and currently, only GIC 128-136 is supported.
+To support both AST2700 A1 and AST2700 A0, there are 10 OR gates in the INTC,
+with gates 1 to 9 supporting GIC 128-136.
+
+Design for GICINT 132
+-
+The orgate has interrupt sources ranging from 0 to 31, with its output pin
+connected to INTC. The output pin is then connected to GIC 132.
+
+Block Diagram of GICINT 196 for AST2700 A1 and GICINT 132 for AST2700 A0
+
+
+.. code-block::
+
+   
|---|
+   |   AST2700 A1 Design   
|
+   |   To GICINT196
|
+   |   
|
+   |   ETH1|---||--|   
 |--|   |
+   |  >|0  || INTCIO   |   
 |  orgates[0]  |   |
+   |   ETH2|  4|   
orgates[0]-->|inpin[0]>outpin[0]|--->| 0|   |
+   |  >|1 5|   
orgates[1]-->|inpin[1]>outpin[1]|--->| 1|   |
+   |   ETH3|  6|   
orgates[2]-->|inpin[2]>outpin[2]|--->| 2|   |
+   |  >|219|   
orgates[3]-->|inpin[3]>outpin[3]|--->| 3  OR[0:9]   |-| |
+   |   UART0   | 
20|-->orgates[4]-->|inpin[4]>outpin[4]|--->| 4| 
| |
+   |  >|721|   
orgates[5]-->|inpin[5]>outpin[5]|--->| 5| | |
+   |   UART1   | 22|   
orgates[6]-->|inpin[6]>outpin[6]|--->| 6| | |
+   |  >|823|   
orgates[7]-->|inpin[7]>outpin[7]|--->| 7| | |
+   |   UART2   | 24|   
orgates[8]-->|inpin[8]>outpin[8]|--->| 8| | |
+   |  >|925|   
orgates[9]-->|inpin[9]>outpin[9]|--->| 9| | |
+   |   UART3   | 26||--|   
 |--| | |
+   |  -|10   27|   
  | |
+   |   UART5   | 28|   
  | |
+   |  >|11   29|   
  | |
+   |   UART6   |   |   
  | |
+   |  >|12   30| 
|---| |
+   |   UART7   | 31| | 
|
+

[PATCH v5 21/29] hw/arm/aspeed_ast27x0: Support two levels of INTC controllers for AST2700 A1

2025-03-06 Thread Jamin Lin via
The design of INTC controllers has significantly changed in AST2700 A1.

There are a total of 480 interrupt sources in AST2700 A1. For interrupt numbers
from 0 to 127, they can route directly to PSP, SSP, and TSP. Due to the
limitation of interrupt numbers of processors, the interrupts are merged every
32 sources for interrupt numbers greater than 127.

There are two levels of interrupt controllers, INTC(CPUD Die) and INTCIO
(IO Die). The interrupt sources of INTC are the interrupt numbers from INTC_0 to
INTC_127 and interrupts from INTCIO. The interrupt sources of INTCIO are the
interrupt numbers greater than INTC_127. INTC_IO controls the interrupts
INTC_128 to INTC_319 only.

Currently, only GIC 192 to 201 are supported, and their source interrupts are
from INTCIO and connected to INTC at input pin 0 and output pins 0 to 9 for
GIC 192-201.

The design of the orgates for GICINT 196 is as follows:
It has interrupt sources ranging from 0 to 31, with its output pin connected to
INTCIO "T0 GICINT_196". The output pin is then connected to INTC "GIC_192_201"
at bit 4, and its bit 4 output should be connected to GIC 196.
The design of INTC GIC_192_201 have 10 output pins, mapped as following:
Bit 0 -> GIC 192
Bit 1 -> GIC 193
Bit 2 -> GIC 194
Bit 3 -> GIC 195
Bit 4 -> GIC 196

To support both AST2700 A1 and A0, INTC input pins 1 to 9 and output pins
10 to 18 remain to support GIC 128-136, which source interrupts from INTC.
These will be removed if we decide not to support AST2700 A0 in the future.

|---|
|   AST2700 A1 Design   
|
|   To GICINT196
|
|   
|
|   ETH1|---||--|   
 |--|   |
|  >|0  || INTCIO   |   
 |  orgates[0]  |   |
|   ETH2|  4|   
orgates[0]-->|inpin[0]>outpin[0]|--->| 0|   |
|  >|1 5|   
orgates[1]-->|inpin[1]>outpin[1]|--->| 1|   |
|   ETH3|  6|   
orgates[2]-->|inpin[2]>outpin[2]|--->| 2|   |
|  >|219|   
orgates[3]-->|inpin[3]>outpin[3]|--->| 3  OR[0:9]   |-| |
|   UART0   | 
20|-->orgates[4]-->|inpin[4]>outpin[4]|--->| 4| 
| |
|  >|721|   
orgates[5]-->|inpin[5]>outpin[5]|--->| 5| | |
|   UART1   | 22|   
orgates[6]-->|inpin[6]>outpin[6]|--->| 6| | |
|  >|823|   
orgates[7]-->|inpin[7]>outpin[7]|--->| 7| | |
|   UART2   | 24|   
orgates[8]-->|inpin[8]>outpin[8]|--->| 8| | |
|  >|925|   
orgates[9]-->|inpin[9]>outpin[9]|--->| 9| | |
|   UART3   | 26||--|   
 |--| | |
|  -|10   27|   
  | |
|   UART5   | 28|   
  | |
|  >|11   29|   
  | |
|   UART6   |   |   
  | |
|  >|12   30| 
|---| |
|   UART7   | 31| | 
|
|  >|13 | | 
|
|   UART8   |  OR[0:31] | ||--| 
  |--|  |
|  >|14 | ||INTC  | 
  | GIC  |  |
|   UART9   |   | ||inpin[0:0]->outpin[0] 
|-->|192   |  |
|  >|15 | ||inpin[0:1]->outpin[1] 
|-->|193   |  |
|   UART10  |   | ||inpin[0:2]->outpin[2] 
|-->|194   |  |
|  >|16 | ||inpin[0:3]->outpin[3] 
|-->|195   |  |
|   UART11  |   | |--> |inpin[0:4]->outpin[4] 
|-->|196   |  |
|  >|17 |  |inpin[0:5]->outpin[5] 
|-->|197   |  |
|   UART12  |   |  |inpin[0:

[PATCH v5 08/29] hw/arm/aspeed: Rename IRQ table and machine name for AST2700 A0

2025-03-06 Thread Jamin Lin via
Currently, AST2700 SoC only supports A0. To support AST2700 A1, rename its IRQ
table and machine name.

To follow the machine deprecation rule, the initial machine "ast2700-evb" is
aliased to "ast2700a0-evb." In the future, we will alias "ast2700-evb" to new
SoCs, such as "ast2700a1-evb."

Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed.c | 9 +
 hw/arm/aspeed_ast27x0.c | 8 
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index c6c18596d6..18f7c450da 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1673,12 +1673,13 @@ static void ast2700_evb_i2c_init(AspeedMachineState 
*bmc)
 TYPE_TMP105, 0x4d);
 }
 
-static void aspeed_machine_ast2700_evb_class_init(ObjectClass *oc, void *data)
+static void aspeed_machine_ast2700a0_evb_class_init(ObjectClass *oc, void 
*data)
 {
 MachineClass *mc = MACHINE_CLASS(oc);
 AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
 
-mc->desc = "Aspeed AST2700 EVB (Cortex-A35)";
+mc->alias = "ast2700-evb";
+mc->desc = "Aspeed AST2700 A0 EVB (Cortex-A35)";
 amc->soc_name  = "ast2700-a0";
 amc->hw_strap1 = AST2700_EVB_HW_STRAP1;
 amc->hw_strap2 = AST2700_EVB_HW_STRAP2;
@@ -1817,9 +1818,9 @@ static const TypeInfo aspeed_machine_types[] = {
 .class_init = aspeed_minibmc_machine_ast1030_evb_class_init,
 #ifdef TARGET_AARCH64
 }, {
-.name  = MACHINE_TYPE_NAME("ast2700-evb"),
+.name  = MACHINE_TYPE_NAME("ast2700a0-evb"),
 .parent= TYPE_ASPEED_MACHINE,
-.class_init= aspeed_machine_ast2700_evb_class_init,
+.class_init= aspeed_machine_ast2700a0_evb_class_init,
 #endif
 }, {
 .name  = TYPE_ASPEED_MACHINE,
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index 10e1358166..de79724446 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -73,7 +73,7 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = {
 #define AST2700_MAX_IRQ 256
 
 /* Shared Peripheral Interrupt values below are offset by -32 from datasheet */
-static const int aspeed_soc_ast2700_irqmap[] = {
+static const int aspeed_soc_ast2700a0_irqmap[] = {
 [ASPEED_DEV_UART0] = 132,
 [ASPEED_DEV_UART1] = 132,
 [ASPEED_DEV_UART2] = 132,
@@ -762,7 +762,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, 
Error **errp)
 create_unimplemented_device("ast2700.io", 0x0, 0x400);
 }
 
-static void aspeed_soc_ast2700_class_init(ObjectClass *oc, void *data)
+static void aspeed_soc_ast2700a0_class_init(ObjectClass *oc, void *data)
 {
 static const char * const valid_cpu_types[] = {
 ARM_CPU_TYPE_NAME("cortex-a35"),
@@ -785,7 +785,7 @@ static void aspeed_soc_ast2700_class_init(ObjectClass *oc, 
void *data)
 sc->uarts_num= 13;
 sc->num_cpus = 4;
 sc->uarts_base   = ASPEED_DEV_UART0;
-sc->irqmap   = aspeed_soc_ast2700_irqmap;
+sc->irqmap   = aspeed_soc_ast2700a0_irqmap;
 sc->memmap   = aspeed_soc_ast2700_memmap;
 sc->get_irq  = aspeed_soc_ast2700_get_irq;
 }
@@ -800,7 +800,7 @@ static const TypeInfo aspeed_soc_ast27x0_types[] = {
 .name   = "ast2700-a0",
 .parent = TYPE_ASPEED27X0_SOC,
 .instance_init  = aspeed_soc_ast2700_init,
-.class_init = aspeed_soc_ast2700_class_init,
+.class_init = aspeed_soc_ast2700a0_class_init,
 },
 };
 
-- 
2.43.0




[PATCH v5 28/29] tests/functional/aspeed: Add test case for AST2700 A1

2025-03-06 Thread Jamin Lin via
Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 tests/functional/test_aarch64_aspeed.py | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/tests/functional/test_aarch64_aspeed.py 
b/tests/functional/test_aarch64_aspeed.py
index 8df6a97a28..c25c966278 100755
--- a/tests/functional/test_aarch64_aspeed.py
+++ b/tests/functional/test_aarch64_aspeed.py
@@ -31,6 +31,10 @@ def do_test_aarch64_aspeed_sdk_start(self, image):
 
'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.05/ast2700-a0-default-obmc.tar.gz',
 'cfbbd1cce72f2a3b73b9080c41eecdadebb7077fba4f7806d72ac99f3e84b74a')
 
+ASSET_SDK_V905_AST2700A1 = Asset(
+
'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.05/ast2700-default-obmc.tar.gz',
+'c1f4496aec06743c812a6e9a1a18d032f34d62f3ddb6956e924fef62aa2046a5')
+
 def start_ast2700_test(self, name):
 num_cpu = 4
 uboot_size = os.path.getsize(self.scratch_file(name,
@@ -95,6 +99,12 @@ def test_aarch64_ast2700_evb_sdk_v09_05(self):
 self.archive_extract(self.ASSET_SDK_V905_AST2700)
 self.start_ast2700_test('ast2700-a0-default')
 
+def test_aarch64_ast2700a1_evb_sdk_v09_05(self):
+self.set_machine('ast2700a1-evb')
+
+self.archive_extract(self.ASSET_SDK_V905_AST2700A1)
+self.start_ast2700_test('ast2700-default')
+
 
 if __name__ == '__main__':
 QemuSystemTest.main()
-- 
2.43.0




[PATCH v5 15/29] hw/intc/aspeed: Introduce IRQ handler function to reduce code duplication

2025-03-06 Thread Jamin Lin via
The behavior of the INTC set IRQ is almost identical between INTC and INTCIO.
To reduce duplicated code, introduce the "aspeed_intc_set_irq_handler" function
to handle both INTC and INTCIO IRQ behavior. No functional change.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/intc/aspeed_intc.c | 70 ---
 1 file changed, 39 insertions(+), 31 deletions(-)

diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 0ac59745f6..d0b91d6420 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -76,11 +76,45 @@ static void aspeed_intc_update(AspeedINTCState *s, int 
inpin_idx,
 qemu_set_irq(s->output_pins[outpin_idx], level);
 }
 
+static void aspeed_intc_set_irq_handler(AspeedINTCState *s,
+const AspeedINTCIRQ *intc_irq,
+uint32_t select)
+{
+const char *name = object_get_typename(OBJECT(s));
+uint32_t status_reg;
+int outpin_idx;
+int inpin_idx;
+
+status_reg = intc_irq->status_reg;
+outpin_idx = intc_irq->outpin_idx;
+inpin_idx = intc_irq->inpin_idx;
+
+if (s->mask[inpin_idx] || s->regs[status_reg]) {
+/*
+ * a. mask is not 0 means in ISR mode
+ * sources interrupt routine are executing.
+ * b. status register value is not 0 means previous
+ * source interrupt does not be executed, yet.
+ *
+ * save source interrupt to pending variable.
+ */
+s->pending[inpin_idx] |= select;
+trace_aspeed_intc_pending_irq(name, inpin_idx, s->pending[inpin_idx]);
+} else {
+/*
+ * notify firmware which source interrupt are coming
+ * by setting status register
+ */
+s->regs[status_reg] = select;
+trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
+  s->regs[status_reg]);
+aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
+}
+}
+
 /*
- * The address of GICINT128 to GICINT136 are from 0x1000 to 0x1804.
- * Utilize "address & 0x0f00" to get the irq and irq output pin index
- * The value of irq should be 0 to num_inpins.
- * The irq 0 indicates GICINT128, irq 1 indicates GICINT129 and so on.
+ * GICINT128 to GICINT136 map 1:1 to input and output IRQs 0 to 8.
+ * The value of input IRQ should be between 0 and the number of inputs.
  */
 static void aspeed_intc_set_irq(void *opaque, int irq, int level)
 {
@@ -88,20 +122,15 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
 const char *name = object_get_typename(OBJECT(s));
 const AspeedINTCIRQ *intc_irq;
-uint32_t status_reg;
 uint32_t select = 0;
 uint32_t enable;
-int outpin_idx;
 int inpin_idx;
 int i;
 
 assert(irq < aic->num_inpins);
 
 intc_irq = &aic->irq_table[irq];
-status_reg = intc_irq->status_reg;
-outpin_idx = intc_irq->outpin_idx;
 inpin_idx = intc_irq->inpin_idx;
-
 trace_aspeed_intc_set_irq(name, inpin_idx, level);
 enable = s->enable[inpin_idx];
 
@@ -122,28 +151,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 }
 
 trace_aspeed_intc_select(name, select);
-
-if (s->mask[inpin_idx] || s->regs[status_reg]) {
-/*
- * a. mask is not 0 means in ISR mode
- * sources interrupt routine are executing.
- * b. status register value is not 0 means previous
- * source interrupt does not be executed, yet.
- *
- * save source interrupt to pending variable.
- */
-s->pending[inpin_idx] |= select;
-trace_aspeed_intc_pending_irq(name, inpin_idx, s->pending[inpin_idx]);
-} else {
-/*
- * notify firmware which source interrupt are coming
- * by setting status register
- */
-s->regs[status_reg] = select;
-trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
-  s->regs[status_reg]);
-aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
-}
+aspeed_intc_set_irq_handler(s, intc_irq, select);
 }
 
 static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset,
-- 
2.43.0




[PATCH v5 02/29] hw/intc/aspeed: Rename status_addr and addr to status_reg and reg for clarity

2025-03-06 Thread Jamin Lin via
Rename the variables "status_addr" to "status_reg" and "addr" to "reg" because
they are used as register index. This change makes the code more appropriate
and improves readability.

Signed-off-by: Jamin Lin 
---
 hw/intc/aspeed_intc.c | 38 +++---
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 033b574c1e..465f41e4fd 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -60,7 +60,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 {
 AspeedINTCState *s = (AspeedINTCState *)opaque;
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
-uint32_t status_addr = GICINT_STATUS_BASE + ((0x100 * irq) >> 2);
+uint32_t status_reg = GICINT_STATUS_BASE + ((0x100 * irq) >> 2);
 uint32_t select = 0;
 uint32_t enable;
 int i;
@@ -92,7 +92,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
 
 trace_aspeed_intc_select(select);
 
-if (s->mask[irq] || s->regs[status_addr]) {
+if (s->mask[irq] || s->regs[status_reg]) {
 /*
  * a. mask is not 0 means in ISR mode
  * sources interrupt routine are executing.
@@ -108,8 +108,8 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int 
level)
  * notify firmware which source interrupt are coming
  * by setting status register
  */
-s->regs[status_addr] = select;
-trace_aspeed_intc_trigger_irq(irq, s->regs[status_addr]);
+s->regs[status_reg] = select;
+trace_aspeed_intc_trigger_irq(irq, s->regs[status_reg]);
 aspeed_intc_update(s, irq, 1);
 }
 }
@@ -117,17 +117,17 @@ static void aspeed_intc_set_irq(void *opaque, int irq, 
int level)
 static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int 
size)
 {
 AspeedINTCState *s = ASPEED_INTC(opaque);
-uint32_t addr = offset >> 2;
+uint32_t reg = offset >> 2;
 uint32_t value = 0;
 
-if (addr >= ASPEED_INTC_NR_REGS) {
+if (reg >= ASPEED_INTC_NR_REGS) {
 qemu_log_mask(LOG_GUEST_ERROR,
   "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
   __func__, offset);
 return 0;
 }
 
-value = s->regs[addr];
+value = s->regs[reg];
 trace_aspeed_intc_read(offset, size, value);
 
 return value;
@@ -138,12 +138,12 @@ static void aspeed_intc_write(void *opaque, hwaddr 
offset, uint64_t data,
 {
 AspeedINTCState *s = ASPEED_INTC(opaque);
 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
-uint32_t addr = offset >> 2;
+uint32_t reg = offset >> 2;
 uint32_t old_enable;
 uint32_t change;
 uint32_t irq;
 
-if (addr >= ASPEED_INTC_NR_REGS) {
+if (reg >= ASPEED_INTC_NR_REGS) {
 qemu_log_mask(LOG_GUEST_ERROR,
   "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
   __func__, offset);
@@ -152,7 +152,7 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, 
uint64_t data,
 
 trace_aspeed_intc_write(offset, size, data);
 
-switch (addr) {
+switch (reg) {
 case R_GICINT128_EN:
 case R_GICINT129_EN:
 case R_GICINT130_EN:
@@ -177,7 +177,7 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, 
uint64_t data,
 
 /* disable all source interrupt */
 if (!data && !s->enable[irq]) {
-s->regs[addr] = data;
+s->regs[reg] = data;
 return;
 }
 
@@ -187,12 +187,12 @@ static void aspeed_intc_write(void *opaque, hwaddr 
offset, uint64_t data,
 /* enable new source interrupt */
 if (old_enable != s->enable[irq]) {
 trace_aspeed_intc_enable(s->enable[irq]);
-s->regs[addr] = data;
+s->regs[reg] = data;
 return;
 }
 
 /* mask and unmask source interrupt */
-change = s->regs[addr] ^ data;
+change = s->regs[reg] ^ data;
 if (change & data) {
 s->mask[irq] &= ~change;
 trace_aspeed_intc_unmask(change, s->mask[irq]);
@@ -200,7 +200,7 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, 
uint64_t data,
 s->mask[irq] |= change;
 trace_aspeed_intc_mask(change, s->mask[irq]);
 }
-s->regs[addr] = data;
+s->regs[reg] = data;
 break;
 case R_GICINT128_STATUS:
 case R_GICINT129_STATUS:
@@ -220,7 +220,7 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, 
uint64_t data,
 }
 
 /* clear status */
-s->regs[addr] &= ~data;
+s->regs[reg] &= ~data;
 
 /*
  * These status registers are used for notify sources ISR are executed.
@@ -233,7 +233,7 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, 
uint64_t data,
 }
 
 /* All source ISR execution are done */
-if (!s->regs[addr]) {
+if (!s->regs[reg]) {
 trace_aspeed

Re: [PATCH 04/12] rust: timer: wrap QEMUTimer with Opaque<> and express pinning requirements

2025-03-06 Thread Zhao Liu
> While neither is good, a zeroed area of memory behaves better than an
> uninitialized one...  In particular, Drop calls timer_del() which works fine
> with a zeroed QEMUTimer.  With Opaque::uninit() you could have a crash just
> with
> 
> drop(Timer::new());

Good point.

> > // No compiling error or runtime panic
> > let t: MaybeUninit = MaybeUninit::zeroed();
> > let _t = unsafe { t.assume_init() };
> > 
> > Further more, I spent some time trying to figure out if MaybeUninit in
> > Opaque<> could help identify UB caused by uninitialized Timer, but I found
> > it doesn't work. :-(
> > 
> > // No compiling error or runtime panic
> > let mut v: UnsafeCell> = 
> > UnsafeCell::new(MaybeUninit::uninit());
> > let _v = unsafe { v.get_mut().assume_init() };
> > 
> > But when I adjust MaybeUninit as the outer wrapper, the UB check can
> > work:
> > 
> > // Runtime panic: Illegal instruction
> > let v: MaybeUninit> = MaybeUninit::uninit();
> > let _v = unsafe { v.assume_init() };
> > 
> > Compared with linux's Opaque, it also puts MaybeUninit on the outermost
> > layer.
> 
> Yes, I admit I just copied what Linux does. :)

Thanks for pointing this! I realized I referred the old code, since this
commit, linux puts the UnsafeCell to the outer layer [2]

[2]: 
https://github.com/torvalds/linux/commit/35cad617df2eeef8440a38e82bb2d81ae32ca50d

It seems that, at least from the Linux view, here the role of MaybeUninit
(as the cases I tested) is not a main concern, and Rust convention is
superior...

> > And there's another example:
> > 
> > https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html#method.raw_get
> > 
> > Emm, I guess now we have UnsafeCell> because interior
> > mutability is expected... but this layout breaks MaybeUninit's 
> > functionality.
> 
> Thanks for the example from the documentation!  Indeed it should be possible
> to do
> 
> /// Returns a raw mutable pointer to the opaque data.
> pub const fn as_mut_ptr(&self) -> *mut T {
> UnsafeCell::raw_get(self.value.as_ptr())
> }
> 
> /// Returns a raw pointer to the opaque data that can be passed to a
> /// C function as `void *`.
> pub const fn as_void_ptr(&self) -> *mut std::ffi::c_void {
> self.as_mut_ptr().cast()
> }
> 
> pub const fn raw_get(slot: *const Self) -> *mut T {
> // SAFETY: even if uninitialized, slot points to a MaybeUninit
> let slot = slot.cast::>>;
> UnsafeCell::raw_get(slot.as_ptr())
> }
> 
> if Opaque<> uses a MaybeUninit>.  I'm a bit worried of
> deviating from what Linux does though...

Thank you, this convertion to UnsafeCell> in Linux
history convinces me... I also agree that we should follow it for now :-).

Regards,
Zhao





Re: [RFC PATCH 04/18] qemu: Introduce 'qemu/legacy_binary_info.h'

2025-03-06 Thread Daniel P . Berrangé
On Thu, Mar 06, 2025 at 12:34:13PM +0100, Paolo Bonzini wrote:
> Il gio 6 mar 2025, 10:27 Philippe Mathieu-Daudé  ha
> scritto:
> 
> > This API is to allow refactoring code for heterogeneous emulation,
> > without changing user-facing behavior of current qemu-system binaries,
> > which I now consider as 'legacy'.
> >
> > Once all current restrictions removed, the new qemu-system-heterogeneous
> > binary is expected to run any combination of targets.
> >
> > qemu-system-$target will be a call to qemu-system-heterogeneous with
> > a restricted subset, possibly in the form of:
> >
> >   $ qemu-system-heterogeneous --target aarch64-softmmu
> >
> 
> Or just qemu-system I guess.
> 
> ^ equivalent of today's qemu-system-aarch64
> >
> > If you don't like 'qemu_legacy_binary_' prefix, I can use
> > 'qemu_single_binary_' instead.
> >
> 
> Still there is a problem with renaming binaries (both the "qemu-kvm" case
> and the good/bad case that Richard pointed out).

We could special case the '-kvm' suffix, because by its nature it
implies the current binary build target.

> 
> I think you should try creating two versions of system/arch_init.c, so that
> it has a separate implementation for heterogeneous vs. single-target
> binaries. Then you can keep separate linking steps for single-target
> binaries and you naturally get the right target info from either the
> target-specific arch_init-single.c, or the --target option for
> arch_init-multi.c.
> 
> (Is --target even necessary? As long as you have a way disambiguate
> same-named machines like -M virt, and have no default machine in the
> multi-target binary, you shouldn't need it).

If we did 'query-machines' on qemu-system-heterogeneous, it would
return all machines from all targets. To disambiguate naming there
are various options

  * The query-machines command would have to gain a new 'target'
field and we would have to document that uniqness is across
the tuple (name, target), not merely name. That's a semantic
change.

We would still need a way to express the 'target' when asking
to instantiate a machine

  * The query-machines command would have to gain a new 'target'
paramter so callers can restrict the data they receive back

We would still need a way to express the 'target' when asking
to instantiate a machine

  * Rename all machine types so they are '-'
The query-machines command doesn't change. Apps would have
to "parse" the machine name to see what 'target' each is
associated with, or we include an explicit 'target' field
in the returned data. Instianting a machine would not need
changing

  * Require --target CLI arg, meaning query-machines remains
unchanged, as does instantiating machines

Any other options ?

The last is the simplest option if we just make --target be defaulted
based on the binary name.

With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




[PATCH v5 19/29] hw/arm/aspeed_ast27x0.c Support AST2700 A1 GIC Interrupt Mapping

2025-03-06 Thread Jamin Lin via
Currently, these IRQ tables support from GIC 128 - 136 for AST2700 A0.
These IRQ tables can be reused for AST2700 A1 from GIC 192 - 197.
Updates the interrupt mapping to include support for AST2700 A1 by extending
the existing mappings to the new GIC range.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/arm/aspeed_ast27x0.c | 77 ++---
 1 file changed, 50 insertions(+), 27 deletions(-)

diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index 2d24361daa..343fe87921 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -120,21 +120,27 @@ static const int aspeed_soc_ast2700a0_irqmap[] = {
 };
 
 /* GICINT 128 */
-static const int aspeed_soc_ast2700_gic128_intcmap[] = {
+/* GICINT 192 */
+static const int ast2700_gic128_gic192_intcmap[] = {
 [ASPEED_DEV_LPC]   = 0,
 [ASPEED_DEV_IBT]   = 2,
 [ASPEED_DEV_KCS]   = 4,
 };
 
+/* GICINT 129 */
+/* GICINT 193 */
+
 /* GICINT 130 */
-static const int aspeed_soc_ast2700_gic130_intcmap[] = {
+/* GICINT 194 */
+static const int ast2700_gic130_gic194_intcmap[] = {
 [ASPEED_DEV_I2C]= 0,
 [ASPEED_DEV_ADC]= 16,
 [ASPEED_DEV_GPIO]   = 18,
 };
 
 /* GICINT 131 */
-static const int aspeed_soc_ast2700_gic131_intcmap[] = {
+/* GICINT 195 */
+static const int ast2700_gic131_gic195_intcmap[] = {
 [ASPEED_DEV_I3C]   = 0,
 [ASPEED_DEV_WDT]   = 16,
 [ASPEED_DEV_FMC]   = 25,
@@ -142,7 +148,8 @@ static const int aspeed_soc_ast2700_gic131_intcmap[] = {
 };
 
 /* GICINT 132 */
-static const int aspeed_soc_ast2700_gic132_intcmap[] = {
+/* GICINT 196 */
+static const int ast2700_gic132_gic196_intcmap[] = {
 [ASPEED_DEV_ETH1]  = 0,
 [ASPEED_DEV_ETH2]  = 1,
 [ASPEED_DEV_ETH3]  = 2,
@@ -161,24 +168,26 @@ static const int aspeed_soc_ast2700_gic132_intcmap[] = {
 };
 
 /* GICINT 133 */
-static const int aspeed_soc_ast2700_gic133_intcmap[] = {
+/* GICINT 197 */
+static const int ast2700_gic133_gic197_intcmap[] = {
 [ASPEED_DEV_SDHCI] = 1,
 [ASPEED_DEV_PECI]  = 4,
 };
 
 /* GICINT 128 ~ 136 */
+/* GICINT 192 ~ 201 */
 struct gic_intc_irq_info {
 int irq;
 const int *ptr;
 };
 
-static const struct gic_intc_irq_info aspeed_soc_ast2700_gic_intcmap[] = {
-{128,  aspeed_soc_ast2700_gic128_intcmap},
+static const struct gic_intc_irq_info ast2700_gic_intcmap[] = {
+{128,  ast2700_gic128_gic192_intcmap},
 {129,  NULL},
-{130,  aspeed_soc_ast2700_gic130_intcmap},
-{131,  aspeed_soc_ast2700_gic131_intcmap},
-{132,  aspeed_soc_ast2700_gic132_intcmap},
-{133,  aspeed_soc_ast2700_gic133_intcmap},
+{130,  ast2700_gic130_gic194_intcmap},
+{131,  ast2700_gic131_gic195_intcmap},
+{132,  ast2700_gic132_gic196_intcmap},
+{133,  ast2700_gic133_gic197_intcmap},
 {134,  NULL},
 {135,  NULL},
 {136,  NULL},
@@ -190,11 +199,11 @@ static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState 
*s, int dev)
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 int i;
 
-for (i = 0; i < ARRAY_SIZE(aspeed_soc_ast2700_gic_intcmap); i++) {
-if (sc->irqmap[dev] == aspeed_soc_ast2700_gic_intcmap[i].irq) {
-assert(aspeed_soc_ast2700_gic_intcmap[i].ptr);
+for (i = 0; i < ARRAY_SIZE(ast2700_gic_intcmap); i++) {
+if (sc->irqmap[dev] == ast2700_gic_intcmap[i].irq) {
+assert(ast2700_gic_intcmap[i].ptr);
 return qdev_get_gpio_in(DEVICE(&a->intc.orgates[i]),
-aspeed_soc_ast2700_gic_intcmap[i].ptr[dev]);
+ast2700_gic_intcmap[i].ptr[dev]);
 }
 }
 
@@ -208,16 +217,17 @@ static qemu_irq 
aspeed_soc_ast2700_get_irq_index(AspeedSoCState *s, int dev,
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 int i;
 
-for (i = 0; i < ARRAY_SIZE(aspeed_soc_ast2700_gic_intcmap); i++) {
-if (sc->irqmap[dev] == aspeed_soc_ast2700_gic_intcmap[i].irq) {
-assert(aspeed_soc_ast2700_gic_intcmap[i].ptr);
+for (i = 0; i < ARRAY_SIZE(ast2700_gic_intcmap); i++) {
+if (sc->irqmap[dev] == ast2700_gic_intcmap[i].irq) {
+assert(ast2700_gic_intcmap[i].ptr);
 return qdev_get_gpio_in(DEVICE(&a->intc.orgates[i]),
-aspeed_soc_ast2700_gic_intcmap[i].ptr[dev] + index);
+ast2700_gic_intcmap[i].ptr[dev] + index);
 }
 }
 
 /*
- * Invalid orgate index, device irq should be 128 to 136.
+ * Invalid OR gate index, device IRQ should be between 128 to 136
+ * and 192 to 201.
  */
 g_assert_not_reached();
 }
@@ -530,17 +540,18 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, 
Error **errp)
 aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc), 0,
 sc->memmap[ASPEED_DEV_INTC]);
 
-/* source orgates -> INTC */
+/* irq sources -> orgates -> INTC */
 for (i = 0; i < ic->num_inpins; i++) {
 qdev_connect_gpio_out(DEVICE(&a->intc.orga

[PATCH v5 09/29] hw/arm/aspeed_ast27x0: Sort the IRQ table by IRQ number

2025-03-06 Thread Jamin Lin via
To improve readability, sort the IRQ table by IRQ number.

Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/arm/aspeed_ast27x0.c | 50 -
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index de79724446..abd1f6b741 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -74,27 +74,13 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = {
 
 /* Shared Peripheral Interrupt values below are offset by -32 from datasheet */
 static const int aspeed_soc_ast2700a0_irqmap[] = {
-[ASPEED_DEV_UART0] = 132,
-[ASPEED_DEV_UART1] = 132,
-[ASPEED_DEV_UART2] = 132,
-[ASPEED_DEV_UART3] = 132,
-[ASPEED_DEV_UART4] = 8,
-[ASPEED_DEV_UART5] = 132,
-[ASPEED_DEV_UART6] = 132,
-[ASPEED_DEV_UART7] = 132,
-[ASPEED_DEV_UART8] = 132,
-[ASPEED_DEV_UART9] = 132,
-[ASPEED_DEV_UART10]= 132,
-[ASPEED_DEV_UART11]= 132,
-[ASPEED_DEV_UART12]= 132,
-[ASPEED_DEV_FMC]   = 131,
 [ASPEED_DEV_SDMC]  = 0,
-[ASPEED_DEV_SCU]   = 12,
-[ASPEED_DEV_ADC]   = 130,
+[ASPEED_DEV_HACE]  = 4,
 [ASPEED_DEV_XDMA]  = 5,
-[ASPEED_DEV_EMMC]  = 15,
-[ASPEED_DEV_GPIO]  = 130,
+[ASPEED_DEV_UART4] = 8,
+[ASPEED_DEV_SCU]   = 12,
 [ASPEED_DEV_RTC]   = 13,
+[ASPEED_DEV_EMMC]  = 15,
 [ASPEED_DEV_TIMER1]= 16,
 [ASPEED_DEV_TIMER2]= 17,
 [ASPEED_DEV_TIMER3]= 18,
@@ -103,19 +89,33 @@ static const int aspeed_soc_ast2700a0_irqmap[] = {
 [ASPEED_DEV_TIMER6]= 21,
 [ASPEED_DEV_TIMER7]= 22,
 [ASPEED_DEV_TIMER8]= 23,
-[ASPEED_DEV_WDT]   = 131,
-[ASPEED_DEV_PWM]   = 131,
+[ASPEED_DEV_DP]= 28,
 [ASPEED_DEV_LPC]   = 128,
 [ASPEED_DEV_IBT]   = 128,
+[ASPEED_DEV_KCS]   = 128,
+[ASPEED_DEV_ADC]   = 130,
+[ASPEED_DEV_GPIO]  = 130,
 [ASPEED_DEV_I2C]   = 130,
-[ASPEED_DEV_PECI]  = 133,
+[ASPEED_DEV_FMC]   = 131,
+[ASPEED_DEV_WDT]   = 131,
+[ASPEED_DEV_PWM]   = 131,
+[ASPEED_DEV_I3C]   = 131,
+[ASPEED_DEV_UART0] = 132,
+[ASPEED_DEV_UART1] = 132,
+[ASPEED_DEV_UART2] = 132,
+[ASPEED_DEV_UART3] = 132,
+[ASPEED_DEV_UART5] = 132,
+[ASPEED_DEV_UART6] = 132,
+[ASPEED_DEV_UART7] = 132,
+[ASPEED_DEV_UART8] = 132,
+[ASPEED_DEV_UART9] = 132,
+[ASPEED_DEV_UART10]= 132,
+[ASPEED_DEV_UART11]= 132,
+[ASPEED_DEV_UART12]= 132,
 [ASPEED_DEV_ETH1]  = 132,
 [ASPEED_DEV_ETH2]  = 132,
 [ASPEED_DEV_ETH3]  = 132,
-[ASPEED_DEV_HACE]  = 4,
-[ASPEED_DEV_KCS]   = 128,
-[ASPEED_DEV_DP]= 28,
-[ASPEED_DEV_I3C]   = 131,
+[ASPEED_DEV_PECI]  = 133,
 [ASPEED_DEV_SDHCI] = 133,
 };
 
-- 
2.43.0




  1   2   3   4   >