[PATCH] hw/dma/pl330: Add memory region to replace default address_space_memory

2021-08-12 Thread Wen, Jianxian
>From f780b0ee2ee36c562ab814915fff0e7217b25e63 Mon Sep 17 00:00:00 2001
From: Jianxian Wen 
Date: Tue, 3 Aug 2021 09:44:35 +0800
Subject: [PATCH] hw/dma/pl330: Add memory region to replace default
 address_space_memory

PL330 needs a memory region which can connect with SMMU translate IOMMU region 
to support SMMU.

Signed-off-by: Jianxian Wen 
---
 hw/arm/exynos4210.c  |  3 +++
 hw/arm/xilinx_zynq.c |  2 ++
 hw/dma/pl330.c   | 24 
 3 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index 5c7a51bba..af0e4820d 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -171,8 +171,11 @@ static DeviceState *pl330_create(uint32_t base, 
qemu_or_irq *orgate,
 SysBusDevice *busdev;
 DeviceState *dev;
 int i;
+MemoryRegion *sysmem = get_system_memory();

 dev = qdev_new("pl330");
+object_property_set_link(OBJECT(dev), "memory",
+OBJECT(sysmem), &error_fatal);
 qdev_prop_set_uint8(dev, "num_events", nevents);
 qdev_prop_set_uint8(dev, "num_chnls",  8);
 qdev_prop_set_uint8(dev, "num_periph_req",  nreq);
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 245af81bb..e0b3a73b9 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -312,6 +312,8 @@ static void zynq_init(MachineState *machine)
 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[39-IRQ_OFFSET]);

 dev = qdev_new("pl330");
+object_property_set_link(OBJECT(dev), "memory",
+OBJECT(address_space_mem), &error_fatal);
 qdev_prop_set_uint8(dev, "num_chnls",  8);
 qdev_prop_set_uint8(dev, "num_periph_req",  4);
 qdev_prop_set_uint8(dev, "num_events",  16);
diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c
index 944ba296b..06747ca0b 100644
--- a/hw/dma/pl330.c
+++ b/hw/dma/pl330.c
@@ -269,6 +269,9 @@ struct PL330State {
 uint8_t num_faulting;
 uint8_t periph_busy[PL330_PERIPH_NUM];

+/* Memory region that DMA operation access */
+MemoryRegion *mem_mr;
+AddressSpace mem_as;
 };

 #define TYPE_PL330 "pl330"
@@ -1108,7 +,8 @@ static inline const PL330InsnDesc 
*pl330_fetch_insn(PL330Chan *ch)
 uint8_t opcode;
 int i;

-dma_memory_read(&address_space_memory, ch->pc, &opcode, 1);
+address_space_read(&ch->parent->mem_as, ch->pc,
+MEMTXATTRS_UNSPECIFIED, &opcode, 1);
 for (i = 0; insn_desc[i].size; i++) {
 if ((opcode & insn_desc[i].opmask) == insn_desc[i].opcode) {
 return &insn_desc[i];
@@ -1122,7 +1126,8 @@ static inline void pl330_exec_insn(PL330Chan *ch, const 
PL330InsnDesc *insn)
 uint8_t buf[PL330_INSN_MAXSIZE];

 assert(insn->size <= PL330_INSN_MAXSIZE);
-dma_memory_read(&address_space_memory, ch->pc, buf, insn->size);
+address_space_read(&ch->parent->mem_as, ch->pc,
+MEMTXATTRS_UNSPECIFIED, buf, insn->size);
 insn->exec(ch, buf[0], &buf[1], insn->size - 1);
 }

@@ -1186,7 +1191,8 @@ static int pl330_exec_cycle(PL330Chan *channel)
 if (q != NULL && q->len <= pl330_fifo_num_free(&s->fifo)) {
 int len = q->len - (q->addr & (q->len - 1));

-dma_memory_read(&address_space_memory, q->addr, buf, len);
+address_space_read(&s->mem_as, q->addr,
+MEMTXATTRS_UNSPECIFIED, buf, len);
 trace_pl330_exec_cycle(q->addr, len);
 if (trace_event_get_state_backends(TRACE_PL330_HEXDUMP)) {
 pl330_hexdump(buf, len);
@@ -1217,7 +1223,8 @@ static int pl330_exec_cycle(PL330Chan *channel)
 fifo_res = pl330_fifo_get(&s->fifo, buf, len, q->tag);
 }
 if (fifo_res == PL330_FIFO_OK || q->z) {
-dma_memory_write(&address_space_memory, q->addr, buf, len);
+address_space_write(&s->mem_as, q->addr,
+MEMTXATTRS_UNSPECIFIED, buf, len);
 trace_pl330_exec_cycle(q->addr, len);
 if (trace_event_get_state_backends(TRACE_PL330_HEXDUMP)) {
 pl330_hexdump(buf, len);
@@ -1562,6 +1569,12 @@ static void pl330_realize(DeviceState *dev, Error **errp)
   "dma", PL330_IOMEM_SIZE);
 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);

+if (!s->mem_mr) {
+error_setg(errp, "'mem_mr' link is not set");
+return;
+}
+address_space_init(&s->mem_as, s->mem_mr, "pl330-memory");
+
 s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pl330_exec_cycle_timer, s);

 s->cfg[0] = (s->mgr_ns_at_rst ? 0x4 : 0) |
@@ -1656,6 +1669,9 @@ static Property pl330_properties[] = {
 DEFINE_PROP_UINT8("rd_q_dep", PL330State, rd_q_dep, 16),
 DEFINE_PROP_UINT16("data_buffer_dep", PL330State, data_buffer_dep, 256),

+DEFINE_PROP_LINK("memory", PL330State, mem_mr,
+ TYPE_MEMORY_REGION, MemoryRegion *),
+
 DEFINE_PROP_END_OF_LIST(),
 };

--


Re: [RFC PATCH v4 0/4] Add basic support for custom CSR

2021-08-12 Thread Alistair Francis
On Fri, Aug 6, 2021 at 3:59 AM Ruinland Chuan-Tzu Tsai
 wrote:
>
> From: Ruinland ChuanTzu Tsai 
>
> Dear all,
>
> In this patch, the implementation of custom CSR handling logic is introduced.
>
> If --enable-riscv-custom is set during configuration, custom CSR logic will be
> turned on. During CPU model initialization, setup_custom_csr() is invoked to
> register vendor-provided custom CSR opsets into a hash table.
> When accessing a CSR, in riscv_csrrw(), is_custom_csr() will be called to 
> check
> whether the encountering csrno is a custom CSR. If that's a custom one, a
> struct riscv_csr_operations will be returned and such CSR will be served
> accordingly.

Thanks for adding this. I don't think we need to expose it via the
config logic. A Kconfig option would be enough, it can be enabled by
default and users can choose to disable it if they really want.

>
> The performance slowdown could be easily tested with a simple program running
> on linux-user mode.
>
> /* test_csr.c */
> #include 
> #include 
> #include 
>
> int main (int ac, char *av[]) {
>struct  timeval start;
>struct  timeval end;
>gettimeofday(&start,NULL);
>unsigned int loop_n = 99 ;
>unsigned char i;
>unsigned char o;
>do {
>for(i=0; i<32; i++) {
>#if defined(FCSR)
>__asm__("csrw fcsr, %0;"::"r"(i));
>__asm__("csrr %0, fcsr;":"=r"(o));
>#elif defined(UITB)
>__asm__("csrw 0x800, %0;"::"r"(i));
>__asm__("csrr %0, 0x800;":"=r"(o));
>#endif
>}
>--loop_n;
>} while (loop_n > 0);
>gettimeofday(&end,NULL);
>unsigned long diff = 100 * 
> (end.tv_sec-start.tv_sec)+end.tv_usec-start.tv_usec;
>printf("%f\n", (double)(diff)/100);
>return 0;
> }
>
> $ riscv64-linux-gnu-gcc -static -DUITB ./test_csr.c -o ./u
> $ riscv64-linux-gnu-gcc -static -DFCSR ./test_csr.c -o ./f
>
> For a custom CSR, uitb, being accessed on andes-ax25 :
> $ ./build/qemu-riscv64 -cpu andes-ax25 ./u
> 4.283091
>
> For a stock CSR, fcsr, being accessed on andes-ax25:
> $ ./build/qemu-riscv64 ./f
> 3.875519
>
> For a custom CSR being accessed on stock rv64:
> $ ./build/qemu-riscv64 -cpu rv64 ./u
> Illegal instruction (core dumped)
> # This is expected to fail.
>
> Currently, the statics on my hands shows that :
> When the custom CSR handling mechanism is activated, we will suffer a 17% 
> slow-
> down on stock CSRs and the penalty of accessing to a custom CSR will be 
> another
> 7% more.

Thanks for testing this.

The critical number here is what is the impact for a CPU that doesn't
have the custom CSRs. So for example what impact does this have on the
rv64 accessing a standard CSR? We don't want to affect performance of
other CPUs. CPUs with custom CSRs can take the performance hit as it
adds a useful feature for them.

Alistair

>
> Cordially yours,
> Ruinland ChuanTzu Tsai
>
> Changes from v3 :
> * Adding options in configure and meson files to turn on/off custom CSR logic.
> * Adding unlikely() to check if custom_csr_map is set.
> * Moving any32 and any out of !(CONFIG_USER_ONLY) for enabling linux-user 
> mode.
> * Fix comment style, add missing license boilerplate.
>
>
> Ruinalnd ChuanTzu Tsai (4):
>   Adding basic custom/vendor CSR handling mechanism
>   Adding Andes AX25 and A25 CPU model
>   Enable custom CSR logic for Andes AX25 and A25
>   Add options to config/meson files for custom CSR
>
>  configure  |   6 ++
>  meson.build|   2 +
>  meson_options.txt  |   2 +
>  target/riscv/andes_cpu_bits.h  | 124 +
>  target/riscv/cpu.c |  51 +++
>  target/riscv/cpu.h |  33 ++-
>  target/riscv/cpu_bits.h|   4 +
>  target/riscv/csr.c |  83 ++---
>  target/riscv/csr_andes.inc.c   | 160 +
>  target/riscv/custom_cpu_bits.h |  12 +++
>  10 files changed, 462 insertions(+), 15 deletions(-)
>  create mode 100644 target/riscv/andes_cpu_bits.h
>  create mode 100644 target/riscv/csr_andes.inc.c
>  create mode 100644 target/riscv/custom_cpu_bits.h
>
> --
> 2.32.0
>
>



Re: [RFC PATCH v4 4/4] Enable custom CSR logic for Andes AX25 and A25

2021-08-12 Thread Alistair Francis
On Fri, Aug 6, 2021 at 11:06 PM Jessica Clarke  wrote:
>
> > From: Ruinalnd ChuanTzu Tsai 
> >
> > In this patch we enabled custom CSR logic for Andes AX25 and A25 logic.
> > Hence csr_andes.inc.c and andes_cpu_bits.h is added.
> >
> > Signed-off-by: Dylan Jhong 
> > ---
> >  target/riscv/andes_cpu_bits.h  | 124 +
> >  target/riscv/cpu.c |  12 +++
> >  target/riscv/csr.c |   2 +-
> >  target/riscv/csr_andes.inc.c   | 160 +
> >  target/riscv/custom_cpu_bits.h |   6 +-
> >  5 files changed, 302 insertions(+), 2 deletions(-)
> >  create mode 100644 target/riscv/andes_cpu_bits.h
> >  create mode 100644 target/riscv/csr_andes.inc.c
> >
> > diff --git a/target/riscv/andes_cpu_bits.h b/target/riscv/andes_cpu_bits.h
> > new file mode 100644
> > index 000..bd2b7d1
> > --- /dev/null
> > +++ b/target/riscv/andes_cpu_bits.h
> > @@ -0,0 +1,124 @@
> > +/*
> > + * Andes custom CSRs bit definitions
> > + *
> > + * Copyright (c) 2021 Andes Technology Corp.
> > + * SPDX-License-Identifier: GPL-2.0+
> > + */
> > +
> > +/* = Missing drafted/standard CSR definitions */
> > +/* Although TINFO is in official debug sepc, it's not in cpu_bits.h yet. */
> > +#define CSR_TINFO   0x7a4
> > +
> > +/* = AndeStar V5 machine mode CSRs = */
> > +/* Configuration Registers */
> > +#define CSR_MICM_CFG0xfc0
> > +#define CSR_MDCM_CFG0xfc1
> > +#define CSR_MMSC_CFG0xfc2
> > +#define CSR_MMSC_CFG2   0xfc3
> > +#define CSR_MVEC_CFG0xfc7
> > +
> > +/* Crash Debug CSRs */
> > +#define CSR_MCRASH_STATESAVE0xfc8
> > +#define CSR_MSTATUS_CRASHSAVE   0xfc9
> > +
> > +/* Memory CSRs */
> > +#define CSR_MILMB   0x7c0
> > +#define CSR_MDLMB   0x7c1
> > +#define CSR_MECC_CODE   0x7C2
> > +#define CSR_MNVEC   0x7c3
> > +#define CSR_MCACHE_CTL  0x7ca
> > +#define CSR_MCCTLBEGINADDR  0x7cb
> > +#define CSR_MCCTLCOMMAND0x7cc
> > +#define CSR_MCCTLDATA   0x7cd
> > +#define CSR_MPPIB   0x7f0
> > +#define CSR_MFIOB   0x7f1
> > +
> > +/* Hardware Stack Protection & Recording */
> > +#define CSR_MHSP_CTL0x7c6
> > +#define CSR_MSP_BOUND   0x7c7
> > +#define CSR_MSP_BASE0x7c8
> > +#define CSR_MXSTATUS0x7c4
> > +#define CSR_MDCAUSE 0x7c9
> > +#define CSR_MSLIDELEG   0x7d5
> > +#define CSR_MSAVESTATUS 0x7d6
> > +#define CSR_MSAVEEPC1   0x7d7
> > +#define CSR_MSAVECAUSE1 0x7d8
> > +#define CSR_MSAVEEPC2   0x7d9
> > +#define CSR_MSAVECAUSE2 0x7da
> > +#define CSR_MSAVEDCAUSE10x7db
> > +#define CSR_MSAVEDCAUSE20x7dc
> > +
> > +/* Control CSRs */
> > +#define CSR_MPFT_CTL0x7c5
> > +#define CSR_MMISC_CTL   0x7d0
> > +#define CSR_MCLK_CTL0x7df
> > +
> > +/* Counter related CSRs */
> > +#define CSR_MCOUNTERWEN 0x7ce
> > +#define CSR_MCOUNTERINTEN   0x7cf
> > +#define CSR_MCOUNTERMASK_M  0x7d1
> > +#define CSR_MCOUNTERMASK_S  0x7d2
> > +#define CSR_MCOUNTERMASK_U  0x7d3
> > +#define CSR_MCOUNTEROVF 0x7d4
> > +
> > +/* Enhanced CLIC CSRs */
> > +#define CSR_MIRQ_ENTRY  0x7ec
> > +#define CSR_MINTSEL_JAL 0x7ed
> > +#define CSR_PUSHMCAUSE  0x7ee
> > +#define CSR_PUSHMEPC0x7ef
> > +#define CSR_PUSHMXSTATUS0x7eb
> > +
> > +/* Andes Physical Memory Attribute(PMA) CSRs */
> > +#define CSR_PMACFG0 0xbc0
> > +#define CSR_PMACFG1 0xbc1
> > +#define CSR_PMACFG2 0xbc2
> > +#define CSR_PMACFG3 0xbc3
> > +#define CSR_PMAADDR00xbd0
> > +#define CSR_PMAADDR10xbd1
> > +#define CSR_PMAADDR20xbd2
> > +#define CSR_PMAADDR30xbd2
> > +#define CSR_PMAADDR40xbd4
> > +#define CSR_PMAADDR50xbd5
> > +#define CSR_PMAADDR60xbd6
> > +#define CSR_PMAADDR70xbd7
> > +#define CSR_PMAADDR80xbd8
> > +#define CSR_PMAADDR90xbd9
> > +#define CSR_PMAADDR10   0xbda
> > +#define CSR_PMAADDR11   0xbdb
> > +#define CSR_PMAADDR12   0xbdc
> > +#define CSR_PMAADDR13   0xbdd
> > +#define CSR_PMAADDR14   0xbde
> > +#define CSR_PMAADDR15   0xbdf
> > +
> > +/* = AndeStar V5 supervisor mode CSRs = */
> > +/* Supervisor trap registers */
> > +#define CSR_SLIE0x9c4
> > +#define CSR_SLIP0x9c5
> > +#define CSR_SDCAUSE 0x9c9
> > +
> > +/* Supervisor counter registers */
> > +#define CSR_SCOUNTERINTEN   0x9cf
> > +#define CSR_SCOUNTERMASK_M  0x9d1
> > +#define CSR_SCOUNTERMASK_S  0x9d2
> > +#define CSR_SCOUNTERMASK_U  0x9d3
> > +#define CSR_SCOUNTEROVF 0x9d4
> > +#define CSR_SCOUNTINHIBIT   0x9e0
> > +#define CSR_SHPMEVENT3  0x9e3
> > 

Re: [RFC PATCH v4 3/4] Adding Andes AX25 and A25 CPU model

2021-08-12 Thread Alistair Francis
On Fri, Aug 6, 2021 at 7:51 PM Bin Meng  wrote:
>
> On Fri, Aug 6, 2021 at 2:12 PM Ruinland Chuan-Tzu Tsa(蔡傳資)
>  wrote:
> >
> > Hi Bin and Alistair,
> >
> > >> Adding Andes AX25 and A25 CPU model into cpu.h and cpu.c without
> >
> > > The latest RISC-V core from Andes is AX45 and A45. Should we just
> > > support the latest one?
> >
> > Maybe we can have them all ?
> > AX25 and A25 is still in production, and we still have new clients using 
> > these CPU models.
> >
>
> Does AX25 and AX45 have any significant difference?

My hope is that the way the custom CSRs are implemented means that the
Andes CPUs can be self contained. That way QEMU can support whatever
Andes upstreams and it shouldn't add a maintenance burden on anyone
else.

Starting with a AX25 is fine with me. Whatever Andes is willing to
upstream, maintain and test works for me.

Alistair

>
> Regards,
> Bin
>



Re: [RFC PATCH v4 2/4] Adding basic custom/vendor CSR handling mechanism

2021-08-12 Thread Alistair Francis
On Fri, Aug 6, 2021 at 3:58 AM Ruinland Chuan-Tzu Tsai
 wrote:
>
> From: Ruinalnd ChuanTzu Tsai 
>
> For now we add a custom CSR handling mechanism to handle non-standard CSR read
> or write.
>
> The write_stub() and read_zero() are provided for quick placeholder usage if
> such CSRs' behavior are expected to fail-over in its user code.
>
> Signed-off-by: Dylan Jhong 
> ---
>  target/riscv/cpu.c | 23 ++
>  target/riscv/cpu.h | 31 -
>  target/riscv/cpu_bits.h|  4 ++
>  target/riscv/csr.c | 83 --
>  target/riscv/custom_cpu_bits.h |  8 
>  5 files changed, 134 insertions(+), 15 deletions(-)
>  create mode 100644 target/riscv/custom_cpu_bits.h
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 7401325..3a638b5 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -144,6 +144,29 @@ static void set_resetvec(CPURISCVState *env, 
> target_ulong resetvec)
>  #endif
>  }
>
> +#if defined(CONFIG_RISCV_CUSTOM)
> +static void setup_custom_csr(CPURISCVState *env,
> + riscv_custom_csr_operations csr_map_struct[]
> + ) {

Can you run `checkpatch.pl` on each patch? That will catch issues like this.


> +
> +env->custom_csr_map = g_hash_table_new_full(g_direct_hash, \
> +g_direct_equal, \
> +NULL, NULL);
> +
> +
> +int i;
> +for (i = 0; i < MAX_CUSTOM_CSR_NUM; i++) {
> +if (csr_map_struct[i].csrno != 0) {
> +g_hash_table_insert(env->custom_csr_map,
> +GINT_TO_POINTER(csr_map_struct[i].csrno),
> +&csr_map_struct[i].csr_opset);
> +} else {
> +break;
> +}
> +}
> +}
> +#endif
> +
>  static void riscv_any_cpu_init(Object *obj)
>  {
>  CPURISCVState *env = &RISCV_CPU(obj)->env;
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 0edb282..52df9bb 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -239,6 +239,16 @@ struct CPURISCVState {
>
>  /* Fields from here on are preserved across CPU reset. */
>  QEMUTimer *timer; /* Internal timer */
> +
> +/*
> + * The reason why we have an opset map for custom CSRs and a seperated
> + * storage map is that we might have heterogeneous architecture, in which
> + * different harts have different custom CSRs.
> + * Custom CSR opset map
> + */
> +GHashTable *custom_csr_map;
> +/* Custom CSR val holder */
> +void *custom_csr_val;
>  };
>
>  OBJECT_DECLARE_TYPE(RISCVCPU, RISCVCPUClass,
> @@ -485,17 +495,36 @@ typedef struct {
>  riscv_csr_op_fn op;
>  } riscv_csr_operations;
>
> +typedef struct {
> +int csrno;
> +riscv_csr_operations csr_opset;
> +} riscv_custom_csr_operations;
> +
> +/*
> + * The reason why we have an abstraction here is that : We could have CSR
> + * number M on hart A is an alias of CSR number N on hart B. So we make a
> + * CSR number to value address map.
> + */
> +typedef struct  {
> +int csrno;
> +target_ulong val;
> +} riscv_custom_csr_vals;

This should be a seperate patch.

> +
>  /* CSR function table constants */
>  enum {
> -CSR_TABLE_SIZE = 0x1000
> +CSR_TABLE_SIZE = 0x1000,
> +MAX_CUSTOM_CSR_NUM = 100
>  };
>
>  /* CSR function table */
> +extern int andes_custom_csr_size;
> +extern riscv_custom_csr_operations 
> andes_custom_csr_table[MAX_CUSTOM_CSR_NUM];

This should be a seperate patch

>  extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
>
>  void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops);
>  void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
>
> +
>  void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
>
>  #endif /* RISCV_CPU_H */
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index caf4599..de77242 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -593,3 +593,7 @@
>  #define MIE_SSIE   (1 << IRQ_S_SOFT)
>  #define MIE_USIE   (1 << IRQ_U_SOFT)
>  #endif
> +
> +#if defined(CONFIG_RISCV_CUSTOM)
> +#include "custom_cpu_bits.h"
> +#endif
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index fd2e636..1c4dc94 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -137,7 +137,8 @@ static int ctr32(CPURISCVState *env, int csrno)
>  return ctr(env, csrno);
>  }
>
> -#if !defined(CONFIG_USER_ONLY)
> +#pragma GCC diagnostic push
> +#pragma GCC diagnostic ignored "-Wunused-function"

Don't do this. It it is unused then just remove it.

>  static int any(CPURISCVState *env, int csrno)
>  {
>  return 0;
> @@ -152,6 +153,25 @@ static int any32(CPURISCVState *env, int csrno)
>  return any(env, csrno);
>
>  }
> +#pragma GCC diagnostic pop
> +
> +/* Machine Information Registers */
> +static int read_zero(CPURISCVState *env, int csrno, tar

Re: [PATCH] net/colo: check vnet_hdr_support flag when using virtio-net

2021-08-12 Thread Tao Xu

Hi Jason,

Do you have any comments on this patch?

Thank you!

On 8/6/2021 2:08 PM, Xu, Tao3 wrote:

When COLO use only one vnet_hdr_support parameter between
COLO network filter(filter-mirror, filter-redirector or
filter-rewriter and colo-compare, packet will not be parsed
correctly. Acquire network driver related to COLO, if it is
nirtio-net, check vnet_hdr_support flag of COLO network filter
and colo-compare.

Signed-off-by: Tao Xu 
Signed-off-by: Zhang Chen 
---
  net/colo-compare.c| 25 +
  net/colo.c| 20 
  net/colo.h|  4 
  net/filter-mirror.c   | 17 +
  net/filter-rewriter.c |  9 +
  5 files changed, 75 insertions(+)

diff --git a/net/colo-compare.c b/net/colo-compare.c
index b100e7b51f..bc1cc951c0 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -838,6 +838,23 @@ static int compare_chr_can_read(void *opaque)
  return COMPARE_READ_LEN_MAX;
  }
  
+/* check vnet_hdr_support flag through COLO filter modules */

+static int colo_vnet_driver_check(void *opaque, QemuOpts *opts, Error **errp)
+{
+const char *colo_obj_type;
+
+colo_obj_type = qemu_opt_get(opts, "qom-type");
+
+if (strcmp(colo_obj_type, "filter-mirror") == 0 ||
+strcmp(colo_obj_type, "filter-redirector") == 0 ||
+strcmp(colo_obj_type, "filter-rewriter") == 0) {
+if (qemu_opt_get(opts, "vnet_hdr_support")) {
+return 1;
+}
+}
+return 0;
+}
+
  /*
   * Called from the main thread on the primary for packets
   * arriving over the socket from the primary.
@@ -1289,6 +1306,14 @@ static void colo_compare_complete(UserCreatable *uc, 
Error **errp)
  return;
  }
  
+if (!s->vnet_hdr &&

+qemu_opts_foreach(qemu_find_opts("object"),
+  colo_vnet_driver_check, NULL, NULL)) {
+error_setg(errp, "colo compare needs 'vnet_hdr_support' "
+   "when colo filter modules work on virtio-net");
+return;
+}
+
  net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, s->vnet_hdr);
  net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, s->vnet_hdr);
  
diff --git a/net/colo.c b/net/colo.c

index 3a3e6e89a0..4a03780f45 100644
--- a/net/colo.c
+++ b/net/colo.c
@@ -243,3 +243,23 @@ bool connection_has_tracked(GHashTable 
*connection_track_table,
  
  return conn ? true : false;

  }
+
+/* check the network driver related to COLO, return 1 if it is virtio-net */
+int vnet_driver_check(void *opaque, QemuOpts *opts, Error **errp)
+{
+const char *driver_type, *netdev_from_driver;
+char *netdev_from_filter = (char *)opaque;
+
+driver_type = qemu_opt_get(opts, "driver");
+netdev_from_driver = qemu_opt_get(opts, "netdev");
+
+if (!driver_type || !netdev_from_driver || !netdev_from_filter) {
+return 0;
+}
+
+if (g_str_has_prefix(driver_type, "virtio-net") &&
+strcmp(netdev_from_driver, netdev_from_filter) == 0) {
+return 1;
+}
+return 0;
+}
diff --git a/net/colo.h b/net/colo.h
index d91cd245c4..d401fc76b6 100644
--- a/net/colo.h
+++ b/net/colo.h
@@ -18,6 +18,9 @@
  #include "qemu/jhash.h"
  #include "qemu/timer.h"
  #include "net/eth.h"
+#include "qemu/option.h"
+#include "qemu/option_int.h"
+#include "qemu/config-file.h"
  
  #define HASHTABLE_MAX_SIZE 16384
  
@@ -104,5 +107,6 @@ Packet *packet_new(const void *data, int size, int vnet_hdr_len);

  Packet *packet_new_nocopy(void *data, int size, int vnet_hdr_len);
  void packet_destroy(void *opaque, void *user_data);
  void packet_destroy_partial(void *opaque, void *user_data);
+int vnet_driver_check(void *opaque, QemuOpts *opts, Error **errp);
  
  #endif /* NET_COLO_H */

diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index f20240cc9f..b8b3f2fe1d 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -12,6 +12,7 @@
  #include "qemu/osdep.h"
  #include "net/filter.h"
  #include "net/net.h"
+#include "net/colo.h"
  #include "qapi/error.h"
  #include "qom/object.h"
  #include "qemu/main-loop.h"
@@ -224,6 +225,14 @@ static void filter_mirror_setup(NetFilterState *nf, Error 
**errp)
  return;
  }
  
+if (!s->vnet_hdr &&

+qemu_opts_foreach(qemu_find_opts("device"),
+ vnet_driver_check, nf->netdev_id, NULL)) {
+error_setg(errp, "filter mirror needs 'vnet_hdr_support' "
+   "when network driver is virtio-net");
+return;
+}
+
  qemu_chr_fe_init(&s->chr_out, chr, errp);
  }
  
@@ -252,6 +261,14 @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp)

  }
  }
  
+if (!s->vnet_hdr &&

+qemu_opts_foreach(qemu_find_opts("device"),
+ vnet_driver_check, nf->netdev_id, NULL)) {
+error_setg(errp, "filter redirector needs 'vnet_hdr_support' "
+   "when network driver is virtio-net");
+return;
+}
+
  net_

Re: [RFC PATCH v4 1/4] Add options to config/meson files for custom CSR

2021-08-12 Thread Alistair Francis
On Fri, Aug 6, 2021 at 11:54 PM Bin Meng  wrote:
>
> On Fri, Aug 6, 2021 at 8:58 PM Jessica Clarke  wrote:
> >
> > > On Fri, Aug 6, 2021 at 10:39 AM Bin Meng  wrote:
> > > >
> > > > On Fri, Aug 6, 2021 at 1:57 AM Ruinland Chuan-Tzu Tsai
> > > >  wrote:
> > > > >
> > > > > From: Ruinland ChuanTzu Tsai 
> > > > >
> > > > > Adding option `riscv_custom` to configure script, meson.build and
> > > > > meson_options.txt so as to toggle custom CSR and will-be-upstreamed 
> > > > > custom
> > > > > instructions handling logic.
> > > > >
> > > > > Signed-off-by: Dylan Jhong 
> > > > > ---
> > > > >  configure | 6 ++
> > > > >  meson.build   | 2 ++
> > > > >  meson_options.txt | 2 ++
> > > > >  3 files changed, 10 insertions(+)
> > > > >
> > > >
> > > > This sounds like unnecessary to bring such a config option to the meson 
> > > > level.
> > > >
> > > > I believe a Kconfig option should just be fine.
> > >
> > > +Alistair
> >
> > I don’t see why this is even a config option. If you request a vendor’s
> > CPU you should get any custom CSRs defined for that vendor’s CPU. If
> > you don’t you don’t. This should be purely a run-time thing, no?
>
> In a generic use case where we build all RISC-V machines into one
> qemu-system-riscv{32,64} executable this makes no difference. The
> Kconfig option will be turned on if any one of the machines requires
> it. It only gets benefits when we build a QEMU executable on a
> per-machine basis.

I agree with Bin that this could be a Kconfig option, that is selected
when a vendor CPU is enabled.

It also doesn't have to be a config and could just be built all the
time. I don't see much of an advantage in allowing it to be disabled,
it's just another thing we would need to test. Maybe is a user was
just interested in the virt machine/KVM they could disable it to avoid
any overhead.

Alistair

>
> Regards,
> Bin
>



Re: [PATCH for-6.2 25/25] arm: Remove system_clock_scale global

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 7:52 PM Peter Maydell  wrote:
>
> All the devices that used to use system_clock_scale have now been
> converted to use Clock inputs instead, so the global is no longer
> needed; remove it and all the code that sets it.
>
> Signed-off-by: Peter Maydell 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  include/hw/timer/armv7m_systick.h | 22 --
>  hw/arm/armsse.c   | 17 +
>  hw/arm/mps2.c |  2 --
>  hw/arm/msf2-soc.c |  2 --
>  hw/arm/netduino2.c|  2 --
>  hw/arm/netduinoplus2.c|  2 --
>  hw/arm/nrf51_soc.c|  2 --
>  hw/arm/stellaris.c|  7 ---
>  hw/arm/stm32vldiscovery.c |  2 --
>  hw/timer/armv7m_systick.c |  2 --
>  10 files changed, 5 insertions(+), 55 deletions(-)
>
> diff --git a/include/hw/timer/armv7m_systick.h 
> b/include/hw/timer/armv7m_systick.h
> index 38adf8d274e..ee09b138810 100644
> --- a/include/hw/timer/armv7m_systick.h
> +++ b/include/hw/timer/armv7m_systick.h
> @@ -47,26 +47,4 @@ struct SysTickState {
>  Clock *cpuclk;
>  };
>
> -/*
> - * Multiplication factor to convert from system clock ticks to qemu timer
> - * ticks. This should be set (by board code, usually) to a value
> - * equal to NANOSECONDS_PER_SECOND / frq, where frq is the clock frequency
> - * in Hz of the CPU.
> - *
> - * This value is used by the systick device when it is running in
> - * its "use the CPU clock" mode (ie when SYST_CSR.CLKSOURCE == 1) to
> - * set how fast the timer should tick.
> - *
> - * TODO: we should refactor this so that rather than using a global
> - * we use a device property or something similar. This is complicated
> - * because (a) the property would need to be plumbed through from the
> - * board code down through various layers to the systick device
> - * and (b) the property needs to be modifiable after realize, because
> - * the stellaris board uses this to implement the behaviour where the
> - * guest can reprogram the PLL registers to downclock the CPU, and the
> - * systick device needs to react accordingly. Possibly this should
> - * be deferred until we have a good API for modelling clock trees.
> - */
> -extern int system_clock_scale;
> -
>  #endif
> diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
> index 70b52c3d4b9..aecdeb9815a 100644
> --- a/hw/arm/armsse.c
> +++ b/hw/arm/armsse.c
> @@ -689,17 +689,6 @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s)
>  qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
>  }
>
> -static void armsse_mainclk_update(void *opaque, ClockEvent event)
> -{
> -ARMSSE *s = ARM_SSE(opaque);
> -
> -/*
> - * Set system_clock_scale from our Clock input; this is what
> - * controls the tick rate of the CPU SysTick timer.
> - */
> -system_clock_scale = clock_ticks_to_ns(s->mainclk, 1);
> -}
> -
>  static void armsse_init(Object *obj)
>  {
>  ARMSSE *s = ARM_SSE(obj);
> @@ -711,8 +700,7 @@ static void armsse_init(Object *obj)
>  assert(info->sram_banks <= MAX_SRAM_BANKS);
>  assert(info->num_cpus <= SSE_MAX_CPUS);
>
> -s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK",
> -armsse_mainclk_update, s, ClockUpdate);
> +s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK", NULL, NULL, 0);
>  s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL, 0);
>
>  memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
> @@ -1654,9 +1642,6 @@ static void armsse_realize(DeviceState *dev, Error 
> **errp)
>   * devices in the ARMSSE.
>   */
>  sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
> -
> -/* Set initial system_clock_scale from MAINCLK */
> -armsse_mainclk_update(s, ClockUpdate);
>  }
>
>  static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
> diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
> index 3671f49ad7b..4634aa1a1ca 100644
> --- a/hw/arm/mps2.c
> +++ b/hw/arm/mps2.c
> @@ -439,8 +439,6 @@ static void mps2_common_init(MachineState *machine)
>   qdev_get_gpio_in(armv7m,
>mmc->fpga_type == FPGA_AN511 ? 47 : 13));
>
> -system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
> -
>  armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
> 0x40);
>  }
> diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
> index dbc6d936a76..b5fe9f364d5 100644
> --- a/hw/arm/msf2-soc.c
> +++ b/hw/arm/msf2-soc.c
> @@ -144,8 +144,6 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, 
> Error **errp)
>  return;
>  }
>
> -system_clock_scale = clock_ticks_to_ns(s->m3clk, 1);
> -
>  for (i = 0; i < MSF2_NUM_UARTS; i++) {
>  if (serial_hd(i)) {
>  serial_mm_init(get_system_memory(), uart_addr[i], 2,
> diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c
> index b5c0ba23ee5..3365da11bf7 100644
> --- a/h

[RFC] vfio/migration: reduce the msix virq setup cost in resume phase

2021-08-12 Thread Longpeng(Mike)
In migration resume phase, all unmasked msix vectors need to be
setup when load the VF state. However, the setup operation would
takes longer if the VF has more unmasked vectors.

In our case, the VF has 65 vectors and each one spend 0.8ms on
setup operation (vfio_add_kvm_msi_virq -> kvm_irqchip_commit_routes),
the total cost of the VF is more than 40ms. Even worse, the VM has
8 VFs, so the downtime increase more than 320ms.

vfio_pci_load_config
  vfio_msix_enable
msix_set_vector_notifiers
  for (vector = 0; vector < dev->msix_entries_nr; vector++) {
vfio_msix_vector_do_use
  vfio_add_kvm_msi_virq
kvm_irqchip_commit_routes <-- 0.8ms
  }

Originaly, We tried to batch all routes and just commit once
outside the loop, but it's not easy to fallback to qemu interrupt
if someone fails.

So this patch trys to defer the KVM interrupt setup, the unmasked
vector will use qemu interrupt as default and switch to kvm interrupt
once it fires.

Signed-off-by: Longpeng(Mike) 
---
 hw/vfio/pci.c | 39 ++-
 hw/vfio/pci.h |  2 ++
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index e1ea1d8..dd35170 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -47,6 +47,8 @@
 
 static void vfio_disable_interrupts(VFIOPCIDevice *vdev);
 static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled);
+static void vfio_add_kvm_msix_virq(VFIOPCIDevice *vdev,
+   VFIOMSIVector *vector, int nr);
 
 /*
  * Disabling BAR mmaping can be slow, but toggling it around INTx can
@@ -347,6 +349,11 @@ static void vfio_msi_interrupt(void *opaque)
 get_msg = msix_get_message;
 notify = msix_notify;
 
+if (unlikely(vector->need_switch)) {
+vfio_add_kvm_msix_virq(vdev, vector, nr);
+vector->need_switch = false;
+}
+
 /* A masked vector firing needs to use the PBA, enable it */
 if (msix_is_masked(&vdev->pdev, nr)) {
 set_bit(nr, vdev->msix->pending);
@@ -438,6 +445,25 @@ static void vfio_add_kvm_msi_virq(VFIOPCIDevice *vdev, 
VFIOMSIVector *vector,
 vector->virq = virq;
 }
 
+static void
+vfio_add_kvm_msix_virq(VFIOPCIDevice *vdev, VFIOMSIVector *vector, int nr)
+{
+Error *err = NULL;
+int fd;
+
+vfio_add_kvm_msi_virq(vdev, vector, nr, true);
+if (vector->virq < 0) {
+return;
+}
+
+fd = event_notifier_get_fd(&vector->kvm_interrupt);
+if (vfio_set_irq_signaling(&vdev->vbasedev,
+   VFIO_PCI_MSIX_IRQ_INDEX, nr,
+   VFIO_IRQ_SET_ACTION_TRIGGER, fd, &err)) {
+error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
+}
+}
+
 static void vfio_remove_kvm_msi_virq(VFIOMSIVector *vector)
 {
 kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, &vector->kvm_interrupt,
@@ -490,7 +516,11 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, 
unsigned int nr,
 }
 } else {
 if (msg) {
-vfio_add_kvm_msi_virq(vdev, vector, nr, true);
+if (unlikely(vdev->defer_set_virq)) {
+vector->need_switch = true;
+} else {
+vfio_add_kvm_msi_virq(vdev, vector, nr, true);
+}
 }
 }
 
@@ -566,6 +596,11 @@ static void vfio_msix_vector_release(PCIDevice *pdev, 
unsigned int nr)
 }
 }
 
+static void inline vfio_msix_defer_set_virq(VFIOPCIDevice *vdev, bool defer)
+{
+vdev->defer_set_virq = defer;
+}
+
 static void vfio_msix_enable(VFIOPCIDevice *vdev)
 {
 PCIDevice *pdev = &vdev->pdev;
@@ -2466,7 +2501,9 @@ static int vfio_pci_load_config(VFIODevice *vbasedev, 
QEMUFile *f)
 if (msi_enabled(pdev)) {
 vfio_msi_enable(vdev);
 } else if (msix_enabled(pdev)) {
+vfio_msix_defer_set_virq(vdev, true);
 vfio_msix_enable(vdev);
+vfio_msix_defer_set_virq(vdev, false);
 }
 
 return ret;
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index 6477751..846ae85 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -95,6 +95,7 @@ typedef struct VFIOMSIVector {
 struct VFIOPCIDevice *vdev; /* back pointer to device */
 int virq;
 bool use;
+bool need_switch; /* switch to kvm interrupt ? */
 } VFIOMSIVector;
 
 enum {
@@ -171,6 +172,7 @@ struct VFIOPCIDevice {
 bool no_kvm_ioeventfd;
 bool no_vfio_ioeventfd;
 bool enable_ramfb;
+bool defer_set_virq;
 VFIODisplay *dpy;
 Notifier irqchip_change_notifier;
 };
-- 
1.8.3.1




[Question] fuzz: double-fetches in a memory region map session

2021-08-12 Thread Li Qiuhao
Hi Alex,

Recently I was reading the DMA call-back functions in the fuzzer. It seems
fuzz_dma_read_cb() is inserted into flatview_read_continue() and
address_space_map() to make the host read changed content between different
DMA actions.

My question is about address_space_map() -- How do we emulate double-fetch
bugs in the same map/unmap session? For example:


  FOO *guest_foo = (FOO *) address_space_map(as, ...);
  
  uint64_t size = guest_foo->size;// first fetch
  if size > limit
goto error;
  
  /* time window */
  
  memcpy(dest, src, guest_foo->size); // double-fetch ?
  
  error:
  address_space_unmap(as, guest_foo, ...)


Thanks,
  Qiuhao Li


[PULL 1/1] Hexagon (disas/hexagon.c) fix memory leak for early exit cases

2021-08-12 Thread Taylor Simpson
Don't allocate the string until error conditions have been checked

Fixes: a00cfed0e ("Hexagon (disas) disassembler")
Eliminate Coverity CID 1460121 (Resource leak)

Reviewed-by: Peter Maydell 
Reviewed-by: Philippe Mathieu-Daud? 
Signed-off-by: Taylor Simpson 
---
 disas/hexagon.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/disas/hexagon.c b/disas/hexagon.c
index 3c24e2a..c1a4ffc 100644
--- a/disas/hexagon.c
+++ b/disas/hexagon.c
@@ -33,7 +33,7 @@ int print_insn_hexagon(bfd_vma memaddr, struct 
disassemble_info *info)
 {
 uint32_t words[PACKET_WORDS_MAX];
 bool found_end = false;
-GString *buf = g_string_sized_new(PACKET_BUFFER_LEN);
+GString *buf;
 int i, len;
 
 for (i = 0; i < PACKET_WORDS_MAX && !found_end; i++) {
@@ -57,6 +57,7 @@ int print_insn_hexagon(bfd_vma memaddr, struct 
disassemble_info *info)
 return PACKET_WORDS_MAX * sizeof(uint32_t);
 }
 
+buf = g_string_sized_new(PACKET_BUFFER_LEN);
 len = disassemble_hexagon(words, i, memaddr, buf);
 (*info->fprintf_func)(info->stream, "%s", buf->str);
 g_string_free(buf, true);
-- 
2.7.4



[PULL 0/1] Hexagon (disas/hexagon) fix memory leak for early exit

2021-08-12 Thread Taylor Simpson
The following changes since commit 703e8cd6189cf699c8d5c094bc68b5f3afa6ad71:

  Update version for v6.1.0-rc3 release (2021-08-10 19:08:09 +0100)

are available in the git repository at:

  https://github.com/quic/qemu tags/pull-hex-20210812

for you to fetch changes up to a7686d5d8528469b596e98eff098a5d3f8328fb3:

  Hexagon (disas/hexagon.c) fix memory leak for early exit cases (2021-08-12 
09:06:05 -0500)



Don't allocate the string until error conditions have been checked

Fixes: a00cfed0e ("Hexagon (disas) disassembler")
Eliminate Coverity CID 1460121 (Resource leak)


Taylor Simpson (1):
  Hexagon (disas/hexagon.c) fix memory leak for early exit cases

 disas/hexagon.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)


[PATCH for-6.2 v5 13/14] machine: Split out the smp parsing code

2021-08-12 Thread Yanan Wang
We are going to introduce an unit test for the parser smp_parse()
in hw/core/machine.c, but now machine.c is only built in softmmu.

In order to solve the build dependency on the smp parsing code and
avoid building unrelated stuff for the unit tests, move the related
code from machine.c into a new common file, i.e., machine-smp.c.

Signed-off-by: Yanan Wang 
Reviewed-by: Andrew Jones 
---
 MAINTAINERS   |   1 +
 hw/core/machine-smp.c | 200 ++
 hw/core/machine.c | 178 -
 hw/core/meson.build   |   1 +
 include/hw/boards.h   |   1 +
 5 files changed, 203 insertions(+), 178 deletions(-)
 create mode 100644 hw/core/machine-smp.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 37b1a8e442..5510aaddfd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1629,6 +1629,7 @@ F: cpu.c
 F: hw/core/cpu.c
 F: hw/core/machine-qmp-cmds.c
 F: hw/core/machine.c
+F: hw/core/machine-smp.c
 F: hw/core/null-machine.c
 F: hw/core/numa.c
 F: hw/cpu/cluster.c
diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c
new file mode 100644
index 00..8fa6b71885
--- /dev/null
+++ b/hw/core/machine-smp.c
@@ -0,0 +1,200 @@
+/*
+ * QEMU Machine (related to SMP)
+ *
+ * Copyright (c) 2021 Huawei Technologies Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "hw/boards.h"
+#include "qapi/error.h"
+#include "qemu/cutils.h"
+
+static char *cpu_topology_hierarchy(MachineState *ms)
+{
+MachineClass *mc = MACHINE_GET_CLASS(ms);
+SMPCompatProps *smp_props = &mc->smp_props;
+char topo_msg[256] = "";
+
+/*
+ * Topology members should be ordered from the largest to the smallest.
+ * Concept of sockets/cores/threads is supported by default and will be
+ * reported in the hierarchy. Unsupported members will not be reported.
+ */
+g_autofree char *sockets_msg = g_strdup_printf(
+" * sockets (%u)", ms->smp.sockets);
+pstrcat(topo_msg, sizeof(topo_msg), sockets_msg);
+
+if (smp_props->dies_supported) {
+g_autofree char *dies_msg = g_strdup_printf(
+" * dies (%u)", ms->smp.dies);
+pstrcat(topo_msg, sizeof(topo_msg), dies_msg);
+}
+
+g_autofree char *cores_msg = g_strdup_printf(
+" * cores (%u)", ms->smp.cores);
+pstrcat(topo_msg, sizeof(topo_msg), cores_msg);
+
+g_autofree char *threads_msg = g_strdup_printf(
+" * threads (%u)", ms->smp.threads);
+pstrcat(topo_msg, sizeof(topo_msg), threads_msg);
+
+return g_strdup_printf("%s", topo_msg + 3);
+}
+
+/*
+ * smp_parse - Generic function used to parse the given SMP configuration
+ *
+ * If not supported by the machine, a topology parameter must be omitted
+ * or specified equal to 1. Concept of sockets/cores/threads is supported
+ * by default. Unsupported members will not be reported in the topology
+ * hierarchy message.
+ *
+ * For compatibility, omitted arch-specific members (e.g. dies) will not
+ * be computed, but will directly default to 1 instead. This logic should
+ * also apply to future introduced ones.
+ *
+ * Omitted arch-neutral parameters (i.e. cpus/sockets/cores/threads/maxcpus)
+ * will be computed based on the provided ones. When both maxcpus and cpus
+ * are omitted, maxcpus will be computed from the given parameters and cpus
+ * will be set equal to maxcpus. When only one of maxcpus and cpus is given
+ * then the omitted one will be set to its given counterpart's value.
+ * Both maxcpus and cpus may be specified, but maxcpus must be equal to or
+ * greater than cpus.
+ *
+ * In calculation of omitted sockets/cores/threads, we prefer sockets over
+ * cores over threads before 6.2, while preferring cores over sockets over
+ * threads since 6.2.
+ */
+void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
+{
+MachineClass *mc = MACHINE_GET_CLASS(ms);
+unsigned cpus= config->has_cpus ? config->cpus : 0;
+unsigned sockets = config->has_sockets ? config->sockets : 0;
+unsigned dies= config->has_dies ? config->dies : 0;
+unsigned cores   = config->has_cores ? config->cores : 0;
+unsigned threads = config->has_threads ? config->threads : 0;
+unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
+
+/*
+ * A specified topology parameter must be greater than zero,

[PATCH for-6.2 v5 12/14] machine: Put all sanity-check in the generic SMP parser

2021-08-12 Thread Yanan Wang
Put both sanity-check of the input SMP configuration and sanity-check
of the output SMP configuration uniformly in the generic parser. Then
machine_set_smp() will become cleaner, also all the invalid scenarios
can be tested only by calling the parser.

Signed-off-by: Yanan Wang 
Reviewed-by: Andrew Jones 
Reviewed-by: Pankaj Gupta 
---
 hw/core/machine.c | 63 +++
 1 file changed, 31 insertions(+), 32 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 7e1dd623ae..653d352cf6 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -813,6 +813,20 @@ static void smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **errp)
 unsigned threads = config->has_threads ? config->threads : 0;
 unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
 
+/*
+ * A specified topology parameter must be greater than zero,
+ * explicit configuration like "cpus=0" is not allowed.
+ */
+if ((config->has_cpus && config->cpus == 0) ||
+(config->has_sockets && config->sockets == 0) ||
+(config->has_dies && config->dies == 0) ||
+(config->has_cores && config->cores == 0) ||
+(config->has_threads && config->threads == 0) ||
+(config->has_maxcpus && config->maxcpus == 0)) {
+error_setg(errp, "CPU topology parameters must be greater than zero");
+return;
+}
+
 /*
  * If not supported by the machine, a topology parameter must be
  * omitted or specified equal to 1.
@@ -892,6 +906,22 @@ static void smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **errp)
topo_msg, maxcpus, cpus);
 return;
 }
+
+if (ms->smp.cpus < mc->min_cpus) {
+error_setg(errp, "Invalid SMP CPUs %d. The min CPUs "
+   "supported by machine '%s' is %d",
+   ms->smp.cpus,
+   mc->name, mc->min_cpus);
+return;
+}
+
+if (ms->smp.max_cpus > mc->max_cpus) {
+error_setg(errp, "Invalid SMP CPUs %d. The max CPUs "
+   "supported by machine '%s' is %d",
+   ms->smp.max_cpus,
+   mc->name, mc->max_cpus);
+return;
+}
 }
 
 static void machine_get_smp(Object *obj, Visitor *v, const char *name,
@@ -914,7 +944,6 @@ static void machine_get_smp(Object *obj, Visitor *v, const 
char *name,
 static void machine_set_smp(Object *obj, Visitor *v, const char *name,
 void *opaque, Error **errp)
 {
-MachineClass *mc = MACHINE_GET_CLASS(obj);
 MachineState *ms = MACHINE(obj);
 SMPConfiguration *config;
 ERRP_GUARD();
@@ -923,40 +952,10 @@ static void machine_set_smp(Object *obj, Visitor *v, 
const char *name,
 return;
 }
 
-/*
- * The CPU topology parameters must be specified greater than zero or
- * just omitted, explicit configuration like "cpus=0" is not allowed.
- */
-if ((config->has_cpus && config->cpus == 0) ||
-(config->has_sockets && config->sockets == 0) ||
-(config->has_dies && config->dies == 0) ||
-(config->has_cores && config->cores == 0) ||
-(config->has_threads && config->threads == 0) ||
-(config->has_maxcpus && config->maxcpus == 0)) {
-error_setg(errp, "CPU topology parameters must be greater than zero");
-goto out_free;
-}
-
 smp_parse(ms, config, errp);
 if (errp) {
-goto out_free;
+qapi_free_SMPConfiguration(config);
 }
-
-/* sanity-check smp_cpus and max_cpus against mc */
-if (ms->smp.cpus < mc->min_cpus) {
-error_setg(errp, "Invalid SMP CPUs %d. The min CPUs "
-   "supported by machine '%s' is %d",
-   ms->smp.cpus,
-   mc->name, mc->min_cpus);
-} else if (ms->smp.max_cpus > mc->max_cpus) {
-error_setg(errp, "Invalid SMP CPUs %d. The max CPUs "
-   "supported by machine '%s' is %d",
-   ms->smp.max_cpus,
-   mc->name, mc->max_cpus);
-}
-
-out_free:
-qapi_free_SMPConfiguration(config);
 }
 
 static void machine_class_init(ObjectClass *oc, void *data)
-- 
2.19.1




[PATCH for-6.2 v5 10/14] machine: Remove smp_parse callback from MachineClass

2021-08-12 Thread Yanan Wang
Now we have a generic smp parser for all arches, and there will
not be any other arch specific ones, so let's remove the callback
from MachineClass and call the parser directly.

Signed-off-by: Yanan Wang 
Reviewed-by: Andrew Jones 
---
 hw/core/machine.c   | 3 +--
 include/hw/boards.h | 5 -
 2 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index b0f82c8811..3823e609e0 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -937,7 +937,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const 
char *name,
 goto out_free;
 }
 
-mc->smp_parse(ms, config, errp);
+smp_parse(ms, config, errp);
 if (errp) {
 goto out_free;
 }
@@ -966,7 +966,6 @@ static void machine_class_init(ObjectClass *oc, void *data)
 /* Default 128 MB as guest ram size */
 mc->default_ram_size = 128 * MiB;
 mc->rom_file_has_mr = true;
-mc->smp_parse = smp_parse;
 
 /* numa node memory size aligned on 8MB by default.
  * On Linux, each node's border has to be 8MB aligned
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 72a23e4e0f..fa284e01e9 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -177,10 +177,6 @@ typedef struct {
  *kvm-type may be NULL if it is not needed.
  * @numa_mem_supported:
  *true if '--numa node.mem' option is supported and false otherwise
- * @smp_parse:
- *The function pointer to hook different machine specific functions for
- *parsing "smp-opts" from QemuOpts to MachineState::CpuTopology and more
- *machine specific topology fields, such as smp_dies for PCMachine.
  * @hotplug_allowed:
  *If the hook is provided, then it'll be called for each device
  *hotplug to check whether the device hotplug is allowed.  Return
@@ -217,7 +213,6 @@ struct MachineClass {
 void (*reset)(MachineState *state);
 void (*wakeup)(MachineState *state);
 int (*kvm_type)(MachineState *machine, const char *arg);
-void (*smp_parse)(MachineState *ms, SMPConfiguration *config, Error 
**errp);
 
 BlockInterfaceType block_default_type;
 int units_per_default_bus;
-- 
2.19.1




[PATCH for-6.2 v5 09/14] machine: Make smp_parse generic enough for all arches

2021-08-12 Thread Yanan Wang
Currently the only difference between smp_parse and pc_smp_parse
is the support of dies parameter and the related error reporting.
With some arch compat variables like "bool dies_supported", we can
make smp_parse generic enough for all arches and the PC specific
one can be removed.

Making smp_parse() generic enough can reduce code duplication and
ease the code maintenance, and also allows extending the topology
with more arch specific members (e.g., clusters) in the future.

Suggested-by: Andrew Jones 
Signed-off-by: Yanan Wang 
Reviewed-by: Andrew Jones 
---
 hw/core/machine.c   | 110 
 hw/i386/pc.c|  84 +
 include/hw/boards.h |   9 
 3 files changed, 100 insertions(+), 103 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index d271456153..b0f82c8811 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -15,6 +15,7 @@
 #include "qapi/qmp/qerror.h"
 #include "sysemu/replay.h"
 #include "qemu/units.h"
+#include "qemu/cutils.h"
 #include "hw/boards.h"
 #include "hw/loader.h"
 #include "qapi/error.h"
@@ -746,20 +747,87 @@ void machine_set_cpu_numa_node(MachineState *machine,
 }
 }
 
+static char *cpu_topology_hierarchy(MachineState *ms)
+{
+MachineClass *mc = MACHINE_GET_CLASS(ms);
+SMPCompatProps *smp_props = &mc->smp_props;
+char topo_msg[256] = "";
+
+/*
+ * Topology members should be ordered from the largest to the smallest.
+ * Concept of sockets/cores/threads is supported by default and will be
+ * reported in the hierarchy. Unsupported members will not be reported.
+ */
+g_autofree char *sockets_msg = g_strdup_printf(
+" * sockets (%u)", ms->smp.sockets);
+pstrcat(topo_msg, sizeof(topo_msg), sockets_msg);
+
+if (smp_props->dies_supported) {
+g_autofree char *dies_msg = g_strdup_printf(
+" * dies (%u)", ms->smp.dies);
+pstrcat(topo_msg, sizeof(topo_msg), dies_msg);
+}
+
+g_autofree char *cores_msg = g_strdup_printf(
+" * cores (%u)", ms->smp.cores);
+pstrcat(topo_msg, sizeof(topo_msg), cores_msg);
+
+g_autofree char *threads_msg = g_strdup_printf(
+" * threads (%u)", ms->smp.threads);
+pstrcat(topo_msg, sizeof(topo_msg), threads_msg);
+
+return g_strdup_printf("%s", topo_msg + 3);
+}
+
+/*
+ * smp_parse - Generic function used to parse the given SMP configuration
+ *
+ * If not supported by the machine, a topology parameter must be omitted
+ * or specified equal to 1. Concept of sockets/cores/threads is supported
+ * by default. Unsupported members will not be reported in the topology
+ * hierarchy message.
+ *
+ * For compatibility, omitted arch-specific members (e.g. dies) will not
+ * be computed, but will directly default to 1 instead. This logic should
+ * also apply to future introduced ones.
+ *
+ * Omitted arch-neutral parameters (i.e. cpus/sockets/cores/threads/maxcpus)
+ * will be computed based on the provided ones. When both maxcpus and cpus
+ * are omitted, maxcpus will be computed from the given parameters and cpus
+ * will be set equal to maxcpus. When only one of maxcpus and cpus is given
+ * then the omitted one will be set to its given counterpart's value.
+ * Both maxcpus and cpus may be specified, but maxcpus must be equal to or
+ * greater than cpus.
+ *
+ * In calculation of omitted sockets/cores/threads, we prefer sockets over
+ * cores over threads before 6.2, while preferring cores over sockets over
+ * threads since 6.2.
+ */
 static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
 {
 MachineClass *mc = MACHINE_GET_CLASS(ms);
 unsigned cpus= config->has_cpus ? config->cpus : 0;
 unsigned sockets = config->has_sockets ? config->sockets : 0;
+unsigned dies= config->has_dies ? config->dies : 0;
 unsigned cores   = config->has_cores ? config->cores : 0;
 unsigned threads = config->has_threads ? config->threads : 0;
 unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
 
-if (config->has_dies && config->dies > 1) {
+/*
+ * If not supported by the machine, a topology parameter must be
+ * omitted or specified equal to 1.
+ */
+if (!mc->smp_props.dies_supported && dies > 1) {
 error_setg(errp, "dies not supported by this machine's CPU topology");
 return;
 }
 
+/*
+ * Omitted arch-specific members will not be computed, but will
+ * directly default to 1 instead.
+ */
+dies = dies > 0 ? dies : 1;
+
 /* compute missing values based on the provided ones */
 if (cpus == 0 && maxcpus == 0) {
 sockets = sockets > 0 ? sockets : 1;
@@ -773,55 +841,57 @@ static void smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **errp)
 if (sockets == 0) {
 cores = cores > 0 ? cores : 1;
 threads = threads > 0 ? threads : 1;
-sockets = maxcpus /

[PATCH for-6.2 v5 05/14] hw: Add compat machines for 6.2

2021-08-12 Thread Yanan Wang
Add 6.2 machine types for arm/i440fx/q35/s390x/spapr.

Signed-off-by: Yanan Wang 
Acked-by: David Gibson 
Reviewed-by: Andrew Jones 
Reviewed-by: Cornelia Huck 
Reviewed-by: Pankaj Gupta 
---
 hw/arm/virt.c  |  9 -
 hw/core/machine.c  |  3 +++
 hw/i386/pc.c   |  3 +++
 hw/i386/pc_piix.c  | 14 +-
 hw/i386/pc_q35.c   | 13 -
 hw/ppc/spapr.c | 15 +--
 hw/s390x/s390-virtio-ccw.c | 14 +-
 include/hw/boards.h|  3 +++
 include/hw/i386/pc.h   |  3 +++
 9 files changed, 71 insertions(+), 6 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 81eda46b0b..01165f7f53 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2788,10 +2788,17 @@ static void machvirt_machine_init(void)
 }
 type_init(machvirt_machine_init);
 
+static void virt_machine_6_2_options(MachineClass *mc)
+{
+}
+DEFINE_VIRT_MACHINE_AS_LATEST(6, 2)
+
 static void virt_machine_6_1_options(MachineClass *mc)
 {
+virt_machine_6_2_options(mc);
+compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
 }
-DEFINE_VIRT_MACHINE_AS_LATEST(6, 1)
+DEFINE_VIRT_MACHINE(6, 1)
 
 static void virt_machine_6_0_options(MachineClass *mc)
 {
diff --git a/hw/core/machine.c b/hw/core/machine.c
index c6646bf922..bdce80df32 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -37,6 +37,9 @@
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-pci.h"
 
+GlobalProperty hw_compat_6_1[] = {};
+const size_t hw_compat_6_1_len = G_N_ELEMENTS(hw_compat_6_1);
+
 GlobalProperty hw_compat_6_0[] = {
 { "gpex-pcihost", "allow-unmapped-accesses", "false" },
 { "i8042", "extended-state", "false"},
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index fcf6905219..afd8b9c283 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -94,6 +94,9 @@
 #include "trace.h"
 #include CONFIG_DEVICES
 
+GlobalProperty pc_compat_6_1[] = {};
+const size_t pc_compat_6_1_len = G_N_ELEMENTS(pc_compat_6_1);
+
 GlobalProperty pc_compat_6_0[] = {
 { "qemu64" "-" TYPE_X86_CPU, "family", "6" },
 { "qemu64" "-" TYPE_X86_CPU, "model", "6" },
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 30b8bd6ea9..fd5c2277f2 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -413,7 +413,7 @@ static void pc_i440fx_machine_options(MachineClass *m)
 machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE);
 }
 
-static void pc_i440fx_6_1_machine_options(MachineClass *m)
+static void pc_i440fx_6_2_machine_options(MachineClass *m)
 {
 PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
 pc_i440fx_machine_options(m);
@@ -422,6 +422,18 @@ static void pc_i440fx_6_1_machine_options(MachineClass *m)
 pcmc->default_cpu_version = 1;
 }
 
+DEFINE_I440FX_MACHINE(v6_2, "pc-i440fx-6.2", NULL,
+  pc_i440fx_6_2_machine_options);
+
+static void pc_i440fx_6_1_machine_options(MachineClass *m)
+{
+pc_i440fx_6_2_machine_options(m);
+m->alias = NULL;
+m->is_default = false;
+compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len);
+compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len);
+}
+
 DEFINE_I440FX_MACHINE(v6_1, "pc-i440fx-6.1", NULL,
   pc_i440fx_6_1_machine_options);
 
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 04b4a4788d..b45903b15e 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -355,7 +355,7 @@ static void pc_q35_machine_options(MachineClass *m)
 m->max_cpus = 288;
 }
 
-static void pc_q35_6_1_machine_options(MachineClass *m)
+static void pc_q35_6_2_machine_options(MachineClass *m)
 {
 PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
 pc_q35_machine_options(m);
@@ -363,6 +363,17 @@ static void pc_q35_6_1_machine_options(MachineClass *m)
 pcmc->default_cpu_version = 1;
 }
 
+DEFINE_Q35_MACHINE(v6_2, "pc-q35-6.2", NULL,
+   pc_q35_6_2_machine_options);
+
+static void pc_q35_6_1_machine_options(MachineClass *m)
+{
+pc_q35_6_2_machine_options(m);
+m->alias = NULL;
+compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len);
+compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len);
+}
+
 DEFINE_Q35_MACHINE(v6_1, "pc-q35-6.1", NULL,
pc_q35_6_1_machine_options);
 
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 81699d4f8b..d39fd4e644 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4685,15 +4685,26 @@ static void 
spapr_machine_latest_class_options(MachineClass *mc)
 }\
 type_init(spapr_machine_register_##suffix)
 
+/*
+ * pseries-6.2
+ */
+static void spapr_machine_6_2_class_options(MachineClass *mc)
+{
+/* Defaults for the latest behaviour inherited from the base class */
+}
+
+DEFINE_SPAPR_MACHINE(6_2, "6.2", true);
+
 /*
  * pseries-6.1
  */
 static void spapr_machine_6_1_class_options(MachineClass *mc)
 {
-/* Defaults for the latest behaviour inherited from the base class */
+

[PATCH for-6.2 v5 00/14] machine: smp parsing fixes and improvement

2021-08-12 Thread Yanan Wang
Hi,

This is new version (v5 with a little update in patch #6) of the series [1]
that I have posted to introduce some fixes and improvement for SMP parsing.

[1] 
https://lore.kernel.org/qemu-devel/20210803080527.156556-1-wangyana...@huawei.com/

Most of this series is about the SMP parsers:
maxcpus is now uniformly used to calculate the omitted topology members,
calculation of omitted maxcpus/cpus is improved, the error reporting is
improved. It's also suggested that we should start to prefer cores over
sockets over threads on the newer machine types, which will make the
computed virtual topology more reflective of the real hardware.

In order to reduce code duplication and ease the code maintenance, smp_parse
in now converted into a parser generic enough for all arches, so that the PC
specific one can be removed. It's also convenient to introduce more topology
members to the generic parser in the future.

Finally, a QEMU unit test for the parsing of given SMP configuration is added.
Since all the parsing logic is in generic function smp_parse(), this test
passes different SMP configurations to the function and compare the parsing
result with what is expected. In the test, all possible collections of the
topology parameters and the corresponding expected results are listed,
including the valid and invalid ones. The preference of sockets over cores
and the preference of cores over sockets, and the support of multi-dies are
also taken into consideration.

---

Changelogs:

v4->v5:
- refactor out the duplicated "threads == 0" case in patch #6 (Pankaj)
- pick up more R-b tags from v4 (thanks very much for the review!)
- v4: 
https://lore.kernel.org/qemu-devel/20210803080527.156556-1-wangyana...@huawei.com/

v3->v4:
- put all the sanity check into the parser
- refine the unit test and add it back to the series
- add the R-b/A-b tags for the reviewed/acked patches
- v3: 
https://lore.kernel.org/qemu-devel/20210728034848.75228-1-wangyana...@huawei.com/

v2->v3:
- apply the calculation improvement to smp_parse and pc_smp_parse
  separately and then convert the finally improved parsers into a
  generic one, so that patches can be reviewed separately.
- to ease review, drop the unit test part for a while until we have
  a good enough generic parser.
- send the patch "machine: Disallow specifying topology parameters as zero"
  for 6.1 separately.
- v2: 
https://lore.kernel.org/qemu-devel/20210719032043.25416-1-wangyana...@huawei.com/

v1->v2:
- disallow "anything=0" in the smp configuration (Andrew)
- make function smp_parse() a generic helper for all arches
- improve the error reporting in the parser
- start to prefer cores over sockets since 6.2 (Daniel)
- add a unit test for the smp parsing (Daniel)
- v1: 
https://lore.kernel.org/qemu-devel/20210702100739.13672-1-wangyana...@huawei.com/

---

Yanan Wang (14):
  machine: Minor refactor/cleanup for the smp parsers
  machine: Uniformly use maxcpus to calculate the omitted parameters
  machine: Set the value of cpus to match maxcpus if it's omitted
  machine: Improve the error reporting of smp parsing
  hw: Add compat machines for 6.2
  machine: Prefer cores over sockets in smp parsing since 6.2
  machine: Use ms instead of global current_machine in sanity-check
  machine: Tweak the order of topology members in struct CpuTopology
  machine: Make smp_parse generic enough for all arches
  machine: Remove smp_parse callback from MachineClass
  machine: Move smp_prefer_sockets to struct SMPCompatProps
  machine: Put all sanity-check in the generic SMP parser
  machine: Split out the smp parsing code
  tests/unit: Add a unit test for smp parsing

 MAINTAINERS |   2 +
 hw/arm/virt.c   |  10 +-
 hw/core/machine-smp.c   | 200 
 hw/core/machine.c   | 106 +
 hw/core/meson.build |   1 +
 hw/i386/pc.c|  66 +--
 hw/i386/pc_piix.c   |  15 +-
 hw/i386/pc_q35.c|  14 +-
 hw/ppc/spapr.c  |  16 +-
 hw/s390x/s390-virtio-ccw.c  |  15 +-
 include/hw/boards.h |  27 +-
 include/hw/i386/pc.h|   3 +
 qemu-options.hx |  14 +-
 tests/unit/meson.build  |   1 +
 tests/unit/test-smp-parse.c | 892 
 15 files changed, 1205 insertions(+), 177 deletions(-)
 create mode 100644 hw/core/machine-smp.c
 create mode 100644 tests/unit/test-smp-parse.c

--
2.19.1




[PATCH for-6.2 v5 08/14] machine: Tweak the order of topology members in struct CpuTopology

2021-08-12 Thread Yanan Wang
Now that all the possible topology parameters are integrated in struct
CpuTopology, tweak the order of topology members to be "cpus/sockets/
dies/cores/threads/maxcpus" for readability and consistency. We also
tweak the comment by adding explanation of dies parameter.

Signed-off-by: Yanan Wang 
Reviewed-by: Andrew Jones 
Reviewed-by: Pankaj Gupta 
---
 hw/core/machine.c   | 8 
 include/hw/boards.h | 7 ---
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 45fa3cd61b..d271456153 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -829,11 +829,11 @@ static void machine_get_smp(Object *obj, Visitor *v, 
const char *name,
 {
 MachineState *ms = MACHINE(obj);
 SMPConfiguration *config = &(SMPConfiguration){
-.has_cores = true, .cores = ms->smp.cores,
+.has_cpus = true, .cpus = ms->smp.cpus,
 .has_sockets = true, .sockets = ms->smp.sockets,
 .has_dies = true, .dies = ms->smp.dies,
+.has_cores = true, .cores = ms->smp.cores,
 .has_threads = true, .threads = ms->smp.threads,
-.has_cpus = true, .cpus = ms->smp.cpus,
 .has_maxcpus = true, .maxcpus = ms->smp.max_cpus,
 };
 if (!visit_type_SMPConfiguration(v, name, &config, &error_abort)) {
@@ -1060,10 +1060,10 @@ static void machine_initfn(Object *obj)
 /* default to mc->default_cpus */
 ms->smp.cpus = mc->default_cpus;
 ms->smp.max_cpus = mc->default_cpus;
-ms->smp.cores = 1;
+ms->smp.sockets = 1;
 ms->smp.dies = 1;
+ms->smp.cores = 1;
 ms->smp.threads = 1;
-ms->smp.sockets = 1;
 }
 
 static void machine_finalize(Object *obj)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 2ae039b74f..2a1bba86c0 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -275,17 +275,18 @@ typedef struct DeviceMemoryState {
 /**
  * CpuTopology:
  * @cpus: the number of present logical processors on the machine
- * @cores: the number of cores in one package
- * @threads: the number of threads in one core
  * @sockets: the number of sockets on the machine
+ * @dies: the number of dies in one socket
+ * @cores: the number of cores in one die
+ * @threads: the number of threads in one core
  * @max_cpus: the maximum number of logical processors on the machine
  */
 typedef struct CpuTopology {
 unsigned int cpus;
+unsigned int sockets;
 unsigned int dies;
 unsigned int cores;
 unsigned int threads;
-unsigned int sockets;
 unsigned int max_cpus;
 } CpuTopology;
 
-- 
2.19.1




[PATCH for-6.2 v5 03/14] machine: Set the value of cpus to match maxcpus if it's omitted

2021-08-12 Thread Yanan Wang
Currently we directly calculate the omitted cpus based on the given
incomplete collection of parameters. This makes some cmdlines like:
  -smp maxcpus=16
  -smp sockets=2,maxcpus=16
  -smp sockets=2,dies=2,maxcpus=16
  -smp sockets=2,cores=4,maxcpus=16
not work. We should probably set the value of cpus to match maxcpus
if it's omitted, which will make above configs start to work.

So the calculation logic of cpus/maxcpus after this patch will be:
When both maxcpus and cpus are omitted, maxcpus will be calculated
from the given parameters and cpus will be set equal to maxcpus.
When only one of maxcpus and cpus is given then the omitted one
will be set to its counterpart's value. Both maxcpus and cpus may
be specified, but maxcpus must be equal to or greater than cpus.

Note: change in this patch won't affect any existing working cmdlines
but allows more incomplete configs to be valid.

Signed-off-by: Yanan Wang 
Reviewed-by: Andrew Jones 
---
 hw/core/machine.c | 29 -
 hw/i386/pc.c  | 29 -
 qemu-options.hx   | 11 ---
 3 files changed, 40 insertions(+), 29 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index ff10347ce8..1a6c6cfd0e 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -757,25 +757,28 @@ static void smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **errp)
 }
 
 /* compute missing values, prefer sockets over cores over threads */
-maxcpus = maxcpus > 0 ? maxcpus : cpus;
-
-if (cpus == 0) {
+if (cpus == 0 && maxcpus == 0) {
 sockets = sockets > 0 ? sockets : 1;
 cores = cores > 0 ? cores : 1;
 threads = threads > 0 ? threads : 1;
-cpus = sockets * cores * threads;
+} else {
 maxcpus = maxcpus > 0 ? maxcpus : cpus;
-} else if (sockets == 0) {
-cores = cores > 0 ? cores : 1;
-threads = threads > 0 ? threads : 1;
-sockets = maxcpus / (cores * threads);
-} else if (cores == 0) {
-threads = threads > 0 ? threads : 1;
-cores = maxcpus / (sockets * threads);
-} else if (threads == 0) {
-threads = maxcpus / (sockets * cores);
+
+if (sockets == 0) {
+cores = cores > 0 ? cores : 1;
+threads = threads > 0 ? threads : 1;
+sockets = maxcpus / (cores * threads);
+} else if (cores == 0) {
+threads = threads > 0 ? threads : 1;
+cores = maxcpus / (sockets * threads);
+} else if (threads == 0) {
+threads = maxcpus / (sockets * cores);
+}
 }
 
+maxcpus = maxcpus > 0 ? maxcpus : sockets * cores * threads;
+cpus = cpus > 0 ? cpus : maxcpus;
+
 if (sockets * cores * threads < cpus) {
 error_setg(errp, "cpu topology: "
"sockets (%u) * cores (%u) * threads (%u) < "
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index a9ff9ef52c..9ad7ae5254 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -725,25 +725,28 @@ static void pc_smp_parse(MachineState *ms, 
SMPConfiguration *config, Error **err
 dies = dies > 0 ? dies : 1;
 
 /* compute missing values, prefer sockets over cores over threads */
-maxcpus = maxcpus > 0 ? maxcpus : cpus;
-
-if (cpus == 0) {
+if (cpus == 0 && maxcpus == 0) {
 sockets = sockets > 0 ? sockets : 1;
 cores = cores > 0 ? cores : 1;
 threads = threads > 0 ? threads : 1;
-cpus = sockets * dies * cores * threads;
+} else {
 maxcpus = maxcpus > 0 ? maxcpus : cpus;
-} else if (sockets == 0) {
-cores = cores > 0 ? cores : 1;
-threads = threads > 0 ? threads : 1;
-sockets = maxcpus / (dies * cores * threads);
-} else if (cores == 0) {
-threads = threads > 0 ? threads : 1;
-cores = maxcpus / (sockets * dies * threads);
-} else if (threads == 0) {
-threads = maxcpus / (sockets * dies * cores);
+
+if (sockets == 0) {
+cores = cores > 0 ? cores : 1;
+threads = threads > 0 ? threads : 1;
+sockets = maxcpus / (dies * cores * threads);
+} else if (cores == 0) {
+threads = threads > 0 ? threads : 1;
+cores = maxcpus / (sockets * dies * threads);
+} else if (threads == 0) {
+threads = maxcpus / (sockets * dies * cores);
+}
 }
 
+maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads;
+cpus = cpus > 0 ? cpus : maxcpus;
+
 if (sockets * dies * cores * threads < cpus) {
 error_setg(errp, "cpu topology: "
"sockets (%u) * dies (%u) * cores (%u) * threads (%u) < "
diff --git a/qemu-options.hx b/qemu-options.hx
index aee622f577..06f819177e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -214,9 +214,14 @@ SRST
 Simulate a SMP system with '\ ``n``\ ' CPUs initially present on
 the machine type board. On boards supporting CPU hotplug, the optional
 '\ ``maxcpus``\ ' parame

[PATCH for-6.2 v5 14/14] tests/unit: Add a unit test for smp parsing

2021-08-12 Thread Yanan Wang
Add a QEMU unit test for the parsing of given SMP configuration.
Since all the parsing logic is in generic function smp_parse(),
this test passes different SMP configurations to the function
and compare the parsing result with what is expected.

In the test, all possible collections of the topology parameters
and the corresponding expected results are listed, including the
valid and invalid ones.

The preference of sockets over cores and the preference of cores
over sockets, and the support of multi-dies are also considered.

Signed-off-by: Yanan Wang 
Reviewed-by: Andrew Jones 
---
 MAINTAINERS |   1 +
 tests/unit/meson.build  |   1 +
 tests/unit/test-smp-parse.c | 892 
 3 files changed, 894 insertions(+)
 create mode 100644 tests/unit/test-smp-parse.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 5510aaddfd..bc05fa8891 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1639,6 +1639,7 @@ F: include/hw/boards.h
 F: include/hw/core/cpu.h
 F: include/hw/cpu/cluster.h
 F: include/sysemu/numa.h
+F: tests/unit/test-smp-parse.c
 T: git https://gitlab.com/ehabkost/qemu.git machine-next
 
 Xtensa Machines
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index 5736d285b2..e208173970 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -45,6 +45,7 @@ tests = {
   'test-uuid': [],
   'ptimer-test': ['ptimer-test-stubs.c', meson.source_root() / 
'hw/core/ptimer.c'],
   'test-qapi-util': [],
+  'test-smp-parse': [qom, meson.source_root() / 'hw/core/machine-smp.c'],
 }
 
 if have_system or have_tools
diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c
new file mode 100644
index 00..291fa3fa60
--- /dev/null
+++ b/tests/unit/test-smp-parse.c
@@ -0,0 +1,892 @@
+/*
+ * SMP parsing unit-tests
+ *
+ * Copyright (c) 2021 Huawei Technologies Co., Ltd
+ *
+ * Authors:
+ *  Yanan Wang 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qom/object.h"
+#include "qemu/module.h"
+#include "qapi/error.h"
+
+#include "hw/boards.h"
+
+#define T true
+#define F false
+
+#define MIN_CPUS 1
+#define MAX_CPUS 512
+
+/* define a CPU topology hierarchy of sockets/cores/threads */
+#define SMP_CONFIG_GENERIC(ha, a, hb, b, hc, c, hd, d, he, e) \
+{ \
+.has_cpus= ha, .cpus= a,  \
+.has_sockets = hb, .sockets = b,  \
+.has_cores   = hc, .cores   = c,  \
+.has_threads = hd, .threads = d,  \
+.has_maxcpus = he, .maxcpus = e,  \
+}
+
+#define CPU_TOPOLOGY_GENERIC(a, b, c, d, e)   \
+{ \
+.cpus = a,\
+.sockets  = b,\
+.cores= c,\
+.threads  = d,\
+.max_cpus = e,\
+}
+
+/* define a CPU topology hierarchy of sockets/dies/cores/threads */
+#define SMP_CONFIG_WITH_DIES(ha, a, hb, b, hc, c, hd, d, he, e, hf, f) \
+{ \
+.has_cpus= ha, .cpus= a,  \
+.has_sockets = hb, .sockets = b,  \
+.has_dies= hc, .dies= c,  \
+.has_cores   = hd, .cores   = d,  \
+.has_threads = he, .threads = e,  \
+.has_maxcpus = hf, .maxcpus = f,  \
+}
+
+#define CPU_TOPOLOGY_WITH_DIES(a, b, c, d, e, f)  \
+{ \
+.cpus = a,\
+.sockets  = b,\
+.dies = c,\
+.cores= d,\
+.threads  = e,\
+.max_cpus = f,\
+}
+
+/**
+ * SMPTestData:
+ * @config - the given SMP configuration
+ * @expect_prefer_sockets - expected topology result for the valid
+ * configuration, when sockets are preferred over cores in parsing
+ * @expect_prefer_cores - expected topology result for the valid
+ * configuration, when cores are preferred over sockets in parsing
+ * @expect_error - expected error report for the invalid configuration
+ */
+typedef struct SMPTestData {
+SMPConfiguration config;
+CpuTopology expect_prefer_sockets;
+CpuTopology expect_prefer_cores;
+const char *expect_error;
+} SMPTestData;
+
+

[PATCH for-6.2 v5 01/14] machine: Minor refactor/cleanup for the smp parsers

2021-08-12 Thread Yanan Wang
To pave the way for the functional improvement in later patches,
make some refactor/cleanup for the smp parsers, including using
local maxcpus instead of ms->smp.max_cpus in the calculation,
defaulting dies to 0 initially like other members, cleanup the
sanity check for dies.

No functional change intended.

Signed-off-by: Yanan Wang 
Reviewed-by: Andrew Jones 
---
 hw/core/machine.c | 19 +++
 hw/i386/pc.c  | 23 ++-
 2 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 06148fc225..5ad646b3f0 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -749,9 +749,11 @@ static void smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **errp)
 unsigned sockets = config->has_sockets ? config->sockets : 0;
 unsigned cores   = config->has_cores ? config->cores : 0;
 unsigned threads = config->has_threads ? config->threads : 0;
+unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
 
-if (config->has_dies && config->dies != 0 && config->dies != 1) {
+if (config->has_dies && config->dies > 1) {
 error_setg(errp, "dies not supported by this machine's CPU topology");
+return;
 }
 
 /* compute missing values, prefer sockets over cores over threads */
@@ -762,8 +764,8 @@ static void smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **errp)
 sockets = sockets > 0 ? sockets : 1;
 cpus = cores * threads * sockets;
 } else {
-ms->smp.max_cpus = config->has_maxcpus ? config->maxcpus : cpus;
-sockets = ms->smp.max_cpus / (cores * threads);
+maxcpus = maxcpus > 0 ? maxcpus : cpus;
+sockets = maxcpus / (cores * threads);
 }
 } else if (cores == 0) {
 threads = threads > 0 ? threads : 1;
@@ -780,26 +782,27 @@ static void smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **errp)
 return;
 }
 
-ms->smp.max_cpus = config->has_maxcpus ? config->maxcpus : cpus;
+maxcpus = maxcpus > 0 ? maxcpus : cpus;
 
-if (ms->smp.max_cpus < cpus) {
+if (maxcpus < cpus) {
 error_setg(errp, "maxcpus must be equal to or greater than smp");
 return;
 }
 
-if (sockets * cores * threads != ms->smp.max_cpus) {
+if (sockets * cores * threads != maxcpus) {
 error_setg(errp, "Invalid CPU topology: "
"sockets (%u) * cores (%u) * threads (%u) "
"!= maxcpus (%u)",
sockets, cores, threads,
-   ms->smp.max_cpus);
+   maxcpus);
 return;
 }
 
 ms->smp.cpus = cpus;
+ms->smp.sockets = sockets;
 ms->smp.cores = cores;
 ms->smp.threads = threads;
-ms->smp.sockets = sockets;
+ms->smp.max_cpus = maxcpus;
 }
 
 static void machine_get_smp(Object *obj, Visitor *v, const char *name,
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index c2b9d62a35..acd31af452 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -716,9 +716,13 @@ static void pc_smp_parse(MachineState *ms, 
SMPConfiguration *config, Error **err
 {
 unsigned cpus= config->has_cpus ? config->cpus : 0;
 unsigned sockets = config->has_sockets ? config->sockets : 0;
-unsigned dies= config->has_dies ? config->dies : 1;
+unsigned dies= config->has_dies ? config->dies : 0;
 unsigned cores   = config->has_cores ? config->cores : 0;
 unsigned threads = config->has_threads ? config->threads : 0;
+unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
+
+/* directly default dies to 1 if it's omitted */
+dies = dies > 0 ? dies : 1;
 
 /* compute missing values, prefer sockets over cores over threads */
 if (cpus == 0 || sockets == 0) {
@@ -728,8 +732,8 @@ static void pc_smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **err
 sockets = sockets > 0 ? sockets : 1;
 cpus = cores * threads * dies * sockets;
 } else {
-ms->smp.max_cpus = config->has_maxcpus ? config->maxcpus : cpus;
-sockets = ms->smp.max_cpus / (cores * threads * dies);
+maxcpus = maxcpus > 0 ? maxcpus : cpus;
+sockets = maxcpus / (dies * cores * threads);
 }
 } else if (cores == 0) {
 threads = threads > 0 ? threads : 1;
@@ -746,27 +750,28 @@ static void pc_smp_parse(MachineState *ms, 
SMPConfiguration *config, Error **err
 return;
 }
 
-ms->smp.max_cpus = config->has_maxcpus ? config->maxcpus : cpus;
+maxcpus = maxcpus > 0 ? maxcpus : cpus;
 
-if (ms->smp.max_cpus < cpus) {
+if (maxcpus < cpus) {
 error_setg(errp, "maxcpus must be equal to or greater than smp");
 return;
 }
 
-if (sockets * dies * cores * threads != ms->smp.max_cpus) {
+if (sockets * dies * cores * threads != maxcpus) {
 error_setg(errp, "Invalid CPU topology deprecated: "
"sockets (%

[PATCH for-6.2 v5 07/14] machine: Use ms instead of global current_machine in sanity-check

2021-08-12 Thread Yanan Wang
In the sanity-check of smp_cpus and max_cpus against mc in function
machine_set_smp(), we are now using ms->smp.max_cpus for the check
but using current_machine->smp.max_cpus in the error message.
Tweak this by uniformly using the local ms.

Signed-off-by: Yanan Wang 
Reviewed-by: Andrew Jones 
Reviewed-by: Pankaj Gupta 
Reviewed-by: Cornelia Huck 
---
 hw/core/machine.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 15b41c52e8..45fa3cd61b 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -881,7 +881,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const 
char *name,
 } else if (ms->smp.max_cpus > mc->max_cpus) {
 error_setg(errp, "Invalid SMP CPUs %d. The max CPUs "
"supported by machine '%s' is %d",
-   current_machine->smp.max_cpus,
+   ms->smp.max_cpus,
mc->name, mc->max_cpus);
 }
 
-- 
2.19.1




[PATCH for-6.2 v5 11/14] machine: Move smp_prefer_sockets to struct SMPCompatProps

2021-08-12 Thread Yanan Wang
Now we have a common structure SMPCompatProps used to store information
about SMP compatibility stuff, so we can also move smp_prefer_sockets
there for cleaner code.

No functional change intended.

Signed-off-by: Yanan Wang 
Acked-by: David Gibson 
Reviewed-by: Andrew Jones 
---
 hw/arm/virt.c  | 2 +-
 hw/core/machine.c  | 2 +-
 hw/i386/pc_piix.c  | 2 +-
 hw/i386/pc_q35.c   | 2 +-
 hw/ppc/spapr.c | 2 +-
 hw/s390x/s390-virtio-ccw.c | 2 +-
 include/hw/boards.h| 3 ++-
 7 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 7babea40dc..ae029680da 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2797,7 +2797,7 @@ static void virt_machine_6_1_options(MachineClass *mc)
 {
 virt_machine_6_2_options(mc);
 compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
-mc->smp_prefer_sockets = true;
+mc->smp_props.prefer_sockets = true;
 }
 DEFINE_VIRT_MACHINE(6, 1)
 
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 3823e609e0..7e1dd623ae 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -836,7 +836,7 @@ static void smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **errp)
 } else {
 maxcpus = maxcpus > 0 ? maxcpus : cpus;
 
-if (mc->smp_prefer_sockets) {
+if (mc->smp_props.prefer_sockets) {
 /* prefer sockets over cores before 6.2 */
 if (sockets == 0) {
 cores = cores > 0 ? cores : 1;
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 9b811fc6ca..a60ebfc2c1 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -432,7 +432,7 @@ static void pc_i440fx_6_1_machine_options(MachineClass *m)
 m->is_default = false;
 compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len);
 compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len);
-m->smp_prefer_sockets = true;
+m->smp_props.prefer_sockets = true;
 }
 
 DEFINE_I440FX_MACHINE(v6_1, "pc-i440fx-6.1", NULL,
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 88efb7fde4..4b622ffb82 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -372,7 +372,7 @@ static void pc_q35_6_1_machine_options(MachineClass *m)
 m->alias = NULL;
 compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len);
 compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len);
-m->smp_prefer_sockets = true;
+m->smp_props.prefer_sockets = true;
 }
 
 DEFINE_Q35_MACHINE(v6_1, "pc-q35-6.1", NULL,
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index a481fade51..efdea43c0d 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4702,7 +4702,7 @@ static void spapr_machine_6_1_class_options(MachineClass 
*mc)
 {
 spapr_machine_6_2_class_options(mc);
 compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
-mc->smp_prefer_sockets = true;
+mc->smp_props.prefer_sockets = true;
 }
 
 DEFINE_SPAPR_MACHINE(6_1, "6.1", false);
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index b40e647883..5bdef9b4d7 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -809,7 +809,7 @@ static void ccw_machine_6_1_class_options(MachineClass *mc)
 {
 ccw_machine_6_2_class_options(mc);
 compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
-mc->smp_prefer_sockets = true;
+mc->smp_props.prefer_sockets = true;
 }
 DEFINE_CCW_MACHINE(6_1, "6.1", false);
 
diff --git a/include/hw/boards.h b/include/hw/boards.h
index fa284e01e9..5adbcbb99b 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -110,9 +110,11 @@ typedef struct {
 
 /**
  * SMPCompatProps:
+ * @prefer_sockets - whether sockets are preferred over cores in smp parsing
  * @dies_supported - whether dies are supported by the machine
  */
 typedef struct {
+bool prefer_sockets;
 bool dies_supported;
 } SMPCompatProps;
 
@@ -250,7 +252,6 @@ struct MachineClass {
 bool nvdimm_supported;
 bool numa_mem_supported;
 bool auto_enable_numa;
-bool smp_prefer_sockets;
 SMPCompatProps smp_props;
 const char *default_ram_id;
 
-- 
2.19.1




[PATCH for-6.2 v5 06/14] machine: Prefer cores over sockets in smp parsing since 6.2

2021-08-12 Thread Yanan Wang
In the real SMP hardware topology world, it's much more likely that
we have high cores-per-socket counts and few sockets totally. While
the current preference of sockets over cores in smp parsing results
in a virtual cpu topology with low cores-per-sockets counts and a
large number of sockets, which is just contrary to the real world.

Given that it is better to make the virtual cpu topology be more
reflective of the real world and also for the sake of compatibility,
we start to prefer cores over sockets over threads in smp parsing
since machine type 6.2 for different arches.

In this patch, a boolean "smp_prefer_sockets" is added, and we only
enable the old preference on older machines and enable the new one
since type 6.2 for all arches by using the machine compat mechanism.

Suggested-by: Daniel P. Berrange 
Signed-off-by: Yanan Wang 
Acked-by: David Gibson 
Acked-by: Cornelia Huck 
Reviewed-by: Andrew Jones 
---
 hw/arm/virt.c  |  1 +
 hw/core/machine.c  | 35 ++-
 hw/i386/pc.c   | 35 ++-
 hw/i386/pc_piix.c  |  1 +
 hw/i386/pc_q35.c   |  1 +
 hw/ppc/spapr.c |  1 +
 hw/s390x/s390-virtio-ccw.c |  1 +
 include/hw/boards.h|  1 +
 qemu-options.hx|  3 ++-
 9 files changed, 60 insertions(+), 19 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 01165f7f53..7babea40dc 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2797,6 +2797,7 @@ static void virt_machine_6_1_options(MachineClass *mc)
 {
 virt_machine_6_2_options(mc);
 compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
+mc->smp_prefer_sockets = true;
 }
 DEFINE_VIRT_MACHINE(6, 1)
 
diff --git a/hw/core/machine.c b/hw/core/machine.c
index bdce80df32..15b41c52e8 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -748,6 +748,7 @@ void machine_set_cpu_numa_node(MachineState *machine,
 
 static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
 {
+MachineClass *mc = MACHINE_GET_CLASS(ms);
 unsigned cpus= config->has_cpus ? config->cpus : 0;
 unsigned sockets = config->has_sockets ? config->sockets : 0;
 unsigned cores   = config->has_cores ? config->cores : 0;
@@ -759,7 +760,7 @@ static void smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **errp)
 return;
 }
 
-/* compute missing values, prefer sockets over cores over threads */
+/* compute missing values based on the provided ones */
 if (cpus == 0 && maxcpus == 0) {
 sockets = sockets > 0 ? sockets : 1;
 cores = cores > 0 ? cores : 1;
@@ -767,14 +768,30 @@ static void smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **errp)
 } else {
 maxcpus = maxcpus > 0 ? maxcpus : cpus;
 
-if (sockets == 0) {
-cores = cores > 0 ? cores : 1;
-threads = threads > 0 ? threads : 1;
-sockets = maxcpus / (cores * threads);
-} else if (cores == 0) {
-threads = threads > 0 ? threads : 1;
-cores = maxcpus / (sockets * threads);
-} else if (threads == 0) {
+if (mc->smp_prefer_sockets) {
+/* prefer sockets over cores before 6.2 */
+if (sockets == 0) {
+cores = cores > 0 ? cores : 1;
+threads = threads > 0 ? threads : 1;
+sockets = maxcpus / (cores * threads);
+} else if (cores == 0) {
+threads = threads > 0 ? threads : 1;
+cores = maxcpus / (sockets * threads);
+}
+} else {
+/* prefer cores over sockets since 6.2 */
+if (cores == 0) {
+sockets = sockets > 0 ? sockets : 1;
+threads = threads > 0 ? threads : 1;
+cores = maxcpus / (sockets * threads);
+} else if (sockets == 0) {
+threads = threads > 0 ? threads : 1;
+sockets = maxcpus / (cores * threads);
+}
+}
+
+/* try to calculate omitted threads at last */
+if (threads == 0) {
 threads = maxcpus / (sockets * cores);
 }
 }
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index afd8b9c283..4b05ff7160 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -717,6 +717,7 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
  */
 static void pc_smp_parse(MachineState *ms, SMPConfiguration *config, Error 
**errp)
 {
+MachineClass *mc = MACHINE_GET_CLASS(ms);
 unsigned cpus= config->has_cpus ? config->cpus : 0;
 unsigned sockets = config->has_sockets ? config->sockets : 0;
 unsigned dies= config->has_dies ? config->dies : 0;
@@ -727,7 +728,7 @@ static void pc_smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **err
 /* directly default dies to 1 if it's omitted */
 dies = dies > 0 ? dies : 1;
 
-/* compute missing values, prefer sockets over co

[PATCH for-6.2 v5 02/14] machine: Uniformly use maxcpus to calculate the omitted parameters

2021-08-12 Thread Yanan Wang
We are currently using maxcpus to calculate the omitted sockets
but using cpus to calculate the omitted cores/threads. This makes
cmdlines like:
  -smp cpus=8,maxcpus=16
  -smp cpus=8,cores=4,maxcpus=16
  -smp cpus=8,threads=2,maxcpus=16
work fine but the ones like:
  -smp cpus=8,sockets=2,maxcpus=16
  -smp cpus=8,sockets=2,cores=4,maxcpus=16
  -smp cpus=8,sockets=2,threads=2,maxcpus=16
break the sanity check.

Since we require for a valid config that the product of "sockets * cores
* threads" should equal to the maxcpus, we should uniformly use maxcpus
to calculate their omitted values.

Also the if-branch of "cpus == 0 || sockets == 0" was split into two
branches of "cpus == 0" and "sockets == 0" so that we can clearly read
that we are parsing the configuration with a preference on cpus over
sockets over cores over threads.

Note: change in this patch won't affect any existing working cmdlines
but improves consistency and allows more incomplete configs to be valid.

Signed-off-by: Yanan Wang 
Reviewed-by: Andrew Jones 
Reviewed-by: Pankaj Gupta 
---
 hw/core/machine.c | 30 +++---
 hw/i386/pc.c  | 30 +++---
 2 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 5ad646b3f0..ff10347ce8 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -757,24 +757,26 @@ static void smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **errp)
 }
 
 /* compute missing values, prefer sockets over cores over threads */
-if (cpus == 0 || sockets == 0) {
+maxcpus = maxcpus > 0 ? maxcpus : cpus;
+
+if (cpus == 0) {
+sockets = sockets > 0 ? sockets : 1;
 cores = cores > 0 ? cores : 1;
 threads = threads > 0 ? threads : 1;
-if (cpus == 0) {
-sockets = sockets > 0 ? sockets : 1;
-cpus = cores * threads * sockets;
-} else {
-maxcpus = maxcpus > 0 ? maxcpus : cpus;
-sockets = maxcpus / (cores * threads);
-}
+cpus = sockets * cores * threads;
+maxcpus = maxcpus > 0 ? maxcpus : cpus;
+} else if (sockets == 0) {
+cores = cores > 0 ? cores : 1;
+threads = threads > 0 ? threads : 1;
+sockets = maxcpus / (cores * threads);
 } else if (cores == 0) {
 threads = threads > 0 ? threads : 1;
-cores = cpus / (sockets * threads);
-cores = cores > 0 ? cores : 1;
+cores = maxcpus / (sockets * threads);
 } else if (threads == 0) {
-threads = cpus / (cores * sockets);
-threads = threads > 0 ? threads : 1;
-} else if (sockets * cores * threads < cpus) {
+threads = maxcpus / (sockets * cores);
+}
+
+if (sockets * cores * threads < cpus) {
 error_setg(errp, "cpu topology: "
"sockets (%u) * cores (%u) * threads (%u) < "
"smp_cpus (%u)",
@@ -782,8 +784,6 @@ static void smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **errp)
 return;
 }
 
-maxcpus = maxcpus > 0 ? maxcpus : cpus;
-
 if (maxcpus < cpus) {
 error_setg(errp, "maxcpus must be equal to or greater than smp");
 return;
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index acd31af452..a9ff9ef52c 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -725,24 +725,26 @@ static void pc_smp_parse(MachineState *ms, 
SMPConfiguration *config, Error **err
 dies = dies > 0 ? dies : 1;
 
 /* compute missing values, prefer sockets over cores over threads */
-if (cpus == 0 || sockets == 0) {
+maxcpus = maxcpus > 0 ? maxcpus : cpus;
+
+if (cpus == 0) {
+sockets = sockets > 0 ? sockets : 1;
 cores = cores > 0 ? cores : 1;
 threads = threads > 0 ? threads : 1;
-if (cpus == 0) {
-sockets = sockets > 0 ? sockets : 1;
-cpus = cores * threads * dies * sockets;
-} else {
-maxcpus = maxcpus > 0 ? maxcpus : cpus;
-sockets = maxcpus / (dies * cores * threads);
-}
+cpus = sockets * dies * cores * threads;
+maxcpus = maxcpus > 0 ? maxcpus : cpus;
+} else if (sockets == 0) {
+cores = cores > 0 ? cores : 1;
+threads = threads > 0 ? threads : 1;
+sockets = maxcpus / (dies * cores * threads);
 } else if (cores == 0) {
 threads = threads > 0 ? threads : 1;
-cores = cpus / (sockets * dies * threads);
-cores = cores > 0 ? cores : 1;
+cores = maxcpus / (sockets * dies * threads);
 } else if (threads == 0) {
-threads = cpus / (cores * dies * sockets);
-threads = threads > 0 ? threads : 1;
-} else if (sockets * dies * cores * threads < cpus) {
+threads = maxcpus / (sockets * dies * cores);
+}
+
+if (sockets * dies * cores * threads < cpus) {
 error_setg(errp, "cpu topology: "
"sockets (%u) * dies (%u) * cores (%u) * threads (%u) < "
 

[PATCH for-6.2 v5 04/14] machine: Improve the error reporting of smp parsing

2021-08-12 Thread Yanan Wang
We have two requirements for a valid SMP configuration:
the product of "sockets * cores * threads" must represent all the
possible cpus, i.e., max_cpus, and then must include the initially
present cpus, i.e., smp_cpus.

So we only need to ensure 1) "sockets * cores * threads == maxcpus"
at first and then ensure 2) "maxcpus >= cpus". With a reasonable
order of the sanity check, we can simplify the error reporting code.
When reporting an error message we also report the exact value of
each topology member to make users easily see what's going on.

Signed-off-by: Yanan Wang 
Reviewed-by: Andrew Jones 
Reviewed-by: Pankaj Gupta 
---
 hw/core/machine.c | 22 +-
 hw/i386/pc.c  | 24 ++--
 2 files changed, 19 insertions(+), 27 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 1a6c6cfd0e..c6646bf922 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -779,25 +779,21 @@ static void smp_parse(MachineState *ms, SMPConfiguration 
*config, Error **errp)
 maxcpus = maxcpus > 0 ? maxcpus : sockets * cores * threads;
 cpus = cpus > 0 ? cpus : maxcpus;
 
-if (sockets * cores * threads < cpus) {
-error_setg(errp, "cpu topology: "
-   "sockets (%u) * cores (%u) * threads (%u) < "
-   "smp_cpus (%u)",
-   sockets, cores, threads, cpus);
+if (sockets * cores * threads != maxcpus) {
+error_setg(errp, "Invalid CPU topology: "
+   "product of the hierarchy must match maxcpus: "
+   "sockets (%u) * cores (%u) * threads (%u) "
+   "!= maxcpus (%u)",
+   sockets, cores, threads, maxcpus);
 return;
 }
 
 if (maxcpus < cpus) {
-error_setg(errp, "maxcpus must be equal to or greater than smp");
-return;
-}
-
-if (sockets * cores * threads != maxcpus) {
 error_setg(errp, "Invalid CPU topology: "
+   "maxcpus must be equal to or greater than smp: "
"sockets (%u) * cores (%u) * threads (%u) "
-   "!= maxcpus (%u)",
-   sockets, cores, threads,
-   maxcpus);
+   "== maxcpus (%u) < smp_cpus (%u)",
+   sockets, cores, threads, maxcpus, cpus);
 return;
 }
 
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 9ad7ae5254..fcf6905219 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -747,25 +747,21 @@ static void pc_smp_parse(MachineState *ms, 
SMPConfiguration *config, Error **err
 maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads;
 cpus = cpus > 0 ? cpus : maxcpus;
 
-if (sockets * dies * cores * threads < cpus) {
-error_setg(errp, "cpu topology: "
-   "sockets (%u) * dies (%u) * cores (%u) * threads (%u) < "
-   "smp_cpus (%u)",
-   sockets, dies, cores, threads, cpus);
+if (sockets * dies * cores * threads != maxcpus) {
+error_setg(errp, "Invalid CPU topology: "
+   "product of the hierarchy must match maxcpus: "
+   "sockets (%u) * dies (%u) * cores (%u) * threads (%u) "
+   "!= maxcpus (%u)",
+   sockets, dies, cores, threads, maxcpus);
 return;
 }
 
 if (maxcpus < cpus) {
-error_setg(errp, "maxcpus must be equal to or greater than smp");
-return;
-}
-
-if (sockets * dies * cores * threads != maxcpus) {
-error_setg(errp, "Invalid CPU topology deprecated: "
+error_setg(errp, "Invalid CPU topology: "
+   "maxcpus must be equal to or greater than smp: "
"sockets (%u) * dies (%u) * cores (%u) * threads (%u) "
-   "!= maxcpus (%u)",
-   sockets, dies, cores, threads,
-   maxcpus);
+   "== maxcpus (%u) < smp_cpus (%u)",
+   sockets, dies, cores, threads, maxcpus, cpus);
 return;
 }
 
-- 
2.19.1




Re: [PATCH v2 1/1] target/riscv: Add User CSRs read-only check

2021-08-12 Thread Alistair Francis
On Tue, Aug 10, 2021 at 11:48 AM LIU Zhiwei  wrote:
>
> For U-mode CSRs, read-only check is also needed.
>
> Signed-off-by: LIU Zhiwei 
> Reviewed-by: Bin Meng 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/csr.c | 8 +---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 9a4ed18ac5..5499cae94a 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -1422,11 +1422,11 @@ RISCVException riscv_csrrw(CPURISCVState *env, int 
> csrno,
>  RISCVException ret;
>  target_ulong old_value;
>  RISCVCPU *cpu = env_archcpu(env);
> +int read_only = get_field(csrno, 0xC00) == 3;
>
>  /* check privileges and return -1 if check fails */
>  #if !defined(CONFIG_USER_ONLY)
>  int effective_priv = env->priv;
> -int read_only = get_field(csrno, 0xC00) == 3;
>
>  if (riscv_has_ext(env, RVH) &&
>  env->priv == PRV_S &&
> @@ -1439,11 +1439,13 @@ RISCVException riscv_csrrw(CPURISCVState *env, int 
> csrno,
>  effective_priv++;
>  }
>
> -if ((write_mask && read_only) ||
> -(!env->debugger && (effective_priv < get_field(csrno, 0x300 {
> +if (!env->debugger && (effective_priv < get_field(csrno, 0x300))) {
>  return RISCV_EXCP_ILLEGAL_INST;
>  }
>  #endif
> +if (write_mask && read_only) {
> +return RISCV_EXCP_ILLEGAL_INST;
> +}
>
>  /* ensure the CSR extension is enabled. */
>  if (!cpu->cfg.ext_icsr) {
> --
> 2.17.1
>
>



Re: [PATCH for-6.2 14/25] hw/arm/stm32vldiscovery: Delete trailing blank line

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 7:44 PM Peter Maydell  wrote:
>
> Delete the trailing blank line at the end of the source file.
>
> Signed-off-by: Peter Maydell 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/arm/stm32vldiscovery.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/hw/arm/stm32vldiscovery.c b/hw/arm/stm32vldiscovery.c
> index 07e401a818d..9b79004703b 100644
> --- a/hw/arm/stm32vldiscovery.c
> +++ b/hw/arm/stm32vldiscovery.c
> @@ -65,4 +65,3 @@ static void stm32vldiscovery_machine_init(MachineClass *mc)
>  }
>
>  DEFINE_MACHINE("stm32vldiscovery", stm32vldiscovery_machine_init)
> -
> --
> 2.20.1
>
>



Re: [PATCH for-6.2 12/25] hw/arm/stm32f205: Wire up sysclk and refclk

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 7:38 PM Peter Maydell  wrote:
>
> Wire up the sysclk and refclk for the stm32f205 SoC.  This SoC always
> runs the systick refclk at 1/8 the frequency of the main CPU clock,
> so the board code only needs to provide a single sysclk clock.
>
> Because there is only one board using this SoC, we convert the SoC
> and the board together, rather than splitting it into "add clock to
> SoC; connect clock in board; add error check in SoC code that clock
> is wired up".
>
> When the systick device starts honouring its clock inputs, this will
> fix an emulation inaccuracy in the netduino2 board where the systick
> reference clock was running at 1MHz rather than 15MHz.
>
> Signed-off-by: Peter Maydell 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  include/hw/arm/stm32f205_soc.h |  4 
>  hw/arm/netduino2.c | 12 +++-
>  hw/arm/stm32f205_soc.c | 30 ++
>  3 files changed, 41 insertions(+), 5 deletions(-)
>
> diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h
> index 75251494917..849d3ed8891 100644
> --- a/include/hw/arm/stm32f205_soc.h
> +++ b/include/hw/arm/stm32f205_soc.h
> @@ -32,6 +32,7 @@
>  #include "hw/or-irq.h"
>  #include "hw/ssi/stm32f2xx_spi.h"
>  #include "hw/arm/armv7m.h"
> +#include "hw/clock.h"
>  #include "qom/object.h"
>
>  #define TYPE_STM32F205_SOC "stm32f205-soc"
> @@ -67,6 +68,9 @@ struct STM32F205State {
>  MemoryRegion sram;
>  MemoryRegion flash;
>  MemoryRegion flash_alias;
> +
> +Clock *sysclk;
> +Clock *refclk;
>  };
>
>  #endif
> diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c
> index 1733b71507c..b5c0ba23ee5 100644
> --- a/hw/arm/netduino2.c
> +++ b/hw/arm/netduino2.c
> @@ -26,6 +26,7 @@
>  #include "qapi/error.h"
>  #include "hw/boards.h"
>  #include "hw/qdev-properties.h"
> +#include "hw/qdev-clock.h"
>  #include "qemu/error-report.h"
>  #include "hw/arm/stm32f205_soc.h"
>  #include "hw/arm/boot.h"
> @@ -36,16 +37,17 @@
>  static void netduino2_init(MachineState *machine)
>  {
>  DeviceState *dev;
> +Clock *sysclk;
>
> -/*
> - * TODO: ideally we would model the SoC RCC and let it handle
> - * system_clock_scale, including its ability to define different
> - * possible SYSCLK sources.
> - */
>  system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
>
> +/* This clock doesn't need migration because it is fixed-frequency */
> +sysclk = clock_new(OBJECT(machine), "SYSCLK");
> +clock_set_hz(sysclk, SYSCLK_FRQ);
> +
>  dev = qdev_new(TYPE_STM32F205_SOC);
>  qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
> +qdev_connect_clock_in(dev, "sysclk", sysclk);
>  sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>
>  armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
> diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c
> index 0bd215aebd7..c6b75a381d9 100644
> --- a/hw/arm/stm32f205_soc.c
> +++ b/hw/arm/stm32f205_soc.c
> @@ -29,6 +29,7 @@
>  #include "exec/address-spaces.h"
>  #include "hw/arm/stm32f205_soc.h"
>  #include "hw/qdev-properties.h"
> +#include "hw/qdev-clock.h"
>  #include "sysemu/sysemu.h"
>
>  /* At the moment only Timer 2 to 5 are modelled */
> @@ -74,6 +75,9 @@ static void stm32f205_soc_initfn(Object *obj)
>  for (i = 0; i < STM_NUM_SPIS; i++) {
>  object_initialize_child(obj, "spi[*]", &s->spi[i], 
> TYPE_STM32F2XX_SPI);
>  }
> +
> +s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
> +s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
>  }
>
>  static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
> @@ -85,6 +89,30 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, 
> Error **errp)
>
>  MemoryRegion *system_memory = get_system_memory();
>
> +/*
> + * We use s->refclk internally and only define it with 
> qdev_init_clock_in()
> + * so it is correctly parented and not leaked on an init/deinit; it is 
> not
> + * intended as an externally exposed clock.
> + */
> +if (clock_has_source(s->refclk)) {
> +error_setg(errp, "refclk clock must not be wired up by the board 
> code");
> +return;
> +}
> +
> +if (!clock_has_source(s->sysclk)) {
> +error_setg(errp, "sysclk clock must be wired up by the board code");
> +return;
> +}
> +
> +/*
> + * TODO: ideally we should model the SoC RCC and its ability to
> + * change the sysclk frequency and define different sysclk sources.
> + */
> +
> +/* The refclk always runs at frequency HCLK / 8 */
> +clock_set_mul_div(s->refclk, 8, 1);
> +clock_set_source(s->refclk, s->sysclk);
> +
>  memory_region_init_rom(&s->flash, OBJECT(dev_soc), "STM32F205.flash",
> FLASH_SIZE, &error_fatal);
>  memory_region_init_alias(&s->flash_alias, OBJECT(dev_soc),
> @@ -101,6 +129,8 @@ static void stm32f2

Re: [PATCH for-6.2 13/25] hw/arm/stm32f405: Wire up sysclk and refclk

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 7:41 PM Peter Maydell  wrote:
>
> Wire up the sysclk and refclk for the stm32f405 SoC.  This SoC always
> runs the systick refclk at 1/8 the frequency of the main CPU clock,
> so the board code only needs to provide a single sysclk clock.
>
> Because there is only one board using this SoC, we convert the SoC
> and the board together, rather than splitting it into "add clock to
> SoC; connect clock in board; add error check in SoC code that clock
> is wired up".
>
> When the systick device starts honouring its clock inputs, this will
> fix an emulation inaccuracy in the netduinoplus2 board where the
> systick reference clock was running at 1MHz rather than 21MHz.
>
> Signed-off-by: Peter Maydell 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  include/hw/arm/stm32f405_soc.h |  3 +++
>  hw/arm/netduinoplus2.c | 12 +++-
>  hw/arm/stm32f405_soc.c | 30 ++
>  3 files changed, 40 insertions(+), 5 deletions(-)
>
> diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
> index 347105e709b..5bb0c8d5697 100644
> --- a/include/hw/arm/stm32f405_soc.h
> +++ b/include/hw/arm/stm32f405_soc.h
> @@ -68,6 +68,9 @@ struct STM32F405State {
>  MemoryRegion sram;
>  MemoryRegion flash;
>  MemoryRegion flash_alias;
> +
> +Clock *sysclk;
> +Clock *refclk;
>  };
>
>  #endif
> diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c
> index d3ad7a2b675..a5a8999cc8c 100644
> --- a/hw/arm/netduinoplus2.c
> +++ b/hw/arm/netduinoplus2.c
> @@ -26,6 +26,7 @@
>  #include "qapi/error.h"
>  #include "hw/boards.h"
>  #include "hw/qdev-properties.h"
> +#include "hw/qdev-clock.h"
>  #include "qemu/error-report.h"
>  #include "hw/arm/stm32f405_soc.h"
>  #include "hw/arm/boot.h"
> @@ -36,16 +37,17 @@
>  static void netduinoplus2_init(MachineState *machine)
>  {
>  DeviceState *dev;
> +Clock *sysclk;
>
> -/*
> - * TODO: ideally we would model the SoC RCC and let it handle
> - * system_clock_scale, including its ability to define different
> - * possible SYSCLK sources.
> - */
>  system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
>
> +/* This clock doesn't need migration because it is fixed-frequency */
> +sysclk = clock_new(OBJECT(machine), "SYSCLK");
> +clock_set_hz(sysclk, SYSCLK_FRQ);
> +
>  dev = qdev_new(TYPE_STM32F405_SOC);
>  qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
> +qdev_connect_clock_in(dev, "sysclk", sysclk);
>  sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>
>  armv7m_load_kernel(ARM_CPU(first_cpu),
> diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
> index cb04c111987..0019b7f4785 100644
> --- a/hw/arm/stm32f405_soc.c
> +++ b/hw/arm/stm32f405_soc.c
> @@ -28,6 +28,7 @@
>  #include "exec/address-spaces.h"
>  #include "sysemu/sysemu.h"
>  #include "hw/arm/stm32f405_soc.h"
> +#include "hw/qdev-clock.h"
>  #include "hw/misc/unimp.h"
>
>  #define SYSCFG_ADD 0x40013800
> @@ -80,6 +81,9 @@ static void stm32f405_soc_initfn(Object *obj)
>  }
>
>  object_initialize_child(obj, "exti", &s->exti, TYPE_STM32F4XX_EXTI);
> +
> +s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
> +s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
>  }
>
>  static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
> @@ -91,6 +95,30 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, 
> Error **errp)
>  Error *err = NULL;
>  int i;
>
> +/*
> + * We use s->refclk internally and only define it with 
> qdev_init_clock_in()
> + * so it is correctly parented and not leaked on an init/deinit; it is 
> not
> + * intended as an externally exposed clock.
> + */
> +if (clock_has_source(s->refclk)) {
> +error_setg(errp, "refclk clock must not be wired up by the board 
> code");
> +return;
> +}
> +
> +if (!clock_has_source(s->sysclk)) {
> +error_setg(errp, "sysclk clock must be wired up by the board code");
> +return;
> +}
> +
> +/*
> + * TODO: ideally we should model the SoC RCC and its ability to
> + * change the sysclk frequency and define different sysclk sources.
> + */
> +
> +/* The refclk always runs at frequency HCLK / 8 */
> +clock_set_mul_div(s->refclk, 8, 1);
> +clock_set_source(s->refclk, s->sysclk);
> +
>  memory_region_init_rom(&s->flash, OBJECT(dev_soc), "STM32F405.flash",
> FLASH_SIZE, &err);
>  if (err != NULL) {
> @@ -116,6 +144,8 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, 
> Error **errp)
>  qdev_prop_set_uint32(armv7m, "num-irq", 96);
>  qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
>  qdev_prop_set_bit(armv7m, "enable-bitband", true);
> +qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
> +qdev_connect_clock_in(armv7m, "refclk", s->refclk)

Re: [PATCH for-6.2 11/25] hw/arm/stm32f100: Wire up sysclk and refclk

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 7:37 PM Peter Maydell  wrote:
>
> Wire up the sysclk and refclk for the stm32f100 SoC.  This SoC always
> runs the systick refclk at 1/8 the frequency of the main CPU clock,
> so the board code only needs to provide a single sysclk clock.
>
> Because there is only one board using this SoC, we convert the SoC
> and the board together, rather than splitting it into "add clock to
> SoC; connect clock in board; add error check in SoC code that clock
> is wired up".
>
> When the systick device starts honouring its clock inputs, this will
> fix an emulation inaccuracy in the stm32vldiscovery board where the
> systick reference clock was running at 1MHz rather than 3MHz.
>
> Signed-off-by: Peter Maydell 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  include/hw/arm/stm32f100_soc.h |  4 
>  hw/arm/stm32f100_soc.c | 30 ++
>  hw/arm/stm32vldiscovery.c  | 12 +++-
>  3 files changed, 41 insertions(+), 5 deletions(-)
>
> diff --git a/include/hw/arm/stm32f100_soc.h b/include/hw/arm/stm32f100_soc.h
> index b7d71c6c634..40cd415b284 100644
> --- a/include/hw/arm/stm32f100_soc.h
> +++ b/include/hw/arm/stm32f100_soc.h
> @@ -29,6 +29,7 @@
>  #include "hw/ssi/stm32f2xx_spi.h"
>  #include "hw/arm/armv7m.h"
>  #include "qom/object.h"
> +#include "hw/clock.h"
>
>  #define TYPE_STM32F100_SOC "stm32f100-soc"
>  OBJECT_DECLARE_SIMPLE_TYPE(STM32F100State, STM32F100_SOC)
> @@ -56,6 +57,9 @@ struct STM32F100State {
>  MemoryRegion sram;
>  MemoryRegion flash;
>  MemoryRegion flash_alias;
> +
> +Clock *sysclk;
> +Clock *refclk;
>  };
>
>  #endif
> diff --git a/hw/arm/stm32f100_soc.c b/hw/arm/stm32f100_soc.c
> index 0be92b2c475..f7b344ba9fb 100644
> --- a/hw/arm/stm32f100_soc.c
> +++ b/hw/arm/stm32f100_soc.c
> @@ -30,6 +30,7 @@
>  #include "exec/address-spaces.h"
>  #include "hw/arm/stm32f100_soc.h"
>  #include "hw/qdev-properties.h"
> +#include "hw/qdev-clock.h"
>  #include "hw/misc/unimp.h"
>  #include "sysemu/sysemu.h"
>
> @@ -57,6 +58,9 @@ static void stm32f100_soc_initfn(Object *obj)
>  for (i = 0; i < STM_NUM_SPIS; i++) {
>  object_initialize_child(obj, "spi[*]", &s->spi[i], 
> TYPE_STM32F2XX_SPI);
>  }
> +
> +s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
> +s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
>  }
>
>  static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp)
> @@ -68,6 +72,30 @@ static void stm32f100_soc_realize(DeviceState *dev_soc, 
> Error **errp)
>
>  MemoryRegion *system_memory = get_system_memory();
>
> +/*
> + * We use s->refclk internally and only define it with 
> qdev_init_clock_in()
> + * so it is correctly parented and not leaked on an init/deinit; it is 
> not
> + * intended as an externally exposed clock.
> + */
> +if (clock_has_source(s->refclk)) {
> +error_setg(errp, "refclk clock must not be wired up by the board 
> code");
> +return;
> +}
> +
> +if (!clock_has_source(s->sysclk)) {
> +error_setg(errp, "sysclk clock must be wired up by the board code");
> +return;
> +}
> +
> +/*
> + * TODO: ideally we should model the SoC RCC and its ability to
> + * change the sysclk frequency and define different sysclk sources.
> + */
> +
> +/* The refclk always runs at frequency HCLK / 8 */
> +clock_set_mul_div(s->refclk, 8, 1);
> +clock_set_source(s->refclk, s->sysclk);
> +
>  /*
>   * Init flash region
>   * Flash starts at 0x0800 and then is aliased to boot memory at 0x0
> @@ -89,6 +117,8 @@ static void stm32f100_soc_realize(DeviceState *dev_soc, 
> Error **errp)
>  qdev_prop_set_uint32(armv7m, "num-irq", 61);
>  qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
>  qdev_prop_set_bit(armv7m, "enable-bitband", true);
> +qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
> +qdev_connect_clock_in(armv7m, "refclk", s->refclk);
>  object_property_set_link(OBJECT(&s->armv7m), "memory",
>   OBJECT(get_system_memory()), &error_abort);
>  if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
> diff --git a/hw/arm/stm32vldiscovery.c b/hw/arm/stm32vldiscovery.c
> index 7e8191ebf5f..07e401a818d 100644
> --- a/hw/arm/stm32vldiscovery.c
> +++ b/hw/arm/stm32vldiscovery.c
> @@ -27,6 +27,7 @@
>  #include "qapi/error.h"
>  #include "hw/boards.h"
>  #include "hw/qdev-properties.h"
> +#include "hw/qdev-clock.h"
>  #include "qemu/error-report.h"
>  #include "hw/arm/stm32f100_soc.h"
>  #include "hw/arm/boot.h"
> @@ -39,16 +40,17 @@
>  static void stm32vldiscovery_init(MachineState *machine)
>  {
>  DeviceState *dev;
> +Clock *sysclk;
>
> -/*
> - * TODO: ideally we would model the SoC RCC and let it handle
> - * system_clock_scale, including its ability to define different
> - * possible SYSCLK sources.
> - */
>  system_clock_scale = NANOSECONDS_PER_S

Re: [PATCH for-6.2 10/25] hw/arm: Don't allocate separate MemoryRegions in stm32 SoC realize

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 7:37 PM Peter Maydell  wrote:
>
> In the realize methods of the stm32f100 and stm32f205 SoC objects, we
> call g_new() to create new MemoryRegion objjects for the sram, flash,
> and flash_alias.  This is unnecessary (and leaves open the
> possibility of leaking the allocations if we exit from realize with
> an error).  Make these MemoryRegions member fields of the device
> state struct instead, as stm32f405 already does.
>
> Signed-off-by: Peter Maydell 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  include/hw/arm/stm32f100_soc.h |  4 
>  include/hw/arm/stm32f205_soc.h |  4 
>  hw/arm/stm32f100_soc.c | 17 +++--
>  hw/arm/stm32f205_soc.c | 17 +++--
>  4 files changed, 22 insertions(+), 20 deletions(-)
>
> diff --git a/include/hw/arm/stm32f100_soc.h b/include/hw/arm/stm32f100_soc.h
> index 71bffcf4fd5..b7d71c6c634 100644
> --- a/include/hw/arm/stm32f100_soc.h
> +++ b/include/hw/arm/stm32f100_soc.h
> @@ -52,6 +52,10 @@ struct STM32F100State {
>
>  STM32F2XXUsartState usart[STM_NUM_USARTS];
>  STM32F2XXSPIState spi[STM_NUM_SPIS];
> +
> +MemoryRegion sram;
> +MemoryRegion flash;
> +MemoryRegion flash_alias;
>  };
>
>  #endif
> diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h
> index 985ff63aa9e..75251494917 100644
> --- a/include/hw/arm/stm32f205_soc.h
> +++ b/include/hw/arm/stm32f205_soc.h
> @@ -63,6 +63,10 @@ struct STM32F205State {
>  STM32F2XXSPIState spi[STM_NUM_SPIS];
>
>  qemu_or_irq *adc_irqs;
> +
> +MemoryRegion sram;
> +MemoryRegion flash;
> +MemoryRegion flash_alias;
>  };
>
>  #endif
> diff --git a/hw/arm/stm32f100_soc.c b/hw/arm/stm32f100_soc.c
> index 0c4a5c66451..0be92b2c475 100644
> --- a/hw/arm/stm32f100_soc.c
> +++ b/hw/arm/stm32f100_soc.c
> @@ -67,25 +67,22 @@ static void stm32f100_soc_realize(DeviceState *dev_soc, 
> Error **errp)
>  int i;
>
>  MemoryRegion *system_memory = get_system_memory();
> -MemoryRegion *sram = g_new(MemoryRegion, 1);
> -MemoryRegion *flash = g_new(MemoryRegion, 1);
> -MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
>
>  /*
>   * Init flash region
>   * Flash starts at 0x0800 and then is aliased to boot memory at 0x0
>   */
> -memory_region_init_rom(flash, OBJECT(dev_soc), "STM32F100.flash",
> +memory_region_init_rom(&s->flash, OBJECT(dev_soc), "STM32F100.flash",
> FLASH_SIZE, &error_fatal);
> -memory_region_init_alias(flash_alias, OBJECT(dev_soc),
> - "STM32F100.flash.alias", flash, 0, FLASH_SIZE);
> -memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> -memory_region_add_subregion(system_memory, 0, flash_alias);
> +memory_region_init_alias(&s->flash_alias, OBJECT(dev_soc),
> + "STM32F100.flash.alias", &s->flash, 0, 
> FLASH_SIZE);
> +memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, 
> &s->flash);
> +memory_region_add_subregion(system_memory, 0, &s->flash_alias);
>
>  /* Init SRAM region */
> -memory_region_init_ram(sram, NULL, "STM32F100.sram", SRAM_SIZE,
> +memory_region_init_ram(&s->sram, NULL, "STM32F100.sram", SRAM_SIZE,
> &error_fatal);
> -memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> +memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, &s->sram);
>
>  /* Init ARMv7m */
>  armv7m = DEVICE(&s->armv7m);
> diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c
> index 9cd41bf56da..0bd215aebd7 100644
> --- a/hw/arm/stm32f205_soc.c
> +++ b/hw/arm/stm32f205_soc.c
> @@ -84,21 +84,18 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, 
> Error **errp)
>  int i;
>
>  MemoryRegion *system_memory = get_system_memory();
> -MemoryRegion *sram = g_new(MemoryRegion, 1);
> -MemoryRegion *flash = g_new(MemoryRegion, 1);
> -MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
>
> -memory_region_init_rom(flash, OBJECT(dev_soc), "STM32F205.flash",
> +memory_region_init_rom(&s->flash, OBJECT(dev_soc), "STM32F205.flash",
> FLASH_SIZE, &error_fatal);
> -memory_region_init_alias(flash_alias, OBJECT(dev_soc),
> - "STM32F205.flash.alias", flash, 0, FLASH_SIZE);
> +memory_region_init_alias(&s->flash_alias, OBJECT(dev_soc),
> + "STM32F205.flash.alias", &s->flash, 0, 
> FLASH_SIZE);
>
> -memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> -memory_region_add_subregion(system_memory, 0, flash_alias);
> +memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, 
> &s->flash);
> +memory_region_add_subregion(system_memory, 0, &s->flash_alias);
>
> -memory_region_init_ram(sram, NULL, "STM32F205.sram", SRAM_SIZE,
> +memory_region_init_ram(&s->sram, NULL, "STM32F205.sram", SRAM_SIZE,
>  

Re: [PATCH for-6.2 09/25] clock: Provide builtin multiplier/divider

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 7:38 PM Peter Maydell  wrote:
>
> It is quite common for a clock tree to involve possibly programmable
> clock multipliers or dividers, where the frequency of a clock is for
> instance divided by 8 to produce a slower clock to feed to a
> particular device.
>
> Currently we provide no convenient mechanism for modelling this.  You
> can implement it by having an input Clock and an output Clock, and
> manually setting the period of the output clock in the period-changed
> callback of the input clock, but that's quite clunky.
>
> This patch adds support in the Clock objects themselves for setting a
> multiplier or divider.  The effect of setting this on a clock is that
> when the clock's period is changed, all the children of the clock are
> set to period * multiplier / divider, rather than being set to the
> same period as the parent clock.
>
> Signed-off-by: Peter Maydell 
> ---
>  docs/devel/clocks.rst   | 23 +++
>  include/hw/clock.h  | 29 +
>  hw/core/clock-vmstate.c | 24 +++-
>  hw/core/clock.c | 29 +
>  4 files changed, 100 insertions(+), 5 deletions(-)
>
> diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
> index 956bd147ea0..430fbd842e5 100644
> --- a/docs/devel/clocks.rst
> +++ b/docs/devel/clocks.rst
> @@ -260,6 +260,29 @@ clocks get the new clock period value: *Clock 2*, *Clock 
> 3* and *Clock 4*.
>  It is not possible to disconnect a clock or to change the clock connection
>  after it is connected.
>
> +Clock multiplier and divider settings
> +-
> +
> +By default, when clocks are connected together, the child
> +clocks run with the same period as their source (parent) clock.
> +The Clock API supports a built-in period multiplier/divider
> +mechanism so you can configure a clock to make its children
> +run at a different period from its own. If you call the
> +``clock_set_mul_div()`` function you can specify the clock's
> +multiplier and divider values. The children of that clock
> +will all run with a period of ``parent_period * multiplier / divider``.
> +For instance, if the clock has a frequency of 8MHz and you set its
> +multiplier to 2 and its divider to 3, the child clocks will run
> +at 12MHz.
> +
> +You can change the multiplier and divider of a clock at runtime,
> +so you can use this to model clock controller devices which
> +have guest-programmable frequency multipliers or dividers.
> +
> +Note that ``clock_set_mul_div()`` does not automatically call
> +``clock_propagate()``. If you make a runtime change to the
> +multiplier or divider you must call clock_propagate() yourself.a

You have an extra `a` here after the full stop.

Otherwise:

Reviewed-by: Alistair Francis 

Alistair

> +
>  Unconnected input clocks
>  
>
> diff --git a/include/hw/clock.h b/include/hw/clock.h
> index a7187eab95e..11f67fb9701 100644
> --- a/include/hw/clock.h
> +++ b/include/hw/clock.h
> @@ -81,6 +81,10 @@ struct Clock {
>  void *callback_opaque;
>  unsigned int callback_events;
>
> +/* Ratio of the parent clock to run the child clocks at */
> +uint32_t multiplier;
> +uint32_t divider;
> +
>  /* Clocks are organized in a clock tree */
>  Clock *source;
>  QLIST_HEAD(, Clock) children;
> @@ -350,4 +354,29 @@ static inline bool clock_is_enabled(const Clock *clk)
>   */
>  char *clock_display_freq(Clock *clk);
>
> +/**
> + * clock_set_mul_div: set multiplier/divider for child clocks
> + * @clk: clock
> + * @multiplier: multiplier value
> + * @divider: divider value
> + *
> + * By default, a Clock's children will all run with the same period
> + * as their parent. This function allows you to adjust the multiplier
> + * and divider used to derive the child clock frequency.
> + * For example, setting a multiplier of 2 and a divider of 3
> + * will run child clocks with a period 2/3 of the parent clock,
> + * so if the parent clock is an 8MHz clock the children will
> + * be 12MHz.
> + *
> + * Setting the multiplier to 0 will stop the child clocks.
> + * Setting the divider to 0 is a programming error (diagnosed with
> + * an assertion failure).
> + * Setting a multiplier value that results in the child period
> + * overflowing is not diagnosed.
> + *
> + * Note that this function does not call clock_propagate(); the
> + * caller should do that if necessary.
> + */
> +void clock_set_mul_div(Clock *clk, uint32_t multiplier, uint32_t divider);
> +
>  #endif /* QEMU_HW_CLOCK_H */
> diff --git a/hw/core/clock-vmstate.c b/hw/core/clock-vmstate.c
> index 260b13fc2c8..07bb45d7ed4 100644
> --- a/hw/core/clock-vmstate.c
> +++ b/hw/core/clock-vmstate.c
> @@ -14,6 +14,24 @@
>  #include "migration/vmstate.h"
>  #include "hw/clock.h"
>
> +static bool muldiv_needed(void *opaque)
> +{
> +Clock *clk = opaque;
> +
> +return clk->multiplier != 1 || clk->divider != 1;
> +}
> +
> +const VMStateDesc

Re: [PATCH for-6.2 07/25] armsse: Wire up systick cpuclk clock

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 7:42 PM Peter Maydell  wrote:
>
> Wire up the cpuclk for the systick devices to the SSE object's
> existing mainclk clock.
>
> We do not wire up the refclk because the SSE subsystems do not
> provide a refclk.  (This is documented in the IoTKit and SSE-200
> TRMs; the SSE-300 TRM doesn't mention it but we assume it follows the
> same approach.) When we update the systick device later to honour "no
> refclk connected" this will fix a minor emulation inaccuracy for the
> SSE-based boards.
>
> Signed-off-by: Peter Maydell 

Acked-by: Alistair Francis 

Alistair

> ---
>  hw/arm/armsse.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
> index a1456cb0f42..70b52c3d4b9 100644
> --- a/hw/arm/armsse.c
> +++ b/hw/arm/armsse.c
> @@ -995,6 +995,9 @@ static void armsse_realize(DeviceState *dev, Error **errp)
>  int j;
>  char *gpioname;
>
> +qdev_connect_clock_in(cpudev, "cpuclk", s->mainclk);
> +/* The SSE subsystems do not wire up a systick refclk */
> +
>  qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + 
> NUM_SSE_IRQS);
>  /*
>   * In real hardware the initial Secure VTOR is set from the 
> INITSVTOR*
> --
> 2.20.1
>
>



Re: [PATCH for-6.2 06/25] hw/arm/armv7m: Create input clocks

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 7:38 PM Peter Maydell  wrote:
>
> Create input clocks on the armv7m container object which pass through
> to the systick timers, so that users of the armv7m object can specify
> the clocks being used.
>
> Signed-off-by: Peter Maydell 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  include/hw/arm/armv7m.h |  6 ++
>  hw/arm/armv7m.c | 23 +++
>  2 files changed, 29 insertions(+)
>
> diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
> index fe8b248a6c6..b7ba0ff409c 100644
> --- a/include/hw/arm/armv7m.h
> +++ b/include/hw/arm/armv7m.h
> @@ -15,6 +15,7 @@
>  #include "hw/misc/armv7m_ras.h"
>  #include "target/arm/idau.h"
>  #include "qom/object.h"
> +#include "hw/clock.h"
>
>  #define TYPE_BITBAND "ARM-bitband-memory"
>  OBJECT_DECLARE_SIMPLE_TYPE(BitBandState, BITBAND)
> @@ -51,6 +52,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(ARMv7MState, ARMV7M)
>   * + Property "vfp": enable VFP (forwarded to CPU object)
>   * + Property "dsp": enable DSP (forwarded to CPU object)
>   * + Property "enable-bitband": expose bitbanded IO
> + * + Clock input "refclk" is the external reference clock for the systick 
> timers
> + * + Clock input "cpuclk" is the main CPU clock
>   */
>  struct ARMv7MState {
>  /*< private >*/
> @@ -82,6 +85,9 @@ struct ARMv7MState {
>  /* MR providing default PPB behaviour */
>  MemoryRegion defaultmem;
>
> +Clock *refclk;
> +Clock *cpuclk;
> +
>  /* Properties */
>  char *cpu_type;
>  /* MemoryRegion the board provides to us (with its devices, RAM, etc) */
> diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
> index 7e7fb7a3ad3..db1bfa98df0 100644
> --- a/hw/arm/armv7m.c
> +++ b/hw/arm/armv7m.c
> @@ -14,12 +14,14 @@
>  #include "hw/arm/boot.h"
>  #include "hw/loader.h"
>  #include "hw/qdev-properties.h"
> +#include "hw/qdev-clock.h"
>  #include "elf.h"
>  #include "sysemu/reset.h"
>  #include "qemu/error-report.h"
>  #include "qemu/module.h"
>  #include "qemu/log.h"
>  #include "target/arm/idau.h"
> +#include "migration/vmstate.h"
>
>  /* Bitbanded IO.  Each word corresponds to a single bit.  */
>
> @@ -265,6 +267,9 @@ static void armv7m_instance_init(Object *obj)
>  object_initialize_child(obj, "bitband[*]", &s->bitband[i],
>  TYPE_BITBAND);
>  }
> +
> +s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk", NULL, NULL, 0);
> +s->cpuclk = qdev_init_clock_in(DEVICE(obj), "cpuclk", NULL, NULL, 0);
>  }
>
>  static void armv7m_realize(DeviceState *dev, Error **errp)
> @@ -416,6 +421,8 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
>  }
>
>  /* Create and map the systick devices */
> +qdev_connect_clock_in(DEVICE(&s->systick[M_REG_NS]), "refclk", 
> s->refclk);
> +qdev_connect_clock_in(DEVICE(&s->systick[M_REG_NS]), "cpuclk", 
> s->cpuclk);
>  if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_NS]), errp)) {
>  return;
>  }
> @@ -431,6 +438,10 @@ static void armv7m_realize(DeviceState *dev, Error 
> **errp)
>   */
>  object_initialize_child(OBJECT(dev), "systick-reg-s",
>  &s->systick[M_REG_S], TYPE_SYSTICK);
> +qdev_connect_clock_in(DEVICE(&s->systick[M_REG_S]), "refclk",
> +  s->refclk);
> +qdev_connect_clock_in(DEVICE(&s->systick[M_REG_S]), "cpuclk",
> +  s->cpuclk);
>
>  if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_S]), errp)) {
>  return;
> @@ -504,11 +515,23 @@ static Property armv7m_properties[] = {
>  DEFINE_PROP_END_OF_LIST(),
>  };
>
> +static const VMStateDescription vmstate_armv7m = {
> +.name = "armv7m",
> +.version_id = 1,
> +.minimum_version_id = 1,
> +.fields = (VMStateField[]) {
> +VMSTATE_CLOCK(refclk, SysTickState),
> +VMSTATE_CLOCK(cpuclk, SysTickState),
> +VMSTATE_END_OF_LIST()
> +}
> +};
> +
>  static void armv7m_class_init(ObjectClass *klass, void *data)
>  {
>  DeviceClass *dc = DEVICE_CLASS(klass);
>
>  dc->realize = armv7m_realize;
> +dc->vmsd = &vmstate_armv7m;
>  device_class_set_props(dc, armv7m_properties);
>  }
>
> --
> 2.20.1
>
>



Re: [PATCH for-6.2 05/25] hw/timer/armv7m_systick: Add input clocks

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 7:36 PM Peter Maydell  wrote:
>
> The v7M systick timer can be programmed to run from either of
> two clocks:
>  * an "external reference clock" (when SYST_CSR.CLKSOURCE == 0)
>  * the main CPU clock (when SYST_CSR.CLKSOURCE == 1)
>
> Our implementation currently hardwires the external reference clock
> to be 1MHz, and allows boards to set the main CPU clock frequency via
> the global 'system_clock_scale'.  (Most boards set that to a constant
> value; the Stellaris boards allow the guest to reprogram it via the
> board-specific RCC registers).
>
> As the first step in converting this to use the Clock infrastructure,
> add input clocks to the systick device for the reference clock and
> the CPU clock.  The device implementation ignores them; once we have
> made all the users of the device correctly wire up the new Clocks we
> will switch the implementation to use them and ignore the old
> system_clock_scale.
>
> This is a migration compat break for all M-profile boards, because of
> the addition of the new clock objects to the vmstate struct.
>
> Signed-off-by: Peter Maydell 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  include/hw/timer/armv7m_systick.h |  7 +++
>  hw/timer/armv7m_systick.c | 10 --
>  2 files changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/include/hw/timer/armv7m_systick.h 
> b/include/hw/timer/armv7m_systick.h
> index 685fc5bc0d7..38adf8d274e 100644
> --- a/include/hw/timer/armv7m_systick.h
> +++ b/include/hw/timer/armv7m_systick.h
> @@ -15,6 +15,7 @@
>  #include "hw/sysbus.h"
>  #include "qom/object.h"
>  #include "hw/ptimer.h"
> +#include "hw/clock.h"
>
>  #define TYPE_SYSTICK "armv7m_systick"
>
> @@ -25,6 +26,10 @@ OBJECT_DECLARE_SIMPLE_TYPE(SysTickState, SYSTICK)
>   *  + sysbus MMIO region 0 is the register interface (covering
>   *the registers which are mapped at address 0xE000E010)
>   *  + sysbus IRQ 0 is the interrupt line to the NVIC
> + *  + Clock input "refclk" is the external reference clock
> + *(used when SYST_CSR.CLKSOURCE == 0)
> + *  + Clock input "cpuclk" is the main CPU clock
> + *(used when SYST_CSR.CLKSOURCE == 1)
>   */
>
>  struct SysTickState {
> @@ -38,6 +43,8 @@ struct SysTickState {
>  ptimer_state *ptimer;
>  MemoryRegion iomem;
>  qemu_irq irq;
> +Clock *refclk;
> +Clock *cpuclk;
>  };
>
>  /*
> diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
> index 2f192011eb0..e43f74114e8 100644
> --- a/hw/timer/armv7m_systick.c
> +++ b/hw/timer/armv7m_systick.c
> @@ -14,6 +14,7 @@
>  #include "migration/vmstate.h"
>  #include "hw/irq.h"
>  #include "hw/sysbus.h"
> +#include "hw/qdev-clock.h"
>  #include "qemu/timer.h"
>  #include "qemu/log.h"
>  #include "qemu/module.h"
> @@ -201,6 +202,9 @@ static void systick_instance_init(Object *obj)
>  memory_region_init_io(&s->iomem, obj, &systick_ops, s, "systick", 0xe0);
>  sysbus_init_mmio(sbd, &s->iomem);
>  sysbus_init_irq(sbd, &s->irq);
> +
> +s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk", NULL, NULL, 0);
> +s->cpuclk = qdev_init_clock_in(DEVICE(obj), "cpuclk", NULL, NULL, 0);
>  }
>
>  static void systick_realize(DeviceState *dev, Error **errp)
> @@ -215,9 +219,11 @@ static void systick_realize(DeviceState *dev, Error 
> **errp)
>
>  static const VMStateDescription vmstate_systick = {
>  .name = "armv7m_systick",
> -.version_id = 2,
> -.minimum_version_id = 2,
> +.version_id = 3,
> +.minimum_version_id = 3,
>  .fields = (VMStateField[]) {
> +VMSTATE_CLOCK(refclk, SysTickState),
> +VMSTATE_CLOCK(cpuclk, SysTickState),
>  VMSTATE_UINT32(control, SysTickState),
>  VMSTATE_INT64(tick, SysTickState),
>  VMSTATE_PTIMER(ptimer, SysTickState),
> --
> 2.20.1
>
>



Re: [PATCH for-6.2 04/25] hw/timer/armv7m_systick: Add usual QEMU interface comment

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 7:34 PM Peter Maydell  wrote:
>
> Add the usual-style QEMU interface comment documenting what
> properties, etc, this device exposes.
>
> Signed-off-by: Peter Maydell 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  include/hw/timer/armv7m_systick.h | 7 +++
>  1 file changed, 7 insertions(+)
>
> diff --git a/include/hw/timer/armv7m_systick.h 
> b/include/hw/timer/armv7m_systick.h
> index 84496faaf96..685fc5bc0d7 100644
> --- a/include/hw/timer/armv7m_systick.h
> +++ b/include/hw/timer/armv7m_systick.h
> @@ -20,6 +20,13 @@
>
>  OBJECT_DECLARE_SIMPLE_TYPE(SysTickState, SYSTICK)
>
> +/*
> + * QEMU interface:
> + *  + sysbus MMIO region 0 is the register interface (covering
> + *the registers which are mapped at address 0xE000E010)
> + *  + sysbus IRQ 0 is the interrupt line to the NVIC
> + */
> +
>  struct SysTickState {
>  /*< private >*/
>  SysBusDevice parent_obj;
> --
> 2.20.1
>
>



Re: [PATCH for-6.2 02/25] arm: Move systick device creation from NVIC to ARMv7M object

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 7:36 PM Peter Maydell  wrote:
>
> There's no particular reason why the NVIC should be owning the
> SysTick device objects; move them into the ARMv7M container object
> instead, as part of consolidating the "create the devices which are
> built into an M-profile CPU and map them into their architected
> locations in the address space" work into one place.
>
> This involves temporarily creating a duplicate copy of the
> nvic_sysreg_ns_ops struct and its read/write functions (renamed as
> v7m_sysreg_ns_*), but we will delete the NVIC's copy of this code in
> a subsequent patch.
>
> Signed-off-by: Peter Maydell 

Acked-by: Alistair Francis 

Alistair

> ---
>  include/hw/arm/armv7m.h   |  12 
>  include/hw/intc/armv7m_nvic.h |   4 --
>  hw/arm/armv7m.c   | 125 ++
>  hw/intc/armv7m_nvic.c |  73 
>  4 files changed, 137 insertions(+), 77 deletions(-)
>
> diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
> index 4cae0d7eeaa..360c35c5fb2 100644
> --- a/include/hw/arm/armv7m.h
> +++ b/include/hw/arm/armv7m.h
> @@ -60,11 +60,23 @@ struct ARMv7MState {
>  BitBandState bitband[ARMV7M_NUM_BITBANDS];
>  ARMCPU *cpu;
>  ARMv7MRAS ras;
> +SysTickState systick[M_REG_NUM_BANKS];
>
>  /* MemoryRegion we pass to the CPU, with our devices layered on
>   * top of the ones the board provides in board_memory.
>   */
>  MemoryRegion container;
> +/*
> + * MemoryRegion which passes the transaction to either the S or the
> + * NS systick device depending on the transaction attributes
> + */
> +MemoryRegion systickmem;
> +/*
> + * MemoryRegion which enforces the S/NS handling of the systick
> + * device NS alias region and passes the transaction to the
> + * NS systick device if appropriate.
> + */
> +MemoryRegion systick_ns_mem;
>
>  /* Properties */
>  char *cpu_type;
> diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
> index 33b6d8810c7..6a6a99090c7 100644
> --- a/include/hw/intc/armv7m_nvic.h
> +++ b/include/hw/intc/armv7m_nvic.h
> @@ -81,16 +81,12 @@ struct NVICState {
>
>  MemoryRegion sysregmem;
>  MemoryRegion sysreg_ns_mem;
> -MemoryRegion systickmem;
> -MemoryRegion systick_ns_mem;
>  MemoryRegion container;
>  MemoryRegion defaultmem;
>
>  uint32_t num_irq;
>  qemu_irq excpout;
>  qemu_irq sysresetreq;
> -
> -SysTickState systick[M_REG_NUM_BANKS];
>  };
>
>  #endif
> diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
> index 8964730d153..364ac069702 100644
> --- a/hw/arm/armv7m.c
> +++ b/hw/arm/armv7m.c
> @@ -124,6 +124,85 @@ static const hwaddr 
> bitband_output_addr[ARMV7M_NUM_BITBANDS] = {
>  0x2200, 0x4200
>  };
>
> +static MemTxResult v7m_sysreg_ns_write(void *opaque, hwaddr addr,
> +   uint64_t value, unsigned size,
> +   MemTxAttrs attrs)
> +{
> +MemoryRegion *mr = opaque;
> +
> +if (attrs.secure) {
> +/* S accesses to the alias act like NS accesses to the real region */
> +attrs.secure = 0;
> +return memory_region_dispatch_write(mr, addr, value,
> +size_memop(size) | MO_TE, attrs);
> +} else {
> +/* NS attrs are RAZ/WI for privileged, and BusFault for user */
> +if (attrs.user) {
> +return MEMTX_ERROR;
> +}
> +return MEMTX_OK;
> +}
> +}
> +
> +static MemTxResult v7m_sysreg_ns_read(void *opaque, hwaddr addr,
> +  uint64_t *data, unsigned size,
> +  MemTxAttrs attrs)
> +{
> +MemoryRegion *mr = opaque;
> +
> +if (attrs.secure) {
> +/* S accesses to the alias act like NS accesses to the real region */
> +attrs.secure = 0;
> +return memory_region_dispatch_read(mr, addr, data,
> +   size_memop(size) | MO_TE, attrs);
> +} else {
> +/* NS attrs are RAZ/WI for privileged, and BusFault for user */
> +if (attrs.user) {
> +return MEMTX_ERROR;
> +}
> +*data = 0;
> +return MEMTX_OK;
> +}
> +}
> +
> +static const MemoryRegionOps v7m_sysreg_ns_ops = {
> +.read_with_attrs = v7m_sysreg_ns_read,
> +.write_with_attrs = v7m_sysreg_ns_write,
> +.endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static MemTxResult v7m_systick_write(void *opaque, hwaddr addr,
> + uint64_t value, unsigned size,
> + MemTxAttrs attrs)
> +{
> +ARMv7MState *s = opaque;
> +MemoryRegion *mr;
> +
> +/* Direct the access to the correct systick */
> +mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systick[attrs.secure]), 
> 0);
> +return memory_region_dispatch_write(mr, addr, value,
> +  

Re: [PATCH for-6.2 01/25] arm: Move M-profile RAS register block into its own device

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 7:34 PM Peter Maydell  wrote:
>
> Currently we implement the RAS register block within the NVIC device.
> It isn't really very tightly coupled with the NVIC proper, so instead
> move it out into a sysbus device of its own and have the top level
> ARMv7M container create it and map it into memory at the right
> address.
>
> Signed-off-by: Peter Maydell 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  include/hw/arm/armv7m.h   |  2 +
>  include/hw/intc/armv7m_nvic.h |  1 -
>  include/hw/misc/armv7m_ras.h  | 37 ++
>  hw/arm/armv7m.c   | 12 +
>  hw/intc/armv7m_nvic.c | 56 -
>  hw/misc/armv7m_ras.c  | 93 +++
>  MAINTAINERS   |  2 +
>  hw/misc/meson.build   |  2 +
>  8 files changed, 148 insertions(+), 57 deletions(-)
>  create mode 100644 include/hw/misc/armv7m_ras.h
>  create mode 100644 hw/misc/armv7m_ras.c
>
> diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
> index bc6733c5184..4cae0d7eeaa 100644
> --- a/include/hw/arm/armv7m.h
> +++ b/include/hw/arm/armv7m.h
> @@ -12,6 +12,7 @@
>
>  #include "hw/sysbus.h"
>  #include "hw/intc/armv7m_nvic.h"
> +#include "hw/misc/armv7m_ras.h"
>  #include "target/arm/idau.h"
>  #include "qom/object.h"
>
> @@ -58,6 +59,7 @@ struct ARMv7MState {
>  NVICState nvic;
>  BitBandState bitband[ARMV7M_NUM_BITBANDS];
>  ARMCPU *cpu;
> +ARMv7MRAS ras;
>
>  /* MemoryRegion we pass to the CPU, with our devices layered on
>   * top of the ones the board provides in board_memory.
> diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
> index 39c71e15936..33b6d8810c7 100644
> --- a/include/hw/intc/armv7m_nvic.h
> +++ b/include/hw/intc/armv7m_nvic.h
> @@ -83,7 +83,6 @@ struct NVICState {
>  MemoryRegion sysreg_ns_mem;
>  MemoryRegion systickmem;
>  MemoryRegion systick_ns_mem;
> -MemoryRegion ras_mem;
>  MemoryRegion container;
>  MemoryRegion defaultmem;
>
> diff --git a/include/hw/misc/armv7m_ras.h b/include/hw/misc/armv7m_ras.h
> new file mode 100644
> index 000..f8773e65b14
> --- /dev/null
> +++ b/include/hw/misc/armv7m_ras.h
> @@ -0,0 +1,37 @@
> +/*
> + * Arm M-profile RAS block
> + *
> + * Copyright (c) 2021 Linaro Limited
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 or
> + *  (at your option) any later version.
> + */
> +
> +/*
> + * This is a model of the RAS register block of an M-profile CPU
> + * (the registers starting at 0xE0005000 with ERRFRn).
> + *
> + * QEMU interface:
> + *  + sysbus MMIO region 0: the register bank
> + *
> + * The QEMU implementation currently provides "minimal RAS" only.
> + */
> +
> +#ifndef HW_MISC_ARMV7M_RAS_H
> +#define HW_MISC_ARMV7M_RAS_H
> +
> +#include "hw/sysbus.h"
> +
> +#define TYPE_ARMV7M_RAS "armv7m-ras"
> +OBJECT_DECLARE_SIMPLE_TYPE(ARMv7MRAS, ARMV7M_RAS)
> +
> +struct ARMv7MRAS {
> +/*< private >*/
> +SysBusDevice parent_obj;
> +
> +/*< public >*/
> +MemoryRegion iomem;
> +};
> +
> +#endif
> diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
> index 9ce5c30cd5c..8964730d153 100644
> --- a/hw/arm/armv7m.c
> +++ b/hw/arm/armv7m.c
> @@ -231,6 +231,18 @@ static void armv7m_realize(DeviceState *dev, Error 
> **errp)
>  memory_region_add_subregion(&s->container, 0xe000,
>  sysbus_mmio_get_region(sbd, 0));
>
> +/* If the CPU has RAS support, create the RAS register block */
> +if (cpu_isar_feature(aa32_ras, s->cpu)) {
> +object_initialize_child(OBJECT(dev), "armv7m-ras",
> +&s->ras, TYPE_ARMV7M_RAS);
> +sbd = SYS_BUS_DEVICE(&s->ras);
> +if (!sysbus_realize(sbd, errp)) {
> +return;
> +}
> +memory_region_add_subregion_overlap(&s->container, 0xe0005000,
> +sysbus_mmio_get_region(sbd, 0), 
> 1);
> +}
> +
>  for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
>  if (s->enable_bitband) {
>  Object *obj = OBJECT(&s->bitband[i]);
> diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
> index 1e7ddcb94cb..a5975592dfa 100644
> --- a/hw/intc/armv7m_nvic.c
> +++ b/hw/intc/armv7m_nvic.c
> @@ -2549,56 +2549,6 @@ static const MemoryRegionOps nvic_systick_ops = {
>  .endianness = DEVICE_NATIVE_ENDIAN,
>  };
>
> -
> -static MemTxResult ras_read(void *opaque, hwaddr addr,
> -uint64_t *data, unsigned size,
> -MemTxAttrs attrs)
> -{
> -if (attrs.user) {
> -return MEMTX_ERROR;
> -}
> -
> -switch (addr) {
> -case 0xe10: /* ERRIIDR */
> -/* architect field = Arm; product/variant/revision 0 */
> -*data = 0x43b;
> -break;
> -case 0xfc8: /* ERRDEVID */
> -/* Minimal RAS: we implement 0 error record

Re: [PATCH] hw/riscv/virt.c: Assemble plic_hart_config string with g_strjoinv()

2021-08-12 Thread Alistair Francis
On Fri, Aug 13, 2021 at 2:17 AM Philippe Mathieu-Daudé  wrote:
>
> Hi Peter,
>
> On 8/12/21 4:46 PM, Peter Maydell wrote:
> > In the riscv virt machine init function, We assemble a string
> > plic_hart_config which is a comma-separated list of N copies of the
> > VIRT_PLIC_HART_CONFIG string.  The code that does this has a
> > misunderstanding of the strncat() length argument.  If the source
> > string is too large strncat() will write a maximum of length+1 bytes
> > (length bytes from the source string plus a trailing NUL), but the
> > code here assumes that it will write only length bytes at most.
> >
> > This isn't an actual bug because the code has correctly precalculated
> > the amount of memory it needs to allocate so that it will never be
> > too small (i.e.  we could have used plain old strcat()), but it does
> > mean that the code looks like it has a guard against accidental
> > overrun when it doesn't.
> >
> > Rewrite the string handling here to use the glib g_strjoinv()
> > function, which means we don't need to do careful accountancy of
> > string lengths, and makes it clearer that what we're doing is
> > "create a comma-separated string".
> >
> > Fixes: Coverity 1460752
> > Signed-off-by: Peter Maydell 
> > ---
> >  hw/riscv/virt.c | 33 -
> >  1 file changed, 20 insertions(+), 13 deletions(-)
> >
> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> > index 4a3cd2599a5..26bc8d289ba 100644
> > --- a/hw/riscv/virt.c
> > +++ b/hw/riscv/virt.c
> > @@ -541,6 +541,24 @@ static FWCfgState *create_fw_cfg(const MachineState 
> > *mc)
> >  return fw_cfg;
> >  }
> >
> > +/*
> > + * Return the per-socket PLIC hart topology configuration string
> > + * (caller must free with g_free())
> > + */
> > +static char *plic_hart_config_string(int hart_count)
> > +{
> > +g_autofree const char **vals = g_new(const char *, hart_count + 1);
> > +int i;
> > +
> > +for (i = 0; i < hart_count; i++) {
> > +vals[i] = VIRT_PLIC_HART_CONFIG;
>
> Have you considered adding plic_hart_config_string() an extra
> 'const char *plic_config' argument (declaring it in a new
> include/hw/riscv/plic_hart.h)?
> We could use it in the other boards:
>
> hw/riscv/microchip_pfsoc.c:267:strncat(plic_hart_config, ","
> MICROCHIP_PFSOC_PLIC_HART_CONFIG,
> hw/riscv/microchip_pfsoc.c:268:plic_hart_config_len);
> hw/riscv/microchip_pfsoc.c:270:strncat(plic_hart_config,
> "M", plic_hart_config_len);
>
> hw/riscv/sifive_u.c:826:strncat(plic_hart_config, ","
> SIFIVE_U_PLIC_HART_CONFIG,
> hw/riscv/sifive_u.c:827:plic_hart_config_len);
> hw/riscv/sifive_u.c:829:strncat(plic_hart_config, "M",
> plic_hart_config_len);
>
> hw/riscv/virt.c:612:strncat(plic_hart_config, ",",
> plic_hart_config_len);
> hw/riscv/virt.c:614:strncat(plic_hart_config,
> VIRT_PLIC_HART_CONFIG,
> hw/riscv/virt.c:615:plic_hart_config_len);
>
> include/hw/riscv/microchip_pfsoc.h:141:#define
> MICROCHIP_PFSOC_PLIC_HART_CONFIG"MS"
> include/hw/riscv/shakti_c.h:63:#define SHAKTI_C_PLIC_HART_CONFIG "MS"
> include/hw/riscv/sifive_e.h:83:#define SIFIVE_E_PLIC_HART_CONFIG "M"
> include/hw/riscv/sifive_u.h:147:#define SIFIVE_U_PLIC_HART_CONFIG "MS"
> include/hw/riscv/virt.h:74:#define VIRT_PLIC_HART_CONFIG "MS"
>
> Obviously someone else could do that as bytetask, so meanwhile
> for Coverity 1460752:
> Reviewed-by: Philippe Mathieu-Daudé 

Thanks for fixing this Peter. Would you like this in for 6.1?

If you want I can fix the other boards?

Reviewed-by: Alistair Francis 

Alistair



Re: [PATCH v2] target/riscv: Don't wrongly override isa version

2021-08-12 Thread Alistair Francis
On Thu, Aug 12, 2021 at 12:46 AM LIU Zhiwei  wrote:
>
> For some cpu, the isa version has already been set in cpu init function.
> Thus only override the isa version when isa version is not set, or
> users set different isa version explicitly by cpu parameters.
>
> Signed-off-by: LIU Zhiwei 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.c | 14 --
>  1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 991a6bb760..1a2b03d579 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -392,9 +392,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> **errp)
>  RISCVCPU *cpu = RISCV_CPU(dev);
>  CPURISCVState *env = &cpu->env;
>  RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
> -int priv_version = PRIV_VERSION_1_11_0;
> -int bext_version = BEXT_VERSION_0_93_0;
> -int vext_version = VEXT_VERSION_0_07_1;
> +int priv_version = 0;
>  target_ulong target_misa = env->misa;
>  Error *local_err = NULL;
>
> @@ -417,9 +415,11 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> **errp)
>  }
>  }
>
> -set_priv_version(env, priv_version);
> -set_bext_version(env, bext_version);
> -set_vext_version(env, vext_version);
> +if (priv_version) {
> +set_priv_version(env, priv_version);
> +} else if (!env->priv_ver) {
> +set_priv_version(env, PRIV_VERSION_1_11_0);
> +}
>
>  if (cpu->cfg.mmu) {
>  set_feature(env, RISCV_FEATURE_MMU);
> @@ -497,6 +497,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> **errp)
>  target_misa |= RVH;
>  }
>  if (cpu->cfg.ext_b) {
> +int bext_version = BEXT_VERSION_0_93_0;
>  target_misa |= RVB;
>
>  if (cpu->cfg.bext_spec) {
> @@ -515,6 +516,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> **errp)
>  set_bext_version(env, bext_version);
>  }
>  if (cpu->cfg.ext_v) {
> +int vext_version = VEXT_VERSION_0_07_1;
>  target_misa |= RVV;
>  if (!is_power_of_2(cpu->cfg.vlen)) {
>  error_setg(errp,
> --
> 2.25.1
>
>



Re: [PATCH 12/19] target/ppc/pmu_book3s_helper.c: enable PMC1 counter negative EBB

2021-08-12 Thread Richard Henderson

On 8/12/21 11:24 AM, Daniel Henrique Barboza wrote:

+void helper_insns_inc(CPUPPCState *env)
+{
+    env->pmu_insns_count++;
+}
+
+void helper_insns_dec(CPUPPCState *env)
+{
+    env->pmu_insns_count--;
+}
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 60f35360b7..c56c656694 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -8689,6 +8689,7 @@ static void ppc_tr_tb_start(DisasContextBase *db, 
CPUState *cs)

  static void ppc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
  {
+    gen_helper_insns_inc(cpu_env);
  tcg_gen_insn_start(dcbase->pc_next);
  }

@@ -8755,6 +8756,8 @@ static void ppc_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cs)
  return;
  }

+    gen_helper_insns_dec(cpu_env);
+
  /* Honor single stepping. */
  sse = ctx->singlestep_enabled & (CPU_SINGLE_STEP | GDBSTUB_SINGLE_STEP);
  if (unlikely(sse)) {


And then I used 'env->pmu_insns_count' to update the instruction counters. And 
it's
working, with a slightly better performance than we have with the icount()
version. I'm not sure why it's working now since I tried something very similar
before and it didn't. Figures.


Not sure why you're decrementing there.

Also, how do you want to count retired instructions? Ones that merely start?  E.g. 
including loads that fault?  How about illegal instructions?  Or does the instruction need 
to run to completion?  Which of these you choose affects where you place the increment.


It is of course extremely heavyweight to call a helper to perform a simple 
addition operation.

You may also wish to look at target/hexagon, gen_exec_counters(), which is doing the same 
sort of thing.  But not completely, since it loses count along dynamic exception paths 
(e.g. faulting load).  That can be fixed as well, via restore_state_to_opc.



r~



Re: [PATCH 12/19] target/ppc/pmu_book3s_helper.c: enable PMC1 counter negative EBB

2021-08-12 Thread Daniel Henrique Barboza




On 8/12/21 7:17 AM, Daniel Henrique Barboza wrote:



On 8/12/21 1:56 AM, Richard Henderson wrote:

On 8/11/21 6:45 PM, Richard Henderson wrote:

On 8/11/21 5:39 PM, David Gibson wrote:

I mean, nothing is stopping us from calculating cycles using time, but in the
end we would do the same thing we're already doing today.


Oh.. ok.  I had assumed that icount worked by instrumenting the
generate TCG code to actually count instructions, rather than working
off the time.


David, you're right, icount instruments the generated tcg code.
You also have to add -icount to the command-line.


Oh, and btw, icount disables multi-threaded tcg, so you're going to be running 
that guest in round-robin mode.

Icount affects so many aspects of qemu that I really do not think it is the 
best option for a PMU.


Using icount in the PMU is my fallback plan. I spent some time trying to
count instructions using translationOps but never got it right. I got
up to a point where the tests were counting instructions for the first
time it was run in the guest, then nothing else counted in consecutive
runs.

I was able to figure out that it had to do with how the translation block
works. If a previously ran TB was found via lookup then the translationOps
callbacks I was using weren't being called. I know that I was missing a
piece of info there, but since I'm trying to deal with other aspects of the
PMU logic I fell back into using icount to get things of the ground.



So, I made an attempt to remove all icount() references from the PMU code and 
instead
did the following (posting just the relevant diff):


+
+void helper_insns_inc(CPUPPCState *env)
+{
+env->pmu_insns_count++;
+}
+
+void helper_insns_dec(CPUPPCState *env)
+{
+env->pmu_insns_count--;
+}
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 60f35360b7..c56c656694 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -8689,6 +8689,7 @@ static void ppc_tr_tb_start(DisasContextBase *db, 
CPUState *cs)
 
 static void ppc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)

 {
+gen_helper_insns_inc(cpu_env);
 tcg_gen_insn_start(dcbase->pc_next);
 }
 
@@ -8755,6 +8756,8 @@ static void ppc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)

 return;
 }
 
+gen_helper_insns_dec(cpu_env);

+
 /* Honor single stepping. */
 sse = ctx->singlestep_enabled & (CPU_SINGLE_STEP | GDBSTUB_SINGLE_STEP);
 if (unlikely(sse)) {


And then I used 'env->pmu_insns_count' to update the instruction counters. And 
it's
working, with a slightly better performance than we have with the icount()
version. I'm not sure why it's working now since I tried something very similar
before and it didn't. Figures.

It's still overshooting the instructions a bit, but then there's the 
optimization
you mentioned previously with the tb lookup logic that could be done to improve
that as well.


I'm not sure if this is in line or close with what you proposed, but it's 
already
better than the icount version that I posted here.


Thanks,


Daniel




All this said 



If you want to count instructions retired, then just do that.  Stuff values 
into tcg_gen_insn_start so they're available for exception unwind, and 
otherwise decrement the counter at the end of a TB.


... I don't bother giving this a try. Can you clarify what do you mean
with "exception unwind"?

I tried something similar with tcg_gen_insn_start() (called via 
ppc_tr_insn_start()).
This this ops is called inside translator_loop(), and translator_loop() isn't
being ran if TB_lookup returns the TB, I was observing the behavior I
described above of a test counting instructions in its first run only.




If you really must interrupt exactly at 0 (and not simply at some point past 
underflow), then we can adjust the tb lookup logic to let you reduce 
tb->cflags.CF_COUNT_MASK in cpu_get_tb_cpu_state.


That would be good, but depending on the amount of work I would consider doing
this is a follow-up of this work. It's ok if the PMU overflows a bit 
instructions
for our current purposes ATM.


Thanks,


Daniel




r~




Re: [RFC PATCH] target/ppc: fix vector registers access in gdbstub for little-endian

2021-08-12 Thread Richard Henderson

On 8/12/21 9:10 AM, matheus.fe...@eldorado.org.br wrote:

  static bool avr_need_swap(CPUPPCState *env)
  {
+bool le;
+#if defined(CONFIG_USER_ONLY)
+le = false;
+#else
+le = msr_le;
+#endif


It certainly doesn't seem like the right fix.

My first guess was that MSR_LE wasn't being properly set up at cpu_reset for user-only, 
but it's there.



r~



Re: [PATCH v2 16/22] target/loongarch: Add floating point move instruction translation

2021-08-12 Thread Richard Henderson

On 8/11/21 11:20 PM, Song Gao wrote:

This is easily implemented inline, followed by a single helper call to re-load 
the rounding mode (if required by the mask).


Hi, Richard,

Sorry to bother you, When I was revising this patch, I found that I didn't seem 
to
understand your opinion. Could you explain it in detail?  thank you very much.

---%<

static const uint32_t fcsr_mask[4] = {
UINT32_MAX, FCSR0_M1, FCSR0_M2, FCSR0_M3
};

bool trans_movgr2fcsr(DisasContext *s, arg_movgr2fcsr *a)
{
uint32_t mask = fcsr_mask[a->fcsr];

if (mask == UINT32_MAX) {
tcg_gen_extrl_i64_i32(fpu_fscr0, get_gpr(a->rj));
} else {
TCGv_i32 tmp = tcg_temp_new_i32();

tcg_gen_extrl_i64_i32(tmp, get_gpr(a->rj));
tcg_gen_andi_i32(tmp, tmp, mask);
tcg_gen_andi_i32(fpu_fcsr0, cpu_fcsr0, ~mask);
tcg_gen_or_i32(fpu_fcsr0, fpu_fcsr0, tmp);
tcg_temp_free_i32(tmp);

/*
 * Install the new rounding mode to fpu_status, if changed.
 * Note that FCSR3 is exactly the rounding mode field.
 */
if (mask != FCSR0_M3) {
return true;
}
}
gen_helper_set_rounding_mode(cpu_env, fpu_fcsr0);
return true;
}

void trans_movfcsr2gr(DisasContext *s, arg_movfcsr2gr *a)
{
TCGv_i32 tmp = tcg_temp_new_i32();

tcg_gen_andi_i32(tmp, fpu_fcsr0, fcsr_mask[a->fcsr]);
tcg_gen_ext_i32_i64(dest_gpr(a->rd), tmp);
tcg_temp_free_i32(tmp);
return true;
}

---%<

DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32)

---%<

void HELPER(set_rounding_mode)(CPULoongArchState *env, uint32_t fcsr)
{
set_float_rounding_mode(ieee_rm[(fcsr0 >> FCSR0_RM) & 0x3],
&env->fp_status);
}


r~



Re: [PATCH for-6.1] tcg/i386: Split P_VEXW from P_REXW

2021-08-12 Thread Peter Maydell
On Thu, 12 Aug 2021 at 19:29, Richard Henderson
 wrote:
>
> PIng for review, or this slips to 6.2.
>
> On 8/10/21 1:25 PM, Richard Henderson wrote:
> > We need to be able to represent VEX.W on a 32-bit host, where REX.W
> > will always be zero.  Fixes the encoding for VPSLLVQ and VPSRLVQ.
> >
> > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/385
> > Signed-off-by: Richard Henderson 

Bug report says this isn't a regression since 6.0, and reporter
says there's still issues with this fix, so I think this is
probably going to go into 6.2 anyway. At any rate, I don't
think it's sufficiently rc to make us spin an rc4 if we weren't
going to anyway.

-- PMM



[RFC PATCH] target/ppc: fix vector registers access in gdbstub for little-endian

2021-08-12 Thread matheus . ferst
From: Matheus Ferst 

It seems that access to elements of ppc_avr_t should only depend on
msr_le when !CONFIG_USER_ONLY.

Signed-off-by: Matheus Ferst 
---
To reproduce the problem, build the following program for ppc64le:

int main(void)
{
__uint128_t a = 0x1122334455667788llu;
a <<= 64;
a |= 0xAABBCCDDEEFFAABBllu;
asm volatile ("xxlor 4, %x0, %x0\n\t"
  "xxlor 34, %x0, %x0\n\t"
  :: "wa" (a) : "vs4", "vs34");
return 0;
}

Run it with qemu-ppc64le, attach gdb, place a breakpoint after the
second xxlor and print vs4 and vs34:
Breakpoint 1, 0x1d88 in main ()
(gdb) p/x $vs4
$1 = {uint128 = 0x1122334455667788aabbccddeeffaabb, v2_double = {0x0,
0x0}, v4_float = {0x0, 0x0, 0x7880, 0x0}, v4_int32 = {
0xeeffaabb, 0xaabbccdd, 0x55667788, 0x11223344}, v8_int16 = {
0xaabb, 0xeeff, 0xccdd, 0xaabb, 0x7788, 0x5566, 0x3344, 0x1122},
  v16_int8 = {0xbb, 0xaa, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x88,
0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11}}
(gdb) p/x $vs34
$2 = {uint128 = 0xaabbccddeeffaabb1122334455667788, v2_double = {0x0,
0x0}, v4_float = {0x7880, 0x0, 0x0, 0x0}, v4_int32 = {
0x55667788, 0x11223344, 0xeeffaabb, 0xaabbccdd}, v8_int16 = {
0x7788, 0x5566, 0x3344, 0x1122, 0xaabb, 0xeeff, 0xccdd, 0xaabb},
  v16_int8 = {0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0xbb,
0xaa, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}}

RFC because I'm not quite sure about the fix.
---
 target/ppc/gdbstub.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index 09ff1328d4..779e4a4e3f 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -391,10 +391,16 @@ const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const 
char *xml_name)
 
 static bool avr_need_swap(CPUPPCState *env)
 {
+bool le;
+#if defined(CONFIG_USER_ONLY)
+le = false;
+#else
+le = msr_le;
+#endif
 #ifdef HOST_WORDS_BIGENDIAN
-return msr_le;
+return le;
 #else
-return !msr_le;
+return !le;
 #endif
 }
 
-- 
2.25.1




[PULL 0/1] Bug fix for -rc4

2021-08-12 Thread Eduardo Habkost
This is a bug fix to be included in case we are going to have a
6.1.0-rc4.  I don't think this bug alone should delay the release
of QEMU 6.1.0.

The following changes since commit 703e8cd6189cf699c8d5c094bc68b5f3afa6ad71:

  Update version for v6.1.0-rc3 release (2021-08-10 19:08:09 +0100)

are available in the Git repository at:

  https://gitlab.com/ehabkost/qemu.git tags/machine-next-pull-request

for you to fetch changes up to 0fa1eecc092feb5a4a373ff1fa761ad3a03ea2d9:

  hw/core: fix error checkig in smp_parse (2021-08-12 14:58:50 -0400)


Bug fix for -rc4

Bug fix:
* Fix error checkig in smp_parse (Daniel P. Berrangé)



Daniel P. Berrangé (1):
  hw/core: fix error checkig in smp_parse

 hw/core/machine.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

-- 
2.31.1





[PULL 1/1] hw/core: fix error checkig in smp_parse

2021-08-12 Thread Eduardo Habkost
From: Daniel P. Berrangé 

The machine_set_smp() mistakenly checks 'errp' not '*errp',
and so thinks there is an error every single time it runs.
This causes it to jump to the end of the method, skipping
the max CPUs checks. The caller meanwhile sees no error
and so carries on execution. The result of all this is:

 $ qemu-system-x86_64 -smp -1
 qemu-system-x86_64: GLib: ../glib/gmem.c:142: failed to allocate 481036337048 
bytes

instead of

 $ qemu-system-x86_64 -smp -1
 qemu-system-x86_64: Invalid SMP CPUs -1. The max CPUs supported by machine 
'pc-i440fx-6.1' is 255

This is a regression from

  commit fe68090e8fbd6e831aaf3fc3bb0459c5cccf14cf
  Author: Paolo Bonzini 
  Date:   Thu May 13 09:03:48 2021 -0400

machine: add smp compound property

Closes: https://gitlab.com/qemu-project/qemu/-/issues/524
Signed-off-by: Daniel P. Berrangé 
Message-Id: <20210812175353.4128471-1-berra...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/core/machine.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 943974d411c..ab4fca6546a 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -832,7 +832,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const 
char *name,
 }
 
 mc->smp_parse(ms, config, errp);
-if (errp) {
+if (*errp) {
 goto out_free;
 }
 
-- 
2.31.1




Re: [PATCH for-6.1 ?] hw/core: fix error checkig in smp_parse

2021-08-12 Thread Eduardo Habkost
On Thu, Aug 12, 2021 at 06:53:53PM +0100, Daniel P. Berrangé wrote:
> The machine_set_smp() mistakenly checks 'errp' not '*errp',
> and so thinks there is an error every single time it runs.
> This causes it to jump to the end of the method, skipping
> the max CPUs checks. The caller meanwhile sees no error
> and so carries on execution. The result of all this is:
> 
>  $ qemu-system-x86_64 -smp -1
>  qemu-system-x86_64: GLib: ../glib/gmem.c:142: failed to allocate 
> 481036337048 bytes
> 
> instead of
> 
>  $ qemu-system-x86_64 -smp -1
>  qemu-system-x86_64: Invalid SMP CPUs -1. The max CPUs supported by machine 
> 'pc-i440fx-6.1' is 255
> 
> This is a regression from
> 
>   commit fe68090e8fbd6e831aaf3fc3bb0459c5cccf14cf
>   Author: Paolo Bonzini 
>   Date:   Thu May 13 09:03:48 2021 -0400
> 
> machine: add smp compound property
> 
> Closes: https://gitlab.com/qemu-project/qemu/-/issues/524
> Signed-off-by: Daniel P. Berrangé 

I will prepare a pull request with this, just in case we are
already going to have a -rc4.  I don't think this bug alone
should delay release of 6.1, though.

> ---
>  hw/core/machine.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index 943974d411..ab4fca6546 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -832,7 +832,7 @@ static void machine_set_smp(Object *obj, Visitor *v, 
> const char *name,
>  }
>  
>  mc->smp_parse(ms, config, errp);
> -if (errp) {
> +if (*errp) {
>  goto out_free;
>  }
>  
> -- 
> 2.31.1
> 

-- 
Eduardo




Re: [PATCH for-6.1] tcg/i386: Split P_VEXW from P_REXW

2021-08-12 Thread Richard Henderson

PIng for review, or this slips to 6.2.

On 8/10/21 1:25 PM, Richard Henderson wrote:

We need to be able to represent VEX.W on a 32-bit host, where REX.W
will always be zero.  Fixes the encoding for VPSLLVQ and VPSRLVQ.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/385
Signed-off-by: Richard Henderson 
---
  tcg/i386/tcg-target.c.inc | 13 +++--
  1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 98d924b91a..997510109d 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -241,8 +241,9 @@ static bool tcg_target_const_match(int64_t val, TCGType 
type, int ct)
  #define P_EXT 0x100   /* 0x0f opcode prefix */
  #define P_EXT38 0x200   /* 0x0f 0x38 opcode prefix */
  #define P_DATA160x400   /* 0x66 opcode prefix */
+#define P_VEXW  0x1000  /* Set VEX.W = 1 */
  #if TCG_TARGET_REG_BITS == 64
-# define P_REXW 0x1000  /* Set REX.W = 1 */
+# define P_REXW P_VEXW  /* Set REX.W = 1; match VEXW */
  # define P_REXB_R   0x2000  /* REG field as byte register */
  # define P_REXB_RM  0x4000  /* R/M field as byte register */
  # define P_GS   0x8000  /* gs segment override */
@@ -410,13 +411,13 @@ static bool tcg_target_const_match(int64_t val, TCGType 
type, int ct)
  #define OPC_VPBROADCASTW (0x79 | P_EXT38 | P_DATA16)
  #define OPC_VPBROADCASTD (0x58 | P_EXT38 | P_DATA16)
  #define OPC_VPBROADCASTQ (0x59 | P_EXT38 | P_DATA16)
-#define OPC_VPERMQ  (0x00 | P_EXT3A | P_DATA16 | P_REXW)
+#define OPC_VPERMQ  (0x00 | P_EXT3A | P_DATA16 | P_VEXW)
  #define OPC_VPERM2I128  (0x46 | P_EXT3A | P_DATA16 | P_VEXL)
  #define OPC_VPSLLVD (0x47 | P_EXT38 | P_DATA16)
-#define OPC_VPSLLVQ (0x47 | P_EXT38 | P_DATA16 | P_REXW)
+#define OPC_VPSLLVQ (0x47 | P_EXT38 | P_DATA16 | P_VEXW)
  #define OPC_VPSRAVD (0x46 | P_EXT38 | P_DATA16)
  #define OPC_VPSRLVD (0x45 | P_EXT38 | P_DATA16)
-#define OPC_VPSRLVQ (0x45 | P_EXT38 | P_DATA16 | P_REXW)
+#define OPC_VPSRLVQ (0x45 | P_EXT38 | P_DATA16 | P_VEXW)
  #define OPC_VZEROUPPER  (0x77 | P_EXT)
  #define OPC_XCHG_ax_r32   (0x90)
  
@@ -576,7 +577,7 @@ static void tcg_out_vex_opc(TCGContext *s, int opc, int r, int v,
  
  /* Use the two byte form if possible, which cannot encode

 VEX.W, VEX.B, VEX.X, or an m- field other than P_EXT.  */
-if ((opc & (P_EXT | P_EXT38 | P_EXT3A | P_REXW)) == P_EXT
+if ((opc & (P_EXT | P_EXT38 | P_EXT3A | P_VEXW)) == P_EXT
  && ((rm | index) & 8) == 0) {
  /* Two byte VEX prefix.  */
  tcg_out8(s, 0xc5);
@@ -601,7 +602,7 @@ static void tcg_out_vex_opc(TCGContext *s, int opc, int r, 
int v,
  tmp |= (rm & 8 ? 0 : 0x20);/* VEX.B */
  tcg_out8(s, tmp);
  
-tmp = (opc & P_REXW ? 0x80 : 0);   /* VEX.W */

+tmp = (opc & P_VEXW ? 0x80 : 0);   /* VEX.W */
  }
  
  tmp |= (opc & P_VEXL ? 0x04 : 0);  /* VEX.L */







[PATCH 2/2] gitlab: don't run CI jobs by default on push to user forks

2021-08-12 Thread Daniel P . Berrangé
Currently pushes to user forks run the same set of build / test jobs as
pushes to the main repo. This results in creation of 120+ individual
jobs. While it is useful for subsystem maintainers, and even regular
contributors to be able to run the full set of jobs, it is wasteful to
run all of them all the time.

In addition, with the expected change in GitLab to set a finite CI
minute allowance on all users we need to be much more conservative.

This patch thus sets up rules so that no CI jobs will run by default
on push, except

 - Pushes to branch name prefix 'staging' on 'qemu-project' repo
   run full set of jobs
 - Pushes to 'master' branch, only run jobs needed to publish
   the website.

In any pushes to users forks, CI is now strictly opt-in. The pipeline
will always be created by every singe job will be marked manual. You
can then use the web UI to start individual jobs.

For more convenience there are three levels of increasing comprehensive
CI job sets that can be chosen between

 - Gating - run exactly the same as pushes to 'staging' branch
(except for jobs needing custom runners)

   Push to 'ci-gating-xxx' branch, or set env QEMU_CI_GATING=1

 - Full - same as 'Gating', except that acceptance tests don't
  get run. This is equivalent to historical CI behaviour
  for pushes to user forks.

   Push to 'ci-full-xxx' branch, or set env QEMU_CI_FULL=1

 - Minimal - a significantly cut down set of jobs to get a
 decent sanity check of builds without burning
 massive amounts of CI time.

   Push to 'ci-min-xxx' branch, or set env QEMU_CI=1

The minimal job set covers:

  * Fedora, CentOS, Ubuntu & Debian system emulator builds
to cover all arch targets.
  * Linux user static build
  * Cross build i386 (to identify any 32-bit build issues)
  * Cross build s390x (to identify any big endian build issues)
  * Containers needed for the above
  * Cirrus CI FreeBSD 12 and macOS 11 (to identify non-Linux issues)
  * Simple checks - python unittests, DCO check, checkpatch.pl, etc

This gives about 30 jobs instead of 120 from the "Full" group. It
is likely reasonable to cut the minimal set down even more, as IMHO
there are too many system emulator jobs there.

This is all controlled by defining a set of 'rules' entries that
apply to (almost) all jobs in the CI pipeline. The exceptions are
those using custom runners, and the firmware build jobs.

Using inherited templates together with rules, doesn't work in
the way you might expect. Any rules defined in the child completely
replace those from the parent, rather than augmenting them. Thus we
need to avoid having rules defined in any jobs at all, by inheriting
from a parent job template that contains the rules. The characteristics
of individual jobs are then defined by variables set against the job.
This is described in the updated content for the docs/devel/ci-jobs.rst
file.

Signed-off-by: Daniel P. Berrangé 
---
 .gitlab-ci.d/buildtest-template.yml  |  17 +--
 .gitlab-ci.d/buildtest.yml   |  43 
 .gitlab-ci.d/cirrus.yml  |   6 +-
 .gitlab-ci.d/container-core.yml  |   4 +
 .gitlab-ci.d/container-cross.yml |   9 +-
 .gitlab-ci.d/container-template.yml  |   1 +
 .gitlab-ci.d/containers.yml  |   4 +
 .gitlab-ci.d/crossbuild-template.yml |   3 +
 .gitlab-ci.d/crossbuilds.yml |   3 +
 .gitlab-ci.d/qemu-project.yml|   1 +
 .gitlab-ci.d/rules.yml   | 116 
 .gitlab-ci.d/static_checks.yml   |  18 ++--
 .gitlab-ci.yml   |   4 -
 docs/devel/ci-jobs.rst   | 155 ---
 14 files changed, 317 insertions(+), 67 deletions(-)
 create mode 100644 .gitlab-ci.d/rules.yml

diff --git a/.gitlab-ci.d/buildtest-template.yml 
b/.gitlab-ci.d/buildtest-template.yml
index fcbcc4e627..8578b3ed11 100644
--- a/.gitlab-ci.d/buildtest-template.yml
+++ b/.gitlab-ci.d/buildtest-template.yml
@@ -1,4 +1,6 @@
+
 .native_build_job_template:
+  extends: .job_rules
   stage: build
   image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
   before_script:
@@ -27,6 +29,7 @@
   fi
 
 .native_test_job_template:
+  extends: .job_rules
   stage: test
   image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
   script:
@@ -67,15 +70,5 @@
   after_script:
 - cd build
 - du -chs ${CI_PROJECT_DIR}/avocado-cache
-  rules:
-# Only run these jobs if running on the mainstream namespace,
-# or if the user set the QEMU_CI_AVOCADO_TESTING variable (either
-# in its namespace setting or via git-push option, see documentation
-# in /.gitlab-ci.yml of this repository).
-- if: '$CI_PROJECT_NAMESPACE == "qemu-project"'
-  when: on_success
-- if: '$QEMU_CI_AVOCADO_TESTING'
-  when: on_success
-# Otherwise, set to manual (the jobs are created but not run).
-- when: manual
-  allow_failure: true
+  variables:
+QEMU_JOB_GATING: 1
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/b

[PATCH 1/2] docs: split the CI docs into two files

2021-08-12 Thread Daniel P . Berrangé
This splits the CI docs into one file talking about job setup and usage
and another file describing provisioning of custom runners.

Signed-off-by: Daniel P. Berrangé 
---
 docs/devel/ci-jobs.rst|  40 ++
 docs/devel/ci-runners.rst | 117 
 docs/devel/ci.rst | 159 +-
 3 files changed, 159 insertions(+), 157 deletions(-)
 create mode 100644 docs/devel/ci-jobs.rst
 create mode 100644 docs/devel/ci-runners.rst

diff --git a/docs/devel/ci-jobs.rst b/docs/devel/ci-jobs.rst
new file mode 100644
index 00..9cd9819786
--- /dev/null
+++ b/docs/devel/ci-jobs.rst
@@ -0,0 +1,40 @@
+Custom CI/CD variables
+==
+
+QEMU CI pipelines can be tuned by setting some CI environment variables.
+
+Set variable globally in the user's CI namespace
+
+
+Variables can be set globally in the user's CI namespace setting.
+
+For further information about how to set these variables, please refer to::
+
+  https://docs.gitlab.com/ee/ci/variables/#add-a-cicd-variable-to-a-project
+
+Set variable manually when pushing a branch or tag to the user's repository
+---
+
+Variables can be set manually when pushing a branch or tag, using
+git-push command line arguments.
+
+Example setting the QEMU_CI_EXAMPLE_VAR variable:
+
+.. code::
+
+   git push -o ci.variable="QEMU_CI_EXAMPLE_VAR=value" myrepo mybranch
+
+For further information about how to set these variables, please refer to::
+
+  
https://docs.gitlab.com/ee/user/project/push_options.html#push-options-for-gitlab-cicd
+
+Here is a list of the most used variables:
+
+QEMU_CI_AVOCADO_TESTING
+~~~
+By default, tests using the Avocado framework are not run automatically in
+the pipelines (because multiple artifacts have to be downloaded, and if
+these artifacts are not already cached, downloading them make the jobs
+reach the timeout limit). Set this variable to have the tests using the
+Avocado framework run automatically.
+
diff --git a/docs/devel/ci-runners.rst b/docs/devel/ci-runners.rst
new file mode 100644
index 00..7817001fb2
--- /dev/null
+++ b/docs/devel/ci-runners.rst
@@ -0,0 +1,117 @@
+Jobs on Custom Runners
+==
+
+Besides the jobs run under the various CI systems listed before, there
+are a number additional jobs that will run before an actual merge.
+These use the same GitLab CI's service/framework already used for all
+other GitLab based CI jobs, but rely on additional systems, not the
+ones provided by GitLab as "shared runners".
+
+The architecture of GitLab's CI service allows different machines to
+be set up with GitLab's "agent", called gitlab-runner, which will take
+care of running jobs created by events such as a push to a branch.
+Here, the combination of a machine, properly configured with GitLab's
+gitlab-runner, is called a "custom runner".
+
+The GitLab CI jobs definition for the custom runners are located under::
+
+  .gitlab-ci.d/custom-runners.yml
+
+Custom runners entail custom machines.  To see a list of the machines
+currently deployed in the QEMU GitLab CI and their maintainers, please
+refer to the QEMU `wiki `__.
+
+Machine Setup Howto
+---
+
+For all Linux based systems, the setup can be mostly automated by the
+execution of two Ansible playbooks.  Create an ``inventory`` file
+under ``scripts/ci/setup``, such as this::
+
+  fully.qualified.domain
+  other.machine.hostname
+
+You may need to set some variables in the inventory file itself.  One
+very common need is to tell Ansible to use a Python 3 interpreter on
+those hosts.  This would look like::
+
+  fully.qualified.domain ansible_python_interpreter=/usr/bin/python3
+  other.machine.hostname ansible_python_interpreter=/usr/bin/python3
+
+Build environment
+~
+
+The ``scripts/ci/setup/build-environment.yml`` Ansible playbook will
+set up machines with the environment needed to perform builds and run
+QEMU tests.  This playbook consists on the installation of various
+required packages (and a general package update while at it).  It
+currently covers a number of different Linux distributions, but it can
+be expanded to cover other systems.
+
+The minimum required version of Ansible successfully tested in this
+playbook is 2.8.0 (a version check is embedded within the playbook
+itself).  To run the playbook, execute::
+
+  cd scripts/ci/setup
+  ansible-playbook -i inventory build-environment.yml
+
+Please note that most of the tasks in the playbook require superuser
+privileges, such as those from the ``root`` account or those obtained
+by ``sudo``.  If necessary, please refer to ``ansible-playbook``
+options such as ``--become``, ``--become-method``, ``--become-user``
+and ``--ask-become-pass``.
+
+gitlab-runner setup and registration
+~~~

[PATCH 0/2] gitlab: prepare for limited CI minutes by not running by default

2021-08-12 Thread Daniel P . Berrangé
A while ago GitLab announced it would be ending the free unlimited CI
minutes for public projects. It hasn't happened yet, but it is certainly
still on the radar. It is possible for OSS projects to get a greater
allowance, but it is still unclear how this will work for contributors'
forks. Even with the greater allowance, we'll burn through it in just
a few pipeline runs. People creating brand new gitlab accounts are
already getting hurt by the new limits IIUC.

This series isn't a full solution, but it gets us started in a more
sustainable direction. See the second patch commit message and the
docs that it adds for full details.

At a high level though, with this series applied, we no longer run
any CI jobs by default, except for the 'staging' branch in the
'qemu-project' namespace.

Users can manually start any individual job from the web UI still
though. Further, they can opt-in to various sets of jobs

 - 100% manual jobs (the new default):

https://gitlab.com/berrange/qemu/-/pipelines/352393697

 - A minimal set of jobs

https://gitlab.com/berrange/qemu/-/pipelines/352397093

 - A full set of jobs (the old default)

https://gitlab.com/berrange/qemu/-/pipelines/352123582

 - A gating set of jobs (identical to what's run on staging)

https://gitlab.com/berrange/qemu/-/pipelines/352195185

With this starting point, the common "rules" definition across
all jobs, makes it easy for us to add more refinements. We can
defining further sets of interesting jobs.

eg could define a set of cross-compilation, or a set for
non-Linux, or a set of Windows, or sets for particular host
architectures, etc.

Daniel P. Berrangé (2):
  docs: split the CI docs into two files
  gitlab: don't run CI jobs by default on push to user forks

 .gitlab-ci.d/buildtest-template.yml  |  17 +--
 .gitlab-ci.d/buildtest.yml   |  43 +++
 .gitlab-ci.d/cirrus.yml  |   6 +-
 .gitlab-ci.d/container-core.yml  |   4 +
 .gitlab-ci.d/container-cross.yml |   9 +-
 .gitlab-ci.d/container-template.yml  |   1 +
 .gitlab-ci.d/containers.yml  |   4 +
 .gitlab-ci.d/crossbuild-template.yml |   3 +
 .gitlab-ci.d/crossbuilds.yml |   3 +
 .gitlab-ci.d/qemu-project.yml|   1 +
 .gitlab-ci.d/rules.yml   | 116 +++
 .gitlab-ci.d/static_checks.yml   |  18 +--
 .gitlab-ci.yml   |   4 -
 docs/devel/ci-jobs.rst   | 161 +++
 docs/devel/ci-runners.rst| 117 +++
 docs/devel/ci.rst| 159 +-
 16 files changed, 459 insertions(+), 207 deletions(-)
 create mode 100644 .gitlab-ci.d/rules.yml
 create mode 100644 docs/devel/ci-jobs.rst
 create mode 100644 docs/devel/ci-runners.rst

-- 
2.31.1





Re: [PATCH] configure: Remove spurious [] from tr

2021-08-12 Thread Dr. David Alan Gilbert
* Paolo Bonzini (pbonz...@redhat.com) wrote:
> On 12/08/21 13:09, Dr. David Alan Gilbert (git) wrote:
> > From: "Dr. David Alan Gilbert" 
> > 
> > ShellCheck points out that tr '[a-z]' actually replaces the []'s
> > and only the a-z is needed.
> > 
> > Remove the spurious [] - although in this use it will make no
> > difference.
> > 
> > Fixes: bb55b712e8dc4d4eb515144d5c26798fea178cba
> > Signed-off-by: Dr. David Alan Gilbert 
> > ---
> >   configure | 2 +-
> >   1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/configure b/configure
> > index 9a79a004d7..5bb8c2a59d 100755
> > --- a/configure
> > +++ b/configure
> > @@ -4549,7 +4549,7 @@ if test "$gprof" = "yes" ; then
> >   fi
> >   echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config_host_mak
> >   for drv in $audio_drv_list; do
> > -def=CONFIG_AUDIO_$(echo $drv | LC_ALL=C tr '[a-z]' '[A-Z]')
> > +def=CONFIG_AUDIO_$(echo $drv | LC_ALL=C tr 'a-z' 'A-Z')
> >   echo "$def=y" >> $config_host_mak
> >   done
> >   if test "$alsa" = "yes" ; then
> > 
> 
> Do we want this in 6.1?  For the next release I'm moving all audio stuff to
> meson anyway. :)

Bah! Not bothered; I just tripped over ShellCheck and that
looked like a trivial one.

Dave

> Paolo
> 
-- 
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK




[PATCH for-6.1 ?] hw/core: fix error checkig in smp_parse

2021-08-12 Thread Daniel P . Berrangé
The machine_set_smp() mistakenly checks 'errp' not '*errp',
and so thinks there is an error every single time it runs.
This causes it to jump to the end of the method, skipping
the max CPUs checks. The caller meanwhile sees no error
and so carries on execution. The result of all this is:

 $ qemu-system-x86_64 -smp -1
 qemu-system-x86_64: GLib: ../glib/gmem.c:142: failed to allocate 481036337048 
bytes

instead of

 $ qemu-system-x86_64 -smp -1
 qemu-system-x86_64: Invalid SMP CPUs -1. The max CPUs supported by machine 
'pc-i440fx-6.1' is 255

This is a regression from

  commit fe68090e8fbd6e831aaf3fc3bb0459c5cccf14cf
  Author: Paolo Bonzini 
  Date:   Thu May 13 09:03:48 2021 -0400

machine: add smp compound property

Closes: https://gitlab.com/qemu-project/qemu/-/issues/524
Signed-off-by: Daniel P. Berrangé 
---
 hw/core/machine.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 943974d411..ab4fca6546 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -832,7 +832,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const 
char *name,
 }
 
 mc->smp_parse(ms, config, errp);
-if (errp) {
+if (*errp) {
 goto out_free;
 }
 
-- 
2.31.1




Re: [PATCH] configure: Remove spurious [] from tr

2021-08-12 Thread Paolo Bonzini

On 12/08/21 15:05, Dr. David Alan Gilbert wrote:

In configure line 4464:
if !(GIT="$git" "$source_path/scripts/git-submodule.sh" "$git_submodules_action" 
"$git_submodules"); then
 ^-- SC1035: You are missing a required space after the !.

which hmm I've not quite got my head around yet; but maybe that one is
real.


Trying

! (echo abc); echo $?
!(echo abc); echo $?

both work in bash, but the latter fails with zsh:

abc
1
ff:2: no matches found: !(echo abc)

Paolo




Re: [PATCH] configure: Remove spurious [] from tr

2021-08-12 Thread Paolo Bonzini

On 12/08/21 13:09, Dr. David Alan Gilbert (git) wrote:

From: "Dr. David Alan Gilbert" 

ShellCheck points out that tr '[a-z]' actually replaces the []'s
and only the a-z is needed.

Remove the spurious [] - although in this use it will make no
difference.

Fixes: bb55b712e8dc4d4eb515144d5c26798fea178cba
Signed-off-by: Dr. David Alan Gilbert 
---
  configure | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure b/configure
index 9a79a004d7..5bb8c2a59d 100755
--- a/configure
+++ b/configure
@@ -4549,7 +4549,7 @@ if test "$gprof" = "yes" ; then
  fi
  echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config_host_mak
  for drv in $audio_drv_list; do
-def=CONFIG_AUDIO_$(echo $drv | LC_ALL=C tr '[a-z]' '[A-Z]')
+def=CONFIG_AUDIO_$(echo $drv | LC_ALL=C tr 'a-z' 'A-Z')
  echo "$def=y" >> $config_host_mak
  done
  if test "$alsa" = "yes" ; then



Do we want this in 6.1?  For the next release I'm moving all audio stuff 
to meson anyway. :)


Paolo




Re: [PATCH] target/i386: Fixed size of constant for Windows

2021-08-12 Thread Paolo Bonzini

On 12/08/21 13:10, Lara Lazier wrote:

~0UL has 64 bits on Linux and 32 bits on Windows.
Fixes: https://gitlab.com/qemu-project/qemu/-/issues/512";.

Reported-by: Volker Rümelin 
Signed-off-by: Lara Lazier 
---
  target/i386/tcg/sysemu/misc_helper.c | 2 +-
  target/i386/tcg/sysemu/svm_helper.c  | 2 +-
  2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/i386/tcg/sysemu/misc_helper.c 
b/target/i386/tcg/sysemu/misc_helper.c
index 0a7a58ca9a..91b0fc916b 100644
--- a/target/i386/tcg/sysemu/misc_helper.c
+++ b/target/i386/tcg/sysemu/misc_helper.c
@@ -97,7 +97,7 @@ void helper_write_crN(CPUX86State *env, int reg, target_ulong 
t0)
  break;
  case 3:
  if ((env->efer & MSR_EFER_LMA) &&
-(t0 & ((~0UL) << env_archcpu(env)->phys_bits))) {
+(t0 & ((~0ULL) << env_archcpu(env)->phys_bits))) {
  cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
  }
  if (!(env->efer & MSR_EFER_LMA)) {
diff --git a/target/i386/tcg/sysemu/svm_helper.c 
b/target/i386/tcg/sysemu/svm_helper.c
index 3891f4e4a8..42cd5053e5 100644
--- a/target/i386/tcg/sysemu/svm_helper.c
+++ b/target/i386/tcg/sysemu/svm_helper.c
@@ -290,7 +290,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int 
next_eip_addend)
  }
  new_cr3 = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, 
save.cr3));
  if ((env->efer & MSR_EFER_LMA) &&
-(new_cr3 & ((~0UL) << cpu->phys_bits))) {
+(new_cr3 & ((~0ULL) << cpu->phys_bits))) {
  cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
  }
  new_cr4 = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, 
save.cr4));



Queued, thanks.

Paolo




Re: [PATCH v7 09/10] hw/arm/virt: add ITS support in virt GIC

2021-08-12 Thread shashi . mallela
On Fri, 2021-08-06 at 13:09 +0200, Igor Mammedov wrote:
> On Thu,  5 Aug 2021 18:30:01 -0400
> Shashi Mallela  wrote:
> 
> > Included creation of ITS as part of virt platform GIC
> > initialization. This Emulated ITS model now co-exists with kvm
> > ITS and is enabled in absence of kvm irq kernel support in a
> > platform.
> > 
> > Signed-off-by: Shashi Mallela 
> > Reviewed-by: Peter Maydell 
> > ---
> >  hw/arm/virt.c | 28 ++--
> >  include/hw/arm/virt.h |  2 ++
> >  target/arm/kvm_arm.h  |  4 ++--
> >  3 files changed, 30 insertions(+), 4 deletions(-)
> > 
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index 81eda46b0b..99cf4f9dbd 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -583,6 +583,12 @@ static void create_its(VirtMachineState *vms)
> >  const char *itsclass = its_class_name();
> >  DeviceState *dev;
> >  
> > +if (!strcmp(itsclass, "arm-gicv3-its")) {
> > +if (!vms->tcg_its) {
> > +itsclass = NULL;
> > +}
> > +}
> > +
> >  if (!itsclass) {
> >  /* Do nothing if not supported */
> >  return;
> > @@ -620,7 +626,7 @@ static void create_v2m(VirtMachineState *vms)
> >  vms->msi_controller = VIRT_MSI_CTRL_GICV2M;
> >  }
> >  
> > -static void create_gic(VirtMachineState *vms)
> > +static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
> >  {
> >  MachineState *ms = MACHINE(vms);
> >  /* We create a standalone GIC */
> > @@ -654,6 +660,14 @@ static void create_gic(VirtMachineState *vms)
> >   nb_redist_regions);
> >  qdev_prop_set_uint32(vms->gic, "redist-region-count[0]",
> > redist0_count);
> >  
> > +if (!kvm_irqchip_in_kernel()) {
> > +if (vms->tcg_its) {
> > +object_property_set_link(OBJECT(vms->gic),
> > "sysmem",
> > + OBJECT(mem),
> > &error_fatal);
> > +qdev_prop_set_bit(vms->gic, "has-lpi", true);
> > +}
> > +}
> > +
> >  if (nb_redist_regions == 2) {
> >  uint32_t redist1_capacity =
> >  vms->memmap[VIRT_HIGH_GIC_REDIST2].size /
> > GICV3_REDIST_SIZE;
> > @@ -2043,7 +2057,7 @@ static void machvirt_init(MachineState
> > *machine)
> >  
> >  virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem);
> >  
> > -create_gic(vms);
> > +create_gic(vms, sysmem);
> >  
> >  virt_cpu_post_init(vms, sysmem);
> >  
> > @@ -2746,6 +2760,12 @@ static void virt_instance_init(Object *obj)
> >  } else {
> >  /* Default allows ITS instantiation */
> >  vms->its = true;
> > +
> > +if (vmc->no_tcg_its) {
> > +vms->tcg_its = false;
> > +} else {
> > +vms->tcg_its = true;
> > +}
> >  }
> >  
> >  /* Default disallows iommu instantiation */
> > @@ -2795,8 +2815,12 @@ DEFINE_VIRT_MACHINE_AS_LATEST(6, 1)
> >  
> >  static void virt_machine_6_0_options(MachineClass *mc)
> >  {
> > +VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
> > +
> >  virt_machine_6_1_options(mc);
> >  compat_props_add(mc->compat_props, hw_compat_6_0,
> > hw_compat_6_0_len);
> > +/* qemu ITS was introduced with 6.1 */
> > +vmc->no_tcg_its = true;
> 
> given it's not going to be in 6.1, shouldn't it be moved to
> virt_machine_6_1_options() with updated comment?
Agreed,moved to virt_machine_6_1_options() and updated comment
> 
> >  }
> >  DEFINE_VIRT_MACHINE(6, 0)
> >  
> > diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
> > index 9661c46699..b461b8d261 100644
> > --- a/include/hw/arm/virt.h
> > +++ b/include/hw/arm/virt.h
> > @@ -120,6 +120,7 @@ struct VirtMachineClass {
> >  MachineClass parent;
> >  bool disallow_affinity_adjustment;
> >  bool no_its;
> > +bool no_tcg_its;
> >  bool no_pmu;
> >  bool claim_edge_triggered_timers;
> >  bool smbios_old_sys_ver;
> > @@ -141,6 +142,7 @@ struct VirtMachineState {
> >  bool highmem;
> >  bool highmem_ecam;
> >  bool its;
> > +bool tcg_its;
> >  bool virt;
> >  bool ras;
> >  bool mte;
> > diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
> > index 34f8daa377..0613454975 100644
> > --- a/target/arm/kvm_arm.h
> > +++ b/target/arm/kvm_arm.h
> > @@ -525,8 +525,8 @@ static inline const char *its_class_name(void)
> >  /* KVM implementation requires this capability */
> >  return kvm_direct_msi_enabled() ? "arm-its-kvm" : NULL;
> >  } else {
> > -/* Software emulation is not implemented yet */
> > -return NULL;
> > +/* Software emulation based model */
> > +return "arm-gicv3-its";
> >  }
> >  }
> >  




[PATCH v8 09/10] hw/arm/virt: add ITS support in virt GIC

2021-08-12 Thread Shashi Mallela
Included creation of ITS as part of virt platform GIC
initialization. This Emulated ITS model now co-exists with kvm
ITS and is enabled in absence of kvm irq kernel support in a
platform.

Signed-off-by: Shashi Mallela 
Reviewed-by: Peter Maydell 
---
 hw/arm/virt.c | 28 ++--
 include/hw/arm/virt.h |  2 ++
 target/arm/kvm_arm.h  |  4 ++--
 3 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 81eda46b0b..3cea2aa039 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -583,6 +583,12 @@ static void create_its(VirtMachineState *vms)
 const char *itsclass = its_class_name();
 DeviceState *dev;
 
+if (!strcmp(itsclass, "arm-gicv3-its")) {
+if (!vms->tcg_its) {
+itsclass = NULL;
+}
+}
+
 if (!itsclass) {
 /* Do nothing if not supported */
 return;
@@ -620,7 +626,7 @@ static void create_v2m(VirtMachineState *vms)
 vms->msi_controller = VIRT_MSI_CTRL_GICV2M;
 }
 
-static void create_gic(VirtMachineState *vms)
+static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
 {
 MachineState *ms = MACHINE(vms);
 /* We create a standalone GIC */
@@ -654,6 +660,14 @@ static void create_gic(VirtMachineState *vms)
  nb_redist_regions);
 qdev_prop_set_uint32(vms->gic, "redist-region-count[0]", 
redist0_count);
 
+if (!kvm_irqchip_in_kernel()) {
+if (vms->tcg_its) {
+object_property_set_link(OBJECT(vms->gic), "sysmem",
+ OBJECT(mem), &error_fatal);
+qdev_prop_set_bit(vms->gic, "has-lpi", true);
+}
+}
+
 if (nb_redist_regions == 2) {
 uint32_t redist1_capacity =
 vms->memmap[VIRT_HIGH_GIC_REDIST2].size / 
GICV3_REDIST_SIZE;
@@ -2043,7 +2057,7 @@ static void machvirt_init(MachineState *machine)
 
 virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem);
 
-create_gic(vms);
+create_gic(vms, sysmem);
 
 virt_cpu_post_init(vms, sysmem);
 
@@ -2746,6 +2760,12 @@ static void virt_instance_init(Object *obj)
 } else {
 /* Default allows ITS instantiation */
 vms->its = true;
+
+if (vmc->no_tcg_its) {
+vms->tcg_its = false;
+} else {
+vms->tcg_its = true;
+}
 }
 
 /* Default disallows iommu instantiation */
@@ -2790,6 +2810,10 @@ type_init(machvirt_machine_init);
 
 static void virt_machine_6_1_options(MachineClass *mc)
 {
+VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
+
+/* qemu ITS was introduced with 6.2 */
+vmc->no_tcg_its = true;
 }
 DEFINE_VIRT_MACHINE_AS_LATEST(6, 1)
 
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 9661c46699..b461b8d261 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -120,6 +120,7 @@ struct VirtMachineClass {
 MachineClass parent;
 bool disallow_affinity_adjustment;
 bool no_its;
+bool no_tcg_its;
 bool no_pmu;
 bool claim_edge_triggered_timers;
 bool smbios_old_sys_ver;
@@ -141,6 +142,7 @@ struct VirtMachineState {
 bool highmem;
 bool highmem_ecam;
 bool its;
+bool tcg_its;
 bool virt;
 bool ras;
 bool mte;
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 34f8daa377..0613454975 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -525,8 +525,8 @@ static inline const char *its_class_name(void)
 /* KVM implementation requires this capability */
 return kvm_direct_msi_enabled() ? "arm-its-kvm" : NULL;
 } else {
-/* Software emulation is not implemented yet */
-return NULL;
+/* Software emulation based model */
+return "arm-gicv3-its";
 }
 }
 
-- 
2.27.0




[PATCH v8 07/10] hw/arm/sbsa-ref: add ITS support in SBSA GIC

2021-08-12 Thread Shashi Mallela
Included creation of ITS as part of SBSA platform GIC
initialization.

Signed-off-by: Shashi Mallela 
---
 hw/arm/sbsa-ref.c | 79 ---
 1 file changed, 75 insertions(+), 4 deletions(-)

diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
index c1629df603..feadae2f33 100644
--- a/hw/arm/sbsa-ref.c
+++ b/hw/arm/sbsa-ref.c
@@ -34,7 +34,7 @@
 #include "hw/boards.h"
 #include "hw/ide/internal.h"
 #include "hw/ide/ahci_internal.h"
-#include "hw/intc/arm_gicv3_common.h"
+#include "hw/intc/arm_gicv3_its_common.h"
 #include "hw/loader.h"
 #include "hw/pci-host/gpex.h"
 #include "hw/qdev-properties.h"
@@ -58,12 +58,26 @@
 #define ARCH_TIMER_NS_EL1_IRQ  14
 #define ARCH_TIMER_NS_EL2_IRQ  10
 
+/*
+ * Enumeration of the possible values of sbsa-ref version
+ * property. These are arbitrary QEMU-internal values.
+ * values are :-
+ * DEFAULT = without ITS memory map
+ * SBSA_GIC_ITS = with ITS memory map between distributor & redistributor
+ *regions. This is the current version supported.
+ */
+typedef enum SbsaRefVersion {
+SBSA_DEFAULT,
+SBSA_ITS,
+} SbsaRefVersion;
+
 enum {
 SBSA_FLASH,
 SBSA_MEM,
 SBSA_CPUPERIPHS,
 SBSA_GIC_DIST,
 SBSA_GIC_REDIST,
+SBSA_GIC_ITS,
 SBSA_SECURE_EC,
 SBSA_GWDT,
 SBSA_GWDT_REFRESH,
@@ -91,6 +105,7 @@ struct SBSAMachineState {
 void *fdt;
 int fdt_size;
 int psci_conduit;
+SbsaRefVersion version;
 DeviceState *gic;
 PFlashCFI01 *flash[2];
 };
@@ -105,8 +120,11 @@ static const MemMapEntry sbsa_ref_memmap[] = {
 [SBSA_SECURE_MEM] = { 0x2000, 0x2000 },
 /* Space reserved for CPU peripheral devices */
 [SBSA_CPUPERIPHS] = { 0x4000, 0x0004 },
+/* GIC components reserved space Start */
 [SBSA_GIC_DIST] =   { 0x4006, 0x0001 },
-[SBSA_GIC_REDIST] = { 0x4008, 0x0400 },
+[SBSA_GIC_ITS] ={ 0x4007, 0x0002 },
+[SBSA_GIC_REDIST] = { 0x400B, 0x0400 },
+/* GIC components reserved space End */
 [SBSA_SECURE_EC] =  { 0x5000, 0x1000 },
 [SBSA_GWDT_REFRESH] =   { 0x5001, 0x1000 },
 [SBSA_GWDT_CONTROL] =   { 0x50011000, 0x1000 },
@@ -377,7 +395,20 @@ static void create_secure_ram(SBSAMachineState *sms,
 memory_region_add_subregion(secure_sysmem, base, secram);
 }
 
-static void create_gic(SBSAMachineState *sms)
+static void create_its(SBSAMachineState *sms)
+{
+DeviceState *dev;
+
+dev = qdev_new(TYPE_ARM_GICV3_ITS);
+SysBusDevice *s = SYS_BUS_DEVICE(dev);
+
+object_property_set_link(OBJECT(dev), "parent-gicv3", OBJECT(sms->gic),
+ &error_abort);
+sysbus_realize_and_unref(s, &error_fatal);
+sysbus_mmio_map(s, 0, sbsa_ref_memmap[SBSA_GIC_ITS].base);
+}
+
+static void create_gic(SBSAMachineState *sms, MemoryRegion *mem)
 {
 unsigned int smp_cpus = MACHINE(sms)->smp.cpus;
 SysBusDevice *gicbusdev;
@@ -404,6 +435,10 @@ static void create_gic(SBSAMachineState *sms)
 qdev_prop_set_uint32(sms->gic, "len-redist-region-count", 1);
 qdev_prop_set_uint32(sms->gic, "redist-region-count[0]", redist0_count);
 
+object_property_set_link(OBJECT(sms->gic), "sysmem", OBJECT(mem),
+ &error_fatal);
+qdev_prop_set_bit(sms->gic, "has-lpi", true);
+
 gicbusdev = SYS_BUS_DEVICE(sms->gic);
 sysbus_realize_and_unref(gicbusdev, &error_fatal);
 sysbus_mmio_map(gicbusdev, 0, sbsa_ref_memmap[SBSA_GIC_DIST].base);
@@ -450,6 +485,7 @@ static void create_gic(SBSAMachineState *sms)
 sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
 }
+create_its(sms);
 }
 
 static void create_uart(const SBSAMachineState *sms, int uart,
@@ -755,7 +791,7 @@ static void sbsa_ref_init(MachineState *machine)
 
 create_secure_ram(sms, secure_sysmem);
 
-create_gic(sms);
+create_gic(sms, sysmem);
 
 create_uart(sms, SBSA_UART, sysmem, serial_hd(0));
 create_uart(sms, SBSA_SECURE_UART, secure_sysmem, serial_hd(1));
@@ -825,10 +861,39 @@ sbsa_ref_get_default_cpu_node_id(const MachineState *ms, 
int idx)
 return idx % ms->numa_state->num_nodes;
 }
 
+static char *sbsa_get_version(Object *obj, Error **errp)
+{
+SBSAMachineState *sms = SBSA_MACHINE(obj);
+
+switch (sms->version) {
+case SBSA_DEFAULT:
+return g_strdup("default");
+case SBSA_ITS:
+return g_strdup("sbsaits");
+default:
+g_assert_not_reached();
+}
+}
+
+static void sbsa_set_version(Object *obj, const char *value, Error **errp)
+{
+SBSAMachineState *sms = SBSA_MACHINE(obj);
+
+if (!strcmp(value, "sbsaits")) {
+sms->version = SBSA_ITS;
+} else if (!strcmp(value, "default")) {
+sms->version = SBSA_DEFAULT;
+} else {
+error_setg(errp, "Invalid version value");
+error_append_hint(errp,

[PATCH v8 10/10] tests/data/acpi/virt: Update IORT files for ITS

2021-08-12 Thread Shashi Mallela
Updated expected IORT files applicable with latest GICv3
ITS changes.

Full diff of new file disassembly:

/*
 * Intel ACPI Component Architecture
 * AML/ASL+ Disassembler version 20180629 (64-bit version)
 * Copyright (c) 2000 - 2018 Intel Corporation
 *
 * Disassembly of tests/data/acpi/virt/IORT.pxb, Tue Jun 29 17:35:38 2021
 *
 * ACPI Data Table [IORT]
 *
 * Format: [HexOffset DecimalOffset ByteLength]  FieldName : FieldValue
 */

[000h    4]Signature : "IORT"[IO Remapping Table]
[004h 0004   4] Table Length : 007C
[008h 0008   1] Revision : 00
[009h 0009   1] Checksum : 07
[00Ah 0010   6]   Oem ID : "BOCHS "
[010h 0016   8] Oem Table ID : "BXPC"
[018h 0024   4] Oem Revision : 0001
[01Ch 0028   4]  Asl Compiler ID : "BXPC"
[020h 0032   4]Asl Compiler Revision : 0001

[024h 0036   4]   Node Count : 0002
[028h 0040   4]  Node Offset : 0030
[02Ch 0044   4] Reserved : 

[030h 0048   1] Type : 00
[031h 0049   2]   Length : 0018
[033h 0051   1] Revision : 00
[034h 0052   4] Reserved : 
[038h 0056   4]Mapping Count : 
[03Ch 0060   4]   Mapping Offset : 

[040h 0064   4] ItsCount : 0001
[044h 0068   4]  Identifiers : 

[048h 0072   1] Type : 02
[049h 0073   2]   Length : 0034
[04Bh 0075   1] Revision : 00
[04Ch 0076   4] Reserved : 
[050h 0080   4]Mapping Count : 0001
[054h 0084   4]   Mapping Offset : 0020

[058h 0088   8]Memory Properties : [IORT Memory Access Properties]
[058h 0088   4]  Cache Coherency : 0001
[05Ch 0092   1]Hints (decoded below) : 00
   Transient : 0
  Write Allocate : 0
   Read Allocate : 0
Override : 0
[05Dh 0093   2] Reserved : 
[05Fh 0095   1] Memory Flags (decoded below) : 03
   Coherency : 1
Device Attribute : 1
[060h 0096   4]ATS Attribute : 
[064h 0100   4]   PCI Segment Number : 
[068h 0104   1]Memory Size Limit : 00
[069h 0105   3] Reserved : 00

[068h 0104   4]   Input base : 
[06Ch 0108   4] ID Count : 
[070h 0112   4]  Output Base : 
[074h 0116   4] Output Reference : 0030
[078h 0120   4]Flags (decoded below) : 
  Single Mapping : 0

Raw Table Data: Length 124 (0x7C)

: 49 4F 52 54 7C 00 00 00 00 07 42 4F 43 48 53 20  // IORT|.BOCHS
0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43  // BXPCBXPC
0020: 01 00 00 00 02 00 00 00 30 00 00 00 00 00 00 00  // 0...
0030: 00 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00  // 
0040: 01 00 00 00 00 00 00 00 02 34 00 00 00 00 00 00  // .4..
0050: 01 00 00 00 20 00 00 00 01 00 00 00 00 00 00 03  //  ...
0060: 00 00 00 00 00 00 00 00 00 00 00 00 FF FF 00 00  // 
0070: 00 00 00 00 30 00 00 00 00 00 00 00  // 0...

Signed-off-by: Shashi Mallela 
Acked-by: Igor Mammedov 
---
 tests/data/acpi/virt/IORT   | Bin 0 -> 124 bytes
 tests/data/acpi/virt/IORT.memhp | Bin 0 -> 124 bytes
 tests/data/acpi/virt/IORT.numamem   | Bin 0 -> 124 bytes
 tests/data/acpi/virt/IORT.pxb   | Bin 0 -> 124 bytes
 tests/qtest/bios-tables-test-allowed-diff.h |   4 
 5 files changed, 4 deletions(-)

diff --git a/tests/data/acpi/virt/IORT b/tests/data/acpi/virt/IORT
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..521acefe9ba66706c5607321a82d330586f3f280
 100644
GIT binary patch
literal 124
zcmebD4+^Pa00MR=e`k+i1*eDrX9XZ&1PX!JAesq?4S*O7Bw!2(4Uz`|CKCt^;wu0#
QRGb+i3L*dhhtM#y0PN=p0RR91

literal 0
HcmV?d1

diff --git a/tests/data/acpi/virt/IORT.memhp b/tests/data/acpi/virt/IORT.memhp
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..521acefe9ba66706c5607321a82d330586f3f280
 100644
GIT binary patch
literal 124
zcmebD4+^Pa00MR=e`k+i1*eDrX9XZ&1PX!JAesq?4S*O7Bw!2(4Uz`|CKCt^;wu0#
QRGb+i3L*dhhtM#y0PN=p0RR91

literal 0
HcmV?d1

diff --git a/tests/data/acpi/virt/IORT.numamem 
b/tests/data/acpi/virt/IORT.numamem
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..521acefe9ba66706c5607321a82d330586f3f280
 100644
GIT binary patch
literal 124
zcmebD4+^Pa00MR=e`k+i1*eDrX9XZ&1PX!JAesq?4S*O7Bw!2(4Uz`|CKCt^;wu0#
QR

[PATCH v8 08/10] tests/data/acpi/virt: Add IORT files for ITS

2021-08-12 Thread Shashi Mallela
Added expected IORT files applicable with latest GICv3
ITS changes.Temporarily differences in these files are
okay.

Signed-off-by: Shashi Mallela 
Acked-by: Igor Mammedov 
---
 tests/data/acpi/virt/IORT   | 0
 tests/data/acpi/virt/IORT.memhp | 0
 tests/data/acpi/virt/IORT.numamem   | 0
 tests/data/acpi/virt/IORT.pxb   | 0
 tests/qtest/bios-tables-test-allowed-diff.h | 4 
 5 files changed, 4 insertions(+)
 create mode 100644 tests/data/acpi/virt/IORT
 create mode 100644 tests/data/acpi/virt/IORT.memhp
 create mode 100644 tests/data/acpi/virt/IORT.numamem
 create mode 100644 tests/data/acpi/virt/IORT.pxb

diff --git a/tests/data/acpi/virt/IORT b/tests/data/acpi/virt/IORT
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/data/acpi/virt/IORT.memhp b/tests/data/acpi/virt/IORT.memhp
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/data/acpi/virt/IORT.numamem 
b/tests/data/acpi/virt/IORT.numamem
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/data/acpi/virt/IORT.pxb b/tests/data/acpi/virt/IORT.pxb
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..2ef211df59 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,5 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/virt/IORT",
+"tests/data/acpi/virt/IORT.memhp",
+"tests/data/acpi/virt/IORT.numamem",
+"tests/data/acpi/virt/IORT.pxb",
-- 
2.27.0




[PATCH v8 04/10] hw/intc: GICv3 ITS Command processing

2021-08-12 Thread Shashi Mallela
Added ITS command queue handling for MAPTI,MAPI commands,handled ITS
translation which triggers an LPI via INT command as well as write
to GITS_TRANSLATER register,defined enum to differentiate between ITS
command interrupt trigger and GITS_TRANSLATER based interrupt trigger.
Each of these commands make use of other functionalities implemented to
get device table entry,collection table entry or interrupt translation
table entry required for their processing.

Signed-off-by: Shashi Mallela 
Reviewed-by: Peter Maydell 
---
 hw/intc/arm_gicv3_its.c| 351 +
 hw/intc/gicv3_internal.h   |  12 +
 include/hw/intc/arm_gicv3_common.h |   2 +
 3 files changed, 365 insertions(+)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 8bdbebbeca..d98b0e0f4c 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -29,6 +29,22 @@ struct GICv3ITSClass {
 void (*parent_reset)(DeviceState *dev);
 };
 
+/*
+ * This is an internal enum used to distinguish between LPI triggered
+ * via command queue and LPI triggered via gits_translater write.
+ */
+typedef enum ItsCmdType {
+NONE = 0, /* internal indication for GITS_TRANSLATER write */
+CLEAR = 1,
+DISCARD = 2,
+INT = 3,
+} ItsCmdType;
+
+typedef struct {
+uint32_t iteh;
+uint64_t itel;
+} IteEntry;
+
 static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
 {
 uint64_t result = 0;
@@ -50,6 +66,323 @@ static uint64_t baser_base_addr(uint64_t value, uint32_t 
page_sz)
 return result;
 }
 
+static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
+MemTxResult *res)
+{
+AddressSpace *as = &s->gicv3->dma_as;
+uint64_t l2t_addr;
+uint64_t value;
+bool valid_l2t;
+uint32_t l2t_id;
+uint32_t max_l2_entries;
+
+if (s->ct.indirect) {
+l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
+
+value = address_space_ldq_le(as,
+ s->ct.base_addr +
+ (l2t_id * L1TABLE_ENTRY_SIZE),
+ MEMTXATTRS_UNSPECIFIED, res);
+
+if (*res == MEMTX_OK) {
+valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
+
+if (valid_l2t) {
+max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
+
+l2t_addr = value & ((1ULL << 51) - 1);
+
+*cte =  address_space_ldq_le(as, l2t_addr +
+((icid % max_l2_entries) * GITS_CTE_SIZE),
+MEMTXATTRS_UNSPECIFIED, res);
+   }
+   }
+} else {
+/* Flat level table */
+*cte =  address_space_ldq_le(as, s->ct.base_addr +
+ (icid * GITS_CTE_SIZE),
+  MEMTXATTRS_UNSPECIFIED, res);
+}
+
+return (*cte & TABLE_ENTRY_VALID_MASK) != 0;
+}
+
+static MemTxResult update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
+  IteEntry ite)
+{
+AddressSpace *as = &s->gicv3->dma_as;
+uint64_t itt_addr;
+MemTxResult res = MEMTX_OK;
+
+itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
+itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
+
+address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
+ sizeof(uint32_t))), ite.itel, MEMTXATTRS_UNSPECIFIED,
+ &res);
+
+if (res == MEMTX_OK) {
+address_space_stl_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
+ sizeof(uint32_t))) + sizeof(uint32_t), ite.iteh,
+ MEMTXATTRS_UNSPECIFIED, &res);
+}
+   return res;
+}
+
+static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
+uint16_t *icid, uint32_t *pIntid, MemTxResult *res)
+{
+AddressSpace *as = &s->gicv3->dma_as;
+uint64_t itt_addr;
+bool status = false;
+IteEntry ite = {};
+
+itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
+itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
+
+ite.itel = address_space_ldq_le(as, itt_addr +
+(eventid * (sizeof(uint64_t) +
+sizeof(uint32_t))), MEMTXATTRS_UNSPECIFIED,
+res);
+
+if (*res == MEMTX_OK) {
+ite.iteh = address_space_ldl_le(as, itt_addr +
+(eventid * (sizeof(uint64_t) +
+sizeof(uint32_t))) + sizeof(uint32_t),
+MEMTXATTRS_UNSPECIFIED, res);
+
+if (*res == MEMTX_OK) {
+if (ite.itel & TABLE_ENTRY_VALID_MASK) {
+if ((ite.itel >> ITE_ENTRY_INTTYPE_SHIFT) &
+GITS_TYPE_PHYSICAL) {
+*pIntid = (ite.itel & ITE_ENTRY_INTID_MASK) >>
+  

[PATCH v8 06/10] hw/intc: GICv3 redistributor ITS processing

2021-08-12 Thread Shashi Mallela
Implemented lpi processing at redistributor to get lpi config info
from lpi configuration table,determine priority,set pending state in
lpi pending table and forward the lpi to cpuif.Added logic to invoke
redistributor lpi processing with translated LPI which set/clear LPI
from ITS device as part of ITS INT,CLEAR,DISCARD command and
GITS_TRANSLATER processing.

Signed-off-by: Shashi Mallela 
Tested-by: Neil Armstrong 
---
 hw/intc/arm_gicv3.c|  14 +++
 hw/intc/arm_gicv3_common.c |   1 +
 hw/intc/arm_gicv3_cpuif.c  |   7 +-
 hw/intc/arm_gicv3_its.c|  23 +
 hw/intc/arm_gicv3_redist.c | 141 +
 hw/intc/gicv3_internal.h   |   9 ++
 include/hw/intc/arm_gicv3_common.h |   7 ++
 7 files changed, 200 insertions(+), 2 deletions(-)

diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
index d63f8af604..3f24707838 100644
--- a/hw/intc/arm_gicv3.c
+++ b/hw/intc/arm_gicv3.c
@@ -165,6 +165,16 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
 cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq);
 }
 
+if ((cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) && cs->gic->lpi_enable &&
+(cs->hpplpi.prio != 0xff)) {
+if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio)) {
+cs->hppi.irq = cs->hpplpi.irq;
+cs->hppi.prio = cs->hpplpi.prio;
+cs->hppi.grp = cs->hpplpi.grp;
+seenbetter = true;
+}
+}
+
 /* If the best interrupt we just found would preempt whatever
  * was the previous best interrupt before this update, then
  * we know it's definitely the best one now.
@@ -339,9 +349,13 @@ static void gicv3_set_irq(void *opaque, int irq, int level)
 
 static void arm_gicv3_post_load(GICv3State *s)
 {
+int i;
 /* Recalculate our cached idea of the current highest priority
  * pending interrupt, but don't set IRQ or FIQ lines.
  */
+for (i = 0; i < s->num_cpu; i++) {
+gicv3_redist_update_lpi(&s->cpu[i]);
+}
 gicv3_full_update_noirqset(s);
 /* Repopulate the cache of GICv3CPUState pointers for target CPUs */
 gicv3_cache_all_target_cpustates(s);
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 53dea2a775..223db16fec 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -435,6 +435,7 @@ static void arm_gicv3_common_reset(DeviceState *dev)
 memset(cs->gicr_ipriorityr, 0, sizeof(cs->gicr_ipriorityr));
 
 cs->hppi.prio = 0xff;
+cs->hpplpi.prio = 0xff;
 
 /* State in the CPU interface must *not* be reset here, because it
  * is part of the CPU's reset domain, not the GIC device's.
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index a032d505f5..462a35f66e 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -899,10 +899,12 @@ static void icc_activate_irq(GICv3CPUState *cs, int irq)
 cs->gicr_iactiver0 = deposit32(cs->gicr_iactiver0, irq, 1, 1);
 cs->gicr_ipendr0 = deposit32(cs->gicr_ipendr0, irq, 1, 0);
 gicv3_redist_update(cs);
-} else {
+} else if (irq < GICV3_LPI_INTID_START) {
 gicv3_gicd_active_set(cs->gic, irq);
 gicv3_gicd_pending_clear(cs->gic, irq);
 gicv3_update(cs->gic, irq, 1);
+} else {
+gicv3_redist_lpi_pending(cs, irq, 0);
 }
 }
 
@@ -1318,7 +1320,8 @@ static void icc_eoir_write(CPUARMState *env, const 
ARMCPRegInfo *ri,
 trace_gicv3_icc_eoir_write(is_eoir0 ? 0 : 1,
gicv3_redist_affid(cs), value);
 
-if (irq >= cs->gic->num_irq) {
+if ((irq >= cs->gic->num_irq) &&
+!(cs->gic->lpi_enable && (irq >= GICV3_LPI_INTID_START))) {
 /* This handles two cases:
  * 1. If software writes the ID of a spurious interrupt [ie 1020-1023]
  * to the GICC_EOIR, the GIC ignores that write.
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index d98b0e0f4c..d09ad6f556 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -228,6 +228,7 @@ static MemTxResult process_its_cmd(GICv3ITSState *s, 
uint64_t value,
 bool ite_valid = false;
 uint64_t cte = 0;
 bool cte_valid = false;
+uint64_t rdbase;
 
 if (cmd == NONE) {
 devid = offset;
@@ -288,6 +289,18 @@ static MemTxResult process_its_cmd(GICv3ITSState *s, 
uint64_t value,
  * Current implementation only supports rdbase == procnum
  * Hence rdbase physical address is ignored
  */
+rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U;
+
+if (rdbase > s->gicv3->num_cpu) {
+return res;
+}
+
+if ((cmd == CLEAR) || (cmd == DISCARD)) {
+gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 0);
+} else {
+gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 1);
+}
+
 if (cmd == DISCARD) {
 IteEntry ite = {

[PATCH v8 05/10] hw/intc: GICv3 ITS Feature enablement

2021-08-12 Thread Shashi Mallela
Added properties to enable ITS feature and define qemu system
address space memory in gicv3 common,setup distributor and
redistributor registers to indicate LPI support.

Signed-off-by: Shashi Mallela 
Reviewed-by: Peter Maydell 
Tested-by: Neil Armstrong 
---
 hw/intc/arm_gicv3_common.c | 12 
 hw/intc/arm_gicv3_dist.c   |  5 -
 hw/intc/arm_gicv3_redist.c | 12 +---
 hw/intc/gicv3_internal.h   |  2 ++
 include/hw/intc/arm_gicv3_common.h |  1 +
 5 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 58ef65f589..53dea2a775 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -345,6 +345,11 @@ static void arm_gicv3_common_realize(DeviceState *dev, 
Error **errp)
 return;
 }
 
+if (s->lpi_enable && !s->dma) {
+error_setg(errp, "Redist-ITS: Guest 'sysmem' reference link not set");
+return;
+}
+
 s->cpu = g_new0(GICv3CPUState, s->num_cpu);
 
 for (i = 0; i < s->num_cpu; i++) {
@@ -381,6 +386,10 @@ static void arm_gicv3_common_realize(DeviceState *dev, 
Error **errp)
 (1 << 24) |
 (i << 8) |
 (last << 4);
+
+if (s->lpi_enable) {
+s->cpu[i].gicr_typer |= GICR_TYPER_PLPIS;
+}
 }
 }
 
@@ -494,9 +503,12 @@ static Property arm_gicv3_common_properties[] = {
 DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1),
 DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
 DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
+DEFINE_PROP_BOOL("has-lpi", GICv3State, lpi_enable, 0),
 DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
 DEFINE_PROP_ARRAY("redist-region-count", GICv3State, nb_redist_regions,
   redist_region_count, qdev_prop_uint32, uint32_t),
+DEFINE_PROP_LINK("sysmem", GICv3State, dma, TYPE_MEMORY_REGION,
+ MemoryRegion *),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
index b65f56f903..43128b376d 100644
--- a/hw/intc/arm_gicv3_dist.c
+++ b/hw/intc/arm_gicv3_dist.c
@@ -371,7 +371,9 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
  * A3V == 1 (non-zero values of Affinity level 3 supported)
  * IDbits == 0xf (we support 16-bit interrupt identifiers)
  * DVIS == 0 (Direct virtual LPI injection not supported)
- * LPIS == 0 (LPIs not supported)
+ * LPIS == 1 (LPIs are supported if affinity routing is enabled)
+ * num_LPIs == 0b0 (bits [15:11],Number of LPIs as indicated
+ *  by GICD_TYPER.IDbits)
  * MBIS == 0 (message-based SPIs not supported)
  * SecurityExtn == 1 if security extns supported
  * CPUNumber == 0 since for us ARE is always 1
@@ -386,6 +388,7 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
 bool sec_extn = !(s->gicd_ctlr & GICD_CTLR_DS);
 
 *data = (1 << 25) | (1 << 24) | (sec_extn << 10) |
+(s->lpi_enable << GICD_TYPER_LPIS_SHIFT) |
 (0xf << 19) | itlinesnumber;
 return MEMTX_OK;
 }
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
index 53da703ed8..2108abfe9c 100644
--- a/hw/intc/arm_gicv3_redist.c
+++ b/hw/intc/arm_gicv3_redist.c
@@ -248,10 +248,16 @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr 
offset,
 case GICR_CTLR:
 /* For our implementation, GICR_TYPER.DPGS is 0 and so all
  * the DPG bits are RAZ/WI. We don't do anything asynchronously,
- * so UWP and RWP are RAZ/WI. And GICR_TYPER.LPIS is 0 (we don't
- * implement LPIs) so Enable_LPIs is RES0. So there are no writable
- * bits for us.
+ * so UWP and RWP are RAZ/WI. GICR_TYPER.LPIS is 1 (we
+ * implement LPIs) so Enable_LPIs is programmable.
  */
+if (cs->gicr_typer & GICR_TYPER_PLPIS) {
+if (value & GICR_CTLR_ENABLE_LPIS) {
+cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS;
+} else {
+cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS;
+}
+}
 return MEMTX_OK;
 case GICR_STATUSR:
 /* RAZ/WI for our implementation */
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index 1966444790..530d1c1789 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -68,6 +68,8 @@
 #define GICD_CTLR_E1NWF (1U << 7)
 #define GICD_CTLR_RWP   (1U << 31)
 
+#define GICD_TYPER_LPIS_SHIFT  17
+
 /* 16 bits EventId */
 #define GICD_TYPER_IDBITS0xf
 
diff --git a/include/hw/intc/arm_gicv3_common.h 
b/include/hw/intc/arm_gicv3_common.h
index 0715b0bc2a..c1348cc60a 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -221,6 +221,7 @@ struct GICv3State {
 uint32_t num_cpu;
 uint32

[PATCH v8 02/10] hw/intc: GICv3 ITS register definitions added

2021-08-12 Thread Shashi Mallela
Defined descriptors for ITS device table,collection table and ITS
command queue entities.Implemented register read/write functions,
extract ITS table parameters and command queue parameters,extended
gicv3 common to capture qemu address space(which host the ITS table
platform memories required for subsequent ITS processing) and
initialize the same in ITS device.

Signed-off-by: Shashi Mallela 
Reviewed-by: Peter Maydell 
Reviewed-by: Eric Auger 
Tested-by: Neil Armstrong 
---
 hw/intc/arm_gicv3_its.c| 376 +
 hw/intc/gicv3_internal.h   |  29 ++
 include/hw/intc/arm_gicv3_common.h |   3 +
 include/hw/intc/arm_gicv3_its_common.h |  23 ++
 4 files changed, 431 insertions(+)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 2286b3f757..b2210dffdc 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -29,6 +29,160 @@ struct GICv3ITSClass {
 void (*parent_reset)(DeviceState *dev);
 };
 
+static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
+{
+uint64_t result = 0;
+
+switch (page_sz) {
+case GITS_PAGE_SIZE_4K:
+case GITS_PAGE_SIZE_16K:
+result = FIELD_EX64(value, GITS_BASER, PHYADDR) << 12;
+break;
+
+case GITS_PAGE_SIZE_64K:
+result = FIELD_EX64(value, GITS_BASER, PHYADDRL_64K) << 16;
+result |= FIELD_EX64(value, GITS_BASER, PHYADDRH_64K) << 48;
+break;
+
+default:
+break;
+}
+return result;
+}
+
+/*
+ * This function extracts the ITS Device and Collection table specific
+ * parameters (like base_addr, size etc) from GITS_BASER register.
+ * It is called during ITS enable and also during post_load migration
+ */
+static void extract_table_params(GICv3ITSState *s)
+{
+uint16_t num_pages = 0;
+uint8_t  page_sz_type;
+uint8_t type;
+uint32_t page_sz = 0;
+uint64_t value;
+
+for (int i = 0; i < 8; i++) {
+value = s->baser[i];
+
+if (!value) {
+continue;
+}
+
+page_sz_type = FIELD_EX64(value, GITS_BASER, PAGESIZE);
+
+switch (page_sz_type) {
+case 0:
+page_sz = GITS_PAGE_SIZE_4K;
+break;
+
+case 1:
+page_sz = GITS_PAGE_SIZE_16K;
+break;
+
+case 2:
+case 3:
+page_sz = GITS_PAGE_SIZE_64K;
+break;
+
+default:
+g_assert_not_reached();
+}
+
+num_pages = FIELD_EX64(value, GITS_BASER, SIZE) + 1;
+
+type = FIELD_EX64(value, GITS_BASER, TYPE);
+
+switch (type) {
+
+case GITS_BASER_TYPE_DEVICE:
+memset(&s->dt, 0 , sizeof(s->dt));
+s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
+
+if (!s->dt.valid) {
+return;
+}
+
+s->dt.page_sz = page_sz;
+s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
+s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
+
+if (!s->dt.indirect) {
+s->dt.max_entries = (num_pages * page_sz) / s->dt.entry_sz;
+} else {
+s->dt.max_entries = (((num_pages * page_sz) /
+ L1TABLE_ENTRY_SIZE) *
+ (page_sz / s->dt.entry_sz));
+}
+
+s->dt.maxids.max_devids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
+   DEVBITS) + 1));
+
+s->dt.base_addr = baser_base_addr(value, page_sz);
+
+break;
+
+case GITS_BASER_TYPE_COLLECTION:
+memset(&s->ct, 0 , sizeof(s->ct));
+s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID);
+
+/*
+ * GITS_TYPER.HCC is 0 for this implementation
+ * hence writes are discarded if ct.valid is 0
+ */
+if (!s->ct.valid) {
+return;
+}
+
+s->ct.page_sz = page_sz;
+s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
+s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
+
+if (!s->ct.indirect) {
+s->ct.max_entries = (num_pages * page_sz) / s->ct.entry_sz;
+} else {
+s->ct.max_entries = (((num_pages * page_sz) /
+ L1TABLE_ENTRY_SIZE) *
+ (page_sz / s->ct.entry_sz));
+}
+
+if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
+s->ct.maxids.max_collids = (1UL << (FIELD_EX64(s->typer,
+GITS_TYPER, CIDBITS) + 1));
+} else {
+/* 16-bit CollectionId supported when CIL == 0 */
+s->ct.maxids.max_collids = (1UL << 16);
+}
+
+s->ct.base_addr = baser_base_addr(value, page_sz);
+
+break;
+
+default:
+break;
+}
+

[PATCH v8 03/10] hw/intc: GICv3 ITS command queue framework

2021-08-12 Thread Shashi Mallela
Added functionality to trigger ITS command queue processing on
write to CWRITE register and process each command queue entry to
identify the command type and handle commands like MAPD,MAPC,SYNC.

Signed-off-by: Shashi Mallela 
Reviewed-by: Peter Maydell 
Reviewed-by: Eric Auger 
Tested-by: Neil Armstrong 
---
 hw/intc/arm_gicv3_its.c  | 306 +++
 hw/intc/gicv3_internal.h |  40 +
 2 files changed, 346 insertions(+)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index b2210dffdc..8bdbebbeca 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -50,6 +50,305 @@ static uint64_t baser_base_addr(uint64_t value, uint32_t 
page_sz)
 return result;
 }
 
+static MemTxResult update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
+  uint64_t rdbase)
+{
+AddressSpace *as = &s->gicv3->dma_as;
+uint64_t value;
+uint64_t l2t_addr;
+bool valid_l2t;
+uint32_t l2t_id;
+uint32_t max_l2_entries;
+uint64_t cte = 0;
+MemTxResult res = MEMTX_OK;
+
+if (!s->ct.valid) {
+return res;
+}
+
+if (valid) {
+/* add mapping entry to collection table */
+cte = (valid & TABLE_ENTRY_VALID_MASK) | (rdbase << 1ULL);
+}
+
+/*
+ * The specification defines the format of level 1 entries of a
+ * 2-level table, but the format of level 2 entries and the format
+ * of flat-mapped tables is IMPDEF.
+ */
+if (s->ct.indirect) {
+l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
+
+value = address_space_ldq_le(as,
+ s->ct.base_addr +
+ (l2t_id * L1TABLE_ENTRY_SIZE),
+ MEMTXATTRS_UNSPECIFIED, &res);
+
+if (res != MEMTX_OK) {
+return res;
+}
+
+valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
+
+if (valid_l2t) {
+max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
+
+l2t_addr = value & ((1ULL << 51) - 1);
+
+address_space_stq_le(as, l2t_addr +
+ ((icid % max_l2_entries) * GITS_CTE_SIZE),
+ cte, MEMTXATTRS_UNSPECIFIED, &res);
+}
+} else {
+/* Flat level table */
+address_space_stq_le(as, s->ct.base_addr + (icid * GITS_CTE_SIZE),
+ cte, MEMTXATTRS_UNSPECIFIED, &res);
+}
+return res;
+}
+
+static MemTxResult process_mapc(GICv3ITSState *s, uint32_t offset)
+{
+AddressSpace *as = &s->gicv3->dma_as;
+uint16_t icid;
+uint64_t rdbase;
+bool valid;
+MemTxResult res = MEMTX_OK;
+uint64_t value;
+
+offset += NUM_BYTES_IN_DW;
+offset += NUM_BYTES_IN_DW;
+
+value = address_space_ldq_le(as, s->cq.base_addr + offset,
+ MEMTXATTRS_UNSPECIFIED, &res);
+
+if (res != MEMTX_OK) {
+return res;
+}
+
+icid = value & ICID_MASK;
+
+rdbase = (value & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
+rdbase &= RDBASE_PROCNUM_MASK;
+
+valid = (value & CMD_FIELD_VALID_MASK);
+
+if ((icid > s->ct.maxids.max_collids) || (rdbase > s->gicv3->num_cpu)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "ITS MAPC: invalid collection table attributes "
+  "icid %d rdbase %lu\n",  icid, rdbase);
+/*
+ * in this implementation, in case of error
+ * we ignore this command and move onto the next
+ * command in the queue
+ */
+} else {
+res = update_cte(s, icid, valid, rdbase);
+}
+
+return res;
+}
+
+static MemTxResult update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
+  uint8_t size, uint64_t itt_addr)
+{
+AddressSpace *as = &s->gicv3->dma_as;
+uint64_t value;
+uint64_t l2t_addr;
+bool valid_l2t;
+uint32_t l2t_id;
+uint32_t max_l2_entries;
+uint64_t dte = 0;
+MemTxResult res = MEMTX_OK;
+
+if (s->dt.valid) {
+if (valid) {
+/* add mapping entry to device table */
+dte = (valid & TABLE_ENTRY_VALID_MASK) |
+  ((size & SIZE_MASK) << 1U) |
+  (itt_addr << GITS_DTE_ITTADDR_SHIFT);
+}
+} else {
+return res;
+}
+
+/*
+ * The specification defines the format of level 1 entries of a
+ * 2-level table, but the format of level 2 entries and the format
+ * of flat-mapped tables is IMPDEF.
+ */
+if (s->dt.indirect) {
+l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
+
+value = address_space_ldq_le(as,
+ s->dt.base_addr +
+ (l2t_id * L1TABLE_ENTRY_SIZE),
+ MEMTXATTRS_UNSPECIFIED, &res);
+
+if (res != MEMTX_OK) {
+return res;
+}
+
+valid_l2t = (value & L2

[PATCH v8 01/10] hw/intc: GICv3 ITS initial framework

2021-08-12 Thread Shashi Mallela
Added register definitions relevant to ITS,implemented overall
ITS device framework with stubs for ITS control and translater
regions read/write,extended ITS common to handle mmio init between
existing kvm device and newer qemu device.

Signed-off-by: Shashi Mallela 
Reviewed-by: Peter Maydell 
Reviewed-by: Eric Auger 
Tested-by: Neil Armstrong 
---
 hw/intc/arm_gicv3_its.c| 245 +
 hw/intc/arm_gicv3_its_common.c |   7 +-
 hw/intc/arm_gicv3_its_kvm.c|   2 +-
 hw/intc/gicv3_internal.h   |  96 +-
 hw/intc/meson.build|   1 +
 include/hw/intc/arm_gicv3_its_common.h |   9 +-
 6 files changed, 346 insertions(+), 14 deletions(-)
 create mode 100644 hw/intc/arm_gicv3_its.c

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
new file mode 100644
index 00..2286b3f757
--- /dev/null
+++ b/hw/intc/arm_gicv3_its.c
@@ -0,0 +1,245 @@
+/*
+ * ITS emulation for a GICv3-based system
+ *
+ * Copyright Linaro.org 2021
+ *
+ * Authors:
+ *  Shashi Mallela 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
+ * option) any later version.  See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/qdev-properties.h"
+#include "hw/intc/arm_gicv3_its_common.h"
+#include "gicv3_internal.h"
+#include "qom/object.h"
+#include "qapi/error.h"
+
+typedef struct GICv3ITSClass GICv3ITSClass;
+/* This is reusing the GICv3ITSState typedef from ARM_GICV3_ITS_COMMON */
+DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSClass,
+ ARM_GICV3_ITS, TYPE_ARM_GICV3_ITS)
+
+struct GICv3ITSClass {
+GICv3ITSCommonClass parent_class;
+void (*parent_reset)(DeviceState *dev);
+};
+
+static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
+   uint64_t data, unsigned size,
+   MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult its_writel(GICv3ITSState *s, hwaddr offset,
+  uint64_t value, MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult its_readl(GICv3ITSState *s, hwaddr offset,
+ uint64_t *data, MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult its_writell(GICv3ITSState *s, hwaddr offset,
+   uint64_t value, MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult its_readll(GICv3ITSState *s, hwaddr offset,
+  uint64_t *data, MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data,
+  unsigned size, MemTxAttrs attrs)
+{
+GICv3ITSState *s = (GICv3ITSState *)opaque;
+MemTxResult result;
+
+switch (size) {
+case 4:
+result = its_readl(s, offset, data, attrs);
+break;
+case 8:
+result = its_readll(s, offset, data, attrs);
+break;
+default:
+result = MEMTX_ERROR;
+break;
+}
+
+if (result == MEMTX_ERROR) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: invalid guest read at offset " TARGET_FMT_plx
+  "size %u\n", __func__, offset, size);
+/*
+ * The spec requires that reserved registers are RAZ/WI;
+ * so use MEMTX_ERROR returns from leaf functions as a way to
+ * trigger the guest-error logging but don't return it to
+ * the caller, or we'll cause a spurious guest data abort.
+ */
+result = MEMTX_OK;
+*data = 0;
+}
+return result;
+}
+
+static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data,
+   unsigned size, MemTxAttrs attrs)
+{
+GICv3ITSState *s = (GICv3ITSState *)opaque;
+MemTxResult result;
+
+switch (size) {
+case 4:
+result = its_writel(s, offset, data, attrs);
+break;
+case 8:
+result = its_writell(s, offset, data, attrs);
+break;
+default:
+result = MEMTX_ERROR;
+break;
+}
+
+if (result == MEMTX_ERROR) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: invalid guest write at offset " TARGET_FMT_plx
+  "size %u\n", __func__, offset, size);
+/*
+ * The spec requires that reserved registers are RAZ/WI;
+ * so use MEMTX_ERROR returns from leaf functions as a way to
+ * trigger the guest-error logging but don't return it to
+ * the caller, or we'll cause a spurious guest data abort.
+ */
+result = MEMTX_OK;
+}
+return result;
+}
+
+static const Me

[PATCH v8 00/10] GICv3 LPI and ITS feature implementation

2021-08-12 Thread Shashi Mallela
This patchset implements qemu device model for enabling physical
LPI support and ITS functionality in GIC as per GICv3 specification.
Both flat table and 2 level tables are implemented.The ITS commands
for adding/deleting ITS table entries,trigerring LPI interrupts are
implemented.Translated LPI interrupt ids are processed by redistributor
to determine priority and set pending state appropriately before
forwarding the same to cpu interface.
The ITS feature support has been added to sbsa-ref platform as well as
virt platform,wherein the emulated functionality co-exists with kvm
kernel functionality.

Changes in v8:
 - moved tcg ITS support to virt platform 6.1 options (since it will be
   supported in 6.2)
 - modified the ite entry access offset based on latest test results
 - All kvm_unit_tests PASS
 - Verified Linux Boot functionality  

Shashi Mallela (10):
  hw/intc: GICv3 ITS initial framework
  hw/intc: GICv3 ITS register definitions added
  hw/intc: GICv3 ITS command queue framework
  hw/intc: GICv3 ITS Command processing
  hw/intc: GICv3 ITS Feature enablement
  hw/intc: GICv3 redistributor ITS processing
  hw/arm/sbsa-ref: add ITS support in SBSA GIC
  tests/data/acpi/virt: Add IORT files for ITS
  hw/arm/virt: add ITS support in virt GIC
  tests/data/acpi/virt: Update IORT files for ITS

 hw/arm/sbsa-ref.c  |   79 +-
 hw/arm/virt.c  |   28 +-
 hw/intc/arm_gicv3.c|   14 +
 hw/intc/arm_gicv3_common.c |   13 +
 hw/intc/arm_gicv3_cpuif.c  |7 +-
 hw/intc/arm_gicv3_dist.c   |5 +-
 hw/intc/arm_gicv3_its.c| 1301 
 hw/intc/arm_gicv3_its_common.c |7 +-
 hw/intc/arm_gicv3_its_kvm.c|2 +-
 hw/intc/arm_gicv3_redist.c |  153 ++-
 hw/intc/gicv3_internal.h   |  188 +++-
 hw/intc/meson.build|1 +
 include/hw/arm/virt.h  |2 +
 include/hw/intc/arm_gicv3_common.h |   13 +
 include/hw/intc/arm_gicv3_its_common.h |   32 +-
 target/arm/kvm_arm.h   |4 +-
 tests/data/acpi/virt/IORT  |  Bin 0 -> 124 bytes
 tests/data/acpi/virt/IORT.memhp|  Bin 0 -> 124 bytes
 tests/data/acpi/virt/IORT.numamem  |  Bin 0 -> 124 bytes
 tests/data/acpi/virt/IORT.pxb  |  Bin 0 -> 124 bytes
 20 files changed, 1821 insertions(+), 28 deletions(-)
 create mode 100644 hw/intc/arm_gicv3_its.c
 create mode 100644 tests/data/acpi/virt/IORT
 create mode 100644 tests/data/acpi/virt/IORT.memhp
 create mode 100644 tests/data/acpi/virt/IORT.numamem
 create mode 100644 tests/data/acpi/virt/IORT.pxb

--
2.27.0



[PATCH] hw/sensor: Add SB-TSI Temperature Sensor Interface

2021-08-12 Thread Hao Wu
SB Temperature Sensor Interface (SB-TSI) is an SMBus compatible
interface that reports AMD SoC's Ttcl (normalized temperature),
and resembles a typical 8-pin remote temperature sensor's I2C interface
to BMC.

This patch implements a basic AMD SB-TSI sensor that is
compatible with the open-source data sheet from AMD and Linux
kernel driver.

Reference:
Linux kernel driver:
https://lkml.org/lkml/2020/12/11/968
Register Map:
https://developer.amd.com/wp-content/resources/56255_3_03.PDF
(Chapter 6)

Signed-off-by: Hao Wu 
Reviewed-by: Doug Evans 
---
 hw/sensor/Kconfig|   4 +
 hw/sensor/meson.build|   1 +
 hw/sensor/tmp_sbtsi.c| 393 +++
 hw/sensor/trace-events   |   5 +
 hw/sensor/trace.h|   1 +
 meson.build  |   1 +
 tests/qtest/meson.build  |   1 +
 tests/qtest/tmp_sbtsi-test.c | 180 
 8 files changed, 586 insertions(+)
 create mode 100644 hw/sensor/tmp_sbtsi.c
 create mode 100644 hw/sensor/trace-events
 create mode 100644 hw/sensor/trace.h
 create mode 100644 tests/qtest/tmp_sbtsi-test.c

diff --git a/hw/sensor/Kconfig b/hw/sensor/Kconfig
index a2b55a4fdb..31e78e6fd5 100644
--- a/hw/sensor/Kconfig
+++ b/hw/sensor/Kconfig
@@ -17,3 +17,7 @@ config ADM1272
 config MAX34451
 bool
 depends on I2C
+
+config AMDSBTSI
+bool
+depends on I2C
diff --git a/hw/sensor/meson.build b/hw/sensor/meson.build
index 034e3e0207..4e6747b2f2 100644
--- a/hw/sensor/meson.build
+++ b/hw/sensor/meson.build
@@ -3,3 +3,4 @@ softmmu_ss.add(when: 'CONFIG_TMP421', if_true: 
files('tmp421.c'))
 softmmu_ss.add(when: 'CONFIG_EMC141X', if_true: files('emc141x.c'))
 softmmu_ss.add(when: 'CONFIG_ADM1272', if_true: files('adm1272.c'))
 softmmu_ss.add(when: 'CONFIG_MAX34451', if_true: files('max34451.c'))
+softmmu_ss.add(when: 'CONFIG_AMDSBTSI', if_true: files('tmp_sbtsi.c'))
diff --git a/hw/sensor/tmp_sbtsi.c b/hw/sensor/tmp_sbtsi.c
new file mode 100644
index 00..b68c7ebf61
--- /dev/null
+++ b/hw/sensor/tmp_sbtsi.c
@@ -0,0 +1,393 @@
+/*
+ * AMD SBI Temperature Sensor Interface (SB-TSI)
+ *
+ * Copyright 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/i2c/smbus_slave.h"
+#include "hw/irq.h"
+#include "migration/vmstate.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "trace.h"
+
+#define TYPE_SBTSI "sbtsi"
+#define SBTSI(obj) OBJECT_CHECK(SBTSIState, (obj), TYPE_SBTSI)
+
+/**
+ * SBTSIState:
+ * temperatures are in units of 0.125 degrees
+ * @temperature: Temperature
+ * @limit_low: Lowest temperature
+ * @limit_high: Highest temperature
+ * @status: The status register
+ * @config: The config register
+ * @alert_config: The config for alarm_l output.
+ * @addr: The address to read/write for the next cmd.
+ * @alarm: The alarm_l output pin (GPIO)
+ */
+typedef struct SBTSIState {
+SMBusDevice parent;
+
+uint32_t temperature;
+uint32_t limit_low;
+uint32_t limit_high;
+uint8_t status;
+uint8_t config;
+uint8_t alert_config;
+uint8_t addr;
+qemu_irq alarm;
+} SBTSIState;
+
+/*
+ * SB-TSI registers only support SMBus byte data access. "_INT" registers are
+ * the integer part of a temperature value or limit, and "_DEC" registers are
+ * corresponding decimal parts.
+ */
+#define SBTSI_REG_TEMP_INT  0x01 /* RO */
+#define SBTSI_REG_STATUS0x02 /* RO */
+#define SBTSI_REG_CONFIG0x03 /* RO */
+#define SBTSI_REG_TEMP_HIGH_INT 0x07 /* RW */
+#define SBTSI_REG_TEMP_LOW_INT  0x08 /* RW */
+#define SBTSI_REG_CONFIG_WR 0x09 /* RW */
+#define SBTSI_REG_TEMP_DEC  0x10 /* RO */
+#define SBTSI_REG_TEMP_HIGH_DEC 0x13 /* RW */
+#define SBTSI_REG_TEMP_LOW_DEC  0x14 /* RW */
+#define SBTSI_REG_ALERT_CONFIG  0xBF /* RW */
+#define SBTSI_REG_MAN   0xFE /* RO */
+#define SBTSI_REG_REV   0xFF /* RO */
+
+#define SBTSI_STATUS_HIGH_ALERT BIT(4)
+#define SBTSI_STATUS_LOW_ALERT  BIT(3)
+#define SBTSI_CONFIG_ALERT_MASK BIT(7)
+#define SBTSI_ALARM_EN  BIT(0)
+
+#define SBTSI_LIMIT_LOW_DEFAULT (0)
+#define SBTSI_LIMIT_HIGH_DEFAULT (560)
+#define SBTSI_MAN_DEFAULT (0)
+#define SBTSI_REV_DEFAULT (4)
+#define SBTSI_ALARM_L "alarm_l"
+
+/* The temperature we stored are in units of 0.125 degrees. */
+#define SBTSI_TEMP_UNIT_IN_MILLIDEGREE 125
+
+/*
+ * The integer part and decimal of the temperature both 8 bits.
+ * Only the top 3 bits of the decimal parts are used.
+ * So the max t

Re: [PATCH] hw/riscv/virt.c: Assemble plic_hart_config string with g_strjoinv()

2021-08-12 Thread Peter Maydell
On Thu, 12 Aug 2021 at 17:09, Philippe Mathieu-Daudé  wrote:
>
> Hi Peter,
>
> On 8/12/21 4:46 PM, Peter Maydell wrote:
> > In the riscv virt machine init function, We assemble a string
> > plic_hart_config which is a comma-separated list of N copies of the
> > VIRT_PLIC_HART_CONFIG string.  The code that does this has a
> > misunderstanding of the strncat() length argument.  If the source
> > string is too large strncat() will write a maximum of length+1 bytes
> > (length bytes from the source string plus a trailing NUL), but the
> > code here assumes that it will write only length bytes at most.
> >
> > This isn't an actual bug because the code has correctly precalculated
> > the amount of memory it needs to allocate so that it will never be
> > too small (i.e.  we could have used plain old strcat()), but it does
> > mean that the code looks like it has a guard against accidental
> > overrun when it doesn't.
> >
> > Rewrite the string handling here to use the glib g_strjoinv()
> > function, which means we don't need to do careful accountancy of
> > string lengths, and makes it clearer that what we're doing is
> > "create a comma-separated string".
> >
> > Fixes: Coverity 1460752
> > Signed-off-by: Peter Maydell 
> > ---
> >  hw/riscv/virt.c | 33 -
> >  1 file changed, 20 insertions(+), 13 deletions(-)
> >
> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> > index 4a3cd2599a5..26bc8d289ba 100644
> > --- a/hw/riscv/virt.c
> > +++ b/hw/riscv/virt.c
> > @@ -541,6 +541,24 @@ static FWCfgState *create_fw_cfg(const MachineState 
> > *mc)
> >  return fw_cfg;
> >  }
> >
> > +/*
> > + * Return the per-socket PLIC hart topology configuration string
> > + * (caller must free with g_free())
> > + */
> > +static char *plic_hart_config_string(int hart_count)
> > +{
> > +g_autofree const char **vals = g_new(const char *, hart_count + 1);
> > +int i;
> > +
> > +for (i = 0; i < hart_count; i++) {
> > +vals[i] = VIRT_PLIC_HART_CONFIG;
>
> Have you considered adding plic_hart_config_string() an extra
> 'const char *plic_config' argument (declaring it in a new
> include/hw/riscv/plic_hart.h)?
> We could use it in the other boards:

I hadn't noticed those, because Coverity doesn't complain about them.
Both sifive_u.c and microchip_pfsoc.c would need slightly different
code, though, because they are setting up a string like "M,MS,MS,MS"
where the first element is different from the others.

This is (I think) because they have the same misconception about
strncat()'s length argument, but they have a counterbalancing bug
where they reduce the 'remaining bytes in buffer' argument by 2 each
time round the loop even though the length of the first element in
their comma separated string is only 1 byte -- so they are accidentally
turning the length value into what it ought to be.

So those other board files should definitely also be updated to
use g_strjoinv(), but I'm not sure that we can usefully share code.
(We could have a function that takes an argument for the string
for the first CPU and one for the other CPUs, which would work
for all the boards we have now, but that feels a bit contrived
and maybe some other boards in future would want to make different
entries in the list be different...)

-- PMM



Re: [PATCH] hw/core/loader: In gunzip(), check index is in range before use, not after

2021-08-12 Thread Philippe Mathieu-Daudé
On 8/12/21 4:18 PM, Peter Maydell wrote:
> The gunzip() function reads various fields from a passed in source
> buffer in order to skip a header before passing the actual compressed
> data to the zlib inflate() function.  It does check whether the
> passed in buffer is too small, but unfortunately it checks that only
> after reading bytes from the src buffer, so it could read off the end
> of the buffer.
> 
> You can see this with valgrind:
> 
>  $ printf "%b" '\x1f\x8b' > /tmp/image
>  $ valgrind qemu-system-aarch64 -display none -M virt -cpu max -kernel 
> /tmp/image

Nice :)

Reviewed-by: Philippe Mathieu-Daudé 

>  [...]
>  ==19224== Invalid read of size 1
>  ==19224==at 0x67302E: gunzip (loader.c:558)
>  ==19224==by 0x673907: load_image_gzipped_buffer (loader.c:788)
>  ==19224==by 0xA18032: load_aarch64_image (boot.c:932)
>  ==19224==by 0xA18489: arm_setup_direct_kernel_boot (boot.c:1063)
>  ==19224==by 0xA18D90: arm_load_kernel (boot.c:1317)
>  ==19224==by 0x9F3651: machvirt_init (virt.c:2114)
>  ==19224==by 0x794B7A: machine_run_board_init (machine.c:1272)
>  ==19224==by 0xD5CAD3: qemu_init_board (vl.c:2618)
>  ==19224==by 0xD5CCA6: qmp_x_exit_preconfig (vl.c:2692)
>  ==19224==by 0xD5F32E: qemu_init (vl.c:3713)
>  ==19224==by 0x5ADDB1: main (main.c:49)
>  ==19224==  Address 0x3802a873 is 0 bytes after a block of size 3 alloc'd
>  ==19224==at 0x4C31B0F: malloc (in 
> /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
>  ==19224==by 0x61E7657: g_file_get_contents (in 
> /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.5600.4)
>  ==19224==by 0x673895: load_image_gzipped_buffer (loader.c:771)
>  ==19224==by 0xA18032: load_aarch64_image (boot.c:932)
>  ==19224==by 0xA18489: arm_setup_direct_kernel_boot (boot.c:1063)
>  ==19224==by 0xA18D90: arm_load_kernel (boot.c:1317)
>  ==19224==by 0x9F3651: machvirt_init (virt.c:2114)
>  ==19224==by 0x794B7A: machine_run_board_init (machine.c:1272)
>  ==19224==by 0xD5CAD3: qemu_init_board (vl.c:2618)
>  ==19224==by 0xD5CCA6: qmp_x_exit_preconfig (vl.c:2692)
>  ==19224==by 0xD5F32E: qemu_init (vl.c:3713)
>  ==19224==by 0x5ADDB1: main (main.c:49)
> 
> Check that we have enough bytes of data to read the header bytes that
> we read before we read them.
> 
> Fixes: Coverity 1458997
> Signed-off-by: Peter Maydell 
> ---
>  hw/core/loader.c | 35 +--
>  1 file changed, 25 insertions(+), 10 deletions(-)



Re: [PATCH] hw/riscv/virt.c: Assemble plic_hart_config string with g_strjoinv()

2021-08-12 Thread Philippe Mathieu-Daudé
Hi Peter,

On 8/12/21 4:46 PM, Peter Maydell wrote:
> In the riscv virt machine init function, We assemble a string
> plic_hart_config which is a comma-separated list of N copies of the
> VIRT_PLIC_HART_CONFIG string.  The code that does this has a
> misunderstanding of the strncat() length argument.  If the source
> string is too large strncat() will write a maximum of length+1 bytes
> (length bytes from the source string plus a trailing NUL), but the
> code here assumes that it will write only length bytes at most.
> 
> This isn't an actual bug because the code has correctly precalculated
> the amount of memory it needs to allocate so that it will never be
> too small (i.e.  we could have used plain old strcat()), but it does
> mean that the code looks like it has a guard against accidental
> overrun when it doesn't.
> 
> Rewrite the string handling here to use the glib g_strjoinv()
> function, which means we don't need to do careful accountancy of
> string lengths, and makes it clearer that what we're doing is
> "create a comma-separated string".
> 
> Fixes: Coverity 1460752
> Signed-off-by: Peter Maydell 
> ---
>  hw/riscv/virt.c | 33 -
>  1 file changed, 20 insertions(+), 13 deletions(-)
> 
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 4a3cd2599a5..26bc8d289ba 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -541,6 +541,24 @@ static FWCfgState *create_fw_cfg(const MachineState *mc)
>  return fw_cfg;
>  }
>  
> +/*
> + * Return the per-socket PLIC hart topology configuration string
> + * (caller must free with g_free())
> + */
> +static char *plic_hart_config_string(int hart_count)
> +{
> +g_autofree const char **vals = g_new(const char *, hart_count + 1);
> +int i;
> +
> +for (i = 0; i < hart_count; i++) {
> +vals[i] = VIRT_PLIC_HART_CONFIG;

Have you considered adding plic_hart_config_string() an extra
'const char *plic_config' argument (declaring it in a new
include/hw/riscv/plic_hart.h)?
We could use it in the other boards:

hw/riscv/microchip_pfsoc.c:267:strncat(plic_hart_config, ","
MICROCHIP_PFSOC_PLIC_HART_CONFIG,
hw/riscv/microchip_pfsoc.c:268:plic_hart_config_len);
hw/riscv/microchip_pfsoc.c:270:strncat(plic_hart_config,
"M", plic_hart_config_len);

hw/riscv/sifive_u.c:826:strncat(plic_hart_config, ","
SIFIVE_U_PLIC_HART_CONFIG,
hw/riscv/sifive_u.c:827:plic_hart_config_len);
hw/riscv/sifive_u.c:829:strncat(plic_hart_config, "M",
plic_hart_config_len);

hw/riscv/virt.c:612:strncat(plic_hart_config, ",",
plic_hart_config_len);
hw/riscv/virt.c:614:strncat(plic_hart_config,
VIRT_PLIC_HART_CONFIG,
hw/riscv/virt.c:615:plic_hart_config_len);

include/hw/riscv/microchip_pfsoc.h:141:#define
MICROCHIP_PFSOC_PLIC_HART_CONFIG"MS"
include/hw/riscv/shakti_c.h:63:#define SHAKTI_C_PLIC_HART_CONFIG "MS"
include/hw/riscv/sifive_e.h:83:#define SIFIVE_E_PLIC_HART_CONFIG "M"
include/hw/riscv/sifive_u.h:147:#define SIFIVE_U_PLIC_HART_CONFIG "MS"
include/hw/riscv/virt.h:74:#define VIRT_PLIC_HART_CONFIG "MS"

Obviously someone else could do that as bytetask, so meanwhile
for Coverity 1460752:
Reviewed-by: Philippe Mathieu-Daudé 

> +}
> +vals[i] = NULL;
> +
> +/* g_strjoinv() obliges us to cast away const here */
> +return g_strjoinv(",", (char **)vals);
> +}
> +
>  static void virt_machine_init(MachineState *machine)
>  {
>  const MemMapEntry *memmap = virt_memmap;
> @@ -549,13 +567,12 @@ static void virt_machine_init(MachineState *machine)
>  MemoryRegion *main_mem = g_new(MemoryRegion, 1);
>  MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
>  char *plic_hart_config, *soc_name;
> -size_t plic_hart_config_len;
>  target_ulong start_addr = memmap[VIRT_DRAM].base;
>  target_ulong firmware_end_addr, kernel_start_addr;
>  uint32_t fdt_load_addr;
>  uint64_t kernel_entry;
>  DeviceState *mmio_plic, *virtio_plic, *pcie_plic;
> -int i, j, base_hartid, hart_count;
> +int i, base_hartid, hart_count;
>  
>  /* Check socket count limit */
>  if (VIRT_SOCKETS_MAX < riscv_socket_count(machine)) {
> @@ -604,17 +621,7 @@ static void virt_machine_init(MachineState *machine)
>  SIFIVE_CLINT_TIMEBASE_FREQ, true);
>  
>  /* Per-socket PLIC hart topology configuration string */
> -plic_hart_config_len =
> -(strlen(VIRT_PLIC_HART_CONFIG) + 1) * hart_count;
> -plic_hart_config = g_malloc0(plic_hart_config_len);
> -for (j = 0; j < hart_count; j++) {
> -if (j != 0) {
> -strncat(plic_hart_config, ",", plic_hart_config_len);
> -}
> -strncat(plic_hart_config, VIRT_PLIC_HART_CONFIG,
> -plic_hart_config_len);
> -plic_hart_config_len -= (strlen(VIRT_PLIC_HART_CONFIG) + 1);
> -}
> +plic_hart_config = plic_hart_

[PATCH v3 6/6] tests/qapi-schema: Test cases for aliases

2021-08-12 Thread Kevin Wolf
Signed-off-by: Kevin Wolf 
---
 tests/unit/test-qobject-input-visitor.c   | 218 ++
 tests/qapi-schema/alias-bad-type.err  |   2 +
 tests/qapi-schema/alias-bad-type.json |   3 +
 tests/qapi-schema/alias-bad-type.out  |   0
 tests/qapi-schema/alias-missing-source.err|   2 +
 tests/qapi-schema/alias-missing-source.json   |   3 +
 tests/qapi-schema/alias-missing-source.out|   0
 tests/qapi-schema/alias-name-bad-type.err |   2 +
 tests/qapi-schema/alias-name-bad-type.json|   3 +
 tests/qapi-schema/alias-name-bad-type.out |   0
 tests/qapi-schema/alias-name-conflict.err |   2 +
 tests/qapi-schema/alias-name-conflict.json|   4 +
 tests/qapi-schema/alias-name-conflict.out |   0
 tests/qapi-schema/alias-recursive.err |   2 +
 tests/qapi-schema/alias-recursive.json|   4 +
 tests/qapi-schema/alias-recursive.out |   0
 tests/qapi-schema/alias-source-bad-type.err   |   2 +
 tests/qapi-schema/alias-source-bad-type.json  |   3 +
 tests/qapi-schema/alias-source-bad-type.out   |   0
 .../alias-source-elem-bad-type.err|   2 +
 .../alias-source-elem-bad-type.json   |   3 +
 .../alias-source-elem-bad-type.out|   0
 tests/qapi-schema/alias-source-empty.err  |   2 +
 tests/qapi-schema/alias-source-empty.json |   3 +
 tests/qapi-schema/alias-source-empty.out  |   0
 .../alias-source-inexistent-variants.err  |   2 +
 .../alias-source-inexistent-variants.json |  12 +
 .../alias-source-inexistent-variants.out  |   0
 tests/qapi-schema/alias-source-inexistent.err |   2 +
 .../qapi-schema/alias-source-inexistent.json  |   3 +
 tests/qapi-schema/alias-source-inexistent.out |   0
 .../alias-source-non-object-path.err  |   2 +
 .../alias-source-non-object-path.json |   3 +
 .../alias-source-non-object-path.out  |   0
 .../alias-source-non-object-wildcard.err  |   2 +
 .../alias-source-non-object-wildcard.json |   3 +
 .../alias-source-non-object-wildcard.out  |   0
 ...lias-source-optional-wildcard-indirect.err |   2 +
 ...ias-source-optional-wildcard-indirect.json |   6 +
 ...lias-source-optional-wildcard-indirect.out |   0
 .../alias-source-optional-wildcard.err|   2 +
 .../alias-source-optional-wildcard.json   |   5 +
 .../alias-source-optional-wildcard.out|   0
 tests/qapi-schema/alias-unknown-key.err   |   3 +
 tests/qapi-schema/alias-unknown-key.json  |   3 +
 tests/qapi-schema/alias-unknown-key.out   |   0
 tests/qapi-schema/aliases-bad-type.err|   2 +
 tests/qapi-schema/aliases-bad-type.json   |   3 +
 tests/qapi-schema/aliases-bad-type.out|   0
 tests/qapi-schema/meson.build |  16 ++
 tests/qapi-schema/qapi-schema-test.json   |  26 +++
 tests/qapi-schema/qapi-schema-test.out|  31 +++
 52 files changed, 388 insertions(+)
 create mode 100644 tests/qapi-schema/alias-bad-type.err
 create mode 100644 tests/qapi-schema/alias-bad-type.json
 create mode 100644 tests/qapi-schema/alias-bad-type.out
 create mode 100644 tests/qapi-schema/alias-missing-source.err
 create mode 100644 tests/qapi-schema/alias-missing-source.json
 create mode 100644 tests/qapi-schema/alias-missing-source.out
 create mode 100644 tests/qapi-schema/alias-name-bad-type.err
 create mode 100644 tests/qapi-schema/alias-name-bad-type.json
 create mode 100644 tests/qapi-schema/alias-name-bad-type.out
 create mode 100644 tests/qapi-schema/alias-name-conflict.err
 create mode 100644 tests/qapi-schema/alias-name-conflict.json
 create mode 100644 tests/qapi-schema/alias-name-conflict.out
 create mode 100644 tests/qapi-schema/alias-recursive.err
 create mode 100644 tests/qapi-schema/alias-recursive.json
 create mode 100644 tests/qapi-schema/alias-recursive.out
 create mode 100644 tests/qapi-schema/alias-source-bad-type.err
 create mode 100644 tests/qapi-schema/alias-source-bad-type.json
 create mode 100644 tests/qapi-schema/alias-source-bad-type.out
 create mode 100644 tests/qapi-schema/alias-source-elem-bad-type.err
 create mode 100644 tests/qapi-schema/alias-source-elem-bad-type.json
 create mode 100644 tests/qapi-schema/alias-source-elem-bad-type.out
 create mode 100644 tests/qapi-schema/alias-source-empty.err
 create mode 100644 tests/qapi-schema/alias-source-empty.json
 create mode 100644 tests/qapi-schema/alias-source-empty.out
 create mode 100644 tests/qapi-schema/alias-source-inexistent-variants.err
 create mode 100644 tests/qapi-schema/alias-source-inexistent-variants.json
 create mode 100644 tests/qapi-schema/alias-source-inexistent-variants.out
 create mode 100644 tests/qapi-schema/alias-source-inexistent.err
 create mode 100644 tests/qapi-schema/alias-source-inexistent.json
 create mode 100644 tests/qapi-schema/alias-source-inexistent.out
 create mode 100644 tests/qapi-schema/alias-source-non-object-path.err
 create mode 100644 tests/qapi-schema/alias-source-non-object-path.json
 create mode 1006

[PATCH v3 5/6] qapi: Add support for aliases

2021-08-12 Thread Kevin Wolf
Introduce alias definitions for object types (structs and unions). This
allows using the same QAPI type and visitor for many syntax variations
that exist in the external representation, like between QMP and the
command line. It also provides a new tool for evolving the schema while
maintaining backwards compatibility during a deprecation period.

Signed-off-by: Kevin Wolf 
---
 docs/devel/qapi-code-gen.rst   | 104 +-
 docs/sphinx/qapidoc.py |   2 +-
 scripts/qapi/expr.py   |  47 +-
 scripts/qapi/schema.py | 116 +++--
 scripts/qapi/types.py  |   4 +-
 scripts/qapi/visit.py  |  34 +++-
 tests/qapi-schema/test-qapi.py |   7 +-
 tests/qapi-schema/double-type.err  |   2 +-
 tests/qapi-schema/unknown-expr-key.err |   2 +-
 9 files changed, 297 insertions(+), 21 deletions(-)

diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst
index 26c62b0e7b..c0883507a8 100644
--- a/docs/devel/qapi-code-gen.rst
+++ b/docs/devel/qapi-code-gen.rst
@@ -262,7 +262,8 @@ Syntax::
'data': MEMBERS,
'*base': STRING,
'*if': COND,
-   '*features': FEATURES }
+   '*features': FEATURES,
+   '*aliases': ALIASES }
 MEMBERS = { MEMBER, ... }
 MEMBER = STRING : TYPE-REF
| STRING : { 'type': TYPE-REF,
@@ -312,6 +313,9 @@ the schema`_ below for more on this.
 The optional 'features' member specifies features.  See Features_
 below for more on this.
 
+The optional 'aliases' member specifies aliases.  See Aliases_ below
+for more on this.
+
 
 Union types
 ---
@@ -321,13 +325,15 @@ Syntax::
 UNION = { 'union': STRING,
   'data': BRANCHES,
   '*if': COND,
-  '*features': FEATURES }
+  '*features': FEATURES,
+  '*aliases': ALIASES }
   | { 'union': STRING,
   'data': BRANCHES,
   'base': ( MEMBERS | STRING ),
   'discriminator': STRING,
   '*if': COND,
-  '*features': FEATURES }
+  '*features': FEATURES,
+  '*aliases': ALIASES }
 BRANCHES = { BRANCH, ... }
 BRANCH = STRING : TYPE-REF
| STRING : { 'type': TYPE-REF, '*if': COND }
@@ -437,6 +443,9 @@ the schema`_ below for more on this.
 The optional 'features' member specifies features.  See Features_
 below for more on this.
 
+The optional 'aliases' member specifies aliases.  See Aliases_ below
+for more on this.
+
 
 Alternate types
 ---
@@ -888,6 +897,95 @@ shows a conditional entity only when the condition is 
satisfied in
 this particular build.
 
 
+Aliases
+---
+
+Object types, including structs and unions, can contain alias
+definitions.
+
+Aliases define alternative member names that may be used in wire input
+to provide a value for a member in the same object or in a nested
+object.
+
+Syntax::
+
+ALIASES = [ ALIAS, ... ]
+ALIAS = { '*name': STRING,
+  'source': [ STRING, ... ] }
+
+If ``name`` is present, then the single member referred to by ``source``
+is made accessible with the name given by ``name`` in the type where the
+alias definition is specified.
+
+If ``name`` is not present, then this is a wildcard alias and all
+members in the object referred to by ``source`` are made accessible in
+the type where the alias definition is specified with the same name as
+they have in ``source``.
+
+``source`` is a non-empty list of member names representing the path to
+an object member. The first name is resolved in the same object.  Each
+subsequent member is resolved in the object named by the preceding
+member.
+
+Do not use optional objects in the path of a wildcard alias unless there
+is no semantic difference between an empty object and an absent object.
+Absent objects are implicitly turned into empty ones if an alias could
+apply and provide a value in the nested object, which is always the case
+for wildcard aliases.
+
+Example: Alternative name for a member in the same object ::
+
+ { 'struct': 'File',
+   'data': { 'path': 'str' },
+   'aliases': [ { 'name': 'filename', 'source': ['path'] } ] }
+
+The member ``path`` may instead be given through its alias ``filename``
+in input.
+
+Example: Alias for a member in a nested object ::
+
+ { 'struct': 'A',
+   'data': { 'zahl': 'int' } }
+ { 'struct': 'B',
+   'data': { 'drei': 'A' } }
+ { 'struct': 'C',
+   'data': { 'zwei': 'B' } }
+ { 'struct': 'D',
+   'data': { 'eins': 'C' },
+   'aliases': [ { 'name': 'number',
+  'source': ['eins', 'zwei', 'drei', 'zahl' ] },
+{ 'name': 'the_B',
+  'source': ['eins','zwei'] } ] }
+
+With this definition, each of the following inputs for ``D`` mean the
+same::
+
+ { 'eins': { 'zwei': { 'drei': { 'zahl': 42 } } } }
+
+ { 'the_B': { 'drei': { 'zahl': 42 } } }
+
+ {

[PATCH v3 0/6] qapi: Add support for aliases

2021-08-12 Thread Kevin Wolf
This series introduces alias definitions for QAPI object types (structs
and unions).

This allows using the same QAPI type and visitor even when the syntax
has some variations between different external interfaces such as QMP
and the command line.

It also provides a new tool for evolving the schema while maintaining
backwards compatibility (possibly during a deprecation period).

The first user is intended to be a QAPIfied -chardev command line
option, for which I'll send a separate series. A git tag is available
that contains both this series and the chardev changes that make use of
it:

https://repo.or.cz/qemu/kevin.git qapi-alias-chardev-v3

v3:
- Mention the new functions in the big comment in visitor.h. However,
  since the comment is about users of the visitor rather than the
  generated code, it seems like to wrong place to go into details.
- Updated commit message for patch 3 ('Simplify full_name_nth() ...')
- Patch 4 ('qapi: Apply aliases in qobject-input-visitor'):
- Multiple matching wildcard aliases are considered conflicting now
- Improved comments for several functions
- Renamed bool *implicit_object into *is_alias_prefix, which
  describes better what it is rather than what it is used for
- Simplified alias_present() into input_present()
- Fixed potential use of wrong StackObject in error message
- Patch 5 ('qapi: Add support for aliases'):
- Made QAPISchemaAlias a QAPISchemaMember
- Check validity of alias source paths (must exist in at least one
  variant, no optional objects in the path of a wildcard alias, no
  alias loops)
- Many new tests cases, both positive and negative, including unit tests
  of the generated visit functions
- Coding style changes
- Rebased documentation (.txt -> .rst conversion in master)

v2:
- Renamed 'alias' to 'name' in all data structures describing aliases
- Tons of new or changed comments and other documentation
- Be more explicit that empty 'source' is invalid and assert it
- Fixed full_name_so() for lists (added a parameter to tell the function
  whether the name of a list member or the list itself is meant)
- Changed some QAPI generator error messages
- Assert the type of parameters in QAPISchemaAlias.__init__()


Kevin Wolf (6):
  qapi: Add interfaces for alias support to Visitor
  qapi: Remember alias definitions in qobject-input-visitor
  qapi: Simplify full_name_nth() in qobject-input-visitor
  qapi: Apply aliases in qobject-input-visitor
  qapi: Add support for aliases
  tests/qapi-schema: Test cases for aliases

 docs/devel/qapi-code-gen.rst  | 104 -
 docs/sphinx/qapidoc.py|   2 +-
 include/qapi/visitor-impl.h   |  12 +
 include/qapi/visitor.h|  59 ++-
 qapi/qapi-visit-core.c|  22 +
 qapi/qobject-input-visitor.c  | 417 --
 tests/unit/test-qobject-input-visitor.c   | 218 +
 scripts/qapi/expr.py  |  47 +-
 scripts/qapi/schema.py| 116 -
 scripts/qapi/types.py |   4 +-
 scripts/qapi/visit.py |  34 +-
 tests/qapi-schema/test-qapi.py|   7 +-
 tests/qapi-schema/alias-bad-type.err  |   2 +
 tests/qapi-schema/alias-bad-type.json |   3 +
 tests/qapi-schema/alias-bad-type.out  |   0
 tests/qapi-schema/alias-missing-source.err|   2 +
 tests/qapi-schema/alias-missing-source.json   |   3 +
 tests/qapi-schema/alias-missing-source.out|   0
 tests/qapi-schema/alias-name-bad-type.err |   2 +
 tests/qapi-schema/alias-name-bad-type.json|   3 +
 tests/qapi-schema/alias-name-bad-type.out |   0
 tests/qapi-schema/alias-name-conflict.err |   2 +
 tests/qapi-schema/alias-name-conflict.json|   4 +
 tests/qapi-schema/alias-name-conflict.out |   0
 tests/qapi-schema/alias-recursive.err |   2 +
 tests/qapi-schema/alias-recursive.json|   4 +
 tests/qapi-schema/alias-recursive.out |   0
 tests/qapi-schema/alias-source-bad-type.err   |   2 +
 tests/qapi-schema/alias-source-bad-type.json  |   3 +
 tests/qapi-schema/alias-source-bad-type.out   |   0
 .../alias-source-elem-bad-type.err|   2 +
 .../alias-source-elem-bad-type.json   |   3 +
 .../alias-source-elem-bad-type.out|   0
 tests/qapi-schema/alias-source-empty.err  |   2 +
 tests/qapi-schema/alias-source-empty.json |   3 +
 tests/qapi-schema/alias-source-empty.out  |   0
 .../alias-source-inexistent-variants.err  |   2 +
 .../alias-source-inexistent-variants.json |  12 +
 .../alias-source-inexistent-variants.out  |   0
 tests/qapi-schema/alias-source-inexistent.err |   2 +
 .../qapi-schema/alias-source-inexistent.json  |   3 +
 tests/qapi-schema/alias-source-inexistent.out |   0
 .../alias-source-non-object-path.err  |   2 +
 .../alias-source-non-object-path.json |   3 +

[PATCH v3 4/6] qapi: Apply aliases in qobject-input-visitor

2021-08-12 Thread Kevin Wolf
When looking for an object in a struct in the external representation,
check not only the currently visited struct, but also whether an alias
in the current StackObject matches and try to fetch the value from the
alias then. Providing two values for the same object through different
aliases is an error.

Signed-off-by: Kevin Wolf 
---
 qapi/qobject-input-visitor.c | 227 +--
 1 file changed, 218 insertions(+), 9 deletions(-)

diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index 16a75442ff..6193df28a5 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -97,6 +97,8 @@ struct QObjectInputVisitor {
 QObject *root;
 bool keyval;/* Assume @root made with keyval_parse() */
 
+QDict *empty_qdict; /* Used for implicit objects */
+
 /* Stack of objects being visited (all entries will be either
  * QDict or QList). */
 QSLIST_HEAD(, StackObject) stack;
@@ -169,9 +171,190 @@ static const char *full_name(QObjectInputVisitor *qiv, 
const char *name)
 return full_name_so(qiv, name, false, tos);
 }
 
+static bool find_object_member(QObjectInputVisitor *qiv,
+   StackObject **so, const char **name,
+   bool *is_alias_prefix, Error **errp);
+
+/*
+ * Check whether the member @name in @so, or an alias for it, is
+ * present in the input and can be used to obtain the value.
+ */
+static bool input_present(QObjectInputVisitor *qiv, StackObject *so,
+  const char *name)
+{
+/*
+ * Check whether the alias member is present in the input
+ * (possibly recursively because aliases are transitive).
+ * The QAPI generator makes sure that alises cannot form loops, so
+ * the recursion guaranteed to terminate.
+ */
+if (!find_object_member(qiv, &so, &name, NULL, NULL)) {
+return false;
+}
+
+/*
+ * Every source can be used only once. If a value in the input
+ * would end up being used twice through aliases, we'll fail the
+ * second access.
+ */
+if (!g_hash_table_contains(so->h, name)) {
+return false;
+}
+
+return true;
+}
+
+/*
+ * Check whether the member @name in the object visited by @so can be
+ * specified in the input by using the alias described by @a (which
+ * must be an alias contained in so->aliases).
+ *
+ * If @name is only a prefix of the alias source, but doesn't match
+ * immediately, false is returned and *is_alias_prefix is set to true
+ * if it is non-NULL.  In all other cases, *is_alias_prefix is left
+ * unchanged.
+ */
+static bool alias_source_matches(QObjectInputVisitor *qiv,
+ StackObject *so, InputVisitorAlias *a,
+ const char *name, bool *is_alias_prefix)
+{
+if (a->src[0] == NULL) {
+assert(a->name == NULL);
+return true;
+}
+
+if (!strcmp(a->src[0], name)) {
+if (a->name && a->src[1] == NULL) {
+/*
+ * We're matching an exact member, the source for this alias is
+ * immediately in @so.
+ */
+return true;
+} else if (is_alias_prefix) {
+/*
+ * We're only looking at a prefix of the source path for the alias.
+ * If the input contains no object of the requested name, we will
+ * implicitly create an empty one so that the alias can still be
+ * used.
+ *
+ * We want to create the implicit object only if the alias is
+ * actually used, but we can't tell here for wildcard aliases (only
+ * a later visitor call will determine this). This means that
+ * wildcard aliases must never have optional keys in their source
+ * path. The QAPI generator checks this condition.
+ */
+if (!a->name || input_present(qiv, a->alias_so, a->name)) {
+*is_alias_prefix = true;
+}
+}
+}
+
+return false;
+}
+
+/*
+ * Find the place in the input where the value for the object member
+ * @name in @so is specified, considering applicable aliases.
+ *
+ * If a value could be found, true is returned and @so and @name are
+ * updated to identify the key name and StackObject where the value
+ * can be found in the input.  (This is either unchanged or the
+ * alias_so/name of an alias.)  The value of @is_alias_prefix on
+ * return is undefined in this case.
+ *
+ * If no value could be found in the input, false is returned and @so
+ * and @name are set to NULL.  This is not an error and @errp remains
+ * unchanged.  If @is_alias_prefix is non-NULL, it is set to true if
+ * the given name is a prefix of the source path of an alias for which
+ * a value may be present in the input.  It is set to false otherwise.
+ *
+ * If an error occurs (e.g. two values are specified for the member
+ * throu

[PATCH v3 2/6] qapi: Remember alias definitions in qobject-input-visitor

2021-08-12 Thread Kevin Wolf
This makes qobject-input-visitor remember the currently valid aliases in
each StackObject. It doesn't actually allow using the aliases yet.

Signed-off-by: Kevin Wolf 
---
 qapi/qobject-input-visitor.c | 147 +++
 1 file changed, 147 insertions(+)

diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index 04b790412e..d0061d33d6 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -30,6 +30,50 @@
 #include "qemu/cutils.h"
 #include "qemu/option.h"
 
+/*
+ * Describes an alias that is relevant for the current StackObject,
+ * either because it aliases a member of the currently visited object
+ * or because it aliases a member of a nested object.
+ *
+ * When processing a nested object, all InputVisitorAlias objects that
+ * are relevant for the nested object are propagated, i.e. copied with
+ * the name of the nested object removed from @source.
+ */
+typedef struct InputVisitorAlias {
+/* StackObject in which the alias was defined */
+struct StackObject *alias_so;
+
+/*
+ * Alias name as defined for @alias_so.
+ * NULL means that this is a wildcard alias, i.e. all members of
+ * @src get an alias in @alias_so with the same name.
+ */
+const char *name;
+
+/*
+ * NULL-terminated array representing a path to the source member
+ * that the alias refers to.
+ *
+ * Must contain at least one non-NULL element if @alias is not NULL.
+ *
+ * If it contains no non-NULL element, @alias_so must be different
+ * from the StackObject which contains this InputVisitorAlias in
+ * its aliases list.  In this case, all elements in the currently
+ * visited object have an alias with the same name in @alias_so.
+ */
+const char **src;
+
+/*
+ * The alias remains valid as long as the StackObject which
+ * contains this InputVisitorAlias in its aliases list has
+ * StackObject.alias_scope_nesting >= InputVisitorAlias.scope_nesting
+ * or until the whole StackObject is removed.
+ */
+int scope_nesting;
+
+QSLIST_ENTRY(InputVisitorAlias) next;
+} InputVisitorAlias;
+
 typedef struct StackObject {
 const char *name;/* Name of @obj in its parent, if any */
 QObject *obj;/* QDict or QList being visited */
@@ -39,6 +83,9 @@ typedef struct StackObject {
 const QListEntry *entry;/* If @obj is QList: unvisited tail */
 unsigned index; /* If @obj is QList: list index of @entry */
 
+QSLIST_HEAD(, InputVisitorAlias) aliases;
+int alias_scope_nesting;/* Number of open alias scopes */
+
 QSLIST_ENTRY(StackObject) node; /* parent */
 } StackObject;
 
@@ -205,6 +252,45 @@ static const char 
*qobject_input_get_keyval(QObjectInputVisitor *qiv,
 return qstring_get_str(qstr);
 }
 
+/*
+ * Propagate aliases from the parent StackObject @src to its direct
+ * child StackObject @dst, which is representing the child struct @name.
+ *
+ * Every alias whose source path begins with @dst->name and which still
+ * applies in @dst (i.e. it is either a wildcard alias or has at least
+ * one more source path element) is propagated to @dst with the first
+ * element (i.e. @dst->name) removed from the source path.
+ */
+static void propagate_aliases(StackObject *dst, StackObject *src)
+{
+InputVisitorAlias *a;
+InputVisitorAlias *propagated_alias;
+
+QSLIST_FOREACH(a, &src->aliases, next) {
+if (!a->src[0] || strcmp(a->src[0], dst->name)) {
+continue;
+}
+
+/*
+ * If this is not a wildcard alias, but a->src[1] is NULL,
+ * then it referred to a->name in src and doesn't apply inside
+ * dst any more.
+ */
+if (a->name && !a->src[1]) {
+continue;
+}
+
+propagated_alias = g_new(InputVisitorAlias, 1);
+*propagated_alias = (InputVisitorAlias) {
+.name   = a->name,
+.alias_so   = a->alias_so,
+.src= &a->src[1],
+};
+
+QSLIST_INSERT_HEAD(&dst->aliases, propagated_alias, next);
+}
+}
+
 static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv,
 const char *name,
 QObject *obj, void *qapi)
@@ -228,6 +314,9 @@ static const QListEntry 
*qobject_input_push(QObjectInputVisitor *qiv,
 g_hash_table_insert(h, (void *)qdict_entry_key(entry), NULL);
 }
 tos->h = h;
+if (!QSLIST_EMPTY(&qiv->stack)) {
+propagate_aliases(tos, QSLIST_FIRST(&qiv->stack));
+}
 } else {
 assert(qlist);
 tos->entry = qlist_first(qlist);
@@ -259,10 +348,17 @@ static bool qobject_input_check_struct(Visitor *v, Error 
**errp)
 
 static void qobject_input_stack_object_free(StackObject *tos)
 {
+InputVisitorAlias *a;
+
 if (tos->h) {
 g_hash_table_unref(tos->h);

[PATCH v3 1/6] qapi: Add interfaces for alias support to Visitor

2021-08-12 Thread Kevin Wolf
This adds functions to the Visitor interface that can be used to define
aliases and alias scopes.

Signed-off-by: Kevin Wolf 
---
 include/qapi/visitor-impl.h | 12 
 include/qapi/visitor.h  | 59 ++---
 qapi/qapi-visit-core.c  | 22 ++
 3 files changed, 89 insertions(+), 4 deletions(-)

diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 3b950f6e3d..704c5ad2d9 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -119,6 +119,18 @@ struct Visitor
 /* Optional */
 bool (*deprecated)(Visitor *v, const char *name);
 
+/*
+ * Optional; intended for input visitors. If not given, aliases are
+ * ignored.
+ */
+void (*define_alias)(Visitor *v, const char *name, const char **source);
+
+/* Must be set if define_alias is set */
+void (*start_alias_scope)(Visitor *v);
+
+/* Must be set if define_alias is set */
+void (*end_alias_scope)(Visitor *v);
+
 /* Must be set */
 VisitorType type;
 
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index b3c9ef7a81..3bf0f4dad2 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -220,10 +220,17 @@
  * 
  *
  * This file provides helpers for use by the generated
- * visit_type_FOO(): visit_optional() for the 'has_member' field
- * associated with optional 'member' in the C struct,
- * visit_next_list() for advancing through a FooList linked list, and
- * visit_is_input() for cleaning up on failure.
+ * visit_type_FOO():
+ *
+ * - visit_optional() for the 'has_member' field associated with
+ *   optional 'member' in the C struct,
+ * - visit_next_list() for advancing through a FooList linked list
+ * - visit_is_input() for cleaning up on failure
+ * - visit_define_alias() for defining alternative names for object
+ *   members in input visitors
+ * - visit_start/end_alias_scope() to limit the scope of aliases
+ *   within a single input object (e.g. aliases defined in the base
+ *   struct should not provide values for the parent struct)
  */
 
 /*** Useful types ***/
@@ -477,6 +484,50 @@ bool visit_deprecated_accept(Visitor *v, const char *name, 
Error **errp);
  */
 bool visit_deprecated(Visitor *v, const char *name);
 
+/*
+ * Defines a new alias rule.
+ *
+ * If @name is non-NULL, the member called @name in the external
+ * representation of the currently visited object is defined as an
+ * alias for the member described by @source.  It is not allowed to
+ * call this function when the currently visited type is not an
+ * object.
+ *
+ * If @name is NULL, all members of the object described by @source
+ * are considered to have alias members with the same key in the
+ * currently visited object.
+ *
+ * @source is a NULL-terminated non-empty array of names that describe
+ * the path to a member, starting from the currently visited object.
+ * All elements in @source except the last one should describe
+ * objects.  If an intermediate element refers to a member with a
+ * non-object type, the alias won't work (this case can legitimately
+ * happen in unions where an alias only makes sense for one branch,
+ * but not for another).
+ *
+ * The alias stays valid until the current alias scope ends.
+ * visit_start/end_struct() implicitly start/end an alias scope.
+ * Additionally, visit_start/end_alias_scope() can be used to explicitly
+ * create a nested alias scope.
+ */
+void visit_define_alias(Visitor *v, const char *name, const char **source);
+
+/*
+ * Begins an explicit alias scope.
+ *
+ * Alias definitions after here will only stay valid until the
+ * corresponding visit_end_alias_scope() is called.
+ */
+void visit_start_alias_scope(Visitor *v);
+
+/*
+ * Ends an explicit alias scope.
+ *
+ * Alias definitions between the correspoding visit_start_alias_scope()
+ * call and here go out of scope and won't apply in later code any more.
+ */
+void visit_end_alias_scope(Visitor *v);
+
 /*
  * Visit an enum value.
  *
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index a641adec51..79df6901ae 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -153,6 +153,28 @@ bool visit_deprecated(Visitor *v, const char *name)
 return true;
 }
 
+void visit_define_alias(Visitor *v, const char *name, const char **source)
+{
+assert(source[0] != NULL);
+if (v->define_alias) {
+v->define_alias(v, name, source);
+}
+}
+
+void visit_start_alias_scope(Visitor *v)
+{
+if (v->start_alias_scope) {
+v->start_alias_scope(v);
+}
+}
+
+void visit_end_alias_scope(Visitor *v)
+{
+if (v->end_alias_scope) {
+v->end_alias_scope(v);
+}
+}
+
 bool visit_is_input(Visitor *v)
 {
 return v->type == VISITOR_INPUT;
-- 
2.31.1




[PATCH v3 3/6] qapi: Simplify full_name_nth() in qobject-input-visitor

2021-08-12 Thread Kevin Wolf
Instead of counting how many elements from the top of the stack we need
to ignore until we find the thing we're interested in, we can just
directly pass the StackObject pointer because all callers already know
it.

We only need a different way now to tell if we want to know the name of
something contained in the given StackObject or of the StackObject
itself. Make this explicit with a new boolean parameter.

This makes the function easier to use in cases where we have the
StackObject, but don't know how many steps down the stack it is. The
following patches will introduce such a caller.

Signed-off-by: Kevin Wolf 
---
 qapi/qobject-input-visitor.c | 43 
 1 file changed, 24 insertions(+), 19 deletions(-)

diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index d0061d33d6..16a75442ff 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -110,20 +110,20 @@ static QObjectInputVisitor *to_qiv(Visitor *v)
 }
 
 /*
- * Find the full name of something @qiv is currently visiting.
- * @qiv is visiting something named @name in the stack of containers
- * @qiv->stack.
- * If @n is zero, return its full name.
- * If @n is positive, return the full name of the @n-th container
- * counting from the top.  The stack of containers must have at least
- * @n elements.
- * The returned string is valid until the next full_name_nth(@v) or
- * destruction of @v.
+ * Find the full name of a member in @so which @qiv is currently
+ * visiting.  If the currently visited thing is an object, @name is
+ * the (local) name of the member to describe.  If it is a list, @name
+ * is ignored and the current index (so->index) is included.
+ *
+ * If @skip_member is true, find the full name of @so itself instead.
+ * @name must be NULL then.
+ *
+ * The returned string is valid until the next full_name_so(@qiv) or
+ * destruction of @qiv.
  */
-static const char *full_name_nth(QObjectInputVisitor *qiv, const char *name,
- int n)
+static const char *full_name_so(QObjectInputVisitor *qiv, const char *name,
+bool skip_member, StackObject *so)
 {
-StackObject *so;
 char buf[32];
 
 if (qiv->errname) {
@@ -132,10 +132,14 @@ static const char *full_name_nth(QObjectInputVisitor 
*qiv, const char *name,
 qiv->errname = g_string_new("");
 }
 
-QSLIST_FOREACH(so , &qiv->stack, node) {
-if (n) {
-n--;
-} else if (qobject_type(so->obj) == QTYPE_QDICT) {
+if (skip_member && so) {
+assert(name == NULL);
+name = so->name;
+so = QSLIST_NEXT(so, node);
+}
+
+for (; so; so = QSLIST_NEXT(so, node)) {
+if (qobject_type(so->obj) == QTYPE_QDICT) {
 g_string_prepend(qiv->errname, name ?: "");
 g_string_prepend_c(qiv->errname, '.');
 } else {
@@ -146,7 +150,6 @@ static const char *full_name_nth(QObjectInputVisitor *qiv, 
const char *name,
 }
 name = so->name;
 }
-assert(!n);
 
 if (name) {
 g_string_prepend(qiv->errname, name);
@@ -161,7 +164,9 @@ static const char *full_name_nth(QObjectInputVisitor *qiv, 
const char *name,
 
 static const char *full_name(QObjectInputVisitor *qiv, const char *name)
 {
-return full_name_nth(qiv, name, 0);
+StackObject *tos = QSLIST_FIRST(&qiv->stack);
+
+return full_name_so(qiv, name, false, tos);
 }
 
 static QObject *qobject_input_try_get_object(QObjectInputVisitor *qiv,
@@ -507,7 +512,7 @@ static bool qobject_input_check_list(Visitor *v, Error 
**errp)
 
 if (tos->entry) {
 error_setg(errp, "Only %u list elements expected in %s",
-   tos->index + 1, full_name_nth(qiv, NULL, 1));
+   tos->index + 1, full_name_so(qiv, NULL, true, tos));
 return false;
 }
 return true;
-- 
2.31.1




Re: [PATCH] hw/acpi: refactor acpi hp modules so that targets can just use what they need

2021-08-12 Thread Ani Sinha


On Thu, 12 Aug 2021, Philippe Mathieu-Daudé wrote:

> On 8/12/21 3:22 PM, Ani Sinha wrote:
> > On Thu, 12 Aug 2021, Ani Sinha wrote:
> >
> >> Currently various acpi hotplug modules like cpu hotplug, memory hotplug, 
> >> pci
> >> hotplug, nvdimm hotplug are all pulled in when CONFIG_ACPI_X86 is turned 
> >> on.
> >> This brings in support for whole lot of subsystems that some targets like
> >> mips does not need. They are added just to satisfy symbol dependencies. 
> >> This
> >> is ugly and should be avoided. Targets should be able to pull in just what 
> >> they
> >> need and no more. For example, mips only needs support for PIIX4 and does 
> >> not
> >> need acpi pci hotplug support or cpu hotplug support or memory hotplug 
> >> support
> >> etc. This change is an effort to clean this up.
> >> In this change, new config variables are added for various acpi hotplug
> >> subsystems. Targets like mips can only enable PIIX4 support and not the 
> >> rest
> >> of all the other modules which were being previously pulled in as a part of
> >> CONFIG_ACPI_X86. Function stubs make sure that symbols which piix4 needs 
> >> but
> >> are not required by mips (for example, symbols specific to pci hotplug etc)
> >> are available to satisfy the dependencies.
> >>
> >> Currently, this change only addresses issues with mips malta targets. In 
> >> future
> >> we might be able to clean up other targets which are similarly pulling in 
> >> lot
> >> of unnecessary hotplug modules by enabling ACPI_X86.
> >>
> >> This change should also address issues such as the following:
> >> https://gitlab.com/qemu-project/qemu/-/issues/221
> >> https://gitlab.com/qemu-project/qemu/-/issues/193
> >
> > I do not have a cross compiled mips64 vmlinux handy, so can't verify that
> > issue #193 was indeed resolved.
>
> The functional tests use some pre-built:
>
> $ git grep I6400 tests/acceptance/
>

Cool! Fantastic! Tested #193 as well, no crashes:

$ ./qemu-system-mips64el -cpu I6400 -nographic -append "clocksource=GIC 
console=ttyS1" -smp 8 -kernel ../vmlinux
Linux version 4.7.0-rc1-dirty (root@2e66df87a9ff) (gcc version 6.3.0
20170516 (Debian 6.3.0-18) ) #1 SMP Sat Feb 1 18:38:13 UTC 2020
earlycon: uart8250 at I/O port 0x3f8 (options '38400n8')
bootconsole [uart8250] enabled
CPU0 revision is: 0001a900 (MIPS I6400)
FPU revision is: 20f30300
MSA revision is: 0300
MIPS: machine is mti,malta
Software DMA cache coherency enabled
Determined physical RAM map:
 memory: 0800 @  (usable)
Zone ranges:
  DMA  [mem 0x-0x00ff]
  DMA32[mem 0x0100-0x]
  Normal   empty
Movable zone start for each node
Early memory node ranges
  node   0: [mem 0x-0x07ff]
Initmem setup node 0 [mem 0x-0x07ff]
VP topology {8} total 8
Primary instruction cache 64kB, VIPT, 4-way, linesize 64 bytes.
Primary data cache 64kB, 4-way, VIPT, no aliases, linesize 64 bytes
percpu: Embedded 5 pages/cpu @98000107c000 s29664 r8192 d44064 u81920
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 8163
Kernel command line: clocksource=GIC console=ttyS1
log_buf_len individual max cpu contribution: 4096 bytes
log_buf_len total cpu_extra contributions: 28672 bytes
log_buf_len min size: 32768 bytes
log_buf_len: 65536 bytes
early log buf free: 30424(92%)
PID hash table entries: 512 (order: -2, 4096 bytes)
Dentry cache hash table entries: 16384 (order: 3, 131072 bytes)
Inode-cache hash table entries: 8192 (order: 2, 65536 bytes)
Writing ErrCtl register=
Readback ErrCtl register=
MAAR configuration:
  [0]: 0x0001-0x07ff speculate
  [1]: disabled
  [2]: disabled
  [3]: disabled
  [4]: disabled
  [5]: disabled
  [6]: disabled
  [7]: disabled
Memory: 121104K/131072K available (5253K kernel code, 380K rwdata, 1276K
rodata, 304K init, 278K bss, 9968K reserved, 0K cma-reserved)
Hierarchical RCU implementation.
Build-time adjustment of leaf fanout to 64.
NR_IRQS:256
CPU frequency 333.33 MHz
GIC frequency 100.00 MHz
clocksource: GIC: mask: 0x max_cycles: 0x, max_idle_ns:
19113018267 ns
clocksource: MIPS: mask: 0x max_cycles: 0x, max_idle_ns:
11467565337 ns
sched_clock: 32 bits at 166MHz, resolution 6ns, wraps every 12884904956ns
Console: colour dummy device 80x25
Calibrating delay loop... 1561.39 BogoMIPS (lpj=7806976)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 2048 (order: 0, 16384 bytes)
Mountpoint-cache hash table entries: 2048 (order: 0, 16384 bytes)
Primary instruction cache 64kB, VIPT, 4-way, linesize 64 bytes.
Primary data cache 64kB, 4-way, VIPT, no aliases, linesize 64 bytes
CPU1 revision is: 0001a900 (MIPS I6400)
FPU revision is: 20f30300
MSA revision is: 0300
Synchronize counters for CPU 1: done.
Primary instruction cache 64kB, VIPT, 4-way, linesize 64 bytes.
Primary data cache 64kB, 4-way, VIPT, no aliases, linesiz

Re: [PATCH for 6.1] plugins: do not limit exported symbols if modules are active

2021-08-12 Thread Alex Bennée


Paolo Bonzini  writes:

> Il gio 12 ago 2021, 11:40 Alex Bennée  ha scritto:
>
>ERROR: glib-2.56 gmodule-noexport-2.0 is required to compile QEMU
>
>  Should it be gmodule-no-export? Hopefully the different distros aren't
>  packaging different .pc files.
>
> My bad. :( It's correct with the dash.

I've patched it locally and it's sitting in my PR branch:

  https://gitlab.com/stsquad/qemu/-/commits/pr/120821-for-6.1-rc4-1

but it looks like it will have to go via stable unless there is a more
compelling reason to cut an rc4.

>  Does this mean --enable-modules would allow plugins to access more of
>  the API space than we intended in the first place?
>
> Yes, but before it would do so even without --enable-modules due to
> using gmodule and not gmodule-no-export.

OK so it's better now. I wonder if this helps with the Windows usage of
modules?

  Subject: [PATCH v6 0/5] Enable plugin support on msys2/mingw
  Date: Tue, 13 Oct 2020 08:28:01 +0800
  Message-Id: <20201013002806.1447-1-luoyongg...@gmail.com>

I really want to avoid the hand hacking of Youngang's proposed changes
so was surprised that glib hadn't papered over the POSIX/Windows cracks.
However like MacOS I don't have easy access to a Windows developer
system to experiment with.

-- 
Alex Bennée



Re: [PATCH 09/10] hw/misc: Add Infineon DPS310 sensor model

2021-08-12 Thread Cédric Le Goater
On 8/11/21 3:25 AM, Joel Stanley wrote:
> On Tue, 10 Aug 2021 at 23:37, Corey Minyard  wrote:
>>
>> On Mon, Aug 09, 2021 at 03:15:55PM +0200, Cédric Le Goater wrote:
>>> From: Joel Stanley 
>>>
>>> This contains some hardcoded register values that were obtained from the
>>> hardware after reading the temperature.
>>>
>>> It does enough to test the Linux kernel driver. The FIFO mode, IRQs and
>>> operation modes other than the default as used by Linux are not modelled.
>>>
>>> Signed-off-by: Joel Stanley 
>>> [ clg: Fix sequential reading ]
>>> Message-Id: <20210616073358.750472-2-j...@jms.id.au>
>>> Signed-off-by: Cédric Le Goater 
>>> Message-Id: <20210629142336.750058-4-...@kaod.org>
>>> Signed-off-by: Cédric Le Goater 
>>> ---
>>>  hw/misc/dps310.c| 227 
>>
>> Can this go into hw/sensor?
> 
> For sure. I wrote it four years ago, when obviously hw/sensor didn't exist.

I moved it under hw/sensor.

C.



[PATCH] softmmu/physmem.c: Check return value from realpath()

2021-08-12 Thread Peter Maydell
The realpath() function can return NULL on error, so we need to check
for it to avoid crashing when we try to strstr() into it.
This can happen if we run out of memory, or if /sys/ is not mounted,
among other situations.

Fixes: Coverity 1459913, 1460474
Fixes: ce317be98db0 ("exec: fetch the alignment of Linux devdax pmem character 
device nodes")
Signed-off-by: Peter Maydell 
---
 softmmu/physmem.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index c47cb6da2e4..eb0595d57c4 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -1451,6 +1451,9 @@ static int64_t get_file_align(int fd)
 path = g_strdup_printf("/sys/dev/char/%d:%d",
 major(st.st_rdev), minor(st.st_rdev));
 rpath = realpath(path, NULL);
+if (!rpath) {
+return -errno;
+}
 
 rc = daxctl_new(&ctx);
 if (rc) {
-- 
2.20.1




[PATCH] softmmu/physmem.c: Remove unneeded NULL check in qemu_ram_alloc_from_fd()

2021-08-12 Thread Peter Maydell
In the alignment check added to qemu_ram_alloc_from_fd() in commit
ce317be98db0dfdfa, the condition includes a check that 'mr' is not
NULL.  This check is unnecessary because we can assume that the
caller always passes us a valid MemoryRegion, and indeed later in the
function we assume mr is not NULL when we pass it to file_ram_alloc()
as new_block->mr.  Remove it.

Fixes: Coverity 1459867
Fixes: ce317be98d ("exec: fetch the alignment of Linux devdax pmem character 
device nodes")
Signed-off-by: Peter Maydell 
---
 softmmu/physmem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index 3c1912a1a07..c47cb6da2e4 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -2075,7 +2075,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, 
MemoryRegion *mr,
 }
 
 file_align = get_file_align(fd);
-if (file_align > 0 && mr && file_align > mr->align) {
+if (file_align > 0 && file_align > mr->align) {
 error_setg(errp, "backing store align 0x%" PRIx64
" is larger than 'align' option 0x%" PRIx64,
file_align, mr->align);
-- 
2.20.1




Re: [PULL 05/18] hw/riscv: virt: Allow creating multiple NUMA sockets

2021-08-12 Thread Peter Maydell
On Mon, 9 Aug 2021 at 10:46, Peter Maydell  wrote:
>
> On Tue, 25 Aug 2020 at 20:03, Alistair Francis  
> wrote:
> >
> > From: Anup Patel 
> >
> > We extend RISC-V virt machine to allow creating a multi-socket
> > machine. Each RISC-V virt machine socket is a NUMA node having
> > a set of HARTs, a memory instance, a CLINT instance, and a PLIC
> > instance. Other devices are shared between all sockets. We also
> > update the generated device tree accordingly.
>
> Hi; Coverity (CID 1460752) points out that this code has
> a misunderstanding of the length argument to strncat().
> (I think this patch is just doing code-movement of this block of code,
> but it seemed like the easiest place to send an email about the issue.)
>
> > +/* Per-socket PLIC hart topology configuration string */
> > +plic_hart_config_len =
> > +(strlen(VIRT_PLIC_HART_CONFIG) + 1) * hart_count;
> > +plic_hart_config = g_malloc0(plic_hart_config_len);
> > +for (j = 0; j < hart_count; j++) {
> > +if (j != 0) {
> > +strncat(plic_hart_config, ",", plic_hart_config_len);
> > +}
> > +strncat(plic_hart_config, VIRT_PLIC_HART_CONFIG,
> > +plic_hart_config_len);
> > +plic_hart_config_len -= (strlen(VIRT_PLIC_HART_CONFIG) + 1);
> > +}
>
> The length argument to strncat() is here being used as if it were
> "do not write more than length bytes", but strncat() will write
> length+1 bytes in the "source too long" case (length characters
> from the source string plus the trailing NUL). This isn't actually
> an issue here because we carefully precalculate the allocation length
> to be exactly correct, but it means that the code looks like it has
> a guard against accidental miscalculation and overrun but it doesn't.
>
> It might be preferable to write this to use glib string methods
> rather than raw strlen/strncat, for example:

Since I'd mostly written the code here anyway, I turned it
into an actual patch:
https://patchew.org/QEMU/20210812144647.10516-1-peter.mayd...@linaro.org/

-- PMM



[PATCH] hw/riscv/virt.c: Assemble plic_hart_config string with g_strjoinv()

2021-08-12 Thread Peter Maydell
In the riscv virt machine init function, We assemble a string
plic_hart_config which is a comma-separated list of N copies of the
VIRT_PLIC_HART_CONFIG string.  The code that does this has a
misunderstanding of the strncat() length argument.  If the source
string is too large strncat() will write a maximum of length+1 bytes
(length bytes from the source string plus a trailing NUL), but the
code here assumes that it will write only length bytes at most.

This isn't an actual bug because the code has correctly precalculated
the amount of memory it needs to allocate so that it will never be
too small (i.e.  we could have used plain old strcat()), but it does
mean that the code looks like it has a guard against accidental
overrun when it doesn't.

Rewrite the string handling here to use the glib g_strjoinv()
function, which means we don't need to do careful accountancy of
string lengths, and makes it clearer that what we're doing is
"create a comma-separated string".

Fixes: Coverity 1460752
Signed-off-by: Peter Maydell 
---
 hw/riscv/virt.c | 33 -
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4a3cd2599a5..26bc8d289ba 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -541,6 +541,24 @@ static FWCfgState *create_fw_cfg(const MachineState *mc)
 return fw_cfg;
 }
 
+/*
+ * Return the per-socket PLIC hart topology configuration string
+ * (caller must free with g_free())
+ */
+static char *plic_hart_config_string(int hart_count)
+{
+g_autofree const char **vals = g_new(const char *, hart_count + 1);
+int i;
+
+for (i = 0; i < hart_count; i++) {
+vals[i] = VIRT_PLIC_HART_CONFIG;
+}
+vals[i] = NULL;
+
+/* g_strjoinv() obliges us to cast away const here */
+return g_strjoinv(",", (char **)vals);
+}
+
 static void virt_machine_init(MachineState *machine)
 {
 const MemMapEntry *memmap = virt_memmap;
@@ -549,13 +567,12 @@ static void virt_machine_init(MachineState *machine)
 MemoryRegion *main_mem = g_new(MemoryRegion, 1);
 MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
 char *plic_hart_config, *soc_name;
-size_t plic_hart_config_len;
 target_ulong start_addr = memmap[VIRT_DRAM].base;
 target_ulong firmware_end_addr, kernel_start_addr;
 uint32_t fdt_load_addr;
 uint64_t kernel_entry;
 DeviceState *mmio_plic, *virtio_plic, *pcie_plic;
-int i, j, base_hartid, hart_count;
+int i, base_hartid, hart_count;
 
 /* Check socket count limit */
 if (VIRT_SOCKETS_MAX < riscv_socket_count(machine)) {
@@ -604,17 +621,7 @@ static void virt_machine_init(MachineState *machine)
 SIFIVE_CLINT_TIMEBASE_FREQ, true);
 
 /* Per-socket PLIC hart topology configuration string */
-plic_hart_config_len =
-(strlen(VIRT_PLIC_HART_CONFIG) + 1) * hart_count;
-plic_hart_config = g_malloc0(plic_hart_config_len);
-for (j = 0; j < hart_count; j++) {
-if (j != 0) {
-strncat(plic_hart_config, ",", plic_hart_config_len);
-}
-strncat(plic_hart_config, VIRT_PLIC_HART_CONFIG,
-plic_hart_config_len);
-plic_hart_config_len -= (strlen(VIRT_PLIC_HART_CONFIG) + 1);
-}
+plic_hart_config = plic_hart_config_string(hart_count);
 
 /* Per-socket PLIC */
 s->plic[i] = sifive_plic_create(
-- 
2.20.1




Re: [PATCH] q35: catch invalid cpu hotplug configuration

2021-08-12 Thread Igor Mammedov
On Thu, 12 Aug 2021 12:23:41 +0200
Gerd Hoffmann  wrote:

> Related: https://bugzilla.redhat.com//show_bug.cgi?id=1985924
> Signed-off-by: Gerd Hoffmann 

Reviewed-by: Igor Mammedov 

> ---
>  hw/isa/lpc_ich9.c | 13 +
>  1 file changed, 13 insertions(+)
> 
> diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
> index 5f9de0239cf9..5f143dca17aa 100644
> --- a/hw/isa/lpc_ich9.c
> +++ b/hw/isa/lpc_ich9.c
> @@ -31,6 +31,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu/log.h"
>  #include "cpu.h"
> +#include "qapi/error.h"
>  #include "qapi/visitor.h"
>  #include "qemu/range.h"
>  #include "hw/isa/isa.h"
> @@ -676,6 +677,18 @@ static void ich9_lpc_realize(PCIDevice *d, Error **errp)
>  DeviceState *dev = DEVICE(d);
>  ISABus *isa_bus;
>  
> +if ((lpc->smi_host_features & 
> BIT_ULL(ICH9_LPC_SMI_F_CPU_HOT_UNPLUG_BIT)) &&
> +!(lpc->smi_host_features & BIT_ULL(ICH9_LPC_SMI_F_CPU_HOTPLUG_BIT))) 
> {
> +/*
> + * smi_features_ok_callback() throws an error on this.
> + *
> + * So bail out here instead of advertizing the invalid
> + * configuration and get obscure firmware failures from that.
> + */
> +error_setg(errp, "cpu hot-unplug requires cpu hot-plug");
> +return;
> +}
> +
>  isa_bus = isa_bus_new(DEVICE(d), get_system_memory(), get_system_io(),
>errp);
>  if (!isa_bus) {




[PATCH] hw/core/loader: In gunzip(), check index is in range before use, not after

2021-08-12 Thread Peter Maydell
The gunzip() function reads various fields from a passed in source
buffer in order to skip a header before passing the actual compressed
data to the zlib inflate() function.  It does check whether the
passed in buffer is too small, but unfortunately it checks that only
after reading bytes from the src buffer, so it could read off the end
of the buffer.

You can see this with valgrind:

 $ printf "%b" '\x1f\x8b' > /tmp/image
 $ valgrind qemu-system-aarch64 -display none -M virt -cpu max -kernel 
/tmp/image
 [...]
 ==19224== Invalid read of size 1
 ==19224==at 0x67302E: gunzip (loader.c:558)
 ==19224==by 0x673907: load_image_gzipped_buffer (loader.c:788)
 ==19224==by 0xA18032: load_aarch64_image (boot.c:932)
 ==19224==by 0xA18489: arm_setup_direct_kernel_boot (boot.c:1063)
 ==19224==by 0xA18D90: arm_load_kernel (boot.c:1317)
 ==19224==by 0x9F3651: machvirt_init (virt.c:2114)
 ==19224==by 0x794B7A: machine_run_board_init (machine.c:1272)
 ==19224==by 0xD5CAD3: qemu_init_board (vl.c:2618)
 ==19224==by 0xD5CCA6: qmp_x_exit_preconfig (vl.c:2692)
 ==19224==by 0xD5F32E: qemu_init (vl.c:3713)
 ==19224==by 0x5ADDB1: main (main.c:49)
 ==19224==  Address 0x3802a873 is 0 bytes after a block of size 3 alloc'd
 ==19224==at 0x4C31B0F: malloc (in 
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
 ==19224==by 0x61E7657: g_file_get_contents (in 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.5600.4)
 ==19224==by 0x673895: load_image_gzipped_buffer (loader.c:771)
 ==19224==by 0xA18032: load_aarch64_image (boot.c:932)
 ==19224==by 0xA18489: arm_setup_direct_kernel_boot (boot.c:1063)
 ==19224==by 0xA18D90: arm_load_kernel (boot.c:1317)
 ==19224==by 0x9F3651: machvirt_init (virt.c:2114)
 ==19224==by 0x794B7A: machine_run_board_init (machine.c:1272)
 ==19224==by 0xD5CAD3: qemu_init_board (vl.c:2618)
 ==19224==by 0xD5CCA6: qmp_x_exit_preconfig (vl.c:2692)
 ==19224==by 0xD5F32E: qemu_init (vl.c:3713)
 ==19224==by 0x5ADDB1: main (main.c:49)

Check that we have enough bytes of data to read the header bytes that
we read before we read them.

Fixes: Coverity 1458997
Signed-off-by: Peter Maydell 
---
 hw/core/loader.c | 35 +--
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/hw/core/loader.c b/hw/core/loader.c
index 5b34869a541..c623318b737 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -555,24 +555,35 @@ ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, 
size_t srclen)
 
 /* skip header */
 i = 10;
+if (srclen < 4) {
+goto toosmall;
+}
 flags = src[3];
 if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
 puts ("Error: Bad gzipped data\n");
 return -1;
 }
-if ((flags & EXTRA_FIELD) != 0)
+if ((flags & EXTRA_FIELD) != 0) {
+if (srclen < 12) {
+goto toosmall;
+}
 i = 12 + src[10] + (src[11] << 8);
-if ((flags & ORIG_NAME) != 0)
-while (src[i++] != 0)
-;
-if ((flags & COMMENT) != 0)
-while (src[i++] != 0)
-;
-if ((flags & HEAD_CRC) != 0)
+}
+if ((flags & ORIG_NAME) != 0) {
+while (i < srclen && src[i++] != 0) {
+/* do nothing */
+}
+}
+if ((flags & COMMENT) != 0) {
+while (i < srclen && src[i++] != 0) {
+/* do nothing */
+}
+}
+if ((flags & HEAD_CRC) != 0) {
 i += 2;
+}
 if (i >= srclen) {
-puts ("Error: gunzip out of data in header\n");
-return -1;
+goto toosmall;
 }
 
 s.zalloc = zalloc;
@@ -596,6 +607,10 @@ ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, 
size_t srclen)
 inflateEnd(&s);
 
 return dstbytes;
+
+toosmall:
+puts("Error: gunzip out of data in header\n");
+return -1;
 }
 
 /* Load a U-Boot image.  */
-- 
2.20.1




[PATCH v3] vhost-vdpa: Do not send empty IOTLB update batches

2021-08-12 Thread Eugenio Pérez
With the introduction of the batch hinting, meaningless batches can be
created with no IOTLB updates if the memory region was skipped by
vhost_vdpa_listener_skipped_section. This is the case of host notifiers
memory regions, device un/realize, and others. This causes the vdpa
device to receive dma mapping settings with no changes, a possibly
expensive operation for nothing.

To avoid that, VHOST_IOTLB_BATCH_BEGIN hint is delayed until we have a
meaningful (not skipped section) mapping or unmapping operation, and
VHOST_IOTLB_BATCH_END is not written unless at least one of _UPDATE /
_INVALIDATE has been issued.

v3:
  * Use a bool instead of a counter avoiding potential number wrapping
  * Fix bad check on _commit
  * Move VHOST_BACKEND_F_IOTLB_BATCH check to
vhost_vdpa_iotlb_batch_begin_once

v2 (from RFC):
  * Rename misleading name
  * Abstract start batching function for listener_add/del

Signed-off-by: Eugenio Pérez 
---
 include/hw/virtio/vhost-vdpa.h |  1 +
 hw/virtio/vhost-vdpa.c | 35 ++
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h
index e98e327f12..6b9288fef8 100644
--- a/include/hw/virtio/vhost-vdpa.h
+++ b/include/hw/virtio/vhost-vdpa.h
@@ -23,6 +23,7 @@ typedef struct vhost_vdpa {
 int device_fd;
 int index;
 uint32_t msg_type;
+bool iotlb_batch_begin_sent;
 MemoryListener listener;
 struct vhost_dev *dev;
 VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX];
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 6ce94a1f4d..93b7db61d1 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -89,19 +89,13 @@ static int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, 
hwaddr iova,
 return ret;
 }
 
-static void vhost_vdpa_listener_begin(MemoryListener *listener)
+static void vhost_vdpa_listener_begin_batch(struct vhost_vdpa *v)
 {
-struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener);
-struct vhost_dev *dev = v->dev;
-struct vhost_msg_v2 msg = {};
 int fd = v->device_fd;
-
-if (!(dev->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) {
-return;
-}
-
-msg.type = v->msg_type;
-msg.iotlb.type = VHOST_IOTLB_BATCH_BEGIN;
+struct vhost_msg_v2 msg = {
+.type = v->msg_type,
+.iotlb.type = VHOST_IOTLB_BATCH_BEGIN,
+};
 
 if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) {
 error_report("failed to write, fd=%d, errno=%d (%s)",
@@ -109,6 +103,16 @@ static void vhost_vdpa_listener_begin(MemoryListener 
*listener)
 }
 }
 
+static void vhost_vdpa_iotlb_batch_begin_once(struct vhost_vdpa *v)
+{
+if (v->dev->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH) &&
+!v->iotlb_batch_begin_sent) {
+vhost_vdpa_listener_begin_batch(v);
+}
+
+v->iotlb_batch_begin_sent = true;
+}
+
 static void vhost_vdpa_listener_commit(MemoryListener *listener)
 {
 struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener);
@@ -120,6 +124,10 @@ static void vhost_vdpa_listener_commit(MemoryListener 
*listener)
 return;
 }
 
+if (!v->iotlb_batch_begin_sent) {
+return;
+}
+
 msg.type = v->msg_type;
 msg.iotlb.type = VHOST_IOTLB_BATCH_END;
 
@@ -127,6 +135,8 @@ static void vhost_vdpa_listener_commit(MemoryListener 
*listener)
 error_report("failed to write, fd=%d, errno=%d (%s)",
  fd, errno, strerror(errno));
 }
+
+v->iotlb_batch_begin_sent = false;
 }
 
 static void vhost_vdpa_listener_region_add(MemoryListener *listener,
@@ -170,6 +180,7 @@ static void vhost_vdpa_listener_region_add(MemoryListener 
*listener,
 
 llsize = int128_sub(llend, int128_make64(iova));
 
+vhost_vdpa_iotlb_batch_begin_once(v);
 ret = vhost_vdpa_dma_map(v, iova, int128_get64(llsize),
  vaddr, section->readonly);
 if (ret) {
@@ -221,6 +232,7 @@ static void vhost_vdpa_listener_region_del(MemoryListener 
*listener,
 
 llsize = int128_sub(llend, int128_make64(iova));
 
+vhost_vdpa_iotlb_batch_begin_once(v);
 ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize));
 if (ret) {
 error_report("vhost_vdpa dma unmap error!");
@@ -234,7 +246,6 @@ static void vhost_vdpa_listener_region_del(MemoryListener 
*listener,
  * depends on the addnop().
  */
 static const MemoryListener vhost_vdpa_memory_listener = {
-.begin = vhost_vdpa_listener_begin,
 .commit = vhost_vdpa_listener_commit,
 .region_add = vhost_vdpa_listener_region_add,
 .region_del = vhost_vdpa_listener_region_del,
-- 
2.27.0




Re: [PATCH] configure: Remove spurious [] from tr

2021-08-12 Thread Eric Blake
On Thu, Aug 12, 2021 at 02:05:36PM +0100, Dr. David Alan Gilbert wrote:
> Indeed it's not; there's LOTS of warnings; although most of them are
> probably irrelevant; there are also two others at the error level:
> 
> In configure line 4406:
> if "$ld" -verbose 2>&1 | grep -q "^[[:space:]]*$emu[[:space:]]*$"; 
> then
>^-- SC1087: Use braces 
> when expanding arrays, e.g. ${array[idx]} (or ${var}[.. to quiet).
> 
> which is probably just needing the ${emu} to shut it up.

Yep. ${var[idx]} is a bashism, but our configure is /bin/sh and not
bash, and we don't want an array access, so using ${emu}[ to shut up
the checker is the right action.

> 
> In configure line 4464:
> if !(GIT="$git" "$source_path/scripts/git-submodule.sh" 
> "$git_submodules_action" "$git_submodules"); then
> ^-- SC1035: You are missing a required space after the !.
> 
> which hmm I've not quite got my head around yet; but maybe that one is
> real.

In bash, !() is an extended glob when using 'shopt -s extglob' - but
we aren't using bash, and we _don't_ want extended glob (execute the
command formed from the set of all filenames in the current working
directory that do not match the contents inside (...), which is likely
to not be a valid command).  When the bash extension is not in use,
'if !()' is the same as 'if ! ()', checking if the exit status of the
subshell is non-zero.  Adding the space ensures we don't trigger an
unintended bash extglob, but would still waste the effort on a
subshell.  So I would suggest we fix the line to:

if ! GIT="$git" "$source_path..".."..$git_submodules"; then

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH] hw/acpi: refactor acpi hp modules so that targets can just use what they need

2021-08-12 Thread Philippe Mathieu-Daudé
On 8/12/21 3:22 PM, Ani Sinha wrote:
> On Thu, 12 Aug 2021, Ani Sinha wrote:
> 
>> Currently various acpi hotplug modules like cpu hotplug, memory hotplug, pci
>> hotplug, nvdimm hotplug are all pulled in when CONFIG_ACPI_X86 is turned on.
>> This brings in support for whole lot of subsystems that some targets like
>> mips does not need. They are added just to satisfy symbol dependencies. This
>> is ugly and should be avoided. Targets should be able to pull in just what 
>> they
>> need and no more. For example, mips only needs support for PIIX4 and does not
>> need acpi pci hotplug support or cpu hotplug support or memory hotplug 
>> support
>> etc. This change is an effort to clean this up.
>> In this change, new config variables are added for various acpi hotplug
>> subsystems. Targets like mips can only enable PIIX4 support and not the rest
>> of all the other modules which were being previously pulled in as a part of
>> CONFIG_ACPI_X86. Function stubs make sure that symbols which piix4 needs but
>> are not required by mips (for example, symbols specific to pci hotplug etc)
>> are available to satisfy the dependencies.
>>
>> Currently, this change only addresses issues with mips malta targets. In 
>> future
>> we might be able to clean up other targets which are similarly pulling in lot
>> of unnecessary hotplug modules by enabling ACPI_X86.
>>
>> This change should also address issues such as the following:
>> https://gitlab.com/qemu-project/qemu/-/issues/221
>> https://gitlab.com/qemu-project/qemu/-/issues/193
> 
> I do not have a cross compiled mips64 vmlinux handy, so can't verify that
> issue #193 was indeed resolved.

The functional tests use some pre-built:

$ git grep I6400 tests/acceptance/

> I have verified that #221 was indeed
> fixed.

Good news!



Re: [PATCH] hw/acpi: refactor acpi hp modules so that targets can just use what they need

2021-08-12 Thread Ani Sinha



On Thu, 12 Aug 2021, Ani Sinha wrote:

> Currently various acpi hotplug modules like cpu hotplug, memory hotplug, pci
> hotplug, nvdimm hotplug are all pulled in when CONFIG_ACPI_X86 is turned on.
> This brings in support for whole lot of subsystems that some targets like
> mips does not need. They are added just to satisfy symbol dependencies. This
> is ugly and should be avoided. Targets should be able to pull in just what 
> they
> need and no more. For example, mips only needs support for PIIX4 and does not
> need acpi pci hotplug support or cpu hotplug support or memory hotplug support
> etc. This change is an effort to clean this up.
> In this change, new config variables are added for various acpi hotplug
> subsystems. Targets like mips can only enable PIIX4 support and not the rest
> of all the other modules which were being previously pulled in as a part of
> CONFIG_ACPI_X86. Function stubs make sure that symbols which piix4 needs but
> are not required by mips (for example, symbols specific to pci hotplug etc)
> are available to satisfy the dependencies.
>
> Currently, this change only addresses issues with mips malta targets. In 
> future
> we might be able to clean up other targets which are similarly pulling in lot
> of unnecessary hotplug modules by enabling ACPI_X86.
>
> This change should also address issues such as the following:
> https://gitlab.com/qemu-project/qemu/-/issues/221
> https://gitlab.com/qemu-project/qemu/-/issues/193

I do not have a cross compiled mips64 vmlinux handy, so can't verify that
issue #193 was indeed resolved. I have verified that #221 was indeed
fixed.



Re: [PATCH] Hexagon (disas/hexagon.c) fix memory leak for early exit cases

2021-08-12 Thread Philippe Mathieu-Daudé
On 8/12/21 3:09 PM, Taylor Simpson wrote:
> Don't allocate the string until error conditions have been checked
> 
> Fixes: a00cfed0e ("Hexagon (disas) disassembler")
> Eliminate Coverity CID 1460121 (Resource leak)
> 
> Signed-off-by: Taylor Simpson 
> ---
>  disas/hexagon.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

Reviewed-by: Philippe Mathieu-Daudé 



Re: [PATCH 3/7] MAINTAINERS: update audio entry.

2021-08-12 Thread Philippe Mathieu-Daudé
Hi all,

On 8/12/21 2:24 PM, Christian Schoenebeck wrote:
> On Donnerstag, 12. August 2021 10:42:10 CEST Gerd Hoffmann wrote:
>>   Hi,
>>
 On Tue, Aug 10, 2021 at 03:17:43PM +0300, cla...@hotmail.com wrote:
> Gerd Hoffmann  writes:
>
> Hell Gerd.
>
>> New maintainer wanted. Downgrade status to "Odd Fixes" for now.
>
> I can try to retake it.
>>
>> Given your track record is zero contributions to qemu in recent years
>> I suggest you start getting involved in the development process as
>> reviewer.  Just send a patch adding a "R: Name " line for
>> yourself to the MAINTAINERS file (best based on my pending pull
>> request to avoid conflicts).  scripts/get_maintainer.pl will Cc: you
>> on any audio-related patches then.
>>
>> I'd recommend to open an gitlab.com account (unless you already have
>> one of course) so you can help triage bugs + issues.  You can also
>> easily run qemu CI then (just push a branch to a qemu repo fork).
>>
>> HTH & take care,
>>   Gerd
> 
> I will add myself as reviewer for audio to help out a bit at least. I won't 
> be 
> able to take over maintainership at this point though.

Thanks for volunteering :)

Following the overall thread, since I have been wondering about
this subsystem during the night.

As of v6.1.0-rc3:

$ find {,include/}audio -type f | xargs cat | wc -l
11412

$ find {,include/}hw/audio -type f | xargs cat | wc -l
14265

So the backends / frontends have almost the same size.

First idea, split the current entry in too, allowing developers
with different interests to add their contact to the relevant entries.

Then looking at the contribution over the last 10 years:

$ git shortlog -n -s --since=10years -- {,include/}audio | head -10
70  Kővágó, Zoltán
62  Volker Rümelin
24  Gerd Hoffmann
13  Markus Armbruster
13  Paolo Bonzini
10  Peter Maydell
 8  Geoffrey McRae
 8  Philippe Mathieu-Daudé
 8  Stefan Weil
 7  Marc-André Lureau

$ git shortlog -n -s --since=10years -- {,include/}hw/audio | head -10
30  Gerd Hoffmann
29  Juan Quintela
29  Paolo Bonzini
26  Markus Armbruster
14  Andreas Färber
13  Eduardo Habkost
12  Philippe Mathieu-Daudé
 8  Peter Maydell
 6  Hervé Poussineau
 6  Xiaoqiang Zhao

The backend part is clearly where the activity is (almost no new sound
devices added), with Zoltán Kővágó and Volker Rümelin the most active
contributors. IMHO they certainly deserve an R: tag (but up to them).
Cc'ing them, reminding a R: tag is not about responsibility but more
to not forgot to Cc contributors with both knowledge and interests:

  Descriptions of section entries:

M: Mail patches to: FullName 
   Maintainers are looking after a certain area and must be CCed
   on patches. They are considered the main contact point.
R: Designated reviewer: FullName 
   These reviewers should be CCed on patches.
   Reviewers are familiar with the subject matter and provide
   feedback even though they are not maintainers.

Regards,

Phil.




Re: [PATCH] Hexagon (disas/hexagon.c) fix memory leak for early exit cases

2021-08-12 Thread Peter Maydell
On Thu, 12 Aug 2021 at 14:09, Taylor Simpson  wrote:
>
> Don't allocate the string until error conditions have been checked
>
> Fixes: a00cfed0e ("Hexagon (disas) disassembler")
> Eliminate Coverity CID 1460121 (Resource leak)
>
> Signed-off-by: Taylor Simpson 
> ---
>  disas/hexagon.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/disas/hexagon.c b/disas/hexagon.c
> index 3c24e2a..c1a4ffc 100644
> --- a/disas/hexagon.c
> +++ b/disas/hexagon.c
> @@ -33,7 +33,7 @@ int print_insn_hexagon(bfd_vma memaddr, struct 
> disassemble_info *info)
>  {
>  uint32_t words[PACKET_WORDS_MAX];
>  bool found_end = false;
> -GString *buf = g_string_sized_new(PACKET_BUFFER_LEN);
> +GString *buf;
>  int i, len;
>
>  for (i = 0; i < PACKET_WORDS_MAX && !found_end; i++) {
> @@ -57,6 +57,7 @@ int print_insn_hexagon(bfd_vma memaddr, struct 
> disassemble_info *info)
>  return PACKET_WORDS_MAX * sizeof(uint32_t);
>  }
>
> +buf = g_string_sized_new(PACKET_BUFFER_LEN);
>  len = disassemble_hexagon(words, i, memaddr, buf);
>  (*info->fprintf_func)(info->stream, "%s", buf->str);
>  g_string_free(buf, true);
> --

Reviewed-by: Peter Maydell 

thanks
-- PMM



[PATCH] Hexagon (disas/hexagon.c) fix memory leak for early exit cases

2021-08-12 Thread Taylor Simpson
Don't allocate the string until error conditions have been checked

Fixes: a00cfed0e ("Hexagon (disas) disassembler")
Eliminate Coverity CID 1460121 (Resource leak)

Signed-off-by: Taylor Simpson 
---
 disas/hexagon.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/disas/hexagon.c b/disas/hexagon.c
index 3c24e2a..c1a4ffc 100644
--- a/disas/hexagon.c
+++ b/disas/hexagon.c
@@ -33,7 +33,7 @@ int print_insn_hexagon(bfd_vma memaddr, struct 
disassemble_info *info)
 {
 uint32_t words[PACKET_WORDS_MAX];
 bool found_end = false;
-GString *buf = g_string_sized_new(PACKET_BUFFER_LEN);
+GString *buf;
 int i, len;
 
 for (i = 0; i < PACKET_WORDS_MAX && !found_end; i++) {
@@ -57,6 +57,7 @@ int print_insn_hexagon(bfd_vma memaddr, struct 
disassemble_info *info)
 return PACKET_WORDS_MAX * sizeof(uint32_t);
 }
 
+buf = g_string_sized_new(PACKET_BUFFER_LEN);
 len = disassemble_hexagon(words, i, memaddr, buf);
 (*info->fprintf_func)(info->stream, "%s", buf->str);
 g_string_free(buf, true);
-- 
2.7.4



  1   2   >