[PATCH v3 00/20] ppc4xx_sdram QOMify and clean ups

2022-09-13 Thread BALATON Zoltan
This is the end of the QOMify series started by Cédric. This series
handles the SDRAM controller models to clean them up, QOMify and unify
them and at least partially clean up the mess that has accumulated
around these in the past. This includes the not yet merged patches
from the last series and new ones that change the DDR2 version used by
sam460ex.

v3: Fix patches that got squashed during rebase
v2: address some review comments and try to avoid compile problem with
gcc 12.2 (untested)

BALATON Zoltan (20):
  ppc440_bamboo: Remove unnecessary memsets
  ppc4xx: Introduce Ppc4xxSdramBank struct
  ppc4xx_sdram: Get rid of the init RAM hack
  ppc4xx: Use Ppc4xxSdramBank in ppc4xx_sdram_banks()
  ppc440_bamboo: Add missing 4 MiB valid memory size
  ppc4xx_sdram: Move size check to ppc4xx_sdram_init()
  ppc4xx_sdram: QOM'ify
  ppc4xx_sdram: Drop extra zeros for readability
  ppc440_sdram: Split off map/unmap of sdram banks for later reuse
  ppc440_sdram: Implement enable bit in the DDR2 SDRAM
  ppc440_sdram: Get rid of the init RAM hack
  ppc440_sdram: Rename local variable for readibility
  ppc4xx_sdram: Rename functions to prevent name clashes
  ppc440_sdram: Move RAM size check to ppc440_sdram_init
  ppc440_sdram: QOM'ify
  ppc4xx_sdram: Move ppc4xx DDR and DDR2 SDRAM controller models
together
  ppc4xx_sdram: Use hwaddr for memory bank size
  ppc4xx_sdram: Rename local state variable for brevity
  ppc4xx_sdram: Generalise bank setup
  ppc4xx_sdram: Convert DDR SDRAM controller to new bank handling

 hw/ppc/meson.build  |   3 +-
 hw/ppc/ppc405.h |   8 +-
 hw/ppc/ppc405_boards.c  |  22 +-
 hw/ppc/ppc405_uc.c  |  33 +-
 hw/ppc/ppc440.h |   4 -
 hw/ppc/ppc440_bamboo.c  |  29 +-
 hw/ppc/ppc440_uc.c  | 267 +--
 hw/ppc/ppc4xx_devs.c| 413 ---
 hw/ppc/ppc4xx_sdram.c   | 723 
 hw/ppc/sam460ex.c   |  48 +--
 hw/ppc/trace-events |   1 +
 include/hw/ppc/ppc4xx.h |  66 +++-
 12 files changed, 847 insertions(+), 770 deletions(-)
 create mode 100644 hw/ppc/ppc4xx_sdram.c

-- 
2.30.4




[PATCH v3 14/20] ppc440_sdram: Move RAM size check to ppc440_sdram_init

2022-09-13 Thread BALATON Zoltan
Move the check for valid memory sizes from board to sdram controller
init. Board now only checks for additional restrictions imposed by
firmware then sdram init checks for valid sizes for SoC.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc440.h|  4 ++--
 hw/ppc/ppc440_uc.c | 15 +++
 hw/ppc/sam460ex.c  | 32 +---
 3 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h
index 01d76b8000..29f6f14ed7 100644
--- a/hw/ppc/ppc440.h
+++ b/hw/ppc/ppc440.h
@@ -11,13 +11,13 @@
 #ifndef PPC440_H
 #define PPC440_H
 
-#include "hw/ppc/ppc4xx.h"
+#include "hw/ppc/ppc.h"
 
 void ppc4xx_l2sram_init(CPUPPCState *env);
 void ppc4xx_cpr_init(CPUPPCState *env);
 void ppc4xx_sdr_init(CPUPPCState *env);
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   Ppc4xxSdramBank *ram_banks);
+   MemoryRegion *ram);
 void ppc4xx_ahb_init(CPUPPCState *env);
 void ppc4xx_dma_init(CPUPPCState *env, int dcr_base);
 void ppc460ex_pcie_init(CPUPPCState *env);
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 565bfffc22..f48eba215a 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -486,7 +486,7 @@ void ppc4xx_sdr_init(CPUPPCState *env)
 typedef struct ppc440_sdram_t {
 uint32_t addr;
 uint32_t mcopt2;
-int nbanks;
+int nbanks; /* Banks to use from the 4, e.g. when board has less slots */
 Ppc4xxSdramBank bank[4];
 } ppc440_sdram_t;
 
@@ -728,18 +728,17 @@ static void sdram_ddr2_reset(void *opaque)
 }
 
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   Ppc4xxSdramBank *ram_banks)
+   MemoryRegion *ram)
 {
 ppc440_sdram_t *s;
-int i;
+const ram_addr_t valid_bank_sizes[] = {
+4 * GiB, 2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB,
+32 * MiB, 16 * MiB, 8 * MiB, 0
+};
 
 s = g_malloc0(sizeof(*s));
 s->nbanks = nbanks;
-for (i = 0; i < nbanks; i++) {
-s->bank[i].ram = ram_banks[i].ram;
-s->bank[i].base = ram_banks[i].base;
-s->bank[i].size = ram_banks[i].size;
-}
+ppc4xx_sdram_banks(ram, s->nbanks, s->bank, valid_bank_sizes);
 qemu_register_reset(_ddr2_reset, s);
 ppc_dcr_register(env, SDRAM0_CFGADDR,
  s, _ddr2_dcr_read, _ddr2_dcr_write);
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index dac329d482..9b850808a3 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -74,13 +74,6 @@
 #define EBC_FREQ 11500
 #define UART_FREQ 11059200
 
-/* The SoC could also handle 4 GiB but firmware does not work with that. */
-/* Maybe it overflows a signed 32 bit number somewhere? */
-static const ram_addr_t ppc460ex_sdram_bank_sizes[] = {
-2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB,
-32 * MiB, 0
-};
-
 struct boot_info {
 uint32_t dt_base;
 uint32_t dt_size;
@@ -273,7 +266,6 @@ static void sam460ex_init(MachineState *machine)
 {
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *isa = g_new(MemoryRegion, 1);
-Ppc4xxSdramBank *ram_banks = g_new0(Ppc4xxSdramBank, 1);
 MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
 DeviceState *uic[4];
 int i;
@@ -340,12 +332,22 @@ static void sam460ex_init(MachineState *machine)
 }
 
 /* SDRAM controller */
-/* put all RAM on first bank because board has one slot
- * and firmware only checks that */
-ppc4xx_sdram_banks(machine->ram, 1, ram_banks, ppc460ex_sdram_bank_sizes);
-
+/* The SoC could also handle 4 GiB but firmware does not work with that. */
+if (machine->ram_size > 2 * GiB) {
+error_report("Memory over 2 GiB is not supported");
+exit(1);
+}
+/* Firmware needs at least 64 MiB */
+if (machine->ram_size < 64 * MiB) {
+error_report("Memory below 64 MiB is not supported");
+exit(1);
+}
+/*
+ * Put all RAM on first bank because board has one slot
+ * and firmware only checks that
+ */
+ppc440_sdram_init(env, 1, machine->ram);
 /* FIXME: does 460EX have ECC interrupts? */
-ppc440_sdram_init(env, 1, ram_banks);
 /* Enable SDRAM memory regions as we may boot without firmware */
 if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x21) ||
 ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x0800)) {
@@ -358,8 +360,8 @@ static void sam460ex_init(MachineState *machine)
qdev_get_gpio_in(uic[0], 2));
 i2c = PPC4xx_I2C(dev)->bus;
 /* SPD EEPROM on RAM module */
-spd_data = spd_data_generate(ram_banks->size < 128 * MiB ? DDR : DDR2,
- ram_banks->size);
+spd_data = spd_data_generate(machine->ram_size < 128 * MiB ? DDR : DDR2,
+ machine->ram_size);
 spd_data[20] = 4; /* SO-DIMM module */
 smbus_eeprom_init_one(i2c, 0x50, spd_data);
 /* RTC */
-- 
2.30.4




[PATCH v4 2/2] x86: re-enable rng seeding via setup_data

2022-09-13 Thread Jason A. Donenfeld
This reverts 3824e25db1 ("x86: disable rng seeding via setup_data"), but
for 7.2 rather than 7.1, now that modifying setup_data is safe to do.

Cc: Laurent Vivier 
Cc: Michael S. Tsirkin 
Cc: Paolo Bonzini 
Cc: Peter Maydell 
Cc: Philippe Mathieu-Daudé 
Cc: Richard Henderson 
Cc: Ard Biesheuvel 
Acked-by: Gerd Hoffmann 
Signed-off-by: Jason A. Donenfeld 
---
 hw/i386/microvm.c | 2 +-
 hw/i386/pc_piix.c | 3 ++-
 hw/i386/pc_q35.c  | 3 ++-
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index 52cafa003d..7fe8cce03e 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -332,7 +332,7 @@ static void microvm_memory_init(MicrovmMachineState *mms)
 rom_set_fw(fw_cfg);
 
 if (machine->kernel_filename != NULL) {
-x86_load_linux(x86ms, fw_cfg, 0, true, true);
+x86_load_linux(x86ms, fw_cfg, 0, true, false);
 }
 
 if (mms->option_roms) {
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 8043a250ad..0b1a79c0fa 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -439,7 +439,6 @@ static void pc_i440fx_7_2_machine_options(MachineClass *m)
 m->alias = "pc";
 m->is_default = true;
 pcmc->default_cpu_version = 1;
-pcmc->legacy_no_rng_seed = true;
 }
 
 DEFINE_I440FX_MACHINE(v7_2, "pc-i440fx-7.2", NULL,
@@ -447,9 +446,11 @@ DEFINE_I440FX_MACHINE(v7_2, "pc-i440fx-7.2", NULL,
 
 static void pc_i440fx_7_1_machine_options(MachineClass *m)
 {
+PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
 pc_i440fx_7_2_machine_options(m);
 m->alias = NULL;
 m->is_default = false;
+pcmc->legacy_no_rng_seed = true;
 compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len);
 compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len);
 }
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 53eda50e81..a496bd6e74 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -376,7 +376,6 @@ static void pc_q35_7_2_machine_options(MachineClass *m)
 pc_q35_machine_options(m);
 m->alias = "q35";
 pcmc->default_cpu_version = 1;
-pcmc->legacy_no_rng_seed = true;
 }
 
 DEFINE_Q35_MACHINE(v7_2, "pc-q35-7.2", NULL,
@@ -384,8 +383,10 @@ DEFINE_Q35_MACHINE(v7_2, "pc-q35-7.2", NULL,
 
 static void pc_q35_7_1_machine_options(MachineClass *m)
 {
+PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
 pc_q35_7_2_machine_options(m);
 m->alias = NULL;
+pcmc->legacy_no_rng_seed = true;
 compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len);
 compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len);
 }
-- 
2.37.3




[PATCH v4 1/2] x86: return modified setup_data only if read as memory, not as file

2022-09-13 Thread Jason A. Donenfeld
If setup_data is being read into a specific memory location, then
generally the setup_data address parameter is read first, so that the
caller knows where to read it into. In that case, we should return
setup_data containing the absolute addresses that are hard coded and
determined a priori. This is the case when kernels are loaded by BIOS,
for example. In contrast, when setup_data is read as a file, then we
shouldn't modify setup_data, since the absolute address will be wrong by
definition. This is the case when OVMF loads the image.

This allows setup_data to be used like normal, without crashing when EFI
tries to use it.

(As a small development note, strangely, fw_cfg_add_file_callback() was
exported but fw_cfg_add_bytes_callback() wasn't, so this makes that
consistent.)

Cc: Gerd Hoffmann 
Cc: Laurent Vivier 
Cc: Michael S. Tsirkin 
Cc: Paolo Bonzini 
Cc: Peter Maydell 
Cc: Philippe Mathieu-Daudé 
Cc: Richard Henderson 
Suggested-by: Ard Biesheuvel 
Signed-off-by: Jason A. Donenfeld 
---
 hw/i386/x86.c | 37 +++--
 hw/nvram/fw_cfg.c | 12 ++--
 include/hw/nvram/fw_cfg.h | 22 ++
 3 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 050eedc0c8..933bbdd836 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -764,6 +764,18 @@ static bool load_elfboot(const char *kernel_filename,
 return true;
 }
 
+struct setup_data_fixup {
+void *pos;
+hwaddr val;
+uint32_t addr;
+};
+
+static void fixup_setup_data(void *opaque)
+{
+struct setup_data_fixup *fixup = opaque;
+stq_p(fixup->pos, fixup->val);
+}
+
 void x86_load_linux(X86MachineState *x86ms,
 FWCfgState *fw_cfg,
 int acpi_data_size,
@@ -1088,8 +1100,11 @@ void x86_load_linux(X86MachineState *x86ms,
 qemu_guest_getrandom_nofail(setup_data->data, RNG_SEED_LENGTH);
 }
 
-/* Offset 0x250 is a pointer to the first setup_data link. */
-stq_p(header + 0x250, first_setup_data);
+fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
+fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
+sev_load_ctx.kernel_data = (char *)kernel;
+sev_load_ctx.kernel_size = kernel_size;
 
 /*
  * If we're starting an encrypted VM, it will be OVMF based, which uses the
@@ -1099,16 +1114,18 @@ void x86_load_linux(X86MachineState *x86ms,
  * file the user passed in.
  */
 if (!sev_enabled()) {
+struct setup_data_fixup *fixup = g_malloc(sizeof(*fixup));
+
 memcpy(setup, header, MIN(sizeof(header), setup_size));
+/* Offset 0x250 is a pointer to the first setup_data link. */
+fixup->pos = setup + 0x250;
+fixup->val = first_setup_data;
+fixup->addr = real_addr;
+fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_SETUP_ADDR, fixup_setup_data, 
NULL,
+  fixup, >addr, sizeof(fixup->addr), 
true);
+} else {
+fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
 }
-
-fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
-fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
-fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
-sev_load_ctx.kernel_data = (char *)kernel;
-sev_load_ctx.kernel_size = kernel_size;
-
-fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
 fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
 fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
 sev_load_ctx.setup_data = (char *)setup;
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index d605f3f45a..564bda3395 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -692,12 +692,12 @@ static const VMStateDescription vmstate_fw_cfg = {
 }
 };
 
-static void fw_cfg_add_bytes_callback(FWCfgState *s, uint16_t key,
-  FWCfgCallback select_cb,
-  FWCfgWriteCallback write_cb,
-  void *callback_opaque,
-  void *data, size_t len,
-  bool read_only)
+void fw_cfg_add_bytes_callback(FWCfgState *s, uint16_t key,
+   FWCfgCallback select_cb,
+   FWCfgWriteCallback write_cb,
+   void *callback_opaque,
+   void *data, size_t len,
+   bool read_only)
 {
 int arch = !!(key & FW_CFG_ARCH_LOCAL);
 
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index 0e7a8bc7af..e4fef393be 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -117,6 +117,28 @@ struct FWCfgMemState {
  */
 void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);
 
+/**
+ * fw_cfg_add_bytes_callback:
+ * @s: fw_cfg 

Re: [PATCH 2/3] vdpa: load vlan configuration at NIC startup

2022-09-13 Thread Jason Wang
On Fri, Sep 9, 2022 at 4:38 PM Michael S. Tsirkin  wrote:
>
> On Fri, Sep 09, 2022 at 10:01:16AM +0200, Eugenio Perez Martin wrote:
> > On Fri, Sep 9, 2022 at 8:40 AM Jason Wang  wrote:
> > >
> > > On Fri, Sep 9, 2022 at 2:38 PM Jason Wang  wrote:
> > > >
> > > > On Wed, Sep 7, 2022 at 12:36 AM Eugenio Pérez  
> > > > wrote:
> > > > >
> > > > > To have enabled vlans at device startup may happen in the destination 
> > > > > of
> > > > > a live migration, so this configuration must be restored.
> > > > >
> > > > > At this moment the code is not accessible, since SVQ refuses to start 
> > > > > if
> > > > > vlan feature is exposed by the device.
> > > > >
> > > > > Signed-off-by: Eugenio Pérez 
> > > > > ---
> > > > >  net/vhost-vdpa.c | 46 --
> > > > >  1 file changed, 44 insertions(+), 2 deletions(-)
> > > > >
> > > > > diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
> > > > > index 4bc3fd01a8..ecbfd08eb9 100644
> > > > > --- a/net/vhost-vdpa.c
> > > > > +++ b/net/vhost-vdpa.c
> > > > > @@ -100,6 +100,8 @@ static const uint64_t vdpa_svq_device_features =
> > > > >  BIT_ULL(VIRTIO_NET_F_RSC_EXT) |
> > > > >  BIT_ULL(VIRTIO_NET_F_STANDBY);
> > > > >
> > > > > +#define MAX_VLAN(1 << 12)   /* Per 802.1Q definition */
> > > > > +
> > > > >  VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc)
> > > > >  {
> > > > >  VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> > > > > @@ -423,6 +425,47 @@ static int vhost_vdpa_net_load_mq(VhostVDPAState 
> > > > > *s,
> > > > >  return *s->status != VIRTIO_NET_OK;
> > > > >  }
> > > > >
> > > > > +static int vhost_vdpa_net_load_single_vlan(VhostVDPAState *s,
> > > > > +   const VirtIONet *n,
> > > > > +   uint16_t vid)
> > > > > +{
> > > > > +ssize_t dev_written = vhost_vdpa_net_load_cmd(s, 
> > > > > VIRTIO_NET_CTRL_VLAN,
> > > > > +  
> > > > > VIRTIO_NET_CTRL_VLAN_ADD,
> > > > > +  , sizeof(vid));
> > > > > +if (unlikely(dev_written < 0)) {
> > > > > +return dev_written;
> > > > > +}
> > > > > +
> > > > > +if (unlikely(*s->status != VIRTIO_NET_OK)) {
> > > > > +return -EINVAL;
> > > > > +}
> > > > > +
> > > > > +return 0;
> > > > > +}
> > > > > +
> > > > > +static int vhost_vdpa_net_load_vlan(VhostVDPAState *s,
> > > > > +const VirtIONet *n)
> > > > > +{
> > > > > +uint64_t features = n->parent_obj.guest_features;
> > > > > +
> > > > > +if (!(features & BIT_ULL(VIRTIO_NET_F_CTRL_VLAN))) {
> > > > > +return 0;
> > > > > +}
> > > > > +
> > > > > +for (int i = 0; i < MAX_VLAN >> 5; i++) {
> > > > > +for (int j = 0; n->vlans[i] && j <= 0x1f; j++) {
> > > > > +if (n->vlans[i] & (1U << j)) {
> > > > > +int r = vhost_vdpa_net_load_single_vlan(s, n, (i << 
> > > > > 5) + j);
> > > >
> > > > This seems to cause a lot of latency if the driver has a lot of vlans.
> > > >
> > > > I wonder if it's simply to let all vlan traffic go by disabling
> > > > CTRL_VLAN feature at vDPA layer.
> > >
> >
> > The guest will not be able to recover that vlan configuration.
> >
> > > Another idea is to extend the spec to allow us to accept a bitmap of
> > > the vlan ids via a single command, then we will be fine.
> > >
> >
> > I'm not sure if adding more ways to configure something is the answer,
> > but I'd be ok to implement it.
> >
> > Another idea is to allow the sending of many CVQ commands in parallel.
> > It shouldn't be very hard to achieve using exposed buffers as ring
> > buffers, and it will short down the start of the devices with many
> > features.
>
> This would seem like a reasonable second step.  A first step would be to
> measure the overhead to make sure there's actually a need to optimize
> this.

+1.

Thanks

>
>
> > Thanks!
> >
> > > Thanks
> > >
> > > >
> > > > Thanks
> > > >
> > > > > +if (unlikely(r != 0)) {
> > > > > +return r;
> > > > > +}
> > > > > +}
> > > > > +}
> > > > > +}
> > > > > +
> > > > > +return 0;
> > > > > +}
> > > > > +
> > > > >  static int vhost_vdpa_net_load(NetClientState *nc)
> > > > >  {
> > > > >  VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> > > > > @@ -445,8 +488,7 @@ static int vhost_vdpa_net_load(NetClientState *nc)
> > > > >  if (unlikely(r)) {
> > > > >  return r;
> > > > >  }
> > > > > -
> > > > > -return 0;
> > > > > +return vhost_vdpa_net_load_vlan(s, n);
> > > > >  }
> > > > >
> > > > >  static NetClientInfo net_vhost_vdpa_cvq_info = {
> > > > > --
> > > > > 2.31.1
> > > > >
> > >
>




Re: [PATCH v2 6/6] vhost: vhost-user: enable vq reset feature

2022-09-13 Thread Jason Wang



在 2022/9/12 11:10, Kangjie Xu 写道:

Add virtqueue reset feature for vhost-user.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 



Acked-by: Jason Wang 



---
  hw/net/vhost_net.c | 1 +
  1 file changed, 1 insertion(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 8b80942e7c..ad319faee8 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -74,6 +74,7 @@ static const int user_feature_bits[] = {
  VIRTIO_NET_F_MTU,
  VIRTIO_F_IOMMU_PLATFORM,
  VIRTIO_F_RING_PACKED,
+VIRTIO_F_RING_RESET,
  VIRTIO_NET_F_RSS,
  VIRTIO_NET_F_HASH_REPORT,
  





[PULL 01/12] linux-user: Add missing signals in strace output

2022-09-13 Thread Helge Deller
Some of the guest signal numbers are currently not converted to
their representative names in the strace output, e.g. SIGVTALRM.

This patch introduces a smart way to generate and keep in sync the
host-to-guest and guest-to-host signal conversion tables for usage in
the qemu signal and strace code. This ensures that any signals
will now show up in both tables.

There is no functional change in this patch - with the exception that yet
missing signal names now show up in the strace code too.

Signed-off-by: Helge Deller 
---
 linux-user/signal-common.h | 46 ++
 linux-user/signal.c| 37 +++---
 linux-user/strace.c| 30 +
 3 files changed, 60 insertions(+), 53 deletions(-)

diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h
index 6a7e4a93fc..3e2dc604c2 100644
--- a/linux-user/signal-common.h
+++ b/linux-user/signal-common.h
@@ -118,4 +118,50 @@ static inline void finish_sigsuspend_mask(int ret)
 }
 }

+#if defined(SIGSTKFLT) && defined(TARGET_SIGSTKFLT)
+#define MAKE_SIG_ENTRY_SIGSTKFLTMAKE_SIG_ENTRY(SIGSTKFLT)
+#else
+#define MAKE_SIG_ENTRY_SIGSTKFLT
+#endif
+
+#if defined(SIGIOT) && defined(TARGET_SIGIOT)
+#define MAKE_SIG_ENTRY_SIGIOT   MAKE_SIG_ENTRY(SIGIOT)
+#else
+#define MAKE_SIG_ENTRY_SIGIOT
+#endif
+
+#define MAKE_SIGNAL_LIST \
+MAKE_SIG_ENTRY(SIGHUP) \
+MAKE_SIG_ENTRY(SIGINT) \
+MAKE_SIG_ENTRY(SIGQUIT) \
+MAKE_SIG_ENTRY(SIGILL) \
+MAKE_SIG_ENTRY(SIGTRAP) \
+MAKE_SIG_ENTRY(SIGABRT) \
+MAKE_SIG_ENTRY(SIGBUS) \
+MAKE_SIG_ENTRY(SIGFPE) \
+MAKE_SIG_ENTRY(SIGKILL) \
+MAKE_SIG_ENTRY(SIGUSR1) \
+MAKE_SIG_ENTRY(SIGSEGV) \
+MAKE_SIG_ENTRY(SIGUSR2) \
+MAKE_SIG_ENTRY(SIGPIPE) \
+MAKE_SIG_ENTRY(SIGALRM) \
+MAKE_SIG_ENTRY(SIGTERM) \
+MAKE_SIG_ENTRY(SIGCHLD) \
+MAKE_SIG_ENTRY(SIGCONT) \
+MAKE_SIG_ENTRY(SIGSTOP) \
+MAKE_SIG_ENTRY(SIGTSTP) \
+MAKE_SIG_ENTRY(SIGTTIN) \
+MAKE_SIG_ENTRY(SIGTTOU) \
+MAKE_SIG_ENTRY(SIGURG) \
+MAKE_SIG_ENTRY(SIGXCPU) \
+MAKE_SIG_ENTRY(SIGXFSZ) \
+MAKE_SIG_ENTRY(SIGVTALRM) \
+MAKE_SIG_ENTRY(SIGPROF) \
+MAKE_SIG_ENTRY(SIGWINCH) \
+MAKE_SIG_ENTRY(SIGIO) \
+MAKE_SIG_ENTRY(SIGPWR) \
+MAKE_SIG_ENTRY(SIGSYS) \
+MAKE_SIG_ENTRY_SIGSTKFLT \
+MAKE_SIG_ENTRY_SIGIOT
+
 #endif
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 8d29bfaa6b..61c6fa3fcf 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -53,40 +53,9 @@ abi_ulong default_rt_sigreturn;
 QEMU_BUILD_BUG_ON(__SIGRTMAX + 1 != _NSIG);
 #endif
 static uint8_t host_to_target_signal_table[_NSIG] = {
-[SIGHUP] = TARGET_SIGHUP,
-[SIGINT] = TARGET_SIGINT,
-[SIGQUIT] = TARGET_SIGQUIT,
-[SIGILL] = TARGET_SIGILL,
-[SIGTRAP] = TARGET_SIGTRAP,
-[SIGABRT] = TARGET_SIGABRT,
-/*[SIGIOT] = TARGET_SIGIOT,*/
-[SIGBUS] = TARGET_SIGBUS,
-[SIGFPE] = TARGET_SIGFPE,
-[SIGKILL] = TARGET_SIGKILL,
-[SIGUSR1] = TARGET_SIGUSR1,
-[SIGSEGV] = TARGET_SIGSEGV,
-[SIGUSR2] = TARGET_SIGUSR2,
-[SIGPIPE] = TARGET_SIGPIPE,
-[SIGALRM] = TARGET_SIGALRM,
-[SIGTERM] = TARGET_SIGTERM,
-#ifdef SIGSTKFLT
-[SIGSTKFLT] = TARGET_SIGSTKFLT,
-#endif
-[SIGCHLD] = TARGET_SIGCHLD,
-[SIGCONT] = TARGET_SIGCONT,
-[SIGSTOP] = TARGET_SIGSTOP,
-[SIGTSTP] = TARGET_SIGTSTP,
-[SIGTTIN] = TARGET_SIGTTIN,
-[SIGTTOU] = TARGET_SIGTTOU,
-[SIGURG] = TARGET_SIGURG,
-[SIGXCPU] = TARGET_SIGXCPU,
-[SIGXFSZ] = TARGET_SIGXFSZ,
-[SIGVTALRM] = TARGET_SIGVTALRM,
-[SIGPROF] = TARGET_SIGPROF,
-[SIGWINCH] = TARGET_SIGWINCH,
-[SIGIO] = TARGET_SIGIO,
-[SIGPWR] = TARGET_SIGPWR,
-[SIGSYS] = TARGET_SIGSYS,
+#define MAKE_SIG_ENTRY(sig) [sig] = TARGET_##sig,
+MAKE_SIGNAL_LIST
+#undef MAKE_SIG_ENTRY
 /* next signals stay the same */
 };

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 7d882526da..a4eeef7ae1 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -17,6 +17,7 @@
 #include "qemu.h"
 #include "user-internals.h"
 #include "strace.h"
+#include "signal-common.h"

 struct syscallname {
 int nr;
@@ -141,30 +142,21 @@ if( cmd == val ) { \
 qemu_log("%d", cmd);
 }

+static const char * const target_signal_name[] = {
+#define MAKE_SIG_ENTRY(sig) [TARGET_##sig] = #sig,
+MAKE_SIGNAL_LIST
+#undef MAKE_SIG_ENTRY
+};
+
 static void
 print_signal(abi_ulong arg, int last)
 {
 const char *signal_name = NULL;
-switch(arg) {
-case TARGET_SIGHUP: signal_name = "SIGHUP"; break;
-case TARGET_SIGINT: signal_name = "SIGINT"; break;
-case TARGET_SIGQUIT: signal_name = "SIGQUIT"; break;
-case TARGET_SIGILL: signal_name = "SIGILL"; break;
-case TARGET_SIGABRT: signal_name = "SIGABRT"; break;
-case TARGET_SIGFPE: signal_name = 

[PULL 08/12] linux-user/hppa: Set TASK_UNMAPPED_BASE to 0xfa000000 for hppa arch

2022-09-13 Thread Helge Deller
On the parisc architecture the stack grows upwards.
Move the TASK_UNMAPPED_BASE to high memory area as it's done by the
kernel on physical machines.

Signed-off-by: Helge Deller 
---
 linux-user/mmap.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 048c4135af..dba6823668 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -251,8 +251,12 @@ static int mmap_frag(abi_ulong real_start,
 # define TASK_UNMAPPED_BASE  (1ul << 38)
 #endif
 #else
+#ifdef TARGET_HPPA
+# define TASK_UNMAPPED_BASE  0xfa00
+#else
 # define TASK_UNMAPPED_BASE  0x4000
 #endif
+#endif
 abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;

 unsigned long last_brk;
--
2.37.2




[PATCH v3 15/20] ppc440_sdram: QOM'ify

2022-09-13 Thread BALATON Zoltan
Change the ppc440_sdram model to a QOM class derived from the
PPC4xx-dcr-device and name it ppc4xx-sdram-ddr2. This is mostly
modelling the DDR2 SDRAM controller found in the 460EX (used on the
sam460ex board). Newer SoCs (regardless of their PPC core, e.g. 405EX)
may have this controller but we only emulate enough of it for the
sam460ex u-boot firmware.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Cédric Le Goater 
---
 hw/ppc/ppc440.h |   2 -
 hw/ppc/ppc440_uc.c  | 115 +---
 hw/ppc/sam460ex.c   |   7 ++-
 include/hw/ppc/ppc4xx.h |  14 +
 4 files changed, 91 insertions(+), 47 deletions(-)

diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h
index 29f6f14ed7..7c24db8504 100644
--- a/hw/ppc/ppc440.h
+++ b/hw/ppc/ppc440.h
@@ -16,8 +16,6 @@
 void ppc4xx_l2sram_init(CPUPPCState *env);
 void ppc4xx_cpr_init(CPUPPCState *env);
 void ppc4xx_sdr_init(CPUPPCState *env);
-void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   MemoryRegion *ram);
 void ppc4xx_ahb_init(CPUPPCState *env);
 void ppc4xx_dma_init(CPUPPCState *env, int dcr_base);
 void ppc460ex_pcie_init(CPUPPCState *env);
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index f48eba215a..114c1a1b1c 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -483,13 +483,6 @@ void ppc4xx_sdr_init(CPUPPCState *env)
 
 /*/
 /* SDRAM controller */
-typedef struct ppc440_sdram_t {
-uint32_t addr;
-uint32_t mcopt2;
-int nbanks; /* Banks to use from the 4, e.g. when board has less slots */
-Ppc4xxSdramBank bank[4];
-} ppc440_sdram_t;
-
 enum {
 SDRAM_R0BAS = 0x40,
 SDRAM_R1BAS,
@@ -578,7 +571,7 @@ static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
 object_unparent(OBJECT(>container));
 }
 
-static void sdram_ddr2_set_bcr(ppc440_sdram_t *sdram, int i,
+static void sdram_ddr2_set_bcr(Ppc4xxSdramDdr2State *sdram, int i,
uint32_t bcr, int enabled)
 {
 if (sdram->bank[i].bcr & 1) {
@@ -596,7 +589,7 @@ static void sdram_ddr2_set_bcr(ppc440_sdram_t *sdram, int i,
 }
 }
 
-static void sdram_ddr2_map_bcr(ppc440_sdram_t *sdram)
+static void sdram_ddr2_map_bcr(Ppc4xxSdramDdr2State *sdram)
 {
 int i;
 
@@ -611,7 +604,7 @@ static void sdram_ddr2_map_bcr(ppc440_sdram_t *sdram)
 }
 }
 
-static void sdram_ddr2_unmap_bcr(ppc440_sdram_t *sdram)
+static void sdram_ddr2_unmap_bcr(Ppc4xxSdramDdr2State *sdram)
 {
 int i;
 
@@ -624,7 +617,7 @@ static void sdram_ddr2_unmap_bcr(ppc440_sdram_t *sdram)
 
 static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn)
 {
-ppc440_sdram_t *sdram = opaque;
+Ppc4xxSdramDdr2State *sdram = opaque;
 uint32_t ret = 0;
 
 switch (dcrn) {
@@ -677,7 +670,7 @@ static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn)
 
 static void sdram_ddr2_dcr_write(void *opaque, int dcrn, uint32_t val)
 {
-ppc440_sdram_t *sdram = opaque;
+Ppc4xxSdramDdr2State *sdram = opaque;
 
 switch (dcrn) {
 case SDRAM_R0BAS:
@@ -719,52 +712,86 @@ static void sdram_ddr2_dcr_write(void *opaque, int dcrn, 
uint32_t val)
 }
 }
 
-static void sdram_ddr2_reset(void *opaque)
+static void ppc4xx_sdram_ddr2_reset(DeviceState *dev)
 {
-ppc440_sdram_t *sdram = opaque;
+Ppc4xxSdramDdr2State *sdram = PPC4xx_SDRAM_DDR2(dev);
 
 sdram->addr = 0;
 sdram->mcopt2 = 0;
 }
 
-void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   MemoryRegion *ram)
+static void ppc4xx_sdram_ddr2_realize(DeviceState *dev, Error **errp)
 {
-ppc440_sdram_t *s;
+Ppc4xxSdramDdr2State *s = PPC4xx_SDRAM_DDR2(dev);
+Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
 const ram_addr_t valid_bank_sizes[] = {
 4 * GiB, 2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB,
 32 * MiB, 16 * MiB, 8 * MiB, 0
 };
 
-s = g_malloc0(sizeof(*s));
-s->nbanks = nbanks;
-ppc4xx_sdram_banks(ram, s->nbanks, s->bank, valid_bank_sizes);
-qemu_register_reset(_ddr2_reset, s);
-ppc_dcr_register(env, SDRAM0_CFGADDR,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM0_CFGDATA,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-
-ppc_dcr_register(env, SDRAM_R0BAS,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM_R1BAS,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM_R2BAS,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM_R3BAS,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM_CONF1HB,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM_PLBADDULL,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM_CONF1LL,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-

[PATCH v3 18/20] ppc4xx_sdram: Rename local state variable for brevity

2022-09-13 Thread BALATON Zoltan
Rename the sdram local state variable to s in dcr read/write functions
and reset methods for better readability and to match realize methods.
Other places not converted will be changed or removed in subsequent
patches.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc4xx_sdram.c | 158 +-
 1 file changed, 79 insertions(+), 79 deletions(-)

diff --git a/hw/ppc/ppc4xx_sdram.c b/hw/ppc/ppc4xx_sdram.c
index 242e2f4c6e..e36898a906 100644
--- a/hw/ppc/ppc4xx_sdram.c
+++ b/hw/ppc/ppc4xx_sdram.c
@@ -233,56 +233,56 @@ static void sdram_ddr_unmap_bcr(Ppc4xxSdramDdrState 
*sdram)
 
 static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
 {
-Ppc4xxSdramDdrState *sdram = opaque;
+Ppc4xxSdramDdrState *s = opaque;
 uint32_t ret;
 
 switch (dcrn) {
 case SDRAM0_CFGADDR:
-ret = sdram->addr;
+ret = s->addr;
 break;
 case SDRAM0_CFGDATA:
-switch (sdram->addr) {
+switch (s->addr) {
 case 0x00: /* SDRAM_BESR0 */
-ret = sdram->besr0;
+ret = s->besr0;
 break;
 case 0x08: /* SDRAM_BESR1 */
-ret = sdram->besr1;
+ret = s->besr1;
 break;
 case 0x10: /* SDRAM_BEAR */
-ret = sdram->bear;
+ret = s->bear;
 break;
 case 0x20: /* SDRAM_CFG */
-ret = sdram->cfg;
+ret = s->cfg;
 break;
 case 0x24: /* SDRAM_STATUS */
-ret = sdram->status;
+ret = s->status;
 break;
 case 0x30: /* SDRAM_RTR */
-ret = sdram->rtr;
+ret = s->rtr;
 break;
 case 0x34: /* SDRAM_PMIT */
-ret = sdram->pmit;
+ret = s->pmit;
 break;
 case 0x40: /* SDRAM_B0CR */
-ret = sdram->bank[0].bcr;
+ret = s->bank[0].bcr;
 break;
 case 0x44: /* SDRAM_B1CR */
-ret = sdram->bank[1].bcr;
+ret = s->bank[1].bcr;
 break;
 case 0x48: /* SDRAM_B2CR */
-ret = sdram->bank[2].bcr;
+ret = s->bank[2].bcr;
 break;
 case 0x4C: /* SDRAM_B3CR */
-ret = sdram->bank[3].bcr;
+ret = s->bank[3].bcr;
 break;
 case 0x80: /* SDRAM_TR */
 ret = -1; /* ? */
 break;
 case 0x94: /* SDRAM_ECCCFG */
-ret = sdram->ecccfg;
+ret = s->ecccfg;
 break;
 case 0x98: /* SDRAM_ECCESR */
-ret = sdram->eccesr;
+ret = s->eccesr;
 break;
 default: /* Error */
 ret = -1;
@@ -300,78 +300,78 @@ static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
 
 static void sdram_ddr_dcr_write(void *opaque, int dcrn, uint32_t val)
 {
-Ppc4xxSdramDdrState *sdram = opaque;
+Ppc4xxSdramDdrState *s = opaque;
 
 switch (dcrn) {
 case SDRAM0_CFGADDR:
-sdram->addr = val;
+s->addr = val;
 break;
 case SDRAM0_CFGDATA:
-switch (sdram->addr) {
+switch (s->addr) {
 case 0x00: /* SDRAM_BESR0 */
-sdram->besr0 &= ~val;
+s->besr0 &= ~val;
 break;
 case 0x08: /* SDRAM_BESR1 */
-sdram->besr1 &= ~val;
+s->besr1 &= ~val;
 break;
 case 0x10: /* SDRAM_BEAR */
-sdram->bear = val;
+s->bear = val;
 break;
 case 0x20: /* SDRAM_CFG */
 val &= 0xFFE0;
-if (!(sdram->cfg & 0x8000) && (val & 0x8000)) {
+if (!(s->cfg & 0x8000) && (val & 0x8000)) {
 trace_ppc4xx_sdram_enable("enable");
 /* validate all RAM mappings */
-sdram_ddr_map_bcr(sdram);
-sdram->status &= ~0x8000;
-} else if ((sdram->cfg & 0x8000) && !(val & 0x8000)) {
+sdram_ddr_map_bcr(s);
+s->status &= ~0x8000;
+} else if ((s->cfg & 0x8000) && !(val & 0x8000)) {
 trace_ppc4xx_sdram_enable("disable");
 /* invalidate all RAM mappings */
-sdram_ddr_unmap_bcr(sdram);
-sdram->status |= 0x8000;
+sdram_ddr_unmap_bcr(s);
+s->status |= 0x8000;
 }
-if (!(sdram->cfg & 0x4000) && (val & 0x4000)) {
-sdram->status |= 0x4000;
-} else if ((sdram->cfg & 0x4000) && !(val & 0x4000)) {
-sdram->status &= ~0x4000;
+if (!(s->cfg & 0x4000) && (val & 0x4000)) {
+s->status |= 0x4000;
+} else if ((s->cfg & 0x4000) && !(val & 0x4000)) {
+s->status &= ~0x4000;
 }
-sdram->cfg = val;
+s->cfg = val;
 break;
   

[PATCH v3 09/20] ppc440_sdram: Split off map/unmap of sdram banks for later reuse

2022-09-13 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc440_uc.c | 31 +++
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 5db59d1190..01184e717b 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -561,26 +561,33 @@ static uint64_t sdram_size(uint32_t bcr)
 return size;
 }
 
+static void sdram_bank_map(Ppc4xxSdramBank *bank)
+{
+memory_region_init(>container, NULL, "sdram-container", bank->size);
+memory_region_add_subregion(>container, 0, >ram);
+memory_region_add_subregion(get_system_memory(), bank->base,
+>container);
+}
+
+static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
+{
+memory_region_del_subregion(get_system_memory(), >container);
+memory_region_del_subregion(>container, >ram);
+object_unparent(OBJECT(>container));
+}
+
 static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
   uint32_t bcr, int enabled)
 {
 if (sdram->bank[i].bcr & 1) {
 /* First unmap RAM if enabled */
-memory_region_del_subregion(get_system_memory(),
->bank[i].container);
-memory_region_del_subregion(>bank[i].container,
->bank[i].ram);
-object_unparent(OBJECT(>bank[i].container));
+sdram_bank_unmap(>bank[i]);
 }
 sdram->bank[i].bcr = bcr & 0xffe0ffc1;
+sdram->bank[i].base = sdram_base(bcr);
+sdram->bank[i].size = sdram_size(bcr);
 if (enabled && (bcr & 1)) {
-memory_region_init(>bank[i].container, NULL, "sdram-container",
-   sdram_size(bcr));
-memory_region_add_subregion(>bank[i].container, 0,
->bank[i].ram);
-memory_region_add_subregion(get_system_memory(),
-sdram_base(bcr),
->bank[i].container);
+sdram_bank_map(>bank[i]);
 }
 }
 
-- 
2.30.4




[PATCH v3 13/20] ppc4xx_sdram: Rename functions to prevent name clashes

2022-09-13 Thread BALATON Zoltan
Rename functions to avoid name clashes when moving the DDR2 controller
model currently called ppc440_sdram to ppc4xx_devs. This also more
clearly shows which function belongs to which model.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc440_uc.c   | 69 ++--
 hw/ppc/ppc4xx_devs.c | 44 ++--
 2 files changed, 57 insertions(+), 56 deletions(-)

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index d8a7947196..565bfffc22 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -502,7 +502,7 @@ enum {
 SDRAM_PLBADDUHB = 0x50,
 };
 
-static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
+static uint32_t sdram_ddr2_bcr(hwaddr ram_base, hwaddr ram_size)
 {
 uint32_t bcr;
 
@@ -547,12 +547,12 @@ static uint32_t sdram_bcr(hwaddr ram_base, hwaddr 
ram_size)
 return bcr;
 }
 
-static inline hwaddr sdram_base(uint32_t bcr)
+static inline hwaddr sdram_ddr2_base(uint32_t bcr)
 {
 return (bcr & 0xffe0) << 2;
 }
 
-static uint64_t sdram_size(uint32_t bcr)
+static uint64_t sdram_ddr2_size(uint32_t bcr)
 {
 uint64_t size;
 int sh;
@@ -578,50 +578,51 @@ static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
 object_unparent(OBJECT(>container));
 }
 
-static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
-  uint32_t bcr, int enabled)
+static void sdram_ddr2_set_bcr(ppc440_sdram_t *sdram, int i,
+   uint32_t bcr, int enabled)
 {
 if (sdram->bank[i].bcr & 1) {
 /* First unmap RAM if enabled */
-trace_ppc4xx_sdram_unmap(sdram_base(sdram->bank[i].bcr),
- sdram_size(sdram->bank[i].bcr));
+trace_ppc4xx_sdram_unmap(sdram_ddr2_base(sdram->bank[i].bcr),
+ sdram_ddr2_size(sdram->bank[i].bcr));
 sdram_bank_unmap(>bank[i]);
 }
 sdram->bank[i].bcr = bcr & 0xffe0ffc1;
-sdram->bank[i].base = sdram_base(bcr);
-sdram->bank[i].size = sdram_size(bcr);
+sdram->bank[i].base = sdram_ddr2_base(bcr);
+sdram->bank[i].size = sdram_ddr2_size(bcr);
 if (enabled && (bcr & 1)) {
-trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr));
+trace_ppc4xx_sdram_map(sdram_ddr2_base(bcr), sdram_ddr2_size(bcr));
 sdram_bank_map(>bank[i]);
 }
 }
 
-static void sdram_map_bcr(ppc440_sdram_t *sdram)
+static void sdram_ddr2_map_bcr(ppc440_sdram_t *sdram)
 {
 int i;
 
 for (i = 0; i < sdram->nbanks; i++) {
 if (sdram->bank[i].size) {
-sdram_set_bcr(sdram, i, sdram_bcr(sdram->bank[i].base,
+sdram_ddr2_set_bcr(sdram, i,
+   sdram_ddr2_bcr(sdram->bank[i].base,
   sdram->bank[i].size), 1);
 } else {
-sdram_set_bcr(sdram, i, 0, 0);
+sdram_ddr2_set_bcr(sdram, i, 0, 0);
 }
 }
 }
 
-static void sdram_unmap_bcr(ppc440_sdram_t *sdram)
+static void sdram_ddr2_unmap_bcr(ppc440_sdram_t *sdram)
 {
 int i;
 
 for (i = 0; i < sdram->nbanks; i++) {
 if (sdram->bank[i].size) {
-sdram_set_bcr(sdram, i, sdram->bank[i].bcr & ~1, 0);
+sdram_ddr2_set_bcr(sdram, i, sdram->bank[i].bcr & ~1, 0);
 }
 }
 }
 
-static uint32_t dcr_read_sdram(void *opaque, int dcrn)
+static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn)
 {
 ppc440_sdram_t *sdram = opaque;
 uint32_t ret = 0;
@@ -632,8 +633,8 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
 case SDRAM_R2BAS:
 case SDRAM_R3BAS:
 if (sdram->bank[dcrn - SDRAM_R0BAS].size) {
-ret = sdram_bcr(sdram->bank[dcrn - SDRAM_R0BAS].base,
-sdram->bank[dcrn - SDRAM_R0BAS].size);
+ret = sdram_ddr2_bcr(sdram->bank[dcrn - SDRAM_R0BAS].base,
+ sdram->bank[dcrn - SDRAM_R0BAS].size);
 }
 break;
 case SDRAM_CONF1HB:
@@ -674,7 +675,7 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
 return ret;
 }
 
-static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
+static void sdram_ddr2_dcr_write(void *opaque, int dcrn, uint32_t val)
 {
 ppc440_sdram_t *sdram = opaque;
 
@@ -700,12 +701,12 @@ static void dcr_write_sdram(void *opaque, int dcrn, 
uint32_t val)
 if (!(sdram->mcopt2 & BIT(27)) && (val & BIT(27))) {
 trace_ppc4xx_sdram_enable("enable");
 /* validate all RAM mappings */
-sdram_map_bcr(sdram);
+sdram_ddr2_map_bcr(sdram);
 sdram->mcopt2 |= BIT(27);
 } else if ((sdram->mcopt2 & BIT(27)) && !(val & BIT(27))) {
 trace_ppc4xx_sdram_enable("disable");
 /* invalidate all RAM mappings */
-sdram_unmap_bcr(sdram);
+sdram_ddr2_unmap_bcr(sdram);
 sdram->mcopt2 &= ~BIT(27);
 }
 break;
@@ -718,7 

Re: [PATCH v4 13/15] virtio-net: support queue reset

2022-09-13 Thread Jason Wang



在 2022/9/12 01:22, Kangjie Xu 写道:

From: Xuan Zhuo 

virtio-net and vhost-kernel implement queue reset.
Queued packets in the corresponding queue pair are flushed
or purged.

For virtio-net, userspace datapath will be disabled later in
__virtio_queue_reset(). It will set addr of vring to 0 and idx to 0.
Thus, virtio_net_receive() and virtio_net_flush_tx() will not receive
or send packets.

For vhost-net, the datapath will be disabled in vhost_net_virtqueue_reset().

Signed-off-by: Xuan Zhuo 
Signed-off-by: Kangjie Xu 



Acked-by: Jason Wang 



---
  hw/net/virtio-net.c | 18 ++
  1 file changed, 18 insertions(+)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 27b59c0ad6..d774a3e652 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -540,6 +540,23 @@ static RxFilterInfo 
*virtio_net_query_rxfilter(NetClientState *nc)
  return info;
  }
  
+static void virtio_net_queue_reset(VirtIODevice *vdev, uint32_t queue_index)

+{
+VirtIONet *n = VIRTIO_NET(vdev);
+NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(queue_index));
+
+if (!nc->peer) {
+return;
+}
+
+if (get_vhost_net(nc->peer) &&
+nc->peer->info->type == NET_CLIENT_DRIVER_TAP) {
+vhost_net_virtqueue_reset(vdev, nc, queue_index);
+}
+
+flush_or_purge_queued_packets(nc);
+}
+
  static void virtio_net_reset(VirtIODevice *vdev)
  {
  VirtIONet *n = VIRTIO_NET(vdev);
@@ -3784,6 +3801,7 @@ static void virtio_net_class_init(ObjectClass *klass, 
void *data)
  vdc->set_features = virtio_net_set_features;
  vdc->bad_features = virtio_net_bad_features;
  vdc->reset = virtio_net_reset;
+vdc->queue_reset = virtio_net_queue_reset;
  vdc->set_status = virtio_net_set_status;
  vdc->guest_notifier_mask = virtio_net_guest_notifier_mask;
  vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;





Re: [PATCH v4 11/15] vhost-net: vhost-kernel: introduce vhost_net_virtqueue_restart()

2022-09-13 Thread Jason Wang



在 2022/9/12 01:22, Kangjie Xu 写道:

Introduce vhost_net_virtqueue_restart(), which can restart the
specific virtqueue when the vhost net started running before.
If it fails to restart the virtqueue, the device will be stopped.

Here we do not reuse vhost_net_start_one() or vhost_dev_start()
because they work at queue pair level. The mem table and features
do not change, so we can call the vhost_virtqueue_start() to
restart a specific queue.

This patch only considers the case of vhost-kernel, when
NetClientDriver is NET_CLIENT_DRIVER_TAP.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
---
  hw/net/vhost_net.c  | 52 +
  include/net/vhost_net.h |  2 ++
  2 files changed, 54 insertions(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 8beecb4d22..1059aa45b4 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -556,3 +556,55 @@ void vhost_net_virtqueue_reset(VirtIODevice *vdev, 
NetClientState *nc,
   net->dev.vqs + idx,
   net->dev.vq_index + idx);
  }
+
+int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
+int vq_index)
+{
+VHostNetState *net = get_vhost_net(nc->peer);
+const VhostOps *vhost_ops = net->dev.vhost_ops;
+struct vhost_vring_file file = { };
+int idx, r;
+
+if (!net->dev.started) {
+return -ENOTSUP;
+}



-EBUSY?



+
+/* should only be called after backend is connected */
+assert(vhost_ops);
+
+idx = vhost_ops->vhost_get_vq_index(>dev, vq_index);
+
+r = vhost_virtqueue_start(>dev,
+  vdev,
+  net->dev.vqs + idx,
+  net->dev.vq_index + idx);
+if (r < 0) {
+goto err_start;
+}
+
+if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
+file.index = idx;
+file.fd = net->backend;
+r = vhost_net_set_backend(>dev, );
+if (r < 0) {
+r = -errno;
+goto err_start;
+}
+}
+
+return 0;
+
+err_start:
+error_report("Error when restarting the queue.");
+
+if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
+file.fd = -1;



Let's try reuse  VHOST_FILE_UNBIND.

Other looks good.

Thanks



+file.index = idx;
+int r = vhost_net_set_backend(>dev, );
+assert(r >= 0);
+}
+
+vhost_dev_stop(>dev, vdev);
+
+return r;
+}
diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index 85d85a4957..40b9a40074 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -50,4 +50,6 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
  
  void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,

 int vq_index);
+int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
+int vq_index);
  #endif





[PATCH v3 19/20] ppc4xx_sdram: Generalise bank setup

2022-09-13 Thread BALATON Zoltan
Currently only base and size are set on initial bank creation and bcr
value is computed on mapping the region. Set bcr at init so the bcr
encoding method becomes local to the controller model and mapping and
unmapping can operate on the bank so it can be shared between
different controller models. This patch converts the DDR2 controller.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc4xx_sdram.c | 93 ++-
 hw/ppc/trace-events   |  1 +
 2 files changed, 48 insertions(+), 46 deletions(-)

diff --git a/hw/ppc/ppc4xx_sdram.c b/hw/ppc/ppc4xx_sdram.c
index e36898a906..79a9efce4b 100644
--- a/hw/ppc/ppc4xx_sdram.c
+++ b/hw/ppc/ppc4xx_sdram.c
@@ -106,6 +106,7 @@ static void ppc4xx_sdram_banks(MemoryRegion *ram, int 
nr_banks,
 
 static void sdram_bank_map(Ppc4xxSdramBank *bank)
 {
+trace_ppc4xx_sdram_map(bank->base, bank->size);
 memory_region_init(>container, NULL, "sdram-container", bank->size);
 memory_region_add_subregion(>container, 0, >ram);
 memory_region_add_subregion(get_system_memory(), bank->base,
@@ -114,11 +115,26 @@ static void sdram_bank_map(Ppc4xxSdramBank *bank)
 
 static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
 {
+trace_ppc4xx_sdram_unmap(bank->base, bank->size);
 memory_region_del_subregion(get_system_memory(), >container);
 memory_region_del_subregion(>container, >ram);
 object_unparent(OBJECT(>container));
 }
 
+static void sdram_bank_set_bcr(Ppc4xxSdramBank *bank, uint32_t bcr,
+   hwaddr base, hwaddr size, int enabled)
+{
+if (memory_region_is_mapped(>container)) {
+sdram_bank_unmap(bank);
+}
+bank->bcr = bcr;
+bank->base = base;
+bank->size = size;
+if (enabled && (bcr & 1)) {
+sdram_bank_map(bank);
+}
+}
+
 /*/
 /* DDR SDRAM controller */
 static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size)
@@ -445,6 +461,8 @@ static void ppc4xx_sdram_ddr_class_init(ObjectClass *oc, 
void *data)
 
 /*/
 /* DDR2 SDRAM controller */
+#define SDRAM_DDR2_BCR_MASK 0xffe0ffc1
+
 enum {
 SDRAM_R0BAS = 0x40,
 SDRAM_R1BAS,
@@ -518,50 +536,6 @@ static hwaddr sdram_ddr2_size(uint32_t bcr)
 return size;
 }
 
-static void sdram_ddr2_set_bcr(Ppc4xxSdramDdr2State *sdram, int i,
-   uint32_t bcr, int enabled)
-{
-if (sdram->bank[i].bcr & 1) {
-/* First unmap RAM if enabled */
-trace_ppc4xx_sdram_unmap(sdram_ddr2_base(sdram->bank[i].bcr),
- sdram_ddr2_size(sdram->bank[i].bcr));
-sdram_bank_unmap(>bank[i]);
-}
-sdram->bank[i].bcr = bcr & 0xffe0ffc1;
-sdram->bank[i].base = sdram_ddr2_base(bcr);
-sdram->bank[i].size = sdram_ddr2_size(bcr);
-if (enabled && (bcr & 1)) {
-trace_ppc4xx_sdram_map(sdram_ddr2_base(bcr), sdram_ddr2_size(bcr));
-sdram_bank_map(>bank[i]);
-}
-}
-
-static void sdram_ddr2_map_bcr(Ppc4xxSdramDdr2State *sdram)
-{
-int i;
-
-for (i = 0; i < sdram->nbanks; i++) {
-if (sdram->bank[i].size) {
-sdram_ddr2_set_bcr(sdram, i,
-   sdram_ddr2_bcr(sdram->bank[i].base,
-  sdram->bank[i].size), 1);
-} else {
-sdram_ddr2_set_bcr(sdram, i, 0, 0);
-}
-}
-}
-
-static void sdram_ddr2_unmap_bcr(Ppc4xxSdramDdr2State *sdram)
-{
-int i;
-
-for (i = 0; i < sdram->nbanks; i++) {
-if (sdram->bank[i].size) {
-sdram_ddr2_set_bcr(sdram, i, sdram->bank[i].bcr & ~1, 0);
-}
-}
-}
-
 static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn)
 {
 Ppc4xxSdramDdr2State *s = opaque;
@@ -618,6 +592,7 @@ static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn)
 static void sdram_ddr2_dcr_write(void *opaque, int dcrn, uint32_t val)
 {
 Ppc4xxSdramDdr2State *s = opaque;
+int i;
 
 switch (dcrn) {
 case SDRAM_R0BAS:
@@ -641,12 +616,24 @@ static void sdram_ddr2_dcr_write(void *opaque, int dcrn, 
uint32_t val)
 if (!(s->mcopt2 & BIT(27)) && (val & BIT(27))) {
 trace_ppc4xx_sdram_enable("enable");
 /* validate all RAM mappings */
-sdram_ddr2_map_bcr(s);
+for (i = 0; i < s->nbanks; i++) {
+if (s->bank[i].size) {
+sdram_bank_set_bcr(>bank[i], s->bank[i].bcr,
+   s->bank[i].base, s->bank[i].size,
+   1);
+}
+}
 s->mcopt2 |= BIT(27);
 } else if ((s->mcopt2 & BIT(27)) && !(val & BIT(27))) {
 trace_ppc4xx_sdram_enable("disable");
 /* invalidate all RAM mappings */
-sdram_ddr2_unmap_bcr(s);
+for (i 

[PULL 03/12] linux-user: Add pidfd_open(), pidfd_send_signal() and pidfd_getfd() syscalls

2022-09-13 Thread Helge Deller
I noticed those were missing when running the glib2.0 testsuite.
Add the syscalls including the strace output.

Signed-off-by: Helge Deller 
---
 linux-user/strace.c| 28 
 linux-user/strace.list |  9 +
 linux-user/syscall.c   | 34 ++
 3 files changed, 71 insertions(+)

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 816e679995..5ac64df02b 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -3317,6 +3317,34 @@ print_openat(CPUArchState *cpu_env, const struct 
syscallname *name,
 }
 #endif

+#ifdef TARGET_NR_pidfd_send_signal
+static void
+print_pidfd_send_signal(CPUArchState *cpu_env, const struct syscallname *name,
+abi_long arg0, abi_long arg1, abi_long arg2,
+abi_long arg3, abi_long arg4, abi_long arg5)
+{
+void *p;
+target_siginfo_t uinfo;
+
+print_syscall_prologue(name);
+print_raw_param("%d", arg0, 0);
+print_signal(arg1, 0);
+
+p = lock_user(VERIFY_READ, arg2, sizeof(target_siginfo_t), 1);
+if (p) {
+get_target_siginfo(, p);
+print_siginfo();
+
+unlock_user(p, arg2, 0);
+} else {
+print_pointer(arg2, 1);
+}
+
+print_raw_param("%u", arg3, 0);
+print_syscall_epilogue(name);
+}
+#endif
+
 #ifdef TARGET_NR_mq_unlink
 static void
 print_mq_unlink(CPUArchState *cpu_env, const struct syscallname *name,
diff --git a/linux-user/strace.list b/linux-user/strace.list
index a78cdf3cdf..4d8b7f6a5e 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1664,6 +1664,15 @@
 #ifdef TARGET_NR_pipe2
 { TARGET_NR_pipe2, "pipe2", NULL, NULL, NULL },
 #endif
+#ifdef TARGET_NR_pidfd_open
+{ TARGET_NR_pidfd_open, "pidfd_open", "%s(%d,%u)", NULL, NULL },
+#endif
+#ifdef TARGET_NR_pidfd_send_signal
+{ TARGET_NR_pidfd_send_signal, "pidfd_send_signal", NULL, 
print_pidfd_send_signal, NULL },
+#endif
+#ifdef TARGET_NR_pidfd_getfd
+{ TARGET_NR_pidfd_getfd, "pidfd_getfd", "%s(%d,%d,%u)", NULL, NULL },
+#endif
 #ifdef TARGET_NR_atomic_cmpxchg_32
 { TARGET_NR_atomic_cmpxchg_32, "atomic_cmpxchg_32", NULL, NULL, NULL },
 #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f409121202..df018f0e32 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -346,6 +346,16 @@ _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
 _syscall6(int,sys_futex_time64,int *,uaddr,int,op,int,val,
   const struct timespec *,timeout,int *,uaddr2,int,val3)
 #endif
+#if defined(__NR_pidfd_open)
+_syscall2(int, pidfd_open, pid_t, pid, unsigned int, flags);
+#endif
+#if defined(__NR_pidfd_send_signal)
+_syscall4(int, pidfd_send_signal, int, pidfd, int, sig, siginfo_t *, info,
+ unsigned int, flags);
+#endif
+#if defined(__NR_pidfd_getfd)
+_syscall3(int, pidfd_getfd, int, pidfd, int, targetfd, unsigned int, flags);
+#endif
 #define __NR_sys_sched_getaffinity __NR_sched_getaffinity
 _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
   unsigned long *, user_mask_ptr);
@@ -8683,6 +8693,30 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int 
num, abi_long arg1,
 ret = do_open_by_handle_at(arg1, arg2, arg3);
 fd_trans_unregister(ret);
 return ret;
+#endif
+#if defined(TARGET_NR_pidfd_open)
+case TARGET_NR_pidfd_open:
+return get_errno(pidfd_open(arg1, arg2));
+#endif
+#if defined(TARGET_NR_pidfd_send_signal)
+case TARGET_NR_pidfd_send_signal:
+{
+siginfo_t uinfo;
+
+p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
+if (!p) {
+return -TARGET_EFAULT;
+}
+target_to_host_siginfo(, p);
+unlock_user(p, arg3, 0);
+ret = get_errno(pidfd_send_signal(arg1, 
target_to_host_signal(arg2),
+, arg4));
+}
+return ret;
+#endif
+#if defined(TARGET_NR_pidfd_getfd)
+case TARGET_NR_pidfd_getfd:
+return get_errno(pidfd_getfd(arg1, arg2, arg3));
 #endif
 case TARGET_NR_close:
 fd_trans_unregister(arg1);
--
2.37.2




[PULL 11/12] linux-user: Add close_range() syscall

2022-09-13 Thread Helge Deller
Signed-off-by: Helge Deller 
---
 linux-user/strace.list |  3 +++
 linux-user/syscall.c   | 12 
 2 files changed, 15 insertions(+)

diff --git a/linux-user/strace.list b/linux-user/strace.list
index 215d971b2a..ad9ef94689 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -103,6 +103,9 @@
 #ifdef TARGET_NR_close
 { TARGET_NR_close, "close" , "%s(%d)", NULL, NULL },
 #endif
+#ifdef TARGET_NR_close_range
+{ TARGET_NR_close_range, "close_range" , "%s(%d,%d,%d)", NULL, NULL },
+#endif
 #ifdef TARGET_NR_connect
 { TARGET_NR_connect, "connect" , "%s(%d,%#x,%d)", NULL, NULL },
 #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index df018f0e32..e63025a5e3 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8721,6 +8721,18 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int 
num, abi_long arg1,
 case TARGET_NR_close:
 fd_trans_unregister(arg1);
 return get_errno(close(arg1));
+#ifdef TARGET_NR_close_range
+case TARGET_NR_close_range:
+{
+abi_long fd;
+abi_long maxfd = (arg2 == (abi_long)-1) ? target_fd_max : arg2;
+
+for (fd = arg1; fd <= maxfd; fd++) {
+fd_trans_unregister(fd);
+}
+}
+return get_errno(close_range(arg1, arg2, arg3));
+#endif

 case TARGET_NR_brk:
 return do_brk(arg1);
--
2.37.2




[PATCH v3 04/20] ppc4xx: Use Ppc4xxSdramBank in ppc4xx_sdram_banks()

2022-09-13 Thread BALATON Zoltan
Change ppc4xx_sdram_banks() to take one Ppc4xxSdramBank array instead
of the separate arrays and adjust ppc4xx_sdram_init() and
ppc440_sdram_init() accordingly as well as machines using these.

Signed-off-by: BALATON Zoltan 
---
v2: Use pointer for ram_banks in the prototype of the init funcs as
an array of struct seems to confuse gcc 12.2.1 and provoke a warning

 hw/ppc/ppc405.h |  4 +---
 hw/ppc/ppc405_uc.c  | 10 +-
 hw/ppc/ppc440.h |  5 ++---
 hw/ppc/ppc440_bamboo.c  | 15 ++-
 hw/ppc/ppc440_uc.c  |  9 -
 hw/ppc/ppc4xx_devs.c| 21 +
 hw/ppc/sam460ex.c   | 15 +--
 include/hw/ppc/ppc4xx.h |  9 +++--
 8 files changed, 35 insertions(+), 53 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 756865621b..ca0972b88b 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -167,9 +167,7 @@ struct Ppc405SoCState {
 DeviceState parent_obj;
 
 /* Public */
-MemoryRegion ram_banks[2];
-hwaddr ram_bases[2], ram_sizes[2];
-
+Ppc4xxSdramBank ram_banks[2];
 MemoryRegion *dram_mr;
 hwaddr ram_size;
 
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 1e02347e57..bcbf35bc14 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1074,14 +1074,14 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 
 /* SDRAM controller */
 /* XXX 405EP has no ECC interrupt */
-s->ram_bases[0] = 0;
-s->ram_sizes[0] = s->ram_size;
-memory_region_init_alias(>ram_banks[0], OBJECT(s),
+s->ram_banks[0].base = 0;
+s->ram_banks[0].size = s->ram_size;
+memory_region_init_alias(>ram_banks[0].ram, OBJECT(s),
  "ppc405.sdram0", s->dram_mr,
- s->ram_bases[0], s->ram_sizes[0]);
+ s->ram_banks[0].base, s->ram_banks[0].size);
 
 ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(>uic), 17), 1,
-  s->ram_banks, s->ram_bases, s->ram_sizes);
+  s->ram_banks);
 
 /* External bus controller */
 if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>ebc), >cpu, errp)) {
diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h
index 7cef936125..e6c905b7d6 100644
--- a/hw/ppc/ppc440.h
+++ b/hw/ppc/ppc440.h
@@ -11,14 +11,13 @@
 #ifndef PPC440_H
 #define PPC440_H
 
-#include "hw/ppc/ppc.h"
+#include "hw/ppc/ppc4xx.h"
 
 void ppc4xx_l2sram_init(CPUPPCState *env);
 void ppc4xx_cpr_init(CPUPPCState *env);
 void ppc4xx_sdr_init(CPUPPCState *env);
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   MemoryRegion *ram_memories,
-   hwaddr *ram_bases, hwaddr *ram_sizes,
+   Ppc4xxSdramBank *ram_banks,
int do_init);
 void ppc4xx_ahb_init(CPUPPCState *env);
 void ppc4xx_dma_init(CPUPPCState *env, int dcr_base);
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index e3412c4fcd..2aac8a3fe9 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -168,9 +168,8 @@ static void bamboo_init(MachineState *machine)
 unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *isa = g_new(MemoryRegion, 1);
-MemoryRegion *ram_memories = g_new(MemoryRegion, PPC440EP_SDRAM_NR_BANKS);
-hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS] = {0};
-hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS] = {0};
+Ppc4xxSdramBank *ram_banks = g_new0(Ppc4xxSdramBank,
+PPC440EP_SDRAM_NR_BANKS);
 PCIBus *pcibus;
 PowerPCCPU *cpu;
 CPUPPCState *env;
@@ -205,13 +204,11 @@ static void bamboo_init(MachineState *machine)
qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
-ppc4xx_sdram_banks(machine->ram, PPC440EP_SDRAM_NR_BANKS, ram_memories,
-   ram_bases, ram_sizes, ppc440ep_sdram_bank_sizes);
+ppc4xx_sdram_banks(machine->ram, PPC440EP_SDRAM_NR_BANKS, ram_banks,
+   ppc440ep_sdram_bank_sizes);
 /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
-ppc4xx_sdram_init(env,
-  qdev_get_gpio_in(uicdev, 14),
-  PPC440EP_SDRAM_NR_BANKS, ram_memories,
-  ram_bases, ram_sizes);
+ppc4xx_sdram_init(env, qdev_get_gpio_in(uicdev, 14),
+  PPC440EP_SDRAM_NR_BANKS, ram_banks);
 /* Enable SDRAM memory regions, this should be done by the firmware */
 if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
 ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 6ab0ad7985..5db59d1190 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -690,8 +690,7 @@ static void sdram_reset(void *opaque)
 }
 
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   MemoryRegion 

[PATCH v3 17/20] ppc4xx_sdram: Use hwaddr for memory bank size

2022-09-13 Thread BALATON Zoltan
This resolves the target_ulong dependency that's clearly wrong and was
also noted in a fixme comment.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/ppc/ppc4xx_sdram.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/hw/ppc/ppc4xx_sdram.c b/hw/ppc/ppc4xx_sdram.c
index bc28d69a26..242e2f4c6e 100644
--- a/hw/ppc/ppc4xx_sdram.c
+++ b/hw/ppc/ppc4xx_sdram.c
@@ -34,7 +34,6 @@
 #include "qapi/error.h"
 #include "qemu/log.h"
 #include "exec/address-spaces.h" /* get_system_memory() */
-#include "exec/cpu-defs.h" /* target_ulong */
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
 #include "qapi/error.h"
@@ -122,11 +121,6 @@ static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
 
 /*/
 /* DDR SDRAM controller */
-/*
- * XXX: TOFIX: some patches have made this code become inconsistent:
- *  there are type inconsistencies, mixing hwaddr, target_ulong
- *  and uint32_t
- */
 static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size)
 {
 uint32_t bcr;
@@ -170,9 +164,9 @@ static inline hwaddr sdram_ddr_base(uint32_t bcr)
 return bcr & 0xFF80;
 }
 
-static target_ulong sdram_ddr_size(uint32_t bcr)
+static hwaddr sdram_ddr_size(uint32_t bcr)
 {
-target_ulong size;
+hwaddr size;
 int sh;
 
 sh = (bcr >> 17) & 0x7;
@@ -513,9 +507,9 @@ static inline hwaddr sdram_ddr2_base(uint32_t bcr)
 return (bcr & 0xffe0) << 2;
 }
 
-static uint64_t sdram_ddr2_size(uint32_t bcr)
+static hwaddr sdram_ddr2_size(uint32_t bcr)
 {
-uint64_t size;
+hwaddr size;
 int sh;
 
 sh = 1024 - ((bcr >> 6) & 0x3ff);
-- 
2.30.4




Re: [PATCH 2/3] vdpa: load vlan configuration at NIC startup

2022-09-13 Thread Jason Wang
On Fri, Sep 9, 2022 at 4:02 PM Eugenio Perez Martin  wrote:
>
> On Fri, Sep 9, 2022 at 8:40 AM Jason Wang  wrote:
> >
> > On Fri, Sep 9, 2022 at 2:38 PM Jason Wang  wrote:
> > >
> > > On Wed, Sep 7, 2022 at 12:36 AM Eugenio Pérez  wrote:
> > > >
> > > > To have enabled vlans at device startup may happen in the destination of
> > > > a live migration, so this configuration must be restored.
> > > >
> > > > At this moment the code is not accessible, since SVQ refuses to start if
> > > > vlan feature is exposed by the device.
> > > >
> > > > Signed-off-by: Eugenio Pérez 
> > > > ---
> > > >  net/vhost-vdpa.c | 46 --
> > > >  1 file changed, 44 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
> > > > index 4bc3fd01a8..ecbfd08eb9 100644
> > > > --- a/net/vhost-vdpa.c
> > > > +++ b/net/vhost-vdpa.c
> > > > @@ -100,6 +100,8 @@ static const uint64_t vdpa_svq_device_features =
> > > >  BIT_ULL(VIRTIO_NET_F_RSC_EXT) |
> > > >  BIT_ULL(VIRTIO_NET_F_STANDBY);
> > > >
> > > > +#define MAX_VLAN(1 << 12)   /* Per 802.1Q definition */
> > > > +
> > > >  VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc)
> > > >  {
> > > >  VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> > > > @@ -423,6 +425,47 @@ static int vhost_vdpa_net_load_mq(VhostVDPAState 
> > > > *s,
> > > >  return *s->status != VIRTIO_NET_OK;
> > > >  }
> > > >
> > > > +static int vhost_vdpa_net_load_single_vlan(VhostVDPAState *s,
> > > > +   const VirtIONet *n,
> > > > +   uint16_t vid)
> > > > +{
> > > > +ssize_t dev_written = vhost_vdpa_net_load_cmd(s, 
> > > > VIRTIO_NET_CTRL_VLAN,
> > > > +  
> > > > VIRTIO_NET_CTRL_VLAN_ADD,
> > > > +  , sizeof(vid));
> > > > +if (unlikely(dev_written < 0)) {
> > > > +return dev_written;
> > > > +}
> > > > +
> > > > +if (unlikely(*s->status != VIRTIO_NET_OK)) {
> > > > +return -EINVAL;
> > > > +}
> > > > +
> > > > +return 0;
> > > > +}
> > > > +
> > > > +static int vhost_vdpa_net_load_vlan(VhostVDPAState *s,
> > > > +const VirtIONet *n)
> > > > +{
> > > > +uint64_t features = n->parent_obj.guest_features;
> > > > +
> > > > +if (!(features & BIT_ULL(VIRTIO_NET_F_CTRL_VLAN))) {
> > > > +return 0;
> > > > +}
> > > > +
> > > > +for (int i = 0; i < MAX_VLAN >> 5; i++) {
> > > > +for (int j = 0; n->vlans[i] && j <= 0x1f; j++) {
> > > > +if (n->vlans[i] & (1U << j)) {
> > > > +int r = vhost_vdpa_net_load_single_vlan(s, n, (i << 5) 
> > > > + j);
> > >
> > > This seems to cause a lot of latency if the driver has a lot of vlans.
> > >
> > > I wonder if it's simply to let all vlan traffic go by disabling
> > > CTRL_VLAN feature at vDPA layer.
> >
>
> The guest will not be able to recover that vlan configuration.

Spec said it's best effort and we actually don't do this for
vhost-net/user for years and manage to survive.

>
> > Another idea is to extend the spec to allow us to accept a bitmap of
> > the vlan ids via a single command, then we will be fine.
> >
>
> I'm not sure if adding more ways to configure something is the answer,
> but I'd be ok to implement it.
>
> Another idea is to allow the sending of many CVQ commands in parallel.
> It shouldn't be very hard to achieve using exposed buffers as ring
> buffers, and it will short down the start of the devices with many
> features.

In the extreme case, what if guests decide to filter all of the vlans?
It means we need MAX_VLAN commands which may exceeds the size of the
control virtqueue.

Thanks

>
> Thanks!
>
> > Thanks
> >
> > >
> > > Thanks
> > >
> > > > +if (unlikely(r != 0)) {
> > > > +return r;
> > > > +}
> > > > +}
> > > > +}
> > > > +}
> > > > +
> > > > +return 0;
> > > > +}
> > > > +
> > > >  static int vhost_vdpa_net_load(NetClientState *nc)
> > > >  {
> > > >  VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> > > > @@ -445,8 +488,7 @@ static int vhost_vdpa_net_load(NetClientState *nc)
> > > >  if (unlikely(r)) {
> > > >  return r;
> > > >  }
> > > > -
> > > > -return 0;
> > > > +return vhost_vdpa_net_load_vlan(s, n);
> > > >  }
> > > >
> > > >  static NetClientInfo net_vhost_vdpa_cvq_info = {
> > > > --
> > > > 2.31.1
> > > >
> >
>




Re: [PATCH v4 14/15] virtio-net: support queue_enable

2022-09-13 Thread Jason Wang



在 2022/9/12 01:22, Kangjie Xu 写道:

Support queue_enable in vhost-kernel scenario. It can be called when
a vq reset operation has been performed and the vq is restared.

It should be noted that we can restart the vq when the vhost has
already started. When launching a new vhost device, the vhost is not
started and all vqs are not initalized until VIRTIO_PCI_COMMON_STATUS
is written. Thus, we should use vhost_started to differentiate the
two cases: vq reset and device start.

Currently it only supports vhost-kernel.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 



Acked-by: Jason Wang 



---
  hw/net/virtio-net.c | 21 +
  1 file changed, 21 insertions(+)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index d774a3e652..7817206596 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -557,6 +557,26 @@ static void virtio_net_queue_reset(VirtIODevice *vdev, 
uint32_t queue_index)
  flush_or_purge_queued_packets(nc);
  }
  
+static void virtio_net_queue_enable(VirtIODevice *vdev, uint32_t queue_index)

+{
+VirtIONet *n = VIRTIO_NET(vdev);
+NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(queue_index));
+int r;
+
+if (!nc->peer || !vdev->vhost_started) {
+return;
+}
+
+if (get_vhost_net(nc->peer) &&
+nc->peer->info->type == NET_CLIENT_DRIVER_TAP) {
+r = vhost_net_virtqueue_restart(vdev, nc, queue_index);
+if (r < 0) {
+error_report("unable to restart vhost net virtqueue: %d, "
+"when resetting the queue", queue_index);
+}
+}
+}
+
  static void virtio_net_reset(VirtIODevice *vdev)
  {
  VirtIONet *n = VIRTIO_NET(vdev);
@@ -3802,6 +3822,7 @@ static void virtio_net_class_init(ObjectClass *klass, 
void *data)
  vdc->bad_features = virtio_net_bad_features;
  vdc->reset = virtio_net_reset;
  vdc->queue_reset = virtio_net_queue_reset;
+vdc->queue_enable = virtio_net_queue_enable;
  vdc->set_status = virtio_net_set_status;
  vdc->guest_notifier_mask = virtio_net_guest_notifier_mask;
  vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;





Re: [PATCH v2 3/6] vhost-net: vhost-user: update vhost_net_virtqueue_reset()

2022-09-13 Thread Jason Wang



在 2022/9/12 11:10, Kangjie Xu 写道:

Update vhost_net_virtqueue_reset() for vhost-user scenario.

In order to reuse some functions, we process the idx for
vhost-user scenario because vhost_get_vq_index behave
differently for vhost-user.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
---
  hw/net/vhost_net.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index ea896ea75b..25e5665489 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -545,6 +545,9 @@ void vhost_net_virtqueue_reset(VirtIODevice *vdev, 
NetClientState *nc,
  assert(vhost_ops);
  
  idx = vhost_ops->vhost_get_vq_index(>dev, vq_index);

+if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
+idx -= net->dev.vq_index;
+}



This looks tricky. Any reason we can't simply use vq_index for both 
vhost-user and vhost-net?


Thanks


  
  if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {

  file.index = idx;





[PATCH v3 10/20] ppc440_sdram: Implement enable bit in the DDR2 SDRAM

2022-09-13 Thread BALATON Zoltan
To allow removing the do_init hack we need to improve the DDR2 SDRAM
controller model to handle the enable/disable bit that it ignored so
far.

Signed-off-by: BALATON Zoltan 
---
v2: replace 0x0800 with BIT(27)

 hw/ppc/ppc440_uc.c | 34 --
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 01184e717b..3c442eaecc 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -23,6 +23,7 @@
 #include "sysemu/reset.h"
 #include "ppc440.h"
 #include "qom/object.h"
+#include "trace.h"
 
 /*/
 /* L2 Cache as SRAM */
@@ -484,6 +485,7 @@ void ppc4xx_sdr_init(CPUPPCState *env)
 /* SDRAM controller */
 typedef struct ppc440_sdram_t {
 uint32_t addr;
+uint32_t mcopt2;
 int nbanks;
 Ppc4xxSdramBank bank[4];
 } ppc440_sdram_t;
@@ -581,12 +583,15 @@ static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
 {
 if (sdram->bank[i].bcr & 1) {
 /* First unmap RAM if enabled */
+trace_ppc4xx_sdram_unmap(sdram_base(sdram->bank[i].bcr),
+ sdram_size(sdram->bank[i].bcr));
 sdram_bank_unmap(>bank[i]);
 }
 sdram->bank[i].bcr = bcr & 0xffe0ffc1;
 sdram->bank[i].base = sdram_base(bcr);
 sdram->bank[i].size = sdram_size(bcr);
 if (enabled && (bcr & 1)) {
+trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr));
 sdram_bank_map(>bank[i]);
 }
 }
@@ -596,7 +601,7 @@ static void sdram_map_bcr(ppc440_sdram_t *sdram)
 int i;
 
 for (i = 0; i < sdram->nbanks; i++) {
-if (sdram->bank[i].size != 0) {
+if (sdram->bank[i].size) {
 sdram_set_bcr(sdram, i, sdram_bcr(sdram->bank[i].base,
   sdram->bank[i].size), 1);
 } else {
@@ -605,6 +610,17 @@ static void sdram_map_bcr(ppc440_sdram_t *sdram)
 }
 }
 
+static void sdram_unmap_bcr(ppc440_sdram_t *sdram)
+{
+int i;
+
+for (i = 0; i < sdram->nbanks; i++) {
+if (sdram->bank[i].size) {
+sdram_set_bcr(sdram, i, sdram->bank[i].bcr & ~1, 0);
+}
+}
+}
+
 static uint32_t dcr_read_sdram(void *opaque, int dcrn)
 {
 ppc440_sdram_t *sdram = opaque;
@@ -636,7 +652,7 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
 ret = 0x8000;
 break;
 case 0x21: /* SDRAM_MCOPT2 */
-ret = 0x0800;
+ret = sdram->mcopt2;
 break;
 case 0x40: /* SDRAM_MB0CF */
 ret = 0x8001;
@@ -680,6 +696,19 @@ static void dcr_write_sdram(void *opaque, int dcrn, 
uint32_t val)
 switch (sdram->addr) {
 case 0x00: /* B0CR */
 break;
+case 0x21: /* SDRAM_MCOPT2 */
+if (!(sdram->mcopt2 & BIT(27)) && (val & BIT(27))) {
+trace_ppc4xx_sdram_enable("enable");
+/* validate all RAM mappings */
+sdram_map_bcr(sdram);
+sdram->mcopt2 |= BIT(27);
+} else if ((sdram->mcopt2 & BIT(27)) && !(val & BIT(27))) {
+trace_ppc4xx_sdram_enable("disable");
+/* invalidate all RAM mappings */
+sdram_unmap_bcr(sdram);
+sdram->mcopt2 &= ~BIT(27);
+}
+break;
 default:
 break;
 }
@@ -694,6 +723,7 @@ static void sdram_reset(void *opaque)
 ppc440_sdram_t *sdram = opaque;
 
 sdram->addr = 0;
+sdram->mcopt2 = BIT(27);
 }
 
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-- 
2.30.4




[PATCH v3 05/20] ppc440_bamboo: Add missing 4 MiB valid memory size

2022-09-13 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
Reviewed-by: Cédric Le Goater 
---
 hw/ppc/ppc440_bamboo.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 2aac8a3fe9..2bd5e41140 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -51,7 +51,7 @@
 #define PPC440EP_SDRAM_NR_BANKS 4
 
 static const ram_addr_t ppc440ep_sdram_bank_sizes[] = {
-256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 0
+256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 4 * MiB, 0
 };
 
 static hwaddr entry;
-- 
2.30.4




Re: [PATCH v4 10/15] vhost-net: vhost-kernel: introduce vhost_net_virtqueue_reset()

2022-09-13 Thread Jason Wang
On Mon, Sep 12, 2022 at 1:22 AM Kangjie Xu  wrote:
>
> Introduce vhost_virtqueue_reset(), which can reset the specific
> virtqueue in the device. Then it will unmap vrings and the desc
> of the virtqueue.
>
> Here we do not reuse the vhost_net_stop_one() or vhost_dev_stop(),
> because they work at queue pair level. We do not use
> vhost_virtqueue_stop() because it may stop the device in the
> backend.
>
> This patch only considers the case of vhost-kernel, when
> NetClientDriver is NET_CLIENT_DRIVER_TAP.
>
> Furthermore, we do not need net->nc->info->poll() because
> it enables userspace datapath and we want to stop all
> datapaths for this reset virtqueue here.
>
> Signed-off-by: Kangjie Xu 
> Signed-off-by: Xuan Zhuo 

Acked-by: Jason Wang 

> ---
>  hw/net/vhost_net.c  | 25 +
>  include/net/vhost_net.h |  2 ++
>  2 files changed, 27 insertions(+)
>
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index d28f8b974b..8beecb4d22 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -531,3 +531,28 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t 
> mtu)
>
>  return vhost_ops->vhost_net_set_mtu(>dev, mtu);
>  }
> +
> +void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
> +   int vq_index)
> +{
> +VHostNetState *net = get_vhost_net(nc->peer);
> +const VhostOps *vhost_ops = net->dev.vhost_ops;
> +struct vhost_vring_file file = { .fd = -1 };
> +int idx;
> +
> +/* should only be called after backend is connected */
> +assert(vhost_ops);
> +
> +idx = vhost_ops->vhost_get_vq_index(>dev, vq_index);
> +
> +if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
> +file.index = idx;
> +int r = vhost_net_set_backend(>dev, );
> +assert(r >= 0);
> +}
> +
> +vhost_virtqueue_stop(>dev,
> + vdev,
> + net->dev.vqs + idx,
> + net->dev.vq_index + idx);
> +}
> diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
> index 387e913e4e..85d85a4957 100644
> --- a/include/net/vhost_net.h
> +++ b/include/net/vhost_net.h
> @@ -48,4 +48,6 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net);
>
>  int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
>
> +void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
> +   int vq_index);
>  #endif
> --
> 2.32.0
>




[PATCH v3 06/20] ppc4xx_sdram: Move size check to ppc4xx_sdram_init()

2022-09-13 Thread BALATON Zoltan
Instead of checking if memory size is valid in board code move this
check to ppc4xx_sdram_init() as this is a restriction imposed by the
SDRAM controller.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc405.h |  2 --
 hw/ppc/ppc405_boards.c  | 10 --
 hw/ppc/ppc405_uc.c  | 11 ++-
 hw/ppc/ppc440_bamboo.c  | 10 +-
 hw/ppc/ppc4xx_devs.c| 14 ++
 include/hw/ppc/ppc4xx.h |  2 +-
 6 files changed, 10 insertions(+), 39 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index ca0972b88b..ad54dff542 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -167,9 +167,7 @@ struct Ppc405SoCState {
 DeviceState parent_obj;
 
 /* Public */
-Ppc4xxSdramBank ram_banks[2];
 MemoryRegion *dram_mr;
-hwaddr ram_size;
 
 PowerPCCPU cpu;
 PPCUIC uic;
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index bf02a71c6d..cdd4e0cb4c 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -271,22 +271,12 @@ static void boot_from_kernel(MachineState *machine, 
PowerPCCPU *cpu)
 static void ppc405_init(MachineState *machine)
 {
 Ppc405MachineState *ppc405 = PPC405_MACHINE(machine);
-MachineClass *mc = MACHINE_GET_CLASS(machine);
 const char *kernel_filename = machine->kernel_filename;
 MemoryRegion *sysmem = get_system_memory();
 CPUPPCState *env;
 
-if (machine->ram_size != mc->default_ram_size) {
-char *sz = size_to_str(mc->default_ram_size);
-error_report("Invalid RAM size, should be %s", sz);
-g_free(sz);
-exit(EXIT_FAILURE);
-}
-
 object_initialize_child(OBJECT(machine), "soc", >soc,
 TYPE_PPC405_SOC);
-object_property_set_uint(OBJECT(>soc), "ram-size",
- machine->ram_size, _fatal);
 object_property_set_link(OBJECT(>soc), "dram",
  OBJECT(machine->ram), _abort);
 object_property_set_uint(OBJECT(>soc), "sys-clk", ,
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index bcbf35bc14..e1c7188e61 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1073,15 +1073,9 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
-/* XXX 405EP has no ECC interrupt */
-s->ram_banks[0].base = 0;
-s->ram_banks[0].size = s->ram_size;
-memory_region_init_alias(>ram_banks[0].ram, OBJECT(s),
- "ppc405.sdram0", s->dram_mr,
- s->ram_banks[0].base, s->ram_banks[0].size);
-
+/* XXX 405EP has no ECC interrupt */
 ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(>uic), 17), 1,
-  s->ram_banks);
+  s->dram_mr);
 
 /* External bus controller */
 if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>ebc), >cpu, errp)) {
@@ -1159,7 +1153,6 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 static Property ppc405_soc_properties[] = {
 DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION,
  MemoryRegion *),
-DEFINE_PROP_UINT64("ram-size", Ppc405SoCState, ram_size, 0),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 2bd5e41140..9b456f1819 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -50,10 +50,6 @@
 
 #define PPC440EP_SDRAM_NR_BANKS 4
 
-static const ram_addr_t ppc440ep_sdram_bank_sizes[] = {
-256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 4 * MiB, 0
-};
-
 static hwaddr entry;
 
 static int bamboo_load_device_tree(hwaddr addr,
@@ -168,8 +164,6 @@ static void bamboo_init(MachineState *machine)
 unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *isa = g_new(MemoryRegion, 1);
-Ppc4xxSdramBank *ram_banks = g_new0(Ppc4xxSdramBank,
-PPC440EP_SDRAM_NR_BANKS);
 PCIBus *pcibus;
 PowerPCCPU *cpu;
 CPUPPCState *env;
@@ -204,11 +198,9 @@ static void bamboo_init(MachineState *machine)
qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
-ppc4xx_sdram_banks(machine->ram, PPC440EP_SDRAM_NR_BANKS, ram_banks,
-   ppc440ep_sdram_bank_sizes);
 /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
 ppc4xx_sdram_init(env, qdev_get_gpio_in(uicdev, 14),
-  PPC440EP_SDRAM_NR_BANKS, ram_banks);
+  PPC440EP_SDRAM_NR_BANKS, machine->ram);
 /* Enable SDRAM memory regions, this should be done by the firmware */
 if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
 ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 7bdcbd6fac..eb3aa97b16 100644
--- 

[PATCH v3 11/20] ppc440_sdram: Get rid of the init RAM hack

2022-09-13 Thread BALATON Zoltan
Remove the do_init parameter of ppc440_sdram_init and enable SDRAM
controller from the board via DCR access instead. Firmware does this
so it may not be needed when booting firmware only with -kernel but we
enable it unconditionally to preserve previous behaviour.

Signed-off-by: BALATON Zoltan 
---
v2: replace 0x0800 with BIT(27)

 hw/ppc/ppc440.h| 3 +--
 hw/ppc/ppc440_uc.c | 8 ++--
 hw/ppc/sam460ex.c  | 8 +++-
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h
index e6c905b7d6..01d76b8000 100644
--- a/hw/ppc/ppc440.h
+++ b/hw/ppc/ppc440.h
@@ -17,8 +17,7 @@ void ppc4xx_l2sram_init(CPUPPCState *env);
 void ppc4xx_cpr_init(CPUPPCState *env);
 void ppc4xx_sdr_init(CPUPPCState *env);
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   Ppc4xxSdramBank *ram_banks,
-   int do_init);
+   Ppc4xxSdramBank *ram_banks);
 void ppc4xx_ahb_init(CPUPPCState *env);
 void ppc4xx_dma_init(CPUPPCState *env, int dcr_base);
 void ppc460ex_pcie_init(CPUPPCState *env);
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 3c442eaecc..b3f56c49b5 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -723,12 +723,11 @@ static void sdram_reset(void *opaque)
 ppc440_sdram_t *sdram = opaque;
 
 sdram->addr = 0;
-sdram->mcopt2 = BIT(27);
+sdram->mcopt2 = 0;
 }
 
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   Ppc4xxSdramBank *ram_banks,
-   int do_init)
+   Ppc4xxSdramBank *ram_banks)
 {
 ppc440_sdram_t *sdram;
 int i;
@@ -745,9 +744,6 @@ void ppc440_sdram_init(CPUPPCState *env, int nbanks,
  sdram, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM0_CFGDATA,
  sdram, _read_sdram, _write_sdram);
-if (do_init) {
-sdram_map_bcr(sdram);
-}
 
 ppc_dcr_register(env, SDRAM_R0BAS,
  sdram, _read_sdram, _write_sdram);
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index f4c2a693fb..dac329d482 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -345,7 +345,13 @@ static void sam460ex_init(MachineState *machine)
 ppc4xx_sdram_banks(machine->ram, 1, ram_banks, ppc460ex_sdram_bank_sizes);
 
 /* FIXME: does 460EX have ECC interrupts? */
-ppc440_sdram_init(env, 1, ram_banks, 1);
+ppc440_sdram_init(env, 1, ram_banks);
+/* Enable SDRAM memory regions as we may boot without firmware */
+if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x21) ||
+ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x0800)) {
+error_report("Couldn't enable memory regions");
+exit(1);
+}
 
 /* IIC controllers and devices */
 dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700,
-- 
2.30.4




[PATCH v3 12/20] ppc440_sdram: Rename local variable for readibility

2022-09-13 Thread BALATON Zoltan
Rename local sdram variable in ppc440_sdram_init to s for readibility.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc440_uc.c | 36 ++--
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index b3f56c49b5..d8a7947196 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -729,40 +729,40 @@ static void sdram_reset(void *opaque)
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
Ppc4xxSdramBank *ram_banks)
 {
-ppc440_sdram_t *sdram;
+ppc440_sdram_t *s;
 int i;
 
-sdram = g_malloc0(sizeof(*sdram));
-sdram->nbanks = nbanks;
+s = g_malloc0(sizeof(*s));
+s->nbanks = nbanks;
 for (i = 0; i < nbanks; i++) {
-sdram->bank[i].ram = ram_banks[i].ram;
-sdram->bank[i].base = ram_banks[i].base;
-sdram->bank[i].size = ram_banks[i].size;
+s->bank[i].ram = ram_banks[i].ram;
+s->bank[i].base = ram_banks[i].base;
+s->bank[i].size = ram_banks[i].size;
 }
-qemu_register_reset(_reset, sdram);
+qemu_register_reset(_reset, s);
 ppc_dcr_register(env, SDRAM0_CFGADDR,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM0_CFGDATA,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 
 ppc_dcr_register(env, SDRAM_R0BAS,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_R1BAS,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_R2BAS,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_R3BAS,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_CONF1HB,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_PLBADDULL,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_CONF1LL,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_CONFPATHB,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_PLBADDUHB,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 }
 
 /*/
-- 
2.30.4




[PATCH v3 08/20] ppc4xx_sdram: Drop extra zeros for readability

2022-09-13 Thread BALATON Zoltan
Constants that are written zero padded for no good reason are hard to
read, it's easier to see what is meant if it's just 0 or 1 instead.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc4xx_devs.c | 40 
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 375834a52b..bfe7b2d3a6 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -49,31 +49,31 @@ static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr 
ram_size)
 
 switch (ram_size) {
 case 4 * MiB:
-bcr = 0x;
+bcr = 0;
 break;
 case 8 * MiB:
-bcr = 0x0002;
+bcr = 0x2;
 break;
 case 16 * MiB:
-bcr = 0x0004;
+bcr = 0x4;
 break;
 case 32 * MiB:
-bcr = 0x0006;
+bcr = 0x6;
 break;
 case 64 * MiB:
-bcr = 0x0008;
+bcr = 0x8;
 break;
 case 128 * MiB:
-bcr = 0x000A;
+bcr = 0xA;
 break;
 case 256 * MiB:
-bcr = 0x000C;
+bcr = 0xC;
 break;
 default:
 qemu_log_mask(LOG_GUEST_ERROR,
   "%s: invalid RAM size 0x%" HWADDR_PRIx "\n", __func__,
   ram_size);
-return 0x;
+return 0;
 }
 bcr |= ram_base & 0xFF80;
 bcr |= 1;
@@ -104,7 +104,7 @@ static target_ulong sdram_size(uint32_t bcr)
 static void sdram_set_bcr(Ppc4xxSdramDdrState *sdram, int i,
   uint32_t bcr, int enabled)
 {
-if (sdram->bank[i].bcr & 0x0001) {
+if (sdram->bank[i].bcr & 1) {
 /* Unmap RAM */
 trace_ppc4xx_sdram_unmap(sdram_base(sdram->bank[i].bcr),
  sdram_size(sdram->bank[i].bcr));
@@ -115,7 +115,7 @@ static void sdram_set_bcr(Ppc4xxSdramDdrState *sdram, int i,
 object_unparent(OBJECT(>bank[i].container));
 }
 sdram->bank[i].bcr = bcr & 0xFFDEE001;
-if (enabled && (bcr & 0x0001)) {
+if (enabled && (bcr & 1)) {
 trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr));
 memory_region_init(>bank[i].container, NULL, "sdram-container",
sdram_size(bcr));
@@ -136,7 +136,7 @@ static void sdram_map_bcr(Ppc4xxSdramDdrState *sdram)
 sdram_set_bcr(sdram, i, sdram_ddr_bcr(sdram->bank[i].base,
   sdram->bank[i].size), 1);
 } else {
-sdram_set_bcr(sdram, i, 0x, 0);
+sdram_set_bcr(sdram, i, 0, 0);
 }
 }
 }
@@ -213,7 +213,7 @@ static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
 break;
 default:
 /* Avoid gcc warning */
-ret = 0x;
+ret = 0;
 break;
 }
 
@@ -306,18 +306,18 @@ static void ppc4xx_sdram_ddr_reset(DeviceState *dev)
 {
 Ppc4xxSdramDdrState *sdram = PPC4xx_SDRAM_DDR(dev);
 
-sdram->addr = 0x;
-sdram->bear = 0x;
-sdram->besr0 = 0x; /* No error */
-sdram->besr1 = 0x; /* No error */
-sdram->cfg = 0x;
-sdram->ecccfg = 0x; /* No ECC */
-sdram->eccesr = 0x; /* No error */
+sdram->addr = 0;
+sdram->bear = 0;
+sdram->besr0 = 0; /* No error */
+sdram->besr1 = 0; /* No error */
+sdram->cfg = 0;
+sdram->ecccfg = 0; /* No ECC */
+sdram->eccesr = 0; /* No error */
 sdram->pmit = 0x07C0;
 sdram->rtr = 0x05F0;
 sdram->tr = 0x00854009;
 /* We pre-initialize RAM banks */
-sdram->status = 0x;
+sdram->status = 0;
 sdram->cfg = 0x0080;
 }
 
-- 
2.30.4




[PATCH v3 20/20] ppc4xx_sdram: Convert DDR SDRAM controller to new bank handling

2022-09-13 Thread BALATON Zoltan
Use the generic bank handling introduced in previous patch in the DDR
SDRAM controller too. This also fixes previously broken region unmap
due to sdram_ddr_unmap_bcr() ignoring container region so it crashed
with an assert when the guest tried to disable the controller.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc4xx_sdram.c | 98 ---
 1 file changed, 37 insertions(+), 61 deletions(-)

diff --git a/hw/ppc/ppc4xx_sdram.c b/hw/ppc/ppc4xx_sdram.c
index 79a9efce4b..c731012940 100644
--- a/hw/ppc/ppc4xx_sdram.c
+++ b/hw/ppc/ppc4xx_sdram.c
@@ -137,6 +137,8 @@ static void sdram_bank_set_bcr(Ppc4xxSdramBank *bank, 
uint32_t bcr,
 
 /*/
 /* DDR SDRAM controller */
+#define SDRAM_DDR_BCR_MASK 0xFFDEE001
+
 static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size)
 {
 uint32_t bcr;
@@ -195,58 +197,6 @@ static hwaddr sdram_ddr_size(uint32_t bcr)
 return size;
 }
 
-static void sdram_ddr_set_bcr(Ppc4xxSdramDdrState *sdram, int i,
-  uint32_t bcr, int enabled)
-{
-if (sdram->bank[i].bcr & 1) {
-/* Unmap RAM */
-trace_ppc4xx_sdram_unmap(sdram_ddr_base(sdram->bank[i].bcr),
- sdram_ddr_size(sdram->bank[i].bcr));
-memory_region_del_subregion(get_system_memory(),
->bank[i].container);
-memory_region_del_subregion(>bank[i].container,
->bank[i].ram);
-object_unparent(OBJECT(>bank[i].container));
-}
-sdram->bank[i].bcr = bcr & 0xFFDEE001;
-if (enabled && (bcr & 1)) {
-trace_ppc4xx_sdram_map(sdram_ddr_base(bcr), sdram_ddr_size(bcr));
-memory_region_init(>bank[i].container, NULL, "sdram-container",
-   sdram_ddr_size(bcr));
-memory_region_add_subregion(>bank[i].container, 0,
->bank[i].ram);
-memory_region_add_subregion(get_system_memory(),
-sdram_ddr_base(bcr),
->bank[i].container);
-}
-}
-
-static void sdram_ddr_map_bcr(Ppc4xxSdramDdrState *sdram)
-{
-int i;
-
-for (i = 0; i < sdram->nbanks; i++) {
-if (sdram->bank[i].size != 0) {
-sdram_ddr_set_bcr(sdram, i, sdram_ddr_bcr(sdram->bank[i].base,
-  sdram->bank[i].size), 1);
-} else {
-sdram_ddr_set_bcr(sdram, i, 0, 0);
-}
-}
-}
-
-static void sdram_ddr_unmap_bcr(Ppc4xxSdramDdrState *sdram)
-{
-int i;
-
-for (i = 0; i < sdram->nbanks; i++) {
-trace_ppc4xx_sdram_unmap(sdram_ddr_base(sdram->bank[i].bcr),
- sdram_ddr_size(sdram->bank[i].bcr));
-memory_region_del_subregion(get_system_memory(),
->bank[i].ram);
-}
-}
-
 static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
 {
 Ppc4xxSdramDdrState *s = opaque;
@@ -317,6 +267,7 @@ static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
 static void sdram_ddr_dcr_write(void *opaque, int dcrn, uint32_t val)
 {
 Ppc4xxSdramDdrState *s = opaque;
+int i;
 
 switch (dcrn) {
 case SDRAM0_CFGADDR:
@@ -338,12 +289,24 @@ static void sdram_ddr_dcr_write(void *opaque, int dcrn, 
uint32_t val)
 if (!(s->cfg & 0x8000) && (val & 0x8000)) {
 trace_ppc4xx_sdram_enable("enable");
 /* validate all RAM mappings */
-sdram_ddr_map_bcr(s);
+for (i = 0; i < s->nbanks; i++) {
+if (s->bank[i].size) {
+sdram_bank_set_bcr(>bank[i], s->bank[i].bcr,
+   s->bank[i].base, s->bank[i].size,
+   1);
+}
+}
 s->status &= ~0x8000;
 } else if ((s->cfg & 0x8000) && !(val & 0x8000)) {
 trace_ppc4xx_sdram_enable("disable");
 /* invalidate all RAM mappings */
-sdram_ddr_unmap_bcr(s);
+for (i = 0; i < s->nbanks; i++) {
+if (s->bank[i].size) {
+sdram_bank_set_bcr(>bank[i], s->bank[i].bcr,
+   s->bank[i].base, s->bank[i].size,
+   0);
+}
+}
 s->status |= 0x8000;
 }
 if (!(s->cfg & 0x4000) && (val & 0x4000)) {
@@ -363,16 +326,16 @@ static void sdram_ddr_dcr_write(void *opaque, int dcrn, 
uint32_t val)
 s->pmit = (val & 0xF800) | 0x07C0;
 break;
 case 0x40: /* SDRAM_B0CR */
-sdram_ddr_set_bcr(s, 0, val, s->cfg & 0x8000);
-break;
 case 0x44: /* 

[PULL 04/12] linux-user: Log failing executable in EXCP_DUMP()

2022-09-13 Thread Helge Deller
Enhance the EXCP_DUMP() macro to print out the failing program too.
During debugging it's sometimes hard to track down the actual failing
program if you are e.g. building a whole debian package.

Signed-off-by: Helge Deller 
---
 linux-user/cpu_loop-common.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/linux-user/cpu_loop-common.h b/linux-user/cpu_loop-common.h
index dc0042e4de..36ff5b14f2 100644
--- a/linux-user/cpu_loop-common.h
+++ b/linux-user/cpu_loop-common.h
@@ -27,9 +27,11 @@
 do {\
 CPUState *cs = env_cpu(env);\
 fprintf(stderr, fmt , ## __VA_ARGS__);  \
+fprintf(stderr, "Failing executable: %s\n", exec_path); \
 cpu_dump_state(cs, stderr, 0);  \
 if (qemu_log_separate()) {  \
 qemu_log(fmt, ## __VA_ARGS__);  \
+qemu_log("Failing executable: %s\n", exec_path);\
 log_cpu_state(cs, 0);   \
 }   \
 } while (0)
--
2.37.2




[PATCH v3 07/20] ppc4xx_sdram: QOM'ify

2022-09-13 Thread BALATON Zoltan
Change the ppc4xx_sdram model to a QOM class derived from the
PPC4xx-dcr-device and name it ppc4xx-sdram-ddr. This is mostly
modelling the DDR SDRAM controller found in the 440EP (used on the
bamboo board) but also backward compatible with the older DDR
controllers on some 405 SoCs so we also use it for those now. This
likely does not cause problems for guests we run as the new features
are just not accessed but to model 405 SoC accurately some features
may have to be disabled or the model split between 440 and older.

Newer SoCs (regardless of their PPC core, e.g. 405EX) may have an
updated DDR2 SDRAM controller implemented by the ppc440_sdram model
(only partially, enough for the 460EX on the sam460ex) that is not yet
QOM'ified in this patch. That is intended to become ppc4xx-sdram-ddr2
when QOM'ified later.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h |  3 +-
 hw/ppc/ppc405_uc.c  | 22 +
 hw/ppc/ppc440_bamboo.c  | 10 +++--
 hw/ppc/ppc4xx_devs.c| 99 ++---
 include/hw/ppc/ppc4xx.h | 27 +--
 5 files changed, 98 insertions(+), 63 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index ad54dff542..9a4312691e 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -167,8 +167,6 @@ struct Ppc405SoCState {
 DeviceState parent_obj;
 
 /* Public */
-MemoryRegion *dram_mr;
-
 PowerPCCPU cpu;
 PPCUIC uic;
 Ppc405CpcState cpc;
@@ -182,6 +180,7 @@ struct Ppc405SoCState {
 Ppc405PobState pob;
 Ppc4xxPlbState plb;
 Ppc4xxMalState mal;
+Ppc4xxSdramDdrState sdram;
 };
 
 #endif /* PPC405_H */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index e1c7188e61..c973cfb04e 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1016,6 +1016,9 @@ static void ppc405_soc_instance_init(Object *obj)
 object_initialize_child(obj, "plb", >plb, TYPE_PPC4xx_PLB);
 
 object_initialize_child(obj, "mal", >mal, TYPE_PPC4xx_MAL);
+
+object_initialize_child(obj, "sdram", >sdram, TYPE_PPC4xx_SDRAM_DDR);
+object_property_add_alias(obj, "dram", OBJECT(>sdram), "dram");
 }
 
 static void ppc405_reset(void *opaque)
@@ -1073,9 +1076,17 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
+/*
+ * We use the 440 DDR SDRAM controller which has more regs and features
+ * but it's compatible enough for now
+ */
+object_property_set_int(OBJECT(>sdram), "nbanks", 2, _abort);
+if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>sdram), >cpu, errp)) {
+return;
+}
 /* XXX 405EP has no ECC interrupt */
-ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(>uic), 17), 1,
-  s->dram_mr);
+sysbus_connect_irq(SYS_BUS_DEVICE(>sdram), 0,
+   qdev_get_gpio_in(DEVICE(>uic), 17));
 
 /* External bus controller */
 if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>ebc), >cpu, errp)) {
@@ -1150,12 +1161,6 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 /* Uses UIC IRQs 9, 15, 17 */
 }
 
-static Property ppc405_soc_properties[] = {
-DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION,
- MemoryRegion *),
-DEFINE_PROP_END_OF_LIST(),
-};
-
 static void ppc405_soc_class_init(ObjectClass *oc, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(oc);
@@ -1163,7 +1168,6 @@ static void ppc405_soc_class_init(ObjectClass *oc, void 
*data)
 dc->realize = ppc405_soc_realize;
 /* Reason: only works as part of a ppc405 board/machine */
 dc->user_creatable = false;
-device_class_set_props(dc, ppc405_soc_properties);
 }
 
 static const TypeInfo ppc405_types[] = {
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 9b456f1819..6052d3a2e0 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -48,8 +48,6 @@
 #define PPC440EP_PCI_IO 0xe800
 #define PPC440EP_PCI_IOLEN  0x0001
 
-#define PPC440EP_SDRAM_NR_BANKS 4
-
 static hwaddr entry;
 
 static int bamboo_load_device_tree(hwaddr addr,
@@ -198,9 +196,13 @@ static void bamboo_init(MachineState *machine)
qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
+dev = qdev_new(TYPE_PPC4xx_SDRAM_DDR);
+object_property_set_link(OBJECT(dev), "dram", OBJECT(machine->ram),
+ _abort);
+ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, _fatal);
+object_unref(OBJECT(dev));
 /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
-ppc4xx_sdram_init(env, qdev_get_gpio_in(uicdev, 14),
-  PPC440EP_SDRAM_NR_BANKS, machine->ram);
+sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(uicdev, 14));
 /* Enable SDRAM memory regions, this should be done by the firmware */
 if (ppc_dcr_write(env->dcr_env, 

[PATCH v3 16/20] ppc4xx_sdram: Move ppc4xx DDR and DDR2 SDRAM controller models together

2022-09-13 Thread BALATON Zoltan
Move the PPC4xx DDR and DDR2 SDRAM contrller models into a new file
called ppc4xx_sdram to separate from other device models and put them
in one place allowing sharing some code between them.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/meson.build  |   3 +-
 hw/ppc/ppc440_uc.c  | 321 -
 hw/ppc/ppc4xx_devs.c| 403 -
 hw/ppc/ppc4xx_sdram.c   | 752 
 include/hw/ppc/ppc4xx.h |  34 +-
 5 files changed, 771 insertions(+), 742 deletions(-)
 create mode 100644 hw/ppc/ppc4xx_sdram.c

diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build
index 62801923f3..74720dd1e1 100644
--- a/hw/ppc/meson.build
+++ b/hw/ppc/meson.build
@@ -59,8 +59,9 @@ ppc_ss.add(when: 'CONFIG_PPC440', if_true: files(
   'ppc440_bamboo.c',
   'ppc440_pcix.c', 'ppc440_uc.c'))
 ppc_ss.add(when: 'CONFIG_PPC4XX', if_true: files(
+  'ppc4xx_devs.c',
   'ppc4xx_pci.c',
-  'ppc4xx_devs.c'))
+  'ppc4xx_sdram.c'))
 ppc_ss.add(when: 'CONFIG_SAM460EX', if_true: files('sam460ex.c'))
 # PReP
 ppc_ss.add(when: 'CONFIG_PREP', if_true: files('prep.c'))
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 114c1a1b1c..651263926e 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -10,20 +10,14 @@
 
 #include "qemu/osdep.h"
 #include "qemu/units.h"
-#include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "qemu/log.h"
-#include "qemu/module.h"
 #include "hw/irq.h"
-#include "exec/memory.h"
 #include "hw/ppc/ppc4xx.h"
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci.h"
-#include "sysemu/block-backend.h"
 #include "sysemu/reset.h"
 #include "ppc440.h"
-#include "qom/object.h"
-#include "trace.h"
 
 /*/
 /* L2 Cache as SRAM */
@@ -379,10 +373,6 @@ enum {
 PESDR1_RSTSTA = 0x365,
 };
 
-#define SDR0_DDR0_DDRM_ENCODE(n)  unsigned long)(n)) & 0x03) << 29)
-#define SDR0_DDR0_DDRM_DDR1   0x2000
-#define SDR0_DDR0_DDRM_DDR2   0x4000
-
 static uint32_t dcr_read_sdr(void *opaque, int dcrn)
 {
 ppc4xx_sdr_t *sdr = opaque;
@@ -481,317 +471,6 @@ void ppc4xx_sdr_init(CPUPPCState *env)
  sdr, _read_sdr, _write_sdr);
 }
 
-/*/
-/* SDRAM controller */
-enum {
-SDRAM_R0BAS = 0x40,
-SDRAM_R1BAS,
-SDRAM_R2BAS,
-SDRAM_R3BAS,
-SDRAM_CONF1HB = 0x45,
-SDRAM_PLBADDULL = 0x4a,
-SDRAM_CONF1LL = 0x4b,
-SDRAM_CONFPATHB = 0x4f,
-SDRAM_PLBADDUHB = 0x50,
-};
-
-static uint32_t sdram_ddr2_bcr(hwaddr ram_base, hwaddr ram_size)
-{
-uint32_t bcr;
-
-switch (ram_size) {
-case (8 * MiB):
-bcr = 0xffc0;
-break;
-case (16 * MiB):
-bcr = 0xff80;
-break;
-case (32 * MiB):
-bcr = 0xff00;
-break;
-case (64 * MiB):
-bcr = 0xfe00;
-break;
-case (128 * MiB):
-bcr = 0xfc00;
-break;
-case (256 * MiB):
-bcr = 0xf800;
-break;
-case (512 * MiB):
-bcr = 0xf000;
-break;
-case (1 * GiB):
-bcr = 0xe000;
-break;
-case (2 * GiB):
-bcr = 0xc000;
-break;
-case (4 * GiB):
-bcr = 0x8000;
-break;
-default:
-error_report("invalid RAM size " TARGET_FMT_plx, ram_size);
-return 0;
-}
-bcr |= ram_base >> 2 & 0xffe0;
-bcr |= 1;
-
-return bcr;
-}
-
-static inline hwaddr sdram_ddr2_base(uint32_t bcr)
-{
-return (bcr & 0xffe0) << 2;
-}
-
-static uint64_t sdram_ddr2_size(uint32_t bcr)
-{
-uint64_t size;
-int sh;
-
-sh = 1024 - ((bcr >> 6) & 0x3ff);
-size = 8 * MiB * sh;
-
-return size;
-}
-
-static void sdram_bank_map(Ppc4xxSdramBank *bank)
-{
-memory_region_init(>container, NULL, "sdram-container", bank->size);
-memory_region_add_subregion(>container, 0, >ram);
-memory_region_add_subregion(get_system_memory(), bank->base,
->container);
-}
-
-static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
-{
-memory_region_del_subregion(get_system_memory(), >container);
-memory_region_del_subregion(>container, >ram);
-object_unparent(OBJECT(>container));
-}
-
-static void sdram_ddr2_set_bcr(Ppc4xxSdramDdr2State *sdram, int i,
-   uint32_t bcr, int enabled)
-{
-if (sdram->bank[i].bcr & 1) {
-/* First unmap RAM if enabled */
-trace_ppc4xx_sdram_unmap(sdram_ddr2_base(sdram->bank[i].bcr),
- sdram_ddr2_size(sdram->bank[i].bcr));
-sdram_bank_unmap(>bank[i]);
-}
-sdram->bank[i].bcr = bcr & 0xffe0ffc1;
-sdram->bank[i].base = sdram_ddr2_base(bcr);
-sdram->bank[i].size = sdram_ddr2_size(bcr);
-if (enabled && (bcr & 1)) {
-trace_ppc4xx_sdram_map(sdram_ddr2_base(bcr), sdram_ddr2_size(bcr));
-sdram_bank_map(>bank[i]);
-}
-}
-
-static void 

Re: [PATCH v2 5/6] virtio-net: vhost-user: update queue_reset and queue_enable

2022-09-13 Thread Jason Wang



在 2022/9/12 11:10, Kangjie Xu 写道:

Update virtio_net_queue_reset() and virtio_net_queue_enable()
for vhost-user scenario.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 



Acked-by: Jason Wang 



---
  hw/net/virtio-net.c | 6 --
  1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 6ab796b399..19a2132180 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -550,7 +550,8 @@ static void virtio_net_queue_reset(VirtIODevice *vdev, 
uint32_t queue_index)
  }
  
  if (get_vhost_net(nc->peer) &&

-nc->peer->info->type == NET_CLIENT_DRIVER_TAP) {
+(nc->peer->info->type == NET_CLIENT_DRIVER_TAP ||
+ nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER)) {
  vhost_net_virtqueue_reset(vdev, nc, queue_index);
  }
  
@@ -568,7 +569,8 @@ static void virtio_net_queue_enable(VirtIODevice *vdev, uint32_t queue_index)

  }
  
  if (get_vhost_net(nc->peer) &&

-nc->peer->info->type == NET_CLIENT_DRIVER_TAP) {
+(nc->peer->info->type == NET_CLIENT_DRIVER_TAP ||
+ nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER)) {
  r = vhost_net_virtqueue_restart(vdev, nc, queue_index);
  if (r < 0) {
  error_report("unable to restart vhost net virtqueue: %d, "





[PATCH v3 02/20] ppc4xx: Introduce Ppc4xxSdramBank struct

2022-09-13 Thread BALATON Zoltan
Instead of storing sdram bank parameters in unrelated arrays put them
in a struct so it's clear they belong to the same bank and simplify
the state struct using this bank type.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/ppc/ppc440_uc.c  | 49 +-
 hw/ppc/ppc4xx_devs.c| 59 -
 include/hw/ppc/ppc4xx.h |  8 ++
 3 files changed, 61 insertions(+), 55 deletions(-)

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 53e981ddf4..db4e29 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -16,7 +16,7 @@
 #include "qemu/module.h"
 #include "hw/irq.h"
 #include "exec/memory.h"
-#include "hw/ppc/ppc.h"
+#include "hw/ppc/ppc4xx.h"
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci.h"
 #include "sysemu/block-backend.h"
@@ -485,11 +485,7 @@ void ppc4xx_sdr_init(CPUPPCState *env)
 typedef struct ppc440_sdram_t {
 uint32_t addr;
 int nbanks;
-MemoryRegion containers[4]; /* used for clipping */
-MemoryRegion *ram_memories;
-hwaddr ram_bases[4];
-hwaddr ram_sizes[4];
-uint32_t bcr[4];
+Ppc4xxSdramBank bank[4];
 } ppc440_sdram_t;
 
 enum {
@@ -570,23 +566,23 @@ static uint64_t sdram_size(uint32_t bcr)
 static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
   uint32_t bcr, int enabled)
 {
-if (sdram->bcr[i] & 1) {
+if (sdram->bank[i].bcr & 1) {
 /* First unmap RAM if enabled */
 memory_region_del_subregion(get_system_memory(),
->containers[i]);
-memory_region_del_subregion(>containers[i],
->ram_memories[i]);
-object_unparent(OBJECT(>containers[i]));
+>bank[i].container);
+memory_region_del_subregion(>bank[i].container,
+>bank[i].ram);
+object_unparent(OBJECT(>bank[i].container));
 }
-sdram->bcr[i] = bcr & 0xffe0ffc1;
+sdram->bank[i].bcr = bcr & 0xffe0ffc1;
 if (enabled && (bcr & 1)) {
-memory_region_init(>containers[i], NULL, "sdram-containers",
+memory_region_init(>bank[i].container, NULL, "sdram-container",
sdram_size(bcr));
-memory_region_add_subregion(>containers[i], 0,
->ram_memories[i]);
+memory_region_add_subregion(>bank[i].container, 0,
+>bank[i].ram);
 memory_region_add_subregion(get_system_memory(),
 sdram_base(bcr),
->containers[i]);
+>bank[i].container);
 }
 }
 
@@ -595,9 +591,9 @@ static void sdram_map_bcr(ppc440_sdram_t *sdram)
 int i;
 
 for (i = 0; i < sdram->nbanks; i++) {
-if (sdram->ram_sizes[i] != 0) {
-sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i],
-  sdram->ram_sizes[i]), 1);
+if (sdram->bank[i].size != 0) {
+sdram_set_bcr(sdram, i, sdram_bcr(sdram->bank[i].base,
+  sdram->bank[i].size), 1);
 } else {
 sdram_set_bcr(sdram, i, 0, 0);
 }
@@ -614,9 +610,9 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
 case SDRAM_R1BAS:
 case SDRAM_R2BAS:
 case SDRAM_R3BAS:
-if (sdram->ram_sizes[dcrn - SDRAM_R0BAS]) {
-ret = sdram_bcr(sdram->ram_bases[dcrn - SDRAM_R0BAS],
-sdram->ram_sizes[dcrn - SDRAM_R0BAS]);
+if (sdram->bank[dcrn - SDRAM_R0BAS].size) {
+ret = sdram_bcr(sdram->bank[dcrn - SDRAM_R0BAS].base,
+sdram->bank[dcrn - SDRAM_R0BAS].size);
 }
 break;
 case SDRAM_CONF1HB:
@@ -701,12 +697,15 @@ void ppc440_sdram_init(CPUPPCState *env, int nbanks,
int do_init)
 {
 ppc440_sdram_t *sdram;
+int i;
 
 sdram = g_malloc0(sizeof(*sdram));
 sdram->nbanks = nbanks;
-sdram->ram_memories = ram_memories;
-memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(hwaddr));
-memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(hwaddr));
+for (i = 0; i < nbanks; i++) {
+sdram->bank[i].ram = ram_memories[i];
+sdram->bank[i].base = ram_bases[i];
+sdram->bank[i].size = ram_sizes[i];
+}
 qemu_register_reset(_reset, sdram);
 ppc_dcr_register(env, SDRAM0_CFGADDR,
  sdram, _read_sdram, _write_sdram);
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index b4cd10f735..1226ec4aa9 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -42,10 +42,7 @@ typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
 struct ppc4xx_sdram_t {
 uint32_t addr;
 int nbanks;
-MemoryRegion containers[4]; /* used for clipping */
-MemoryRegion *ram_memories;
-hwaddr 

[PATCH v3 03/20] ppc4xx_sdram: Get rid of the init RAM hack

2022-09-13 Thread BALATON Zoltan
The do_init parameter of ppc4xx_sdram_init() is used to map memory
regions that is normally done by the firmware by programming the SDRAM
controller. This is needed when booting a kernel directly from -kernel
without a firmware. Do this from board code accesing normal SDRAM
controller registers the same way as firmware would do, so we can get
rid of this hack.

Signed-off-by: BALATON Zoltan 
---
v2: Fix ref405ep boot with -kernel and U-Boot

 hw/ppc/ppc405.h |  1 -
 hw/ppc/ppc405_boards.c  | 12 ++--
 hw/ppc/ppc405_uc.c  |  4 +---
 hw/ppc/ppc440_bamboo.c  |  8 +++-
 hw/ppc/ppc440_uc.c  |  2 --
 hw/ppc/ppc4xx_devs.c| 11 +--
 include/hw/ppc/ppc4xx.h |  8 ++--
 7 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 1e558c7831..756865621b 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -169,7 +169,6 @@ struct Ppc405SoCState {
 /* Public */
 MemoryRegion ram_banks[2];
 hwaddr ram_bases[2], ram_sizes[2];
-bool do_dram_init;
 
 MemoryRegion *dram_mr;
 hwaddr ram_size;
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 083f12b23e..bf02a71c6d 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -274,6 +274,7 @@ static void ppc405_init(MachineState *machine)
 MachineClass *mc = MACHINE_GET_CLASS(machine);
 const char *kernel_filename = machine->kernel_filename;
 MemoryRegion *sysmem = get_system_memory();
+CPUPPCState *env;
 
 if (machine->ram_size != mc->default_ram_size) {
 char *sz = size_to_str(mc->default_ram_size);
@@ -288,12 +289,19 @@ static void ppc405_init(MachineState *machine)
  machine->ram_size, _fatal);
 object_property_set_link(OBJECT(>soc), "dram",
  OBJECT(machine->ram), _abort);
-object_property_set_bool(OBJECT(>soc), "dram-init",
- kernel_filename != NULL, _abort);
 object_property_set_uint(OBJECT(>soc), "sys-clk", ,
  _abort);
 qdev_realize(DEVICE(>soc), NULL, _fatal);
 
+/* Enable SDRAM memory regions */
+/* FIXME This shouldn't be needed with firmware but we lack SPD data */
+env = >soc.cpu.env;
+if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
+ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {
+error_report("Could not enable memory regions");
+exit(1);
+}
+
 /* allocate and load BIOS */
 if (machine->firmware) {
 MemoryRegion *bios = g_new(MemoryRegion, 1);
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 2ca42fdef6..1e02347e57 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1081,8 +1081,7 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
  s->ram_bases[0], s->ram_sizes[0]);
 
 ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(>uic), 17), 1,
-  s->ram_banks, s->ram_bases, s->ram_sizes,
-  s->do_dram_init);
+  s->ram_banks, s->ram_bases, s->ram_sizes);
 
 /* External bus controller */
 if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>ebc), >cpu, errp)) {
@@ -1160,7 +1159,6 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 static Property ppc405_soc_properties[] = {
 DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION,
  MemoryRegion *),
-DEFINE_PROP_BOOL("dram-init", Ppc405SoCState, do_dram_init, 0),
 DEFINE_PROP_UINT64("ram-size", Ppc405SoCState, ram_size, 0),
 DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 5ec82fa8c2..e3412c4fcd 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -211,7 +211,13 @@ static void bamboo_init(MachineState *machine)
 ppc4xx_sdram_init(env,
   qdev_get_gpio_in(uicdev, 14),
   PPC440EP_SDRAM_NR_BANKS, ram_memories,
-  ram_bases, ram_sizes, 1);
+  ram_bases, ram_sizes);
+/* Enable SDRAM memory regions, this should be done by the firmware */
+if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
+ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {
+error_report("couldn't enable memory regions");
+exit(1);
+}
 
 /* PCI */
 dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index db4e29..6ab0ad7985 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -489,8 +489,6 @@ typedef struct ppc440_sdram_t {
 } ppc440_sdram_t;
 
 enum {
-SDRAM0_CFGADDR = 0x10,
-SDRAM0_CFGDATA,
 SDRAM_R0BAS = 0x40,
 SDRAM_R1BAS,
 SDRAM_R2BAS,
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 1226ec4aa9..936d6f77fe 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -56,11 +56,6 @@ struct 

[PATCH v3 01/20] ppc440_bamboo: Remove unnecessary memsets

2022-09-13 Thread BALATON Zoltan
In ppc4xx_sdram_init() the struct is allocated with g_new0() so no
need to clear its elements. In the bamboo machine init memset can be
replaced with array initialiser which is shorter.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc440_bamboo.c | 6 ++
 hw/ppc/ppc4xx_devs.c   | 8 ++--
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index ea945a1c99..5ec82fa8c2 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -169,8 +169,8 @@ static void bamboo_init(MachineState *machine)
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *isa = g_new(MemoryRegion, 1);
 MemoryRegion *ram_memories = g_new(MemoryRegion, PPC440EP_SDRAM_NR_BANKS);
-hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS];
-hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS];
+hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS] = {0};
+hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS] = {0};
 PCIBus *pcibus;
 PowerPCCPU *cpu;
 CPUPPCState *env;
@@ -205,8 +205,6 @@ static void bamboo_init(MachineState *machine)
qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
-memset(ram_bases, 0, sizeof(ram_bases));
-memset(ram_sizes, 0, sizeof(ram_sizes));
 ppc4xx_sdram_banks(machine->ram, PPC440EP_SDRAM_NR_BANKS, ram_memories,
ram_bases, ram_sizes, ppc440ep_sdram_bank_sizes);
 /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index ce38ae65e6..b4cd10f735 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -363,12 +363,8 @@ void ppc4xx_sdram_init(CPUPPCState *env, qemu_irq irq, int 
nbanks,
 sdram->irq = irq;
 sdram->nbanks = nbanks;
 sdram->ram_memories = ram_memories;
-memset(sdram->ram_bases, 0, 4 * sizeof(hwaddr));
-memcpy(sdram->ram_bases, ram_bases,
-   nbanks * sizeof(hwaddr));
-memset(sdram->ram_sizes, 0, 4 * sizeof(hwaddr));
-memcpy(sdram->ram_sizes, ram_sizes,
-   nbanks * sizeof(hwaddr));
+memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(hwaddr));
+memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(hwaddr));
 qemu_register_reset(_reset, sdram);
 ppc_dcr_register(env, SDRAM0_CFGADDR,
  sdram, _read_sdram, _write_sdram);
-- 
2.30.4




Re: [PATCH v2 1/6] net: virtio: rename vhost_set_vring_enable to vhost_set_dev_enable

2022-09-13 Thread Jason Wang



在 2022/9/12 11:10, Kangjie Xu 写道:

Previously, vhost_set_vring_enable will enable/disable all vrings
in a device,



Nit: It would be more clear to say to disable all vrings for a specific 
vhost device.


Since in the case of multiqueue virtio-net, a single virtio-net device 
may have multiple vhost devices.


Thanks



which causes ambiguity. So we rename it to
vhost_set_dev_enable.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
---
  backends/cryptodev-vhost.c| 12 ++--
  hw/net/vhost_net-stub.c   |  2 +-
  hw/net/vhost_net.c|  8 
  hw/net/virtio-net.c   |  4 ++--
  hw/virtio/vhost-user.c|  4 ++--
  include/hw/virtio/vhost-backend.h |  6 +++---
  include/net/vhost_net.h   |  2 +-
  7 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/backends/cryptodev-vhost.c b/backends/cryptodev-vhost.c
index bc13e466b4..b83e939760 100644
--- a/backends/cryptodev-vhost.c
+++ b/backends/cryptodev-vhost.c
@@ -147,9 +147,9 @@ cryptodev_vhost_set_vq_index(CryptoDevBackendVhost *crypto,
  }
  
  static int

-vhost_set_vring_enable(CryptoDevBackendClient *cc,
-CryptoDevBackend *b,
-uint16_t queue, int enable)
+vhost_set_dev_enable(CryptoDevBackendClient *cc,
+ CryptoDevBackend *b,
+ uint16_t queue, int enable)
  {
  CryptoDevBackendVhost *crypto =
 cryptodev_get_vhost(cc, b, queue);
@@ -162,8 +162,8 @@ vhost_set_vring_enable(CryptoDevBackendClient *cc,
  }
  
  vhost_ops = crypto->dev.vhost_ops;

-if (vhost_ops->vhost_set_vring_enable) {
-return vhost_ops->vhost_set_vring_enable(>dev, enable);
+if (vhost_ops->vhost_set_dev_enable) {
+return vhost_ops->vhost_set_dev_enable(>dev, enable);
  }
  
  return 0;

@@ -219,7 +219,7 @@ int cryptodev_vhost_start(VirtIODevice *dev, int 
total_queues)
  
  if (cc->vring_enable) {

  /* restore vring enable state */
-r = vhost_set_vring_enable(cc, b, i, cc->vring_enable);
+r = vhost_set_dev_enable(cc, b, i, cc->vring_enable);
  
  if (r < 0) {

  goto err_start;
diff --git a/hw/net/vhost_net-stub.c b/hw/net/vhost_net-stub.c
index 89d71cfb8e..ac5f217dc1 100644
--- a/hw/net/vhost_net-stub.c
+++ b/hw/net/vhost_net-stub.c
@@ -92,7 +92,7 @@ VHostNetState *get_vhost_net(NetClientState *nc)
  return 0;
  }
  
-int vhost_set_vring_enable(NetClientState *nc, int enable)

+int vhost_set_dev_enable(NetClientState *nc, int enable)
  {
  return 0;
  }
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 97cdf9280b..ea896ea75b 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -396,7 +396,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
  
  if (peer->vring_enable) {

  /* restore vring enable state */
-r = vhost_set_vring_enable(peer, peer->vring_enable);
+r = vhost_set_dev_enable(peer, peer->vring_enable);
  
  if (r < 0) {

  vhost_net_stop_one(get_vhost_net(peer), dev);
@@ -508,15 +508,15 @@ VHostNetState *get_vhost_net(NetClientState *nc)
  return vhost_net;
  }
  
-int vhost_set_vring_enable(NetClientState *nc, int enable)

+int vhost_set_dev_enable(NetClientState *nc, int enable)
  {
  VHostNetState *net = get_vhost_net(nc);
  const VhostOps *vhost_ops = net->dev.vhost_ops;
  
  nc->vring_enable = enable;
  
-if (vhost_ops && vhost_ops->vhost_set_vring_enable) {

-return vhost_ops->vhost_set_vring_enable(>dev, enable);
+if (vhost_ops && vhost_ops->vhost_set_dev_enable) {
+return vhost_ops->vhost_set_dev_enable(>dev, enable);
  }
  
  return 0;

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 7817206596..6ab796b399 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -696,7 +696,7 @@ static int peer_attach(VirtIONet *n, int index)
  }
  
  if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {

-vhost_set_vring_enable(nc->peer, 1);
+vhost_set_dev_enable(nc->peer, 1);
  }
  
  if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {

@@ -719,7 +719,7 @@ static int peer_detach(VirtIONet *n, int index)
  }
  
  if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {

-vhost_set_vring_enable(nc->peer, 0);
+vhost_set_dev_enable(nc->peer, 0);
  }
  
  if (nc->peer->info->type !=  NET_CLIENT_DRIVER_TAP) {

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index bd24741be8..794519359b 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1198,7 +1198,7 @@ static int vhost_user_set_vring_base(struct vhost_dev 
*dev,
  return vhost_set_vring(dev, VHOST_USER_SET_VRING_BASE, ring);
  }
  
-static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable)

+static int 

Re: [PATCH v2 2/6] vhost-user: add op to enable or disable a single vring

2022-09-13 Thread Jason Wang



在 2022/9/12 11:10, Kangjie Xu 写道:

There is only vhost_set_dev_enable op in VhostOps. Thus, we introduce
the interface vhost_set_vring_enable to set the enable status for a
single vring.

Resetting a single vq will rely on this interface.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 



Acked-by: Jason Wang 



---
  hw/virtio/vhost-user.c| 25 ++---
  include/hw/virtio/vhost-backend.h |  3 +++
  2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 794519359b..3f140d5085 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1198,6 +1198,22 @@ static int vhost_user_set_vring_base(struct vhost_dev 
*dev,
  return vhost_set_vring(dev, VHOST_USER_SET_VRING_BASE, ring);
  }
  
+static int vhost_user_set_vring_enable(struct vhost_dev *dev,

+   int index,
+   int enable)
+{
+if (index < dev->vq_index || index >= dev->vq_index + dev->nvqs) {
+return -EINVAL;
+}
+
+struct vhost_vring_state state = {
+.index = index,
+.num   = enable,
+};
+
+return vhost_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, );
+}
+
  static int vhost_user_set_dev_enable(struct vhost_dev *dev, int enable)
  {
  int i;
@@ -1207,13 +1223,7 @@ static int vhost_user_set_dev_enable(struct vhost_dev 
*dev, int enable)
  }
  
  for (i = 0; i < dev->nvqs; ++i) {

-int ret;
-struct vhost_vring_state state = {
-.index = dev->vq_index + i,
-.num   = enable,
-};
-
-ret = vhost_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, );
+int ret = vhost_user_set_vring_enable(dev, dev->vq_index + i, enable);
  if (ret < 0) {
  /*
   * Restoring the previous state is likely infeasible, as well as
@@ -2627,6 +2637,7 @@ const VhostOps user_ops = {
  .vhost_set_owner = vhost_user_set_owner,
  .vhost_reset_device = vhost_user_reset_device,
  .vhost_get_vq_index = vhost_user_get_vq_index,
+.vhost_set_vring_enable = vhost_user_set_vring_enable,
  .vhost_set_dev_enable = vhost_user_set_dev_enable,
  .vhost_requires_shm_log = vhost_user_requires_shm_log,
  .vhost_migration_done = vhost_user_migration_done,
diff --git a/include/hw/virtio/vhost-backend.h 
b/include/hw/virtio/vhost-backend.h
index b49432045f..dad7191bac 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -81,6 +81,8 @@ typedef int (*vhost_set_backend_cap_op)(struct vhost_dev 
*dev);
  typedef int (*vhost_set_owner_op)(struct vhost_dev *dev);
  typedef int (*vhost_reset_device_op)(struct vhost_dev *dev);
  typedef int (*vhost_get_vq_index_op)(struct vhost_dev *dev, int idx);
+typedef int (*vhost_set_vring_enable_op)(struct vhost_dev *dev,
+ int index, int enable);
  typedef int (*vhost_set_dev_enable_op)(struct vhost_dev *dev,
 int enable);
  typedef bool (*vhost_requires_shm_log_op)(struct vhost_dev *dev);
@@ -155,6 +157,7 @@ typedef struct VhostOps {
  vhost_set_owner_op vhost_set_owner;
  vhost_reset_device_op vhost_reset_device;
  vhost_get_vq_index_op vhost_get_vq_index;
+vhost_set_vring_enable_op vhost_set_vring_enable;
  vhost_set_dev_enable_op vhost_set_dev_enable;
  vhost_requires_shm_log_op vhost_requires_shm_log;
  vhost_migration_done_op vhost_migration_done;





Re: [PATCH v8 03/14] net: simplify net_client_parse() error management

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:49AM +0200, Laurent Vivier wrote:
> All net_client_parse() callers exit in case of error.
> 
> Move exit(1) to net_client_parse() and remove error checking from
> the callers.
> 
> Suggested-by: Markus Armbruster 
> Signed-off-by: Laurent Vivier 
> Reviewed-by: Markus Armbruster 

Reviewed-by: David Gibson 
> ---
>  include/net/net.h |  2 +-
>  net/net.c |  6 ++
>  softmmu/vl.c  | 12 +++-
>  3 files changed, 6 insertions(+), 14 deletions(-)
> 
> diff --git a/include/net/net.h b/include/net/net.h
> index c1c34a58f849..55023e7e9fa9 100644
> --- a/include/net/net.h
> +++ b/include/net/net.h
> @@ -220,7 +220,7 @@ extern NICInfo nd_table[MAX_NICS];
>  extern const char *host_net_devices[];
>  
>  /* from net.c */
> -int net_client_parse(QemuOptsList *opts_list, const char *str);
> +void net_client_parse(QemuOptsList *opts_list, const char *str);
>  void show_netdevs(void);
>  void net_init_clients(void);
>  void net_check_clients(void);
> diff --git a/net/net.c b/net/net.c
> index 15958f881776..f056e8aebfb2 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -1579,13 +1579,11 @@ void net_init_clients(void)
>_fatal);
>  }
>  
> -int net_client_parse(QemuOptsList *opts_list, const char *optarg)
> +void net_client_parse(QemuOptsList *opts_list, const char *optarg)
>  {
>  if (!qemu_opts_parse_noisily(opts_list, optarg, true)) {
> -return -1;
> +exit(1);
>  }
> -
> -return 0;
>  }
>  
>  /* From FreeBSD */
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 1fe8b5c5a120..55d163475e9e 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -2809,21 +2809,15 @@ void qemu_init(int argc, char **argv, char **envp)
>  break;
>  case QEMU_OPTION_netdev:
>  default_net = 0;
> -if (net_client_parse(qemu_find_opts("netdev"), optarg) == 
> -1) {
> -exit(1);
> -}
> +net_client_parse(qemu_find_opts("netdev"), optarg);
>  break;
>  case QEMU_OPTION_nic:
>  default_net = 0;
> -if (net_client_parse(qemu_find_opts("nic"), optarg) == -1) {
> -exit(1);
> -}
> +net_client_parse(qemu_find_opts("nic"), optarg);
>  break;
>  case QEMU_OPTION_net:
>  default_net = 0;
> -if (net_client_parse(qemu_find_opts("net"), optarg) == -1) {
> -exit(1);
> -}
> +net_client_parse(qemu_find_opts("net"), optarg);
>  break;
>  #ifdef CONFIG_LIBISCSI
>  case QEMU_OPTION_iscsi:

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


[PATCH v5 04/15] virtio: introduce virtio_queue_enable()

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Introduce the interface queue_enable() in VirtioDeviceClass and the
fucntion virtio_queue_enable() in virtio, it can be called when
VIRTIO_PCI_COMMON_Q_ENABLE is written and related virtqueue can be
started. It only supports the devices of virtio 1 or later. The
not-supported devices can only start the virtqueue when DRIVER_OK.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/virtio/virtio.c | 14 ++
 include/hw/virtio/virtio.h |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 0e9d41366f..141f18c633 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2050,6 +2050,20 @@ void virtio_queue_reset(VirtIODevice *vdev, uint32_t 
queue_index)
 __virtio_queue_reset(vdev, queue_index);
 }
 
+void virtio_queue_enable(VirtIODevice *vdev, uint32_t queue_index)
+{
+VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+
+if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
+error_report("queue_enable is only suppported in devices of virtio "
+ "1.0 or later.");
+}
+
+if (k->queue_enable) {
+k->queue_enable(vdev, queue_index);
+}
+}
+
 void virtio_reset(void *opaque)
 {
 VirtIODevice *vdev = opaque;
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 879394299b..085997d8f3 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -131,6 +131,7 @@ struct VirtioDeviceClass {
 void (*reset)(VirtIODevice *vdev);
 void (*set_status)(VirtIODevice *vdev, uint8_t val);
 void (*queue_reset)(VirtIODevice *vdev, uint32_t queue_index);
+void (*queue_enable)(VirtIODevice *vdev, uint32_t queue_index);
 /* For transitional devices, this is a bitmap of features
  * that are only exposed on the legacy interface but not
  * the modern one.
@@ -270,6 +271,7 @@ int virtio_queue_set_host_notifier_mr(VirtIODevice *vdev, 
int n,
 int virtio_set_status(VirtIODevice *vdev, uint8_t val);
 void virtio_reset(void *opaque);
 void virtio_queue_reset(VirtIODevice *vdev, uint32_t queue_index);
+void virtio_queue_enable(VirtIODevice *vdev, uint32_t queue_index);
 void virtio_update_irq(VirtIODevice *vdev);
 int virtio_set_features(VirtIODevice *vdev, uint64_t val);
 
-- 
2.32.0.3.g01195cf9f




[PATCH v5 02/15] virtio: introduce __virtio_queue_reset()

2022-09-13 Thread Xuan Zhuo
Separate the logic of vq reset. This logic will be called directly
later.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/virtio/virtio.c | 37 +
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 5d607aeaa0..67d54832a9 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2019,6 +2019,26 @@ static enum virtio_device_endian 
virtio_current_cpu_endian(void)
 }
 }
 
+static void __virtio_queue_reset(VirtIODevice *vdev, uint32_t i)
+{
+vdev->vq[i].vring.desc = 0;
+vdev->vq[i].vring.avail = 0;
+vdev->vq[i].vring.used = 0;
+vdev->vq[i].last_avail_idx = 0;
+vdev->vq[i].shadow_avail_idx = 0;
+vdev->vq[i].used_idx = 0;
+vdev->vq[i].last_avail_wrap_counter = true;
+vdev->vq[i].shadow_avail_wrap_counter = true;
+vdev->vq[i].used_wrap_counter = true;
+virtio_queue_set_vector(vdev, i, VIRTIO_NO_VECTOR);
+vdev->vq[i].signalled_used = 0;
+vdev->vq[i].signalled_used_valid = false;
+vdev->vq[i].notification = true;
+vdev->vq[i].vring.num = vdev->vq[i].vring.num_default;
+vdev->vq[i].inuse = 0;
+virtio_virtqueue_reset_region_cache(>vq[i]);
+}
+
 void virtio_reset(void *opaque)
 {
 VirtIODevice *vdev = opaque;
@@ -2050,22 +2070,7 @@ void virtio_reset(void *opaque)
 virtio_notify_vector(vdev, vdev->config_vector);
 
 for(i = 0; i < VIRTIO_QUEUE_MAX; i++) {
-vdev->vq[i].vring.desc = 0;
-vdev->vq[i].vring.avail = 0;
-vdev->vq[i].vring.used = 0;
-vdev->vq[i].last_avail_idx = 0;
-vdev->vq[i].shadow_avail_idx = 0;
-vdev->vq[i].used_idx = 0;
-vdev->vq[i].last_avail_wrap_counter = true;
-vdev->vq[i].shadow_avail_wrap_counter = true;
-vdev->vq[i].used_wrap_counter = true;
-virtio_queue_set_vector(vdev, i, VIRTIO_NO_VECTOR);
-vdev->vq[i].signalled_used = 0;
-vdev->vq[i].signalled_used_valid = false;
-vdev->vq[i].notification = true;
-vdev->vq[i].vring.num = vdev->vq[i].vring.num_default;
-vdev->vq[i].inuse = 0;
-virtio_virtqueue_reset_region_cache(>vq[i]);
+__virtio_queue_reset(vdev, i);
 }
 }
 
-- 
2.32.0.3.g01195cf9f




[PATCH v5 09/15] vhost: expose vhost_virtqueue_stop()

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Expose vhost_virtqueue_stop(), we need to use it when resetting a
virtqueue.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/virtio/vhost.c | 8 
 include/hw/virtio/vhost.h | 2 ++
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 7900bc81ab..5407f60226 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1201,10 +1201,10 @@ fail_alloc_desc:
 return r;
 }
 
-static void vhost_virtqueue_stop(struct vhost_dev *dev,
-struct VirtIODevice *vdev,
-struct vhost_virtqueue *vq,
-unsigned idx)
+void vhost_virtqueue_stop(struct vhost_dev *dev,
+  struct VirtIODevice *vdev,
+  struct vhost_virtqueue *vq,
+  unsigned idx)
 {
 int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, idx);
 struct vhost_vring_state state = {
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index b092f57d98..2b168b2269 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -281,6 +281,8 @@ int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t 
iova, int write);
 
 int vhost_virtqueue_start(struct vhost_dev *dev, struct VirtIODevice *vdev,
   struct vhost_virtqueue *vq, unsigned idx);
+void vhost_virtqueue_stop(struct vhost_dev *dev, struct VirtIODevice *vdev,
+  struct vhost_virtqueue *vq, unsigned idx);
 
 void vhost_dev_reset_inflight(struct vhost_inflight *inflight);
 void vhost_dev_free_inflight(struct vhost_inflight *inflight);
-- 
2.32.0.3.g01195cf9f




[PATCH v5 07/15] virtio-pci: support queue enable

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

PCI devices support device specific vq enable.

Based on this function, the driver can re-enable the virtqueue after the
virtqueue is reset.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/virtio/virtio-pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 79b9e641dd..a53b5d9f1e 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1342,6 +1342,7 @@ static void virtio_pci_common_write(void *opaque, hwaddr 
addr,
proxy->vqs[vdev->queue_sel].used[0]);
 proxy->vqs[vdev->queue_sel].enabled = 1;
 proxy->vqs[vdev->queue_sel].reset = 0;
+virtio_queue_enable(vdev, vdev->queue_sel);
 } else {
 virtio_error(vdev, "wrong value for queue_enable %"PRIx64, val);
 }
-- 
2.32.0.3.g01195cf9f




Re: [PATCH] e1000e: set RX desc status with DD flag in a separate operation

2022-09-13 Thread Jason Wang
On Fri, Sep 9, 2022 at 7:20 PM dinghui  wrote:
>
> On 2022/9/9 10:40, Jason Wang wrote:
> > On Sat, Aug 27, 2022 at 12:06 AM Ding Hui  wrote:
> >>
> >> Like commit 034d00d48581 ("e1000: set RX descriptor status in
> >> a separate operation"), there is also same issue in e1000e, which
> >> would cause lost packets or stop sending packets to VM with DPDK.
> >>
> >> Do similar fix in e1000e.
> >>
> >> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/402
> >> Signed-off-by: Ding Hui 
> >> ---
> >>   hw/net/e1000e_core.c | 54 +++-
> >>   1 file changed, 53 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
> >> index 208e3e0d79..b8038e4014 100644
> >> --- a/hw/net/e1000e_core.c
> >> +++ b/hw/net/e1000e_core.c
> >> @@ -1364,6 +1364,58 @@ struct NetRxPkt *pkt, const E1000E_RSSInfo 
> >> *rss_info,
> >>   }
> >>   }
> >>
> >> +static inline void
> >> +e1000e_pci_dma_write_rx_desc(E1000ECore *core, dma_addr_t addr,
> >> + uint8_t *desc, dma_addr_t len)
> >> +{
> >> +PCIDevice *dev = core->owner;
> >> +
> >> +if (e1000e_rx_use_legacy_descriptor(core)) {
> >> +struct e1000_rx_desc *d = (struct e1000_rx_desc *) desc;
> >> +size_t offset = offsetof(struct e1000_rx_desc, status);
> >> +typeof(d->status) status = d->status;
> >> +
> >> +d->status &= ~E1000_RXD_STAT_DD;
> >> +pci_dma_write(dev, addr, desc, len);
> >> +
> >> +if (status & E1000_RXD_STAT_DD) {
> >> +d->status = status;
> >> +pci_dma_write(dev, addr + offset, , sizeof(status));
> >> +}
> >> +} else {
> >> +if (core->mac[RCTL] & E1000_RCTL_DTYP_PS) {
> >> +union e1000_rx_desc_packet_split *d =
> >> +(union e1000_rx_desc_packet_split *) desc;
> >> +size_t offset = offsetof(union e1000_rx_desc_packet_split,
> >> +wb.middle.status_error);
> >> +typeof(d->wb.middle.status_error) status =
> >> +d->wb.middle.status_error;
> >
> > Any reason to use typeof here? Its type is known to be uint32_t?
> >
>
> My intention was using exact type same with struct member status_error,
> which is indeed uint32_t now. If the type of status_error in struct be
> changed in some case, we do not need to change everywhere.
>
> Maybe I worry too much, the struct is related to h/w spec, so it is
> unlikely be changed in the future.
>
> Should I send v2 to use uint32_t directly? I'm also OK with it.

Yes, please.

Thanks

>
> >> +
> >> +d->wb.middle.status_error &= ~E1000_RXD_STAT_DD;
> >> +pci_dma_write(dev, addr, desc, len);
> >> +
> >> +if (status & E1000_RXD_STAT_DD) {
> >> +d->wb.middle.status_error = status;
> >> +pci_dma_write(dev, addr + offset, , 
> >> sizeof(status));
> >> +}
> >> +} else {
> >> +union e1000_rx_desc_extended *d =
> >> +(union e1000_rx_desc_extended *) desc;
> >> +size_t offset = offsetof(union e1000_rx_desc_extended,
> >> +wb.upper.status_error);
> >> +typeof(d->wb.upper.status_error) status = 
> >> d->wb.upper.status_error;
> >
> > So did here.
> >
> > Thanks
> >
> >> +
> >> +d->wb.upper.status_error &= ~E1000_RXD_STAT_DD;
> >> +pci_dma_write(dev, addr, desc, len);
> >> +
> >> +if (status & E1000_RXD_STAT_DD) {
> >> +d->wb.upper.status_error = status;
> >> +pci_dma_write(dev, addr + offset, , 
> >> sizeof(status));
> >> +}
> >> +}
> >> +}
> >> +}
> >> +
> >>   typedef struct e1000e_ba_state_st {
> >>   uint16_t written[MAX_PS_BUFFERS];
> >>   uint8_t cur_idx;
> >> @@ -1600,7 +1652,7 @@ e1000e_write_packet_to_guest(E1000ECore *core, 
> >> struct NetRxPkt *pkt,
> >>
> >>   e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL,
> >>  rss_info, do_ps ? ps_hdr_len : 0, 
> >> );
> >> -pci_dma_write(d, base, , core->rx_desc_len);
> >> +e1000e_pci_dma_write_rx_desc(core, base, desc, core->rx_desc_len);
> >>
> >>   e1000e_ring_advance(core, rxi,
> >>   core->rx_desc_len / E1000_MIN_RX_DESC_LEN);
> >> --
> >> 2.17.1
> >>
> >
> >
>
>
> --
> Thanks,
> - Ding Hui
>




Re: [PATCH v8 01/14] net: introduce convert_host_port()

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:47AM +0200, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier 
> Reviewed-by: Stefano Brivio 

Reviewed-by: David Gibson 

Although, if you do respin, an actual commit message would be nice to
have.


> ---
>  include/qemu/sockets.h |  2 ++
>  net/net.c  | 62 ++
>  2 files changed, 34 insertions(+), 30 deletions(-)
> 
> diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
> index 038faa157f59..47194b9732f8 100644
> --- a/include/qemu/sockets.h
> +++ b/include/qemu/sockets.h
> @@ -47,6 +47,8 @@ void socket_listen_cleanup(int fd, Error **errp);
>  int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
>  
>  /* Old, ipv4 only bits.  Don't use for new code. */
> +int convert_host_port(struct sockaddr_in *saddr, const char *host,
> +  const char *port, Error **errp);
>  int parse_host_port(struct sockaddr_in *saddr, const char *str,
>  Error **errp);
>  int socket_init(void);
> diff --git a/net/net.c b/net/net.c
> index 2db160e0634d..d2288bd3a929 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -66,55 +66,57 @@ static QTAILQ_HEAD(, NetClientState) net_clients;
>  /***/
>  /* network device redirectors */
>  
> -int parse_host_port(struct sockaddr_in *saddr, const char *str,
> -Error **errp)
> +int convert_host_port(struct sockaddr_in *saddr, const char *host,
> +  const char *port, Error **errp)
>  {
> -gchar **substrings;
>  struct hostent *he;
> -const char *addr, *p, *r;
> -int port, ret = 0;
> +const char *r;
> +long p;
>  
>  memset(saddr, 0, sizeof(*saddr));
>  
> -substrings = g_strsplit(str, ":", 2);
> -if (!substrings || !substrings[0] || !substrings[1]) {
> -error_setg(errp, "host address '%s' doesn't contain ':' "
> -   "separating host from port", str);
> -ret = -1;
> -goto out;
> -}
> -
> -addr = substrings[0];
> -p = substrings[1];
> -
>  saddr->sin_family = AF_INET;
> -if (addr[0] == '\0') {
> +if (host[0] == '\0') {
>  saddr->sin_addr.s_addr = 0;
>  } else {
> -if (qemu_isdigit(addr[0])) {
> -if (!inet_aton(addr, >sin_addr)) {
> +if (qemu_isdigit(host[0])) {
> +if (!inet_aton(host, >sin_addr)) {
>  error_setg(errp, "host address '%s' is not a valid "
> -   "IPv4 address", addr);
> -ret = -1;
> -goto out;
> +   "IPv4 address", host);
> +return -1;
>  }
>  } else {
> -he = gethostbyname(addr);
> +he = gethostbyname(host);
>  if (he == NULL) {
> -error_setg(errp, "can't resolve host address '%s'", addr);
> -ret = -1;
> -goto out;
> +error_setg(errp, "can't resolve host address '%s'", host);
> +return -1;
>  }
>  saddr->sin_addr = *(struct in_addr *)he->h_addr;
>  }
>  }
> -port = strtol(p, (char **), 0);
> -if (r == p) {
> -error_setg(errp, "port number '%s' is invalid", p);
> +if (qemu_strtol(port, , 0, ) != 0) {
> +error_setg(errp, "port number '%s' is invalid", port);
> +return -1;
> +}
> +saddr->sin_port = htons(p);
> +return 0;
> +}
> +
> +int parse_host_port(struct sockaddr_in *saddr, const char *str,
> +Error **errp)
> +{
> +gchar **substrings;
> +int ret;
> +
> +substrings = g_strsplit(str, ":", 2);
> +if (!substrings || !substrings[0] || !substrings[1]) {
> +error_setg(errp, "host address '%s' doesn't contain ':' "
> +   "separating host from port", str);
>  ret = -1;
>  goto out;
>  }
> -saddr->sin_port = htons(port);
> +
> +ret = convert_host_port(saddr, substrings[0], substrings[1], errp);
>  
>  out:
>  g_strfreev(substrings);

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [PATCH v8 07/14] net: stream: add unix socket

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:53AM +0200, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier 
> Reviewed-by: Stefano Brivio 
> ---
>  net/stream.c| 108 +---
>  qapi/net.json   |   2 +-
>  qemu-options.hx |   1 +
>  3 files changed, 105 insertions(+), 6 deletions(-)
> 
> diff --git a/net/stream.c b/net/stream.c
> index e8afbaca50b6..0f91ff20df61 100644
> --- a/net/stream.c
> +++ b/net/stream.c
> @@ -235,7 +235,7 @@ static NetStreamState 
> *net_stream_fd_init_stream(NetClientState *peer,
>  static void net_stream_accept(void *opaque)
>  {
>  NetStreamState *s = opaque;
> -struct sockaddr_in saddr;
> +struct sockaddr_storage saddr;
>  socklen_t len;
>  int fd;
>  
> @@ -253,9 +253,27 @@ static void net_stream_accept(void *opaque)
>  s->fd = fd;
>  s->nc.link_down = false;
>  net_stream_connect(s);
> -snprintf(s->nc.info_str, sizeof(s->nc.info_str),
> - "connection from %s:%d",
> - inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
> +switch (saddr.ss_family) {
> +case AF_INET: {
> +struct sockaddr_in *saddr_in = (struct sockaddr_in *)
> +
> +snprintf(s->nc.info_str, sizeof(s->nc.info_str),
> + "connection from %s:%d",
> + inet_ntoa(saddr_in->sin_addr), ntohs(saddr_in->sin_port));
> +break;
> +}
> +case AF_UNIX: {
> +struct sockaddr_un saddr_un;
> +
> +len = sizeof(saddr_un);
> +getsockname(s->listen_fd, (struct sockaddr *)_un, );

It seems like there's an asymmetry here in that we've gotten the
connection address outside the switch for inet sockets, but we need an
additional getsockname() for unix sockets.  Am I missing something? 

> +snprintf(s->nc.info_str, sizeof(s->nc.info_str),
> + "connect from %s", saddr_un.sun_path);
> +break;
> +}
> +default:
> +g_assert_not_reached();
> +}
>  }
>  
>  static int net_stream_server_init(NetClientState *peer,
> @@ -295,6 +313,43 @@ static int net_stream_server_init(NetClientState *peer,
>  }
>  break;
>  }
> +case SOCKET_ADDRESS_TYPE_UNIX: {
> +struct sockaddr_un saddr_un;
> +
> +ret = unlink(addr->u.q_unix.path);
> +if (ret < 0 && errno != ENOENT) {
> +error_setg_errno(errp, errno, "failed to unlink socket %s",
> + addr->u.q_unix.path);
> +return -1;
> +}
> +
> +saddr_un.sun_family = PF_UNIX;
> +ret = snprintf(saddr_un.sun_path, sizeof(saddr_un.sun_path), "%s",
> +   addr->u.q_unix.path);
> +if (ret < 0 || ret >= sizeof(saddr_un.sun_path)) {
> +error_setg(errp, "UNIX socket path '%s' is too long",
> +   addr->u.q_unix.path);
> +error_append_hint(errp, "Path must be less than %zu bytes\n",
> +  sizeof(saddr_un.sun_path));
> +return -1;
> +}
> +
> +fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
> +if (fd < 0) {
> +error_setg_errno(errp, errno, "can't create stream socket");
> +return -1;
> +}
> +qemu_socket_set_nonblock(fd);
> +
> +ret = bind(fd, (struct sockaddr *)_un, sizeof(saddr_un));
> +if (ret < 0) {
> +error_setg_errno(errp, errno, "can't create socket with path: 
> %s",
> + saddr_un.sun_path);
> +closesocket(fd);
> +return -1;
> +}
> +break;
> +}
>  case SOCKET_ADDRESS_TYPE_FD:
>  fd = monitor_fd_param(monitor_cur(), addr->u.fd.str, errp);
>  if (fd == -1) {
> @@ -380,6 +435,49 @@ static int net_stream_client_init(NetClientState *peer,
> ntohs(saddr_in.sin_port));
>  break;
>  }
> +case SOCKET_ADDRESS_TYPE_UNIX: {
> +struct sockaddr_un saddr_un;
> +
> +saddr_un.sun_family = PF_UNIX;
> +ret = snprintf(saddr_un.sun_path, sizeof(saddr_un.sun_path), "%s",
> +   addr->u.q_unix.path);
> +if (ret < 0 || ret >= sizeof(saddr_un.sun_path)) {
> +error_setg(errp, "UNIX socket path '%s' is too long",
> +   addr->u.q_unix.path);
> +error_append_hint(errp, "Path must be less than %zu bytes\n",
> +  sizeof(saddr_un.sun_path));
> +return -1;
> +}
> +
> +fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
> +if (fd < 0) {
> +error_setg_errno(errp, errno, "can't create stream socket");
> +return -1;
> +}
> +qemu_socket_set_nonblock(fd);
> +
> +connected = 0;
> +for (;;) {
> +ret = connect(fd, (struct sockaddr *)_un, 
> sizeof(saddr_un));
> +if (ret < 0) {
> +if (errno == EINTR || errno == EWOULDBLOCK) {
> + 

Re: [PATCH v8 05/14] qapi: net: add stream and dgram netdevs

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:51AM +0200, Laurent Vivier wrote:
> Copied from socket netdev file and modified to use SocketAddress
> to be able to introduce new features like unix socket.
> 
> "udp" and "mcast" are squashed into dgram netdev, multicast is detected
> according to the IP address type.
> "listen" and "connect" modes are managed by stream netdev. An optional
> parameter "server" defines the mode (server by default)
> 
> The two new types need to be parsed the modern way with -netdev, because
> with the traditional way, the "type" field of netdev structure collides with
> the "type" field of SocketAddress and prevents the correct evaluation of the
> command line option. Moreover the traditional way doesn't allow to use
> the same type (SocketAddress) several times with the -netdev option
> (needed to specify "local" and "remote" addresses).
> 
> The previous commit paved the way for parsing the modern way, but
> omitted one detail: how to pick modern vs. traditional, in
> netdev_is_modern().
> 
> We want to pick based on the value of parameter "type".  But how to
> extract it from the option argument?
> 
> Parsing the option argument, either the modern or the traditional way,
> extracts it for us, but only if parsing succeeds.
> 
> If parsing fails, there is no good option.  No matter which parser we
> pick, it'll be the wrong one for some arguments, and the error
> reporting will be confusing.
> 
> Fortunately, the traditional parser accepts *anything* when called in
> a certain way.  This maximizes our chance to extract the value of
> "type", and in turn minimizes the risk of confusing error reporting.
> 
> Signed-off-by: Laurent Vivier 
> Reviewed-by: Stefano Brivio 
> ---
>  hmp-commands.hx |   2 +-
>  net/clients.h   |   6 +
>  net/dgram.c | 631 
>  net/hub.c   |   2 +
>  net/meson.build |   2 +
>  net/net.c   |  30 ++-
>  net/stream.c| 423 
>  qapi/net.json   |  63 -
>  qemu-options.hx |  12 +
>  9 files changed, 1167 insertions(+), 4 deletions(-)
>  create mode 100644 net/dgram.c
>  create mode 100644 net/stream.c
> 
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 182e639d1498..83e8d45a2a8b 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1276,7 +1276,7 @@ ERST
>  {
>  .name   = "netdev_add",
>  .args_type  = "netdev:O",
> -.params = "[user|tap|socket|vde|bridge|hubport|netmap|vhost-user"
> +.params = 
> "[user|tap|socket|stream|dgram|vde|bridge|hubport|netmap|vhost-user"
>  #ifdef CONFIG_VMNET
>"|vmnet-host|vmnet-shared|vmnet-bridged"
>  #endif
> diff --git a/net/clients.h b/net/clients.h
> index c9157789f2ce..ed8bdfff1e7c 100644
> --- a/net/clients.h
> +++ b/net/clients.h
> @@ -40,6 +40,12 @@ int net_init_hubport(const Netdev *netdev, const char 
> *name,
>  int net_init_socket(const Netdev *netdev, const char *name,
>  NetClientState *peer, Error **errp);
>  
> +int net_init_stream(const Netdev *netdev, const char *name,
> +NetClientState *peer, Error **errp);
> +
> +int net_init_dgram(const Netdev *netdev, const char *name,
> +   NetClientState *peer, Error **errp);
> +
>  int net_init_tap(const Netdev *netdev, const char *name,
>   NetClientState *peer, Error **errp);
>  
> diff --git a/net/dgram.c b/net/dgram.c
> new file mode 100644
> index ..dbe65102d174
> --- /dev/null
> +++ b/net/dgram.c
> @@ -0,0 +1,631 @@
> +/*
> + * QEMU System Emulator
> + *
> + * Copyright (c) 2003-2008 Fabrice Bellard

Shouldn't this have your copyright as well as Fabrice's old one copied
from socket.c?

> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a 
> copy
> + * of this software and associated documentation files (the "Software"), to 
> deal
> + * in the Software without restriction, including without limitation the 
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
> FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "net/net.h"
> +#include "clients.h"
> +#include 

Re: [PATCH v5 11/15] vhost-net: vhost-kernel: introduce vhost_net_virtqueue_restart()

2022-09-13 Thread Jason Wang
On Wed, Sep 14, 2022 at 12:21 PM Xuan Zhuo  wrote:
>
> From: Kangjie Xu 
>
> Introduce vhost_net_virtqueue_restart(), which can restart the
> specific virtqueue when the vhost net started running before.
> If it fails to restart the virtqueue, the device will be stopped.
>
> Here we do not reuse vhost_net_start_one() or vhost_dev_start()
> because they work at queue pair level. The mem table and features
> do not change, so we can call the vhost_virtqueue_start() to
> restart a specific queue.
>
> This patch only considers the case of vhost-kernel, when
> NetClientDriver is NET_CLIENT_DRIVER_TAP.
>
> Signed-off-by: Kangjie Xu 
> Signed-off-by: Xuan Zhuo 

Acked-by: Jason Wang 

> ---
>  hw/net/vhost_net.c  | 53 +
>  include/net/vhost_net.h |  2 ++
>  2 files changed, 55 insertions(+)
>
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index 8beecb4d22..d2926e2ed6 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -34,6 +34,7 @@
>  #include "standard-headers/linux/virtio_ring.h"
>  #include "hw/virtio/vhost.h"
>  #include "hw/virtio/virtio-bus.h"
> +#include "linux-headers/linux/vhost.h"
>
>
>  /* Features supported by host kernel. */
> @@ -556,3 +557,55 @@ void vhost_net_virtqueue_reset(VirtIODevice *vdev, 
> NetClientState *nc,
>   net->dev.vqs + idx,
>   net->dev.vq_index + idx);
>  }
> +
> +int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
> +int vq_index)
> +{
> +VHostNetState *net = get_vhost_net(nc->peer);
> +const VhostOps *vhost_ops = net->dev.vhost_ops;
> +struct vhost_vring_file file = { };
> +int idx, r;
> +
> +if (!net->dev.started) {
> +return -EBUSY;
> +}
> +
> +/* should only be called after backend is connected */
> +assert(vhost_ops);
> +
> +idx = vhost_ops->vhost_get_vq_index(>dev, vq_index);
> +
> +r = vhost_virtqueue_start(>dev,
> +  vdev,
> +  net->dev.vqs + idx,
> +  net->dev.vq_index + idx);
> +if (r < 0) {
> +goto err_start;
> +}
> +
> +if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
> +file.index = idx;
> +file.fd = net->backend;
> +r = vhost_net_set_backend(>dev, );
> +if (r < 0) {
> +r = -errno;
> +goto err_start;
> +}
> +}
> +
> +return 0;
> +
> +err_start:
> +error_report("Error when restarting the queue.");
> +
> +if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
> +file.fd = VHOST_FILE_UNBIND;
> +file.index = idx;
> +int r = vhost_net_set_backend(>dev, );
> +assert(r >= 0);
> +}
> +
> +vhost_dev_stop(>dev, vdev);
> +
> +return r;
> +}
> diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
> index 85d85a4957..40b9a40074 100644
> --- a/include/net/vhost_net.h
> +++ b/include/net/vhost_net.h
> @@ -50,4 +50,6 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
>
>  void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
> int vq_index);
> +int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
> +int vq_index);
>  #endif
> --
> 2.32.0.3.g01195cf9f
>




Re: [PATCH v8 06/14] net: stream: Don't ignore EINVAL on netdev socket connection

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:52AM +0200, Laurent Vivier wrote:
> From: Stefano Brivio 
> 
> Other errors are treated as failure by net_stream_client_init(),
> but if connect() returns EINVAL, we'll fail silently. Remove the
> related exception.

Is this also a bug in net_socket_connect_init()?  Is there an
equivalent bug in dgram.c?

> Signed-off-by: Stefano Brivio 
> [lvivier: applied to net/stream.c]
> Signed-off-by: Laurent Vivier 
> Reviewed-by: Daniel P. Berrangé 
> ---
>  net/stream.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/net/stream.c b/net/stream.c
> index 0851e90becca..e8afbaca50b6 100644
> --- a/net/stream.c
> +++ b/net/stream.c
> @@ -363,8 +363,7 @@ static int net_stream_client_init(NetClientState *peer,
>  if (errno == EINTR || errno == EWOULDBLOCK) {
>  /* continue */
>  } else if (errno == EINPROGRESS ||
> -   errno == EALREADY ||
> -   errno == EINVAL) {
> +   errno == EALREADY) {
>  break;
>  } else {
>  error_setg_errno(errp, errno, "can't connect socket");

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


[PATCH v5 03/15] virtio: introduce virtio_queue_reset()

2022-09-13 Thread Xuan Zhuo
Introduce a new interface function virtio_queue_reset() to implement
reset for vq.

Add a new callback to VirtioDeviceClass for queue reset operation for
each child device.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/virtio/virtio.c | 11 +++
 include/hw/virtio/virtio.h |  2 ++
 2 files changed, 13 insertions(+)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 67d54832a9..0e9d41366f 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2039,6 +2039,17 @@ static void __virtio_queue_reset(VirtIODevice *vdev, 
uint32_t i)
 virtio_virtqueue_reset_region_cache(>vq[i]);
 }
 
+void virtio_queue_reset(VirtIODevice *vdev, uint32_t queue_index)
+{
+VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+
+if (k->queue_reset) {
+k->queue_reset(vdev, queue_index);
+}
+
+__virtio_queue_reset(vdev, queue_index);
+}
+
 void virtio_reset(void *opaque)
 {
 VirtIODevice *vdev = opaque;
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index db1c0ddf6b..879394299b 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -130,6 +130,7 @@ struct VirtioDeviceClass {
 void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
 void (*reset)(VirtIODevice *vdev);
 void (*set_status)(VirtIODevice *vdev, uint8_t val);
+void (*queue_reset)(VirtIODevice *vdev, uint32_t queue_index);
 /* For transitional devices, this is a bitmap of features
  * that are only exposed on the legacy interface but not
  * the modern one.
@@ -268,6 +269,7 @@ int virtio_queue_set_host_notifier_mr(VirtIODevice *vdev, 
int n,
   MemoryRegion *mr, bool assign);
 int virtio_set_status(VirtIODevice *vdev, uint8_t val);
 void virtio_reset(void *opaque);
+void virtio_queue_reset(VirtIODevice *vdev, uint32_t queue_index);
 void virtio_update_irq(VirtIODevice *vdev);
 int virtio_set_features(VirtIODevice *vdev, uint64_t val);
 
-- 
2.32.0.3.g01195cf9f




[PATCH v5 01/15] virtio: sync relevant definitions with linux

2022-09-13 Thread Xuan Zhuo
This is updated using scripts/update-linux-headers.sh.

Added VIRTIO_F_RING_RESET, VIRTIO_PCI_COMMON_Q_RESET. It came from here:
https://github.com/oasis-tcs/virtio-spec/issues/124
https://github.com/oasis-tcs/virtio-spec/issues/139

Add VIRTIO_PCI_COMMON_Q_NDATA, which comes from here:
https://github.com/oasis-tcs/virtio-spec/issues/89

Signed-off-by: Xuan Zhuo 
Signed-off-by: Kangjie Xu 
Acked-by: Jason Wang 
---
 include/standard-headers/linux/virtio_config.h | 5 +
 include/standard-headers/linux/virtio_pci.h| 2 ++
 2 files changed, 7 insertions(+)

diff --git a/include/standard-headers/linux/virtio_config.h 
b/include/standard-headers/linux/virtio_config.h
index 7acd8d4abc..47a7eef5e4 100644
--- a/include/standard-headers/linux/virtio_config.h
+++ b/include/standard-headers/linux/virtio_config.h
@@ -96,4 +96,9 @@
  * Does the device support Single Root I/O Virtualization?
  */
 #define VIRTIO_F_SR_IOV37
+
+/*
+ * This feature indicates that the driver can reset a queue individually.
+ */
+#define VIRTIO_F_RING_RESET40
 #endif /* _LINUX_VIRTIO_CONFIG_H */
diff --git a/include/standard-headers/linux/virtio_pci.h 
b/include/standard-headers/linux/virtio_pci.h
index db7a8e2fcb..be912cfc95 100644
--- a/include/standard-headers/linux/virtio_pci.h
+++ b/include/standard-headers/linux/virtio_pci.h
@@ -202,6 +202,8 @@ struct virtio_pci_cfg_cap {
 #define VIRTIO_PCI_COMMON_Q_AVAILHI44
 #define VIRTIO_PCI_COMMON_Q_USEDLO 48
 #define VIRTIO_PCI_COMMON_Q_USEDHI 52
+#define VIRTIO_PCI_COMMON_Q_NDATA  56
+#define VIRTIO_PCI_COMMON_Q_RESET  58
 
 #endif /* VIRTIO_PCI_NO_MODERN */
 
-- 
2.32.0.3.g01195cf9f




Re: [PATCH v8 02/14] net: remove the @errp argument of net_client_inits()

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:48AM +0200, Laurent Vivier wrote:
> The only caller passes _fatal, so use this directly in the function.
> 
> It's what we do for -blockdev, -device, and -object.
> 
> Suggested-by: Markus Armbruster 
> Signed-off-by: Laurent Vivier 
> Reviewed-by: Markus Armbruster 

Reviewed-by: David Gibson 

> ---
>  include/net/net.h |  2 +-
>  net/net.c | 20 +++-
>  softmmu/vl.c  |  2 +-
>  3 files changed, 9 insertions(+), 15 deletions(-)
> 
> diff --git a/include/net/net.h b/include/net/net.h
> index 81d0b21defce..c1c34a58f849 100644
> --- a/include/net/net.h
> +++ b/include/net/net.h
> @@ -222,7 +222,7 @@ extern const char *host_net_devices[];
>  /* from net.c */
>  int net_client_parse(QemuOptsList *opts_list, const char *str);
>  void show_netdevs(void);
> -int net_init_clients(Error **errp);
> +void net_init_clients(void);
>  void net_check_clients(void);
>  void net_cleanup(void);
>  void hmp_host_net_add(Monitor *mon, const QDict *qdict);
> diff --git a/net/net.c b/net/net.c
> index d2288bd3a929..15958f881776 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -1562,27 +1562,21 @@ out:
>  return ret;
>  }
>  
> -int net_init_clients(Error **errp)
> +void net_init_clients(void)
>  {
>  net_change_state_entry =
>  qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL);
>  
>  QTAILQ_INIT(_clients);
>  
> -if (qemu_opts_foreach(qemu_find_opts("netdev"),
> -  net_init_netdev, NULL, errp)) {
> -return -1;
> -}
> -
> -if (qemu_opts_foreach(qemu_find_opts("nic"), net_param_nic, NULL, errp)) 
> {
> -return -1;
> -}
> +qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL,
> +  _fatal);
>  
> -if (qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL, 
> errp)) {
> -return -1;
> -}
> +qemu_opts_foreach(qemu_find_opts("nic"), net_param_nic, NULL,
> +  _fatal);
>  
> -return 0;
> +qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL,
> +  _fatal);
>  }
>  
>  int net_client_parse(QemuOptsList *opts_list, const char *optarg)
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index dea4005e4791..1fe8b5c5a120 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -1906,7 +1906,7 @@ static void qemu_create_late_backends(void)
>  qtest_server_init(qtest_chrdev, qtest_log, _fatal);
>  }
>  
> -net_init_clients(_fatal);
> +net_init_clients();
>  
>  object_option_foreach_add(object_create_late);
>  

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [PATCH v8 11/14] qemu-sockets: move and rename SocketAddress_to_str()

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:57AM +0200, Laurent Vivier wrote:
> Rename SocketAddress_to_str() to socket_uri() and move it to
> util/qemu-sockets.c close to socket_parse().
> 
> socket_uri() generates a string from a SocketAddress while
> socket_parse() generates a SocketAddress from a string.
> 
> Signed-off-by: Laurent Vivier 

Reviewed-by: David Gibson 

> ---
>  include/qemu/sockets.h |  2 +-
>  monitor/hmp-cmds.c | 23 +--
>  util/qemu-sockets.c| 20 
>  3 files changed, 22 insertions(+), 23 deletions(-)
> 
> diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
> index 47194b9732f8..e5a06d2e3729 100644
> --- a/include/qemu/sockets.h
> +++ b/include/qemu/sockets.h
> @@ -40,6 +40,7 @@ NetworkAddressFamily inet_netfamily(int family);
>  int unix_listen(const char *path, Error **errp);
>  int unix_connect(const char *path, Error **errp);
>  
> +char *socket_uri(SocketAddress *addr);
>  SocketAddress *socket_parse(const char *str, Error **errp);
>  int socket_connect(SocketAddress *addr, Error **errp);
>  int socket_listen(SocketAddress *addr, int num, Error **errp);
> @@ -123,5 +124,4 @@ SocketAddress *socket_address_flatten(SocketAddressLegacy 
> *addr);
>   * Return 0 on success.
>   */
>  int socket_address_parse_named_fd(SocketAddress *addr, Error **errp);
> -
>  #endif /* QEMU_SOCKETS_H */
> diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
> index c6cd6f91dde6..cb35059c2d45 100644
> --- a/monitor/hmp-cmds.c
> +++ b/monitor/hmp-cmds.c
> @@ -197,27 +197,6 @@ void hmp_info_mice(Monitor *mon, const QDict *qdict)
>  qapi_free_MouseInfoList(mice_list);
>  }
>  
> -static char *SocketAddress_to_str(SocketAddress *addr)
> -{
> -switch (addr->type) {
> -case SOCKET_ADDRESS_TYPE_INET:
> -return g_strdup_printf("tcp:%s:%s",
> -   addr->u.inet.host,
> -   addr->u.inet.port);
> -case SOCKET_ADDRESS_TYPE_UNIX:
> -return g_strdup_printf("unix:%s",
> -   addr->u.q_unix.path);
> -case SOCKET_ADDRESS_TYPE_FD:
> -return g_strdup_printf("fd:%s", addr->u.fd.str);
> -case SOCKET_ADDRESS_TYPE_VSOCK:
> -return g_strdup_printf("tcp:%s:%s",
> -   addr->u.vsock.cid,
> -   addr->u.vsock.port);
> -default:
> -return g_strdup("unknown address type");
> -}
> -}
> -
>  void hmp_info_migrate(Monitor *mon, const QDict *qdict)
>  {
>  MigrationInfo *info;
> @@ -380,7 +359,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
>  monitor_printf(mon, "socket address: [\n");
>  
>  for (addr = info->socket_address; addr; addr = addr->next) {
> -char *s = SocketAddress_to_str(addr->value);
> +char *s = socket_uri(addr->value);
>  monitor_printf(mon, "\t%s\n", s);
>  g_free(s);
>  }
> diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
> index 83f4bd6fd211..9f6f655fd526 100644
> --- a/util/qemu-sockets.c
> +++ b/util/qemu-sockets.c
> @@ -1077,6 +1077,26 @@ int unix_connect(const char *path, Error **errp)
>  return sock;
>  }
>  
> +char *socket_uri(SocketAddress *addr)
> +{
> +switch (addr->type) {
> +case SOCKET_ADDRESS_TYPE_INET:
> +return g_strdup_printf("tcp:%s:%s",
> +   addr->u.inet.host,
> +   addr->u.inet.port);
> +case SOCKET_ADDRESS_TYPE_UNIX:
> +return g_strdup_printf("unix:%s",
> +   addr->u.q_unix.path);
> +case SOCKET_ADDRESS_TYPE_FD:
> +return g_strdup_printf("fd:%s", addr->u.fd.str);
> +case SOCKET_ADDRESS_TYPE_VSOCK:
> +return g_strdup_printf("tcp:%s:%s",
> +   addr->u.vsock.cid,
> +   addr->u.vsock.port);
> +default:
> +return g_strdup("unknown address type");
> +}
> +}
>  
>  SocketAddress *socket_parse(const char *str, Error **errp)
>  {

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


[PATCH v5 10/15] vhost-net: vhost-kernel: introduce vhost_net_virtqueue_reset()

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Introduce vhost_virtqueue_reset(), which can reset the specific
virtqueue in the device. Then it will unmap vrings and the desc
of the virtqueue.

Here we do not reuse the vhost_net_stop_one() or vhost_dev_stop(),
because they work at queue pair level. We do not use
vhost_virtqueue_stop() because it may stop the device in the
backend.

This patch only considers the case of vhost-kernel, when
NetClientDriver is NET_CLIENT_DRIVER_TAP.

Furthermore, we do not need net->nc->info->poll() because
it enables userspace datapath and we want to stop all
datapaths for this reset virtqueue here.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/net/vhost_net.c  | 25 +
 include/net/vhost_net.h |  2 ++
 2 files changed, 27 insertions(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index d28f8b974b..8beecb4d22 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -531,3 +531,28 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
 
 return vhost_ops->vhost_net_set_mtu(>dev, mtu);
 }
+
+void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
+   int vq_index)
+{
+VHostNetState *net = get_vhost_net(nc->peer);
+const VhostOps *vhost_ops = net->dev.vhost_ops;
+struct vhost_vring_file file = { .fd = -1 };
+int idx;
+
+/* should only be called after backend is connected */
+assert(vhost_ops);
+
+idx = vhost_ops->vhost_get_vq_index(>dev, vq_index);
+
+if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
+file.index = idx;
+int r = vhost_net_set_backend(>dev, );
+assert(r >= 0);
+}
+
+vhost_virtqueue_stop(>dev,
+ vdev,
+ net->dev.vqs + idx,
+ net->dev.vq_index + idx);
+}
diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index 387e913e4e..85d85a4957 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -48,4 +48,6 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net);
 
 int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
 
+void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
+   int vq_index);
 #endif
-- 
2.32.0.3.g01195cf9f




[PATCH v5 05/15] virtio: core: vq reset feature negotation support

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

A a new command line parameter "queue_reset" is added.

Meanwhile, the vq reset feature is disabled for pre-7.2 machines.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/core/machine.c  | 4 +++-
 include/hw/virtio/virtio.h | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index aa520e74a8..907fa78ff0 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -40,7 +40,9 @@
 #include "hw/virtio/virtio-pci.h"
 #include "qom/object_interfaces.h"
 
-GlobalProperty hw_compat_7_1[] = {};
+GlobalProperty hw_compat_7_1[] = {
+{ "virtio-device", "queue_reset", "false" },
+};
 const size_t hw_compat_7_1_len = G_N_ELEMENTS(hw_compat_7_1);
 
 GlobalProperty hw_compat_7_0[] = {
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 085997d8f3..ed3ecbef80 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -295,7 +295,9 @@ typedef struct VirtIORNGConf VirtIORNGConf;
 DEFINE_PROP_BIT64("iommu_platform", _state, _field, \
   VIRTIO_F_IOMMU_PLATFORM, false), \
 DEFINE_PROP_BIT64("packed", _state, _field, \
-  VIRTIO_F_RING_PACKED, false)
+  VIRTIO_F_RING_PACKED, false), \
+DEFINE_PROP_BIT64("queue_reset", _state, _field, \
+  VIRTIO_F_RING_RESET, true)
 
 hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n);
 bool virtio_queue_enabled_legacy(VirtIODevice *vdev, int n);
-- 
2.32.0.3.g01195cf9f




[PATCH v5 08/15] vhost: expose vhost_virtqueue_start()

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Expose vhost_virtqueue_start(), we need to use it when restarting a
virtqueue.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/virtio/vhost.c | 8 
 include/hw/virtio/vhost.h | 3 +++
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index f758f177bb..7900bc81ab 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1081,10 +1081,10 @@ out:
 return ret;
 }
 
-static int vhost_virtqueue_start(struct vhost_dev *dev,
-struct VirtIODevice *vdev,
-struct vhost_virtqueue *vq,
-unsigned idx)
+int vhost_virtqueue_start(struct vhost_dev *dev,
+  struct VirtIODevice *vdev,
+  struct vhost_virtqueue *vq,
+  unsigned idx)
 {
 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
 VirtioBusState *vbus = VIRTIO_BUS(qbus);
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index a346f23d13..b092f57d98 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -279,6 +279,9 @@ int vhost_net_set_backend(struct vhost_dev *hdev,
 
 int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write);
 
+int vhost_virtqueue_start(struct vhost_dev *dev, struct VirtIODevice *vdev,
+  struct vhost_virtqueue *vq, unsigned idx);
+
 void vhost_dev_reset_inflight(struct vhost_inflight *inflight);
 void vhost_dev_free_inflight(struct vhost_inflight *inflight);
 void vhost_dev_save_inflight(struct vhost_inflight *inflight, QEMUFile *f);
-- 
2.32.0.3.g01195cf9f




[PATCH v5 12/15] virtio-net: introduce flush_or_purge_queued_packets()

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Introduce the fucntion flush_or_purge_queued_packets(), it will be
used in device reset and virtqueue reset. Therefore, we extract the
common logic as a new function.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/net/virtio-net.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index dd0d056fde..27b59c0ad6 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -118,6 +118,16 @@ static int vq2q(int queue_index)
 return queue_index / 2;
 }
 
+static void flush_or_purge_queued_packets(NetClientState *nc)
+{
+if (!nc->peer) {
+return;
+}
+
+qemu_flush_or_purge_queued_packets(nc->peer, true);
+assert(!virtio_net_get_subqueue(nc)->async_tx.elem);
+}
+
 /* TODO
  * - we could suppress RX interrupt if we were so inclined.
  */
@@ -560,12 +570,7 @@ static void virtio_net_reset(VirtIODevice *vdev)
 
 /* Flush any async TX */
 for (i = 0;  i < n->max_queue_pairs; i++) {
-NetClientState *nc = qemu_get_subqueue(n->nic, i);
-
-if (nc->peer) {
-qemu_flush_or_purge_queued_packets(nc->peer, true);
-assert(!virtio_net_get_subqueue(nc)->async_tx.elem);
-}
+flush_or_purge_queued_packets(qemu_get_subqueue(n->nic, i));
 }
 }
 
-- 
2.32.0.3.g01195cf9f




[PATCH v5 15/15] vhost: vhost-kernel: enable vq reset feature

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Add virtqueue reset feature for vhost-kernel.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
---
 hw/net/vhost_net.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index d2926e2ed6..53b2fac4f6 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -47,6 +47,7 @@ static const int kernel_feature_bits[] = {
 VIRTIO_NET_F_MTU,
 VIRTIO_F_IOMMU_PLATFORM,
 VIRTIO_F_RING_PACKED,
+VIRTIO_F_RING_RESET,
 VIRTIO_NET_F_HASH_REPORT,
 VHOST_INVALID_FEATURE_BIT
 };
-- 
2.32.0.3.g01195cf9f




[PATCH v5 14/15] virtio-net: support queue_enable

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Support queue_enable in vhost-kernel scenario. It can be called when
a vq reset operation has been performed and the vq is restared.

It should be noted that we can restart the vq when the vhost has
already started. When launching a new vhost device, the vhost is not
started and all vqs are not initalized until VIRTIO_PCI_COMMON_STATUS
is written. Thus, we should use vhost_started to differentiate the
two cases: vq reset and device start.

Currently it only supports vhost-kernel.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/net/virtio-net.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index d774a3e652..7817206596 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -557,6 +557,26 @@ static void virtio_net_queue_reset(VirtIODevice *vdev, 
uint32_t queue_index)
 flush_or_purge_queued_packets(nc);
 }
 
+static void virtio_net_queue_enable(VirtIODevice *vdev, uint32_t queue_index)
+{
+VirtIONet *n = VIRTIO_NET(vdev);
+NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(queue_index));
+int r;
+
+if (!nc->peer || !vdev->vhost_started) {
+return;
+}
+
+if (get_vhost_net(nc->peer) &&
+nc->peer->info->type == NET_CLIENT_DRIVER_TAP) {
+r = vhost_net_virtqueue_restart(vdev, nc, queue_index);
+if (r < 0) {
+error_report("unable to restart vhost net virtqueue: %d, "
+"when resetting the queue", queue_index);
+}
+}
+}
+
 static void virtio_net_reset(VirtIODevice *vdev)
 {
 VirtIONet *n = VIRTIO_NET(vdev);
@@ -3802,6 +3822,7 @@ static void virtio_net_class_init(ObjectClass *klass, 
void *data)
 vdc->bad_features = virtio_net_bad_features;
 vdc->reset = virtio_net_reset;
 vdc->queue_reset = virtio_net_queue_reset;
+vdc->queue_enable = virtio_net_queue_enable;
 vdc->set_status = virtio_net_set_status;
 vdc->guest_notifier_mask = virtio_net_guest_notifier_mask;
 vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;
-- 
2.32.0.3.g01195cf9f




Re: [PATCH v5 15/15] vhost: vhost-kernel: enable vq reset feature

2022-09-13 Thread Jason Wang
On Wed, Sep 14, 2022 at 12:21 PM Xuan Zhuo  wrote:
>
> From: Kangjie Xu 
>
> Add virtqueue reset feature for vhost-kernel.
>
> Signed-off-by: Kangjie Xu 
> Signed-off-by: Xuan Zhuo 

Acked-by: Jason Wang 

> ---
>  hw/net/vhost_net.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index d2926e2ed6..53b2fac4f6 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -47,6 +47,7 @@ static const int kernel_feature_bits[] = {
>  VIRTIO_NET_F_MTU,
>  VIRTIO_F_IOMMU_PLATFORM,
>  VIRTIO_F_RING_PACKED,
> +VIRTIO_F_RING_RESET,
>  VIRTIO_NET_F_HASH_REPORT,
>  VHOST_INVALID_FEATURE_BIT
>  };
> --
> 2.32.0.3.g01195cf9f
>




[PATCH v5 06/15] virtio-pci: support queue reset

2022-09-13 Thread Xuan Zhuo
PCI devices support vq reset.

Based on this function, the driver can adjust the size of the ring, and
quickly recycle the buffer in the ring.

The migration of the virtio devices will not happen during a reset
operation. This is becuase the global iothread lock is held. Migration
thread also needs the lock. As a result, when migration of virtio
devices starts, the 'reset' status of VirtIOPCIQueue will always be 0.
Thus, we do not need to add it in vmstate_virtio_pci_modern_queue_state.

Signed-off-by: Xuan Zhuo 
Signed-off-by: Kangjie Xu 
Acked-by: Jason Wang 
---
 hw/virtio/virtio-pci.c | 15 +++
 include/hw/virtio/virtio-pci.h |  5 +
 2 files changed, 20 insertions(+)

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index a50c5a57d7..79b9e641dd 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1251,6 +1251,9 @@ static uint64_t virtio_pci_common_read(void *opaque, 
hwaddr addr,
 case VIRTIO_PCI_COMMON_Q_USEDHI:
 val = proxy->vqs[vdev->queue_sel].used[1];
 break;
+case VIRTIO_PCI_COMMON_Q_RESET:
+val = proxy->vqs[vdev->queue_sel].reset;
+break;
 default:
 val = 0;
 }
@@ -1338,6 +1341,7 @@ static void virtio_pci_common_write(void *opaque, hwaddr 
addr,
((uint64_t)proxy->vqs[vdev->queue_sel].used[1]) << 32 |
proxy->vqs[vdev->queue_sel].used[0]);
 proxy->vqs[vdev->queue_sel].enabled = 1;
+proxy->vqs[vdev->queue_sel].reset = 0;
 } else {
 virtio_error(vdev, "wrong value for queue_enable %"PRIx64, val);
 }
@@ -1360,6 +1364,16 @@ static void virtio_pci_common_write(void *opaque, hwaddr 
addr,
 case VIRTIO_PCI_COMMON_Q_USEDHI:
 proxy->vqs[vdev->queue_sel].used[1] = val;
 break;
+case VIRTIO_PCI_COMMON_Q_RESET:
+if (val == 1) {
+proxy->vqs[vdev->queue_sel].reset = 1;
+
+virtio_queue_reset(vdev, vdev->queue_sel);
+
+proxy->vqs[vdev->queue_sel].reset = 0;
+proxy->vqs[vdev->queue_sel].enabled = 0;
+}
+break;
 default:
 break;
 }
@@ -1954,6 +1968,7 @@ static void virtio_pci_reset(DeviceState *qdev)
 
 for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
 proxy->vqs[i].enabled = 0;
+proxy->vqs[i].reset = 0;
 proxy->vqs[i].num = 0;
 proxy->vqs[i].desc[0] = proxy->vqs[i].desc[1] = 0;
 proxy->vqs[i].avail[0] = proxy->vqs[i].avail[1] = 0;
diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h
index 2446dcd9ae..938799e8f6 100644
--- a/include/hw/virtio/virtio-pci.h
+++ b/include/hw/virtio/virtio-pci.h
@@ -117,6 +117,11 @@ typedef struct VirtIOPCIRegion {
 typedef struct VirtIOPCIQueue {
   uint16_t num;
   bool enabled;
+  /*
+   * No need to migrate the reset status, because it is always 0
+   * when the migration starts.
+   */
+  bool reset;
   uint32_t desc[2];
   uint32_t avail[2];
   uint32_t used[2];
-- 
2.32.0.3.g01195cf9f




[PATCH v5 00/15] Support VIRTIO_F_RING_RESET for virtio-net, vhost-net kernel in virtio pci-modern

2022-09-13 Thread Xuan Zhuo
The virtio queue reset function has already been defined in the virtio spec 1.2.
The relevant virtio spec information is here:

https://github.com/oasis-tcs/virtio-spec/issues/124
https://github.com/oasis-tcs/virtio-spec/issues/139

This patch set is to support this function in QEMU. It consists of several 
parts:
1. Patches 1-7 are the basic interfaces for vq reset in virtio and virtio-pci.
2. Patches 8-11 support vq reset and vq restart for vhost-kernel.
3. Patches 12-14 support vq reset and vq restart for virtio-net.
5. Patch 15 enables the vq reset feature for vhost-kernel.

The process of virtqueue reset can be concluded as:
1. The virtqueue is disabled when VIRTIO_PCI_COMMON_Q_RESET is written.
2. Then the virtqueue can be optionally restarted(re-enabled).

Since this patch set involves multiple modules and seems a bit messy, we 
briefly describe the
calling process for different modes below.
virtio-net:
1. VIRTIO_PCI_COMMON_Q_RESET is written [virtio-pci]
-> virtio_queue_reset() [virtio]
-> virtio_net_queue_reset() [virtio-net]
-> __virtio_queue_reset()
2. VIRTIO_PCI_COMMON_Q_ENABLE is written [virtio-pci]
-> set enabled, reset status of vq.

vhost-kernel:
1. VIRTIO_PCI_COMMON_Q_RESET is written [virtio-pci]
-> virtio_queue_reset() [virtio]
-> virtio_net_queue_reset() [virtio-net]
-> vhost_net_virtqueue_stop() [vhost-net]
-> vhost_net_set_backend() [vhost]
-> vhost_virtqueue_stop()
-> __virtio_queue_reset()
2. VIRTIO_PCI_COMMON_Q_ENABLE is written [virtio-pci]
-> virtio_queue_enable() [virtio]
-> virtio_net_queue_enable() [virtio-net]
-> vhost_net_virtqueue_restart() [vhost-net]
-> vhost_virtqueue_start() [vhost]
-> vhost_net_set_backend()
-> set enabled, reset status of vq.


Test environment and method:
Host: 5.19.0-rc3 (With vq reset support)
Qemu: QEMU emulator version 7.0.50
Guest: 5.19.0-rc3 (With vq reset support)
Test Cmd: ethtool -g eth1; ethtool -G eth1 rx $1 tx $2; ethtool -g eth1;

The drvier can resize the virtio queue, then virtio queue reset function 
should
be triggered.

The default is split mode, modify Qemu virtio-net to add PACKED feature to
test packed mode.

Guest Kernel Patch:

https://lore.kernel.org/bpf/20220801063902.129329-1-xuanz...@linux.alibaba.com/

Host Kernel Patch:

https://lore.kernel.org/bpf/20220825085610.80315-1-kangjie...@linux.alibaba.com/

Looking forward to your review and comments. Thanks.

changelog:

v5:
  1. vhost_net_virtqueue_restart() use -EBUSY replace -ENOTSUP. @Jason
  2. reuse  VHOST_FILE_UNBIND. @Jason

v4:
  1. Add explanation for preventing userspace datapath in virtio-net.
  2. Return error when vhost is not started in vhost_net_virtqueue_restart().
  3. Reset the virtqueue in the device reusing vhost_virtqueue_stop().
  4. Disable queue reset feature for pre-7.2 machine.

v3:
  1. Remove support for vhost-user in this series and refactor the code.
  2. Rename 'vhost_net_virtqueue_stop' to 'vhost_net_virtqueue_reset'.
  3. Make PCI transport ready before device ready when queue_enabled is set to 
true.
  4. Add some comments.

v2:
  1. Add support for vhost-net kernel scenario.
  2. Add a new vhost-user message VHOST_USER_RESET_VRING.
  3. Add migration compatibility for virtqueue reset.

Kangjie Xu (10):
  virtio: introduce virtio_queue_enable()
  virtio: core: vq reset feature negotation support
  virtio-pci: support queue enable
  vhost: expose vhost_virtqueue_start()
  vhost: expose vhost_virtqueue_stop()
  vhost-net: vhost-kernel: introduce vhost_net_virtqueue_reset()
  vhost-net: vhost-kernel: introduce vhost_net_virtqueue_restart()
  virtio-net: introduce flush_or_purge_queued_packets()
  virtio-net: support queue_enable
  vhost: vhost-kernel: enable vq reset feature

Xuan Zhuo (5):
  virtio: sync relevant definitions with linux
  virtio: introduce __virtio_queue_reset()
  virtio: introduce virtio_queue_reset()
  virtio-pci: support queue reset
  virtio-net: support queue reset

 hw/core/machine.c |  4 +-
 hw/net/vhost_net.c| 79 +++
 hw/net/virtio-net.c   | 56 +++--
 hw/virtio/vhost.c | 16 ++--
 hw/virtio/virtio-pci.c| 16 
 hw/virtio/virtio.c| 62 +++
 include/hw/virtio/vhost.h |  5 ++
 include/hw/virtio/virtio-pci.h|  5 ++
 include/hw/virtio/virtio.h|  8 +-
 include/net/vhost_net.h   |  4 +
 .../standard-headers/linux/virtio_config.h|  5 ++
 include/standard-headers/linux/virtio_pci.h   |  2 +
 12 files changed, 230 insertions(+), 32 deletions(-)

--
2.32.0.3.g01195cf9f




[PATCH v5 11/15] vhost-net: vhost-kernel: introduce vhost_net_virtqueue_restart()

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Introduce vhost_net_virtqueue_restart(), which can restart the
specific virtqueue when the vhost net started running before.
If it fails to restart the virtqueue, the device will be stopped.

Here we do not reuse vhost_net_start_one() or vhost_dev_start()
because they work at queue pair level. The mem table and features
do not change, so we can call the vhost_virtqueue_start() to
restart a specific queue.

This patch only considers the case of vhost-kernel, when
NetClientDriver is NET_CLIENT_DRIVER_TAP.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
---
 hw/net/vhost_net.c  | 53 +
 include/net/vhost_net.h |  2 ++
 2 files changed, 55 insertions(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 8beecb4d22..d2926e2ed6 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -34,6 +34,7 @@
 #include "standard-headers/linux/virtio_ring.h"
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/virtio-bus.h"
+#include "linux-headers/linux/vhost.h"
 
 
 /* Features supported by host kernel. */
@@ -556,3 +557,55 @@ void vhost_net_virtqueue_reset(VirtIODevice *vdev, 
NetClientState *nc,
  net->dev.vqs + idx,
  net->dev.vq_index + idx);
 }
+
+int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
+int vq_index)
+{
+VHostNetState *net = get_vhost_net(nc->peer);
+const VhostOps *vhost_ops = net->dev.vhost_ops;
+struct vhost_vring_file file = { };
+int idx, r;
+
+if (!net->dev.started) {
+return -EBUSY;
+}
+
+/* should only be called after backend is connected */
+assert(vhost_ops);
+
+idx = vhost_ops->vhost_get_vq_index(>dev, vq_index);
+
+r = vhost_virtqueue_start(>dev,
+  vdev,
+  net->dev.vqs + idx,
+  net->dev.vq_index + idx);
+if (r < 0) {
+goto err_start;
+}
+
+if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
+file.index = idx;
+file.fd = net->backend;
+r = vhost_net_set_backend(>dev, );
+if (r < 0) {
+r = -errno;
+goto err_start;
+}
+}
+
+return 0;
+
+err_start:
+error_report("Error when restarting the queue.");
+
+if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
+file.fd = VHOST_FILE_UNBIND;
+file.index = idx;
+int r = vhost_net_set_backend(>dev, );
+assert(r >= 0);
+}
+
+vhost_dev_stop(>dev, vdev);
+
+return r;
+}
diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index 85d85a4957..40b9a40074 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -50,4 +50,6 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
 
 void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
int vq_index);
+int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
+int vq_index);
 #endif
-- 
2.32.0.3.g01195cf9f




[PATCH v5 13/15] virtio-net: support queue reset

2022-09-13 Thread Xuan Zhuo
virtio-net and vhost-kernel implement queue reset.
Queued packets in the corresponding queue pair are flushed
or purged.

For virtio-net, userspace datapath will be disabled later in
__virtio_queue_reset(). It will set addr of vring to 0 and idx to 0.
Thus, virtio_net_receive() and virtio_net_flush_tx() will not receive
or send packets.

For vhost-net, the datapath will be disabled in vhost_net_virtqueue_reset().

Signed-off-by: Xuan Zhuo 
Signed-off-by: Kangjie Xu 
Acked-by: Jason Wang 
---
 hw/net/virtio-net.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 27b59c0ad6..d774a3e652 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -540,6 +540,23 @@ static RxFilterInfo 
*virtio_net_query_rxfilter(NetClientState *nc)
 return info;
 }
 
+static void virtio_net_queue_reset(VirtIODevice *vdev, uint32_t queue_index)
+{
+VirtIONet *n = VIRTIO_NET(vdev);
+NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(queue_index));
+
+if (!nc->peer) {
+return;
+}
+
+if (get_vhost_net(nc->peer) &&
+nc->peer->info->type == NET_CLIENT_DRIVER_TAP) {
+vhost_net_virtqueue_reset(vdev, nc, queue_index);
+}
+
+flush_or_purge_queued_packets(nc);
+}
+
 static void virtio_net_reset(VirtIODevice *vdev)
 {
 VirtIONet *n = VIRTIO_NET(vdev);
@@ -3784,6 +3801,7 @@ static void virtio_net_class_init(ObjectClass *klass, 
void *data)
 vdc->set_features = virtio_net_set_features;
 vdc->bad_features = virtio_net_bad_features;
 vdc->reset = virtio_net_reset;
+vdc->queue_reset = virtio_net_queue_reset;
 vdc->set_status = virtio_net_set_status;
 vdc->guest_notifier_mask = virtio_net_guest_notifier_mask;
 vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;
-- 
2.32.0.3.g01195cf9f




[PATCH v8 03/14] net: simplify net_client_parse() error management

2022-09-13 Thread Laurent Vivier
All net_client_parse() callers exit in case of error.

Move exit(1) to net_client_parse() and remove error checking from
the callers.

Suggested-by: Markus Armbruster 
Signed-off-by: Laurent Vivier 
Reviewed-by: Markus Armbruster 
---
 include/net/net.h |  2 +-
 net/net.c |  6 ++
 softmmu/vl.c  | 12 +++-
 3 files changed, 6 insertions(+), 14 deletions(-)

diff --git a/include/net/net.h b/include/net/net.h
index c1c34a58f849..55023e7e9fa9 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -220,7 +220,7 @@ extern NICInfo nd_table[MAX_NICS];
 extern const char *host_net_devices[];
 
 /* from net.c */
-int net_client_parse(QemuOptsList *opts_list, const char *str);
+void net_client_parse(QemuOptsList *opts_list, const char *str);
 void show_netdevs(void);
 void net_init_clients(void);
 void net_check_clients(void);
diff --git a/net/net.c b/net/net.c
index 15958f881776..f056e8aebfb2 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1579,13 +1579,11 @@ void net_init_clients(void)
   _fatal);
 }
 
-int net_client_parse(QemuOptsList *opts_list, const char *optarg)
+void net_client_parse(QemuOptsList *opts_list, const char *optarg)
 {
 if (!qemu_opts_parse_noisily(opts_list, optarg, true)) {
-return -1;
+exit(1);
 }
-
-return 0;
 }
 
 /* From FreeBSD */
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 1fe8b5c5a120..55d163475e9e 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2809,21 +2809,15 @@ void qemu_init(int argc, char **argv, char **envp)
 break;
 case QEMU_OPTION_netdev:
 default_net = 0;
-if (net_client_parse(qemu_find_opts("netdev"), optarg) == -1) {
-exit(1);
-}
+net_client_parse(qemu_find_opts("netdev"), optarg);
 break;
 case QEMU_OPTION_nic:
 default_net = 0;
-if (net_client_parse(qemu_find_opts("nic"), optarg) == -1) {
-exit(1);
-}
+net_client_parse(qemu_find_opts("nic"), optarg);
 break;
 case QEMU_OPTION_net:
 default_net = 0;
-if (net_client_parse(qemu_find_opts("net"), optarg) == -1) {
-exit(1);
-}
+net_client_parse(qemu_find_opts("net"), optarg);
 break;
 #ifdef CONFIG_LIBISCSI
 case QEMU_OPTION_iscsi:
-- 
2.37.3




[PATCH v8 10/14] net: dgram: add unix socket

2022-09-13 Thread Laurent Vivier
Signed-off-by: Laurent Vivier 
Reviewed-by: Stefano Brivio 
---
 net/dgram.c | 65 ++---
 qapi/net.json   |  2 +-
 qemu-options.hx |  1 +
 3 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/net/dgram.c b/net/dgram.c
index 16e2d909755c..9f3eafee3b67 100644
--- a/net/dgram.c
+++ b/net/dgram.c
@@ -86,8 +86,15 @@ static ssize_t net_dgram_receive_dgram(NetClientState *nc,
 
 do {
 if (s->dgram_dst) {
-ret = sendto(s->fd, buf, size, 0, s->dgram_dst,
- sizeof(struct sockaddr_in));
+socklen_t len;
+
+if (s->dgram_dst->sa_family == AF_INET) {
+len = sizeof(struct sockaddr_in);
+} else {
+len = sizeof(struct sockaddr_un);
+}
+
+ret = sendto(s->fd, buf, size, 0, s->dgram_dst, len);
 } else {
 ret = send(s->fd, buf, size, 0);
 }
@@ -509,7 +516,7 @@ static int net_dgram_udp_init(NetClientState *peer,
 }
 } else {
 if (local->type != SOCKET_ADDRESS_TYPE_FD) {
-error_setg(errp, "type=inet requires remote parameter");
+error_setg(errp, "type=inet or unix require remote parameter");
 return -1;
 }
 }
@@ -559,6 +566,58 @@ static int net_dgram_udp_init(NetClientState *peer,
 
 break;
 }
+case SOCKET_ADDRESS_TYPE_UNIX: {
+struct sockaddr_un laddr_un, raddr_un;
+
+ret = unlink(local->u.q_unix.path);
+if (ret < 0 && errno != ENOENT) {
+error_setg_errno(errp, errno, "failed to unlink socket %s",
+ local->u.q_unix.path);
+return -1;
+}
+
+laddr_un.sun_family = PF_UNIX;
+ret = snprintf(laddr_un.sun_path, sizeof(laddr_un.sun_path), "%s",
+   local->u.q_unix.path);
+if (ret < 0 || ret >= sizeof(laddr_un.sun_path)) {
+error_setg(errp, "UNIX socket path '%s' is too long",
+   local->u.q_unix.path);
+error_append_hint(errp, "Path must be less than %zu bytes\n",
+  sizeof(laddr_un.sun_path));
+}
+
+raddr_un.sun_family = PF_UNIX;
+ret = snprintf(raddr_un.sun_path, sizeof(raddr_un.sun_path), "%s",
+   remote->u.q_unix.path);
+if (ret < 0 || ret >= sizeof(raddr_un.sun_path)) {
+error_setg(errp, "UNIX socket path '%s' is too long",
+   remote->u.q_unix.path);
+error_append_hint(errp, "Path must be less than %zu bytes\n",
+  sizeof(raddr_un.sun_path));
+}
+
+fd = qemu_socket(PF_UNIX, SOCK_DGRAM, 0);
+if (fd < 0) {
+error_setg_errno(errp, errno, "can't create datagram socket");
+return -1;
+}
+
+ret = bind(fd, (struct sockaddr *)_un, sizeof(laddr_un));
+if (ret < 0) {
+error_setg_errno(errp, errno, "can't bind unix=%s to socket",
+ laddr_un.sun_path);
+closesocket(fd);
+return -1;
+}
+qemu_socket_set_nonblock(fd);
+
+dgram_dst = g_malloc(sizeof(raddr_un));
+memcpy(dgram_dst, _un, sizeof(raddr_un));
+
+info_str = g_strdup_printf("udp=%s:%s",
+   laddr_un.sun_path, raddr_un.sun_path);
+break;
+}
 case SOCKET_ADDRESS_TYPE_FD: {
 SocketAddress *sa;
 SocketAddressType sa_type;
diff --git a/qapi/net.json b/qapi/net.json
index bb96701a49a7..9cc4be7535bb 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -600,7 +600,7 @@
 # @remote: remote address
 # @local: local address
 #
-# Only SocketAddress types 'inet' and 'fd' are supported.
+# Only SocketAddress types 'unix', 'inet' and 'fd' are supported.
 #
 # The code checks there is at least one of these options and reports an error
 # if not. If remote address is present and it's a multicast address, local
diff --git a/qemu-options.hx b/qemu-options.hx
index 8870bcce6bcd..ee2436ae14a7 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2742,6 +2742,7 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
 "configure a network backend to connect to a multicast 
maddr and port\n"
 "use ``local.host=addr`` to specify the host address to 
send packets from\n"
 "-netdev 
dgram,id=str,local.type=inet,local.host=addr,local.port=port[,remote.type=inet,remote.host=addr,remote.port=port]\n"
+"-netdev 
dgram,id=str,local.type=unix,local.path=path[,remote.type=unix,remote.path=path]\n"
 "-netdev dgram,id=str,local.type=fd,local.str=h\n"
 "configure a network backend to connect to another 
network\n"
 "using an UDP tunnel\n"
-- 
2.37.3




[PATCH v8 13/14] net: stream: move to QIO

2022-09-13 Thread Laurent Vivier
Use QIOChannel, QIOChannelSocket and QIONetListener.

Signed-off-by: Laurent Vivier 
---
 net/stream.c| 482 +---
 qemu-options.hx |   4 +-
 2 files changed, 171 insertions(+), 315 deletions(-)

diff --git a/net/stream.c b/net/stream.c
index 0f91ff20df61..a84295f209e2 100644
--- a/net/stream.c
+++ b/net/stream.c
@@ -34,48 +34,36 @@
 #include "qemu/iov.h"
 #include "qemu/main-loop.h"
 #include "qemu/cutils.h"
+#include "io/channel.h"
+#include "io/channel-socket.h"
+#include "io/net-listener.h"
 
 typedef struct NetStreamState {
 NetClientState nc;
-int listen_fd;
-int fd;
+QIOChannel *listen_ioc;
+QIONetListener *listener;
+QIOChannel *ioc;
+guint ioc_read_tag;
+guint ioc_write_tag;
 SocketReadState rs;
 unsigned int send_index;  /* number of bytes sent*/
-IOHandler *send_fn;
-bool read_poll;   /* waiting to receive data? */
-bool write_poll;  /* waiting to transmit data? */
 } NetStreamState;
 
-static void net_stream_accept(void *opaque);
-static void net_stream_writable(void *opaque);
+static void net_stream_listen(QIONetListener *listener,
+  QIOChannelSocket *cioc,
+  void *opaque);
 
-static void net_stream_update_fd_handler(NetStreamState *s)
+static gboolean net_stream_writable(QIOChannel *ioc,
+GIOCondition condition,
+gpointer data)
 {
-qemu_set_fd_handler(s->fd,
-s->read_poll ? s->send_fn : NULL,
-s->write_poll ? net_stream_writable : NULL,
-s);
-}
+NetStreamState *s = data;
 
-static void net_stream_read_poll(NetStreamState *s, bool enable)
-{
-s->read_poll = enable;
-net_stream_update_fd_handler(s);
-}
-
-static void net_stream_write_poll(NetStreamState *s, bool enable)
-{
-s->write_poll = enable;
-net_stream_update_fd_handler(s);
-}
-
-static void net_stream_writable(void *opaque)
-{
-NetStreamState *s = opaque;
-
-net_stream_write_poll(s, false);
+s->ioc_write_tag = 0;
 
 qemu_flush_queued_packets(>nc);
+
+return G_SOURCE_REMOVE;
 }
 
 static ssize_t net_stream_receive(NetClientState *nc, const uint8_t *buf,
@@ -92,13 +80,16 @@ static ssize_t net_stream_receive(NetClientState *nc, const 
uint8_t *buf,
 .iov_len  = size,
 },
 };
+struct iovec local_iov[2];
+unsigned int nlocal_iov;
 size_t remaining;
 ssize_t ret;
 
-remaining = iov_size(iov, 2) - s->send_index;
-ret = iov_send(s->fd, iov, 2, s->send_index, remaining);
 
-if (ret == -1 && errno == EAGAIN) {
+remaining = iov_size(iov, 2) - s->send_index;
+nlocal_iov = iov_copy(local_iov, 2, iov, 2, s->send_index, remaining);
+ret = qio_channel_writev(s->ioc, local_iov, nlocal_iov, NULL);
+if (ret == QIO_CHANNEL_ERR_BLOCK) {
 ret = 0; /* handled further down */
 }
 if (ret == -1) {
@@ -107,19 +98,25 @@ static ssize_t net_stream_receive(NetClientState *nc, 
const uint8_t *buf,
 }
 if (ret < (ssize_t)remaining) {
 s->send_index += ret;
-net_stream_write_poll(s, true);
+s->ioc_write_tag = qio_channel_add_watch(s->ioc, G_IO_OUT,
+ net_stream_writable, s, NULL);
 return 0;
 }
 s->send_index = 0;
 return size;
 }
 
+static gboolean net_stream_send(QIOChannel *ioc,
+GIOCondition condition,
+gpointer data);
+
 static void net_stream_send_completed(NetClientState *nc, ssize_t len)
 {
 NetStreamState *s = DO_UPCAST(NetStreamState, nc, nc);
 
-if (!s->read_poll) {
-net_stream_read_poll(s, true);
+if (!s->ioc_read_tag) {
+s->ioc_read_tag = qio_channel_add_watch(s->ioc, G_IO_IN,
+net_stream_send, s, NULL);
 }
 }
 
@@ -130,19 +127,24 @@ static void net_stream_rs_finalize(SocketReadState *rs)
 if (qemu_send_packet_async(>nc, rs->buf,
rs->packet_len,
net_stream_send_completed) == 0) {
-net_stream_read_poll(s, false);
+if (s->ioc_read_tag) {
+g_source_remove(s->ioc_read_tag);
+s->ioc_read_tag = 0;
+}
 }
 }
 
-static void net_stream_send(void *opaque)
+static gboolean net_stream_send(QIOChannel *ioc,
+GIOCondition condition,
+gpointer data)
 {
-NetStreamState *s = opaque;
+NetStreamState *s = data;
 int size;
 int ret;
-uint8_t buf1[NET_BUFSIZE];
-const uint8_t *buf;
+char buf1[NET_BUFSIZE];
+const char *buf;
 
-size = recv(s->fd, buf1, sizeof(buf1), 0);
+size = qio_channel_read(s->ioc, buf1, sizeof(buf1), NULL);
 if (size < 0) {
 if (errno != 

[PATCH v8 11/14] qemu-sockets: move and rename SocketAddress_to_str()

2022-09-13 Thread Laurent Vivier
Rename SocketAddress_to_str() to socket_uri() and move it to
util/qemu-sockets.c close to socket_parse().

socket_uri() generates a string from a SocketAddress while
socket_parse() generates a SocketAddress from a string.

Signed-off-by: Laurent Vivier 
---
 include/qemu/sockets.h |  2 +-
 monitor/hmp-cmds.c | 23 +--
 util/qemu-sockets.c| 20 
 3 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 47194b9732f8..e5a06d2e3729 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -40,6 +40,7 @@ NetworkAddressFamily inet_netfamily(int family);
 int unix_listen(const char *path, Error **errp);
 int unix_connect(const char *path, Error **errp);
 
+char *socket_uri(SocketAddress *addr);
 SocketAddress *socket_parse(const char *str, Error **errp);
 int socket_connect(SocketAddress *addr, Error **errp);
 int socket_listen(SocketAddress *addr, int num, Error **errp);
@@ -123,5 +124,4 @@ SocketAddress *socket_address_flatten(SocketAddressLegacy 
*addr);
  * Return 0 on success.
  */
 int socket_address_parse_named_fd(SocketAddress *addr, Error **errp);
-
 #endif /* QEMU_SOCKETS_H */
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index c6cd6f91dde6..cb35059c2d45 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -197,27 +197,6 @@ void hmp_info_mice(Monitor *mon, const QDict *qdict)
 qapi_free_MouseInfoList(mice_list);
 }
 
-static char *SocketAddress_to_str(SocketAddress *addr)
-{
-switch (addr->type) {
-case SOCKET_ADDRESS_TYPE_INET:
-return g_strdup_printf("tcp:%s:%s",
-   addr->u.inet.host,
-   addr->u.inet.port);
-case SOCKET_ADDRESS_TYPE_UNIX:
-return g_strdup_printf("unix:%s",
-   addr->u.q_unix.path);
-case SOCKET_ADDRESS_TYPE_FD:
-return g_strdup_printf("fd:%s", addr->u.fd.str);
-case SOCKET_ADDRESS_TYPE_VSOCK:
-return g_strdup_printf("tcp:%s:%s",
-   addr->u.vsock.cid,
-   addr->u.vsock.port);
-default:
-return g_strdup("unknown address type");
-}
-}
-
 void hmp_info_migrate(Monitor *mon, const QDict *qdict)
 {
 MigrationInfo *info;
@@ -380,7 +359,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
 monitor_printf(mon, "socket address: [\n");
 
 for (addr = info->socket_address; addr; addr = addr->next) {
-char *s = SocketAddress_to_str(addr->value);
+char *s = socket_uri(addr->value);
 monitor_printf(mon, "\t%s\n", s);
 g_free(s);
 }
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 83f4bd6fd211..9f6f655fd526 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -1077,6 +1077,26 @@ int unix_connect(const char *path, Error **errp)
 return sock;
 }
 
+char *socket_uri(SocketAddress *addr)
+{
+switch (addr->type) {
+case SOCKET_ADDRESS_TYPE_INET:
+return g_strdup_printf("tcp:%s:%s",
+   addr->u.inet.host,
+   addr->u.inet.port);
+case SOCKET_ADDRESS_TYPE_UNIX:
+return g_strdup_printf("unix:%s",
+   addr->u.q_unix.path);
+case SOCKET_ADDRESS_TYPE_FD:
+return g_strdup_printf("fd:%s", addr->u.fd.str);
+case SOCKET_ADDRESS_TYPE_VSOCK:
+return g_strdup_printf("tcp:%s:%s",
+   addr->u.vsock.cid,
+   addr->u.vsock.port);
+default:
+return g_strdup("unknown address type");
+}
+}
 
 SocketAddress *socket_parse(const char *str, Error **errp)
 {
-- 
2.37.3




[PATCH v8 02/14] net: remove the @errp argument of net_client_inits()

2022-09-13 Thread Laurent Vivier
The only caller passes _fatal, so use this directly in the function.

It's what we do for -blockdev, -device, and -object.

Suggested-by: Markus Armbruster 
Signed-off-by: Laurent Vivier 
Reviewed-by: Markus Armbruster 
---
 include/net/net.h |  2 +-
 net/net.c | 20 +++-
 softmmu/vl.c  |  2 +-
 3 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/include/net/net.h b/include/net/net.h
index 81d0b21defce..c1c34a58f849 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -222,7 +222,7 @@ extern const char *host_net_devices[];
 /* from net.c */
 int net_client_parse(QemuOptsList *opts_list, const char *str);
 void show_netdevs(void);
-int net_init_clients(Error **errp);
+void net_init_clients(void);
 void net_check_clients(void);
 void net_cleanup(void);
 void hmp_host_net_add(Monitor *mon, const QDict *qdict);
diff --git a/net/net.c b/net/net.c
index d2288bd3a929..15958f881776 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1562,27 +1562,21 @@ out:
 return ret;
 }
 
-int net_init_clients(Error **errp)
+void net_init_clients(void)
 {
 net_change_state_entry =
 qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL);
 
 QTAILQ_INIT(_clients);
 
-if (qemu_opts_foreach(qemu_find_opts("netdev"),
-  net_init_netdev, NULL, errp)) {
-return -1;
-}
-
-if (qemu_opts_foreach(qemu_find_opts("nic"), net_param_nic, NULL, errp)) {
-return -1;
-}
+qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL,
+  _fatal);
 
-if (qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL, errp)) 
{
-return -1;
-}
+qemu_opts_foreach(qemu_find_opts("nic"), net_param_nic, NULL,
+  _fatal);
 
-return 0;
+qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL,
+  _fatal);
 }
 
 int net_client_parse(QemuOptsList *opts_list, const char *optarg)
diff --git a/softmmu/vl.c b/softmmu/vl.c
index dea4005e4791..1fe8b5c5a120 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -1906,7 +1906,7 @@ static void qemu_create_late_backends(void)
 qtest_server_init(qtest_chrdev, qtest_log, _fatal);
 }
 
-net_init_clients(_fatal);
+net_init_clients();
 
 object_option_foreach_add(object_create_late);
 
-- 
2.37.3




Re: [PATCH v4 08/15] vhost: expose vhost_virtqueue_start()

2022-09-13 Thread Jason Wang
On Mon, Sep 12, 2022 at 1:22 AM Kangjie Xu  wrote:
>
> Expose vhost_virtqueue_start(), we need to use it when restarting a
> virtqueue.
>
> Signed-off-by: Kangjie Xu 
> Signed-off-by: Xuan Zhuo 

Acked-by: Jason Wang 

> ---
>  hw/virtio/vhost.c | 8 
>  include/hw/virtio/vhost.h | 3 +++
>  2 files changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
> index f758f177bb..7900bc81ab 100644
> --- a/hw/virtio/vhost.c
> +++ b/hw/virtio/vhost.c
> @@ -1081,10 +1081,10 @@ out:
>  return ret;
>  }
>
> -static int vhost_virtqueue_start(struct vhost_dev *dev,
> -struct VirtIODevice *vdev,
> -struct vhost_virtqueue *vq,
> -unsigned idx)
> +int vhost_virtqueue_start(struct vhost_dev *dev,
> +  struct VirtIODevice *vdev,
> +  struct vhost_virtqueue *vq,
> +  unsigned idx)
>  {
>  BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
>  VirtioBusState *vbus = VIRTIO_BUS(qbus);
> diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
> index a346f23d13..b092f57d98 100644
> --- a/include/hw/virtio/vhost.h
> +++ b/include/hw/virtio/vhost.h
> @@ -279,6 +279,9 @@ int vhost_net_set_backend(struct vhost_dev *hdev,
>
>  int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write);
>
> +int vhost_virtqueue_start(struct vhost_dev *dev, struct VirtIODevice *vdev,
> +  struct vhost_virtqueue *vq, unsigned idx);
> +
>  void vhost_dev_reset_inflight(struct vhost_inflight *inflight);
>  void vhost_dev_free_inflight(struct vhost_inflight *inflight);
>  void vhost_dev_save_inflight(struct vhost_inflight *inflight, QEMUFile *f);
> --
> 2.32.0
>




[PATCH v8 09/14] net: dgram: move mcast specific code from net_socket_fd_init_dgram()

2022-09-13 Thread Laurent Vivier
It is less complex to manage special cases directly in
net_dgram_mcast_init() and net_dgram_udp_init().

Signed-off-by: Laurent Vivier 
Reviewed-by: Stefano Brivio 
---
 net/dgram.c | 143 +++-
 1 file changed, 73 insertions(+), 70 deletions(-)

diff --git a/net/dgram.c b/net/dgram.c
index dcc2205305c5..16e2d909755c 100644
--- a/net/dgram.c
+++ b/net/dgram.c
@@ -302,52 +302,11 @@ static NetClientInfo net_dgram_socket_info = {
 static NetDgramState *net_dgram_fd_init_dgram(NetClientState *peer,
   const char *model,
   const char *name,
-  int fd, int is_fd,
-  SocketAddress *mcast,
+  int fd,
   Error **errp)
 {
-struct sockaddr_in *saddr = NULL;
-int newfd;
 NetClientState *nc;
 NetDgramState *s;
-SocketAddress *sa;
-SocketAddressType sa_type;
-
-sa = socket_local_address(fd, errp);
-if (!sa) {
-return NULL;
-}
-sa_type = sa->type;
-qapi_free_SocketAddress(sa);
-
-/*
- * fd passed: multicast: "learn" dgram_dst address from bound address and
- * save it. Because this may be "shared" socket from a "master" process,
- * datagrams would be recv() by ONLY ONE process: we must "clone" this
- * dgram socket --jjo
- */
-
-if (is_fd && mcast != NULL) {
-saddr = g_new(struct sockaddr_in, 1);
-
-if (convert_host_port(saddr, mcast->u.inet.host, 
mcast->u.inet.port,
-  errp) < 0) {
-goto err;
-}
-/* must be bound */
-if (saddr->sin_addr.s_addr == 0) {
-error_setg(errp, "can't setup multicast destination address");
-goto err;
-}
-/* clone dgram socket */
-newfd = net_dgram_mcast_create(saddr, NULL, errp);
-if (newfd < 0) {
-goto err;
-}
-/* clone newfd to fd, close newfd */
-dup2(newfd, fd);
-close(newfd);
-}
 
 nc = qemu_new_net_client(_dgram_socket_info, peer, model, name);
 
@@ -359,24 +318,7 @@ static NetDgramState 
*net_dgram_fd_init_dgram(NetClientState *peer,
 net_socket_rs_init(>rs, net_dgram_rs_finalize, false);
 net_dgram_read_poll(s, true);
 
-/* mcast: save bound address as dst */
-if (saddr) {
-g_assert(s->dgram_dst == NULL);
-s->dgram_dst = (struct sockaddr *)saddr;
-snprintf(nc->info_str, sizeof(nc->info_str),
- "fd=%d (cloned mcast=%s:%d)",
- fd, inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port));
-} else {
-snprintf(nc->info_str, sizeof(nc->info_str), "fd=%d %s", fd,
- SocketAddressType_str(sa_type));
-}
-
 return s;
-
-err:
-g_free(saddr);
-closesocket(fd);
-return NULL;
 }
 
 static void net_dgram_connect(void *opaque)
@@ -421,6 +363,7 @@ static int net_dgram_mcast_init(NetClientState *peer,
 NetDgramState *s;
 int fd, ret;
 struct sockaddr_in *saddr;
+gchar *info_str;
 
 if (remote->type != SOCKET_ADDRESS_TYPE_INET) {
 error_setg(errp, "multicast only support inet type");
@@ -440,6 +383,9 @@ static int net_dgram_mcast_init(NetClientState *peer,
 g_free(saddr);
 return -1;
 }
+info_str = g_strdup_printf("mcast=%s:%d",
+   inet_ntoa(saddr->sin_addr),
+   ntohs(saddr->sin_port));
 } else {
 switch (local->type) {
 case SOCKET_ADDRESS_TYPE_INET: {
@@ -457,9 +403,14 @@ static int net_dgram_mcast_init(NetClientState *peer,
 g_free(saddr);
 return -1;
 }
+info_str = g_strdup_printf("mcast=%s:%d",
+   inet_ntoa(saddr->sin_addr),
+   ntohs(saddr->sin_port));
 break;
 }
-case SOCKET_ADDRESS_TYPE_FD:
+case SOCKET_ADDRESS_TYPE_FD: {
+int newfd;
+
 fd = monitor_fd_param(monitor_cur(), local->u.fd.str, errp);
 if (fd == -1) {
 g_free(saddr);
@@ -472,7 +423,46 @@ static int net_dgram_mcast_init(NetClientState *peer,
  name, fd);
 return -1;
 }
+
+/*
+ * fd passed: multicast: "learn" dgram_dst address from bound
+ * address and save it. Because this may be "shared" socket from a
+ * "master" process, datagrams would be recv() by ONLY ONE process:
+ * we must "clone" this dgram socket --jjo
+ */
+
+saddr = g_new(struct sockaddr_in, 1);
+
+if 

[PATCH v8 05/14] qapi: net: add stream and dgram netdevs

2022-09-13 Thread Laurent Vivier
Copied from socket netdev file and modified to use SocketAddress
to be able to introduce new features like unix socket.

"udp" and "mcast" are squashed into dgram netdev, multicast is detected
according to the IP address type.
"listen" and "connect" modes are managed by stream netdev. An optional
parameter "server" defines the mode (server by default)

The two new types need to be parsed the modern way with -netdev, because
with the traditional way, the "type" field of netdev structure collides with
the "type" field of SocketAddress and prevents the correct evaluation of the
command line option. Moreover the traditional way doesn't allow to use
the same type (SocketAddress) several times with the -netdev option
(needed to specify "local" and "remote" addresses).

The previous commit paved the way for parsing the modern way, but
omitted one detail: how to pick modern vs. traditional, in
netdev_is_modern().

We want to pick based on the value of parameter "type".  But how to
extract it from the option argument?

Parsing the option argument, either the modern or the traditional way,
extracts it for us, but only if parsing succeeds.

If parsing fails, there is no good option.  No matter which parser we
pick, it'll be the wrong one for some arguments, and the error
reporting will be confusing.

Fortunately, the traditional parser accepts *anything* when called in
a certain way.  This maximizes our chance to extract the value of
"type", and in turn minimizes the risk of confusing error reporting.

Signed-off-by: Laurent Vivier 
Reviewed-by: Stefano Brivio 
---
 hmp-commands.hx |   2 +-
 net/clients.h   |   6 +
 net/dgram.c | 631 
 net/hub.c   |   2 +
 net/meson.build |   2 +
 net/net.c   |  30 ++-
 net/stream.c| 423 
 qapi/net.json   |  63 -
 qemu-options.hx |  12 +
 9 files changed, 1167 insertions(+), 4 deletions(-)
 create mode 100644 net/dgram.c
 create mode 100644 net/stream.c

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 182e639d1498..83e8d45a2a8b 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1276,7 +1276,7 @@ ERST
 {
 .name   = "netdev_add",
 .args_type  = "netdev:O",
-.params = "[user|tap|socket|vde|bridge|hubport|netmap|vhost-user"
+.params = 
"[user|tap|socket|stream|dgram|vde|bridge|hubport|netmap|vhost-user"
 #ifdef CONFIG_VMNET
   "|vmnet-host|vmnet-shared|vmnet-bridged"
 #endif
diff --git a/net/clients.h b/net/clients.h
index c9157789f2ce..ed8bdfff1e7c 100644
--- a/net/clients.h
+++ b/net/clients.h
@@ -40,6 +40,12 @@ int net_init_hubport(const Netdev *netdev, const char *name,
 int net_init_socket(const Netdev *netdev, const char *name,
 NetClientState *peer, Error **errp);
 
+int net_init_stream(const Netdev *netdev, const char *name,
+NetClientState *peer, Error **errp);
+
+int net_init_dgram(const Netdev *netdev, const char *name,
+   NetClientState *peer, Error **errp);
+
 int net_init_tap(const Netdev *netdev, const char *name,
  NetClientState *peer, Error **errp);
 
diff --git a/net/dgram.c b/net/dgram.c
new file mode 100644
index ..dbe65102d174
--- /dev/null
+++ b/net/dgram.c
@@ -0,0 +1,631 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+
+#include "net/net.h"
+#include "clients.h"
+#include "monitor/monitor.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "qemu/option.h"
+#include "qemu/sockets.h"
+#include "qemu/iov.h"
+#include "qemu/main-loop.h"
+#include "qemu/cutils.h"
+
+typedef struct NetDgramState {
+NetClientState nc;
+int listen_fd;
+int fd;
+SocketReadState rs;
+  /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */

[PATCH v8 06/14] net: stream: Don't ignore EINVAL on netdev socket connection

2022-09-13 Thread Laurent Vivier
From: Stefano Brivio 

Other errors are treated as failure by net_stream_client_init(),
but if connect() returns EINVAL, we'll fail silently. Remove the
related exception.

Signed-off-by: Stefano Brivio 
[lvivier: applied to net/stream.c]
Signed-off-by: Laurent Vivier 
Reviewed-by: Daniel P. Berrangé 
---
 net/stream.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/net/stream.c b/net/stream.c
index 0851e90becca..e8afbaca50b6 100644
--- a/net/stream.c
+++ b/net/stream.c
@@ -363,8 +363,7 @@ static int net_stream_client_init(NetClientState *peer,
 if (errno == EINTR || errno == EWOULDBLOCK) {
 /* continue */
 } else if (errno == EINPROGRESS ||
-   errno == EALREADY ||
-   errno == EINVAL) {
+   errno == EALREADY) {
 break;
 } else {
 error_setg_errno(errp, errno, "can't connect socket");
-- 
2.37.3




Re: Any interest in a QEMU emulation BoF at KVM Forum?

2022-09-13 Thread Alex Bennée
The BoF session will be in Lifey A (the big hall) this afternoon. I thought
being able to sit around tables while we discuss things would make things a
bit easier. We can share note taking on the etherpad:

  https://etherpad.opendev.org/p/qemu-emulation-bof%40kvmforum2022

I'll run a HO at: https://meet.google.com/rac-axef-xvv

On Wed, 31 Aug 2022 at 16:19, Alex Bennée  wrote:

> Hi,
>
> Given our slowly growing range of TCG emulations and the evident
> interest in keeping up with modern processor architectures is it worth
> having an emulation focused BoF at the up-coming KVM Forum?
>
> Some potential topics for discussion I could think of might include:
>
>  * Progress towards heterogeneous vCPU emulation
>
>  We've been making slow progress in removing assumptions from the
>  various front-ends about their global nature and adding accel:TCG
>  abstractions and support for the translator loop. We can already have
>  CPUs from the same architecture family in a model. What else do we need
>  to do so we can have those funky ARM+RiscV+Tricore heterogeneous
>  models? Is it library or something else?
>
>  * External Device Models
>
>  I know this is a contentious topic given the potential for GPL
>  end-runs. However there are also good arguments for enabling the
>  testing of open source designs without having forcing the
>  implementation of a separate C model to test software. For example if
>  we hypothetically modelled a Pi Pico would it make sense to model the
>  PIO in C if we could just compile the Verilog for it into a SystemC
>  model? Would a plethora of closed device models be the inevitable
>  consequence of such an approach? Would it matter if we just
>  concentrated on supporting useful open source solutions?
>
>  * Dynamic Machine Models
>
>  While we try and avoid modelling bespoke virtual HW in QEMU
>  (virt/goldfish not withstanding ;-) there is obviously a desire in the
>  EDA space to allow such experimentation. Is this something we can
>  provide so aspiring HW engineers can experiment with system
>  architectures without having to form QEMU and learn QOM. There have
>  been suggestions about consuming device trees or maybe translating to
>  QMP calls and adding support for wiring devices together. Given the
>  number of forks that exist is this something that could be better
>  supported upstream without degenerating into messy hacks?
>
>  * A sense of time
>
>  Currently we have the fairly limited support for -icount in QEMU. At
>  the same time we have no desire to start expanding frontends with
>  the details cost models required for a more realistic sense of time to
>  be presented. One suggestion is to expand the TCG plugin interface to
>  allow for the plugin to control time allowing as much or little logic
>  to be pushed there as we like and freeing up frontends from ever having
>  to consider it.
>
> Are any of these topics of interest? Are there any other emulation
> topics people would like to discuss?
>
> --
> Alex Bennée
>


-- 
Alex Bennée
KVM/QEMU Hacker for Linaro


Re: [PATCH v3 03/24] disas/nanomips: Delete NMD class field

2022-09-13 Thread Richard Henderson

On 9/12/22 13:26, Milica Lazarevic wrote:

The m_requested_instruction_categories field always has the same value,
ALL_ATTRIBUTES. The only use of that field is within the if statement.
When replaced with a specific value, the if statement is always false,
so it has been removed.

Now, when the only use of the m_requested_instruction_categories field
is removed, we can delete the field declaration and initialization in
the NMD class. Also, we're changing the way of the construction of the
NMD object in the nanomips_dis function.

Signed-off-by: Milica Lazarevic
---
  disas/nanomips.cpp | 13 +
  disas/nanomips.h   |  4 +---
  2 files changed, 2 insertions(+), 15 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: Any interest in a QEMU emulation BoF at KVM Forum?

2022-09-13 Thread Daniel P . Berrangé
On Tue, Sep 13, 2022 at 09:16:07AM +0200, Cédric Le Goater wrote:
> On 9/13/22 09:12, Alex Bennée wrote:
> > The BoF session will be in Lifey A (the big hall) this afternoon. I thought 
> > being able to sit around tables while we discuss things would make things a 
> > bit easier. We can share note taking on the etherpad:
> > 
> > https://etherpad.opendev.org/p/qemu-emulation-bof%40kvmforum2022 
> > 
> > 
> > I'll run a HO at: https://meet.google.com/rac-axef-xvv 
> > 
> 
> Thanks for that. I will try to join. What time approximately ?

The Tuesday BoF slot is 17:40-18:10

  https://events.linuxfoundation.org/kvm-forum/program/schedule/

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




Re: [PATCH v3 17/24] disas/nanomips: Remove CPR function

2022-09-13 Thread Richard Henderson

On 9/12/22 13:26, Milica Lazarevic wrote:

CPR functions has been removed.

Before this patch, we'd been calling img_format twice, the first time
through the CPR function to get an appropriate string and the second
time to print that formatted string. There's no more need for that.
Therefore, calls to CPR are removed, and now we're directly printing
"CP" and integer value instead.

Signed-off-by: Milica Lazarevic
---
  disas/nanomips.cpp | 110 +++--
  1 file changed, 45 insertions(+), 65 deletions(-)


Reviewed-by: Richard Henderson 

r~



[PATCH v8 01/14] net: introduce convert_host_port()

2022-09-13 Thread Laurent Vivier
Signed-off-by: Laurent Vivier 
Reviewed-by: Stefano Brivio 
---
 include/qemu/sockets.h |  2 ++
 net/net.c  | 62 ++
 2 files changed, 34 insertions(+), 30 deletions(-)

diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 038faa157f59..47194b9732f8 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -47,6 +47,8 @@ void socket_listen_cleanup(int fd, Error **errp);
 int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
 
 /* Old, ipv4 only bits.  Don't use for new code. */
+int convert_host_port(struct sockaddr_in *saddr, const char *host,
+  const char *port, Error **errp);
 int parse_host_port(struct sockaddr_in *saddr, const char *str,
 Error **errp);
 int socket_init(void);
diff --git a/net/net.c b/net/net.c
index 2db160e0634d..d2288bd3a929 100644
--- a/net/net.c
+++ b/net/net.c
@@ -66,55 +66,57 @@ static QTAILQ_HEAD(, NetClientState) net_clients;
 /***/
 /* network device redirectors */
 
-int parse_host_port(struct sockaddr_in *saddr, const char *str,
-Error **errp)
+int convert_host_port(struct sockaddr_in *saddr, const char *host,
+  const char *port, Error **errp)
 {
-gchar **substrings;
 struct hostent *he;
-const char *addr, *p, *r;
-int port, ret = 0;
+const char *r;
+long p;
 
 memset(saddr, 0, sizeof(*saddr));
 
-substrings = g_strsplit(str, ":", 2);
-if (!substrings || !substrings[0] || !substrings[1]) {
-error_setg(errp, "host address '%s' doesn't contain ':' "
-   "separating host from port", str);
-ret = -1;
-goto out;
-}
-
-addr = substrings[0];
-p = substrings[1];
-
 saddr->sin_family = AF_INET;
-if (addr[0] == '\0') {
+if (host[0] == '\0') {
 saddr->sin_addr.s_addr = 0;
 } else {
-if (qemu_isdigit(addr[0])) {
-if (!inet_aton(addr, >sin_addr)) {
+if (qemu_isdigit(host[0])) {
+if (!inet_aton(host, >sin_addr)) {
 error_setg(errp, "host address '%s' is not a valid "
-   "IPv4 address", addr);
-ret = -1;
-goto out;
+   "IPv4 address", host);
+return -1;
 }
 } else {
-he = gethostbyname(addr);
+he = gethostbyname(host);
 if (he == NULL) {
-error_setg(errp, "can't resolve host address '%s'", addr);
-ret = -1;
-goto out;
+error_setg(errp, "can't resolve host address '%s'", host);
+return -1;
 }
 saddr->sin_addr = *(struct in_addr *)he->h_addr;
 }
 }
-port = strtol(p, (char **), 0);
-if (r == p) {
-error_setg(errp, "port number '%s' is invalid", p);
+if (qemu_strtol(port, , 0, ) != 0) {
+error_setg(errp, "port number '%s' is invalid", port);
+return -1;
+}
+saddr->sin_port = htons(p);
+return 0;
+}
+
+int parse_host_port(struct sockaddr_in *saddr, const char *str,
+Error **errp)
+{
+gchar **substrings;
+int ret;
+
+substrings = g_strsplit(str, ":", 2);
+if (!substrings || !substrings[0] || !substrings[1]) {
+error_setg(errp, "host address '%s' doesn't contain ':' "
+   "separating host from port", str);
 ret = -1;
 goto out;
 }
-saddr->sin_port = htons(port);
+
+ret = convert_host_port(saddr, substrings[0], substrings[1], errp);
 
 out:
 g_strfreev(substrings);
-- 
2.37.3




[PATCH v8 04/14] qapi: net: introduce a way to bypass qemu_opts_parse_noisily()

2022-09-13 Thread Laurent Vivier
As qemu_opts_parse_noisily() flattens the QAPI structures ("type" field
of Netdev structure can collides with "type" field of SocketAddress),
we introduce a way to bypass qemu_opts_parse_noisily() and use directly
visit_type_Netdev() to parse the backend parameters.

More details from Markus:

qemu_init() passes the argument of -netdev, -nic, and -net to
net_client_parse().

net_client_parse() parses with qemu_opts_parse_noisily(), passing
QemuOptsList qemu_netdev_opts for -netdev, qemu_nic_opts for -nic, and
qemu_net_opts for -net.  Their desc[] are all empty, which means any
keys are accepted.  The result of the parse (a QemuOpts) is stored in
the QemuOptsList.

Note that QemuOpts is flat by design.  In some places, we layer non-flat
on top using dotted keys convention, but not here.

net_init_clients() iterates over the stored QemuOpts, and passes them to
net_init_netdev(), net_param_nic(), or net_init_client(), respectively.

These functions pass the QemuOpts to net_client_init().  They also do
other things with the QemuOpts, which we can ignore here.

net_client_init() uses the opts visitor to convert the (flat) QemOpts to
a (non-flat) QAPI object Netdev.  Netdev is also the argument of QMP
command netdev_add.

The opts visitor was an early attempt to support QAPI in
(QemuOpts-based) CLI.  It restricts QAPI types to a certain shape; see
commit eb7ee2cbeb "qapi: introduce OptsVisitor".

A more modern way to support QAPI is qobject_input_visitor_new_str().
It uses keyval_parse() instead of QemuOpts for KEY=VALUE,... syntax, and
it also supports JSON syntax.  The former isn't quite as expressive as
JSON, but it's a lot closer than QemuOpts + opts visitor.

This commit paves the way to use of the modern way instead.

Signed-off-by: Laurent Vivier 
Reviewed-by: Markus Armbruster 
---
 include/net/net.h |  2 ++
 net/net.c | 57 +++
 softmmu/vl.c  |  6 -
 3 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/include/net/net.h b/include/net/net.h
index 55023e7e9fa9..025dbf1e143b 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -220,6 +220,8 @@ extern NICInfo nd_table[MAX_NICS];
 extern const char *host_net_devices[];
 
 /* from net.c */
+bool netdev_is_modern(const char *optarg);
+void netdev_parse_modern(const char *optarg);
 void net_client_parse(QemuOptsList *opts_list, const char *str);
 void show_netdevs(void);
 void net_init_clients(void);
diff --git a/net/net.c b/net/net.c
index f056e8aebfb2..ffe3e5a2cf1d 100644
--- a/net/net.c
+++ b/net/net.c
@@ -54,6 +54,7 @@
 #include "net/colo-compare.h"
 #include "net/filter.h"
 #include "qapi/string-output-visitor.h"
+#include "qapi/qobject-input-visitor.h"
 
 /* Net bridge is currently not supported for W32. */
 #if !defined(_WIN32)
@@ -63,6 +64,16 @@
 static VMChangeStateEntry *net_change_state_entry;
 static QTAILQ_HEAD(, NetClientState) net_clients;
 
+typedef struct NetdevQueueEntry {
+Netdev *nd;
+Location loc;
+QSIMPLEQ_ENTRY(NetdevQueueEntry) entry;
+} NetdevQueueEntry;
+
+typedef QSIMPLEQ_HEAD(, NetdevQueueEntry) NetdevQueue;
+
+static NetdevQueue nd_queue = QSIMPLEQ_HEAD_INITIALIZER(nd_queue);
+
 /***/
 /* network device redirectors */
 
@@ -1562,6 +1573,20 @@ out:
 return ret;
 }
 
+static void netdev_init_modern(void)
+{
+while (!QSIMPLEQ_EMPTY(_queue)) {
+NetdevQueueEntry *nd = QSIMPLEQ_FIRST(_queue);
+
+QSIMPLEQ_REMOVE_HEAD(_queue, entry);
+loc_push_restore(>loc);
+net_client_init1(nd->nd, true, _fatal);
+loc_pop(>loc);
+qapi_free_Netdev(nd->nd);
+g_free(nd);
+}
+}
+
 void net_init_clients(void)
 {
 net_change_state_entry =
@@ -1569,6 +1594,8 @@ void net_init_clients(void)
 
 QTAILQ_INIT(_clients);
 
+netdev_init_modern();
+
 qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL,
   _fatal);
 
@@ -1579,6 +1606,36 @@ void net_init_clients(void)
   _fatal);
 }
 
+/*
+ * Does this -netdev argument use modern rather than traditional syntax?
+ * Modern syntax is to be parsed with netdev_parse_modern().
+ * Traditional syntax is to be parsed with net_client_parse().
+ */
+bool netdev_is_modern(const char *optarg)
+{
+return false;
+}
+
+/*
+ * netdev_parse_modern() uses modern, more expressive syntax than
+ * net_client_parse(), but supports only the -netdev option.
+ * netdev_parse_modern() appends to @nd_queue, whereas net_client_parse()
+ * appends to @qemu_netdev_opts.
+ */
+void netdev_parse_modern(const char *optarg)
+{
+Visitor *v;
+NetdevQueueEntry *nd;
+
+v = qobject_input_visitor_new_str(optarg, "type", _fatal);
+nd = g_new(NetdevQueueEntry, 1);
+visit_type_Netdev(v, NULL, >nd, _fatal);
+visit_free(v);
+loc_save(>loc);
+
+QSIMPLEQ_INSERT_TAIL(_queue, nd, entry);
+}
+
 void net_client_parse(QemuOptsList *opts_list, const char *optarg)

[PATCH v8 14/14] tests/qtest: netdev: test stream and dgram backends

2022-09-13 Thread Laurent Vivier
Signed-off-by: Laurent Vivier 
---
 tests/qtest/meson.build |   1 +
 tests/qtest/netdev-socket.c | 391 
 2 files changed, 392 insertions(+)
 create mode 100644 tests/qtest/netdev-socket.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index e910cb32ca15..38ee8b7a2d56 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -27,6 +27,7 @@ qtests_generic = [
   'test-hmp',
   'qos-test',
   'readconfig-test',
+  'netdev-socket',
 ]
 if config_host.has_key('CONFIG_MODULES')
   qtests_generic += [ 'modules-test' ]
diff --git a/tests/qtest/netdev-socket.c b/tests/qtest/netdev-socket.c
new file mode 100644
index ..55e0c07f18ec
--- /dev/null
+++ b/tests/qtest/netdev-socket.c
@@ -0,0 +1,391 @@
+/*
+ * QTest testcase for netdev stream and dgram
+ *
+ * Copyright (c) 2022 Red Hat, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include "libqtest.h"
+
+#define CONNECTION_TIMEOUT5
+
+#define EXPECT_STATE(q, e, t) \
+do {  \
+char *resp = qtest_hmp(q, "info network");\
+if (t) {  \
+strrchr(resp, t)[0] = 0;  \
+} \
+g_test_timer_start(); \
+while (g_test_timer_elapsed() < CONNECTION_TIMEOUT) { \
+if (strcmp(resp, e) == 0) {   \
+break;\
+} \
+g_free(resp); \
+resp = qtest_hmp(q, "info network");  \
+if (t) {  \
+strrchr(resp, t)[0] = 0;  \
+} \
+} \
+g_assert_cmpstr(resp, ==, e); \
+g_free(resp); \
+} while (0)
+
+static int inet_get_free_port(void)
+{
+int sock;
+struct sockaddr_in addr;
+socklen_t len;
+int port;
+
+sock = socket(AF_INET, SOCK_STREAM, 0);
+if (sock < 0) {
+return -1;
+}
+
+memset(, 0, sizeof(addr));
+addr.sin_family = AF_INET;
+addr.sin_addr.s_addr = INADDR_ANY;
+addr.sin_port = 0;
+if (bind(sock, (struct sockaddr *), sizeof(addr)) < 0) {
+return -1;
+}
+
+len = sizeof(addr);
+if (getsockname(sock,  (struct sockaddr *), ) < 0) {
+return -1;
+}
+
+port = ntohs(addr.sin_port);
+
+close(sock);
+
+return port;
+}
+
+static void test_stream_inet_ipv4(void)
+{
+QTestState *qts0, *qts1;
+char *expect;
+int port;
+
+port = inet_get_free_port();
+qts0 = qtest_initf("-nodefaults "
+   "-netdev stream,id=st0,addr.type=inet,"
+   "addr.ipv4=on,addr.ipv6=off,"
+   "addr.host=localhost,addr.port=%d", port);
+
+EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
+
+qts1 = qtest_initf("-nodefaults "
+   "-netdev stream,server=false,id=st0,addr.type=inet,"
+   "addr.ipv4=on,addr.ipv6=off,"
+   "addr.host=localhost,addr.port=%d", port);
+
+expect = g_strdup_printf("st0: index=0,type=stream,tcp:127.0.0.1:%d\r\n",
+ port);
+EXPECT_STATE(qts1, expect, 0);
+g_free(expect);
+
+/* the port is unknown, check only the address */
+EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:127.0.0.1", ':');
+
+qtest_quit(qts1);
+qtest_quit(qts0);
+}
+
+static void test_stream_inet_ipv6(void)
+{
+QTestState *qts0, *qts1;
+char *expect;
+int port;
+
+port = inet_get_free_port();
+qts0 = qtest_initf("-nodefaults "
+   "-netdev stream,id=st0,addr.type=inet,"
+   "addr.ipv4=off,addr.ipv6=on,"
+   "addr.host=localhost,addr.port=%d", port);
+
+EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
+
+qts1 = qtest_initf("-nodefaults "
+   "-netdev stream,server=false,id=st0,addr.type=inet,"
+   "addr.ipv4=off,addr.ipv6=on,"
+   "addr.host=localhost,addr.port=%d", port);
+
+expect = g_strdup_printf("st0: index=0,type=stream,tcp:::1:%d\r\n",
+ port);
+EXPECT_STATE(qts1, expect, 0);
+g_free(expect);
+
+/* the port is unknown, check only the address */
+EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:::1", ':');
+
+qtest_quit(qts1);
+qtest_quit(qts0);
+}
+
+static void test_stream_unix(void)
+{
+QTestState *qts0, *qts1;
+char *expect;
+gchar *path;
+int ret;
+
+ret = 

[PATCH v8 08/14] net: dgram: make dgram_dst generic

2022-09-13 Thread Laurent Vivier
dgram_dst is a sockaddr_in structure. To be able to use it with
unix socket, use a pointer to a generic sockaddr structure.

Signed-off-by: Laurent Vivier 
Reviewed-by: Stefano Brivio 
---
 net/dgram.c | 76 +++--
 1 file changed, 45 insertions(+), 31 deletions(-)

diff --git a/net/dgram.c b/net/dgram.c
index dbe65102d174..dcc2205305c5 100644
--- a/net/dgram.c
+++ b/net/dgram.c
@@ -40,9 +40,8 @@ typedef struct NetDgramState {
 int listen_fd;
 int fd;
 SocketReadState rs;
-  /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
-struct sockaddr_in dgram_dst;
-IOHandler *send_fn;   /* differs between SOCK_STREAM/SOCK_DGRAM */
+struct sockaddr *dgram_dst; /* contains destination iff connectionless */
+IOHandler *send_fn;
 bool read_poll;   /* waiting to receive data? */
 bool write_poll;  /* waiting to transmit data? */
 } NetDgramState;
@@ -86,10 +85,9 @@ static ssize_t net_dgram_receive_dgram(NetClientState *nc,
 ssize_t ret;
 
 do {
-if (s->dgram_dst.sin_family != AF_UNIX) {
-ret = sendto(s->fd, buf, size, 0,
- (struct sockaddr *)>dgram_dst,
- sizeof(s->dgram_dst));
+if (s->dgram_dst) {
+ret = sendto(s->fd, buf, size, 0, s->dgram_dst,
+ sizeof(struct sockaddr_in));
 } else {
 ret = send(s->fd, buf, size, 0);
 }
@@ -290,6 +288,8 @@ static void net_dgram_cleanup(NetClientState *nc)
 closesocket(s->listen_fd);
 s->listen_fd = -1;
 }
+g_free(s->dgram_dst);
+s->dgram_dst = NULL;
 }
 
 static NetClientInfo net_dgram_socket_info = {
@@ -306,7 +306,7 @@ static NetDgramState 
*net_dgram_fd_init_dgram(NetClientState *peer,
   SocketAddress *mcast,
   Error **errp)
 {
-struct sockaddr_in saddr;
+struct sockaddr_in *saddr = NULL;
 int newfd;
 NetClientState *nc;
 NetDgramState *s;
@@ -328,24 +328,25 @@ static NetDgramState 
*net_dgram_fd_init_dgram(NetClientState *peer,
  */
 
 if (is_fd && mcast != NULL) {
-if (convert_host_port(, mcast->u.inet.host,
-  mcast->u.inet.port, errp) < 0) {
+saddr = g_new(struct sockaddr_in, 1);
+
+if (convert_host_port(saddr, mcast->u.inet.host, 
mcast->u.inet.port,
+  errp) < 0) {
 goto err;
 }
 /* must be bound */
-if (saddr.sin_addr.s_addr == 0) {
+if (saddr->sin_addr.s_addr == 0) {
 error_setg(errp, "can't setup multicast destination address");
 goto err;
 }
 /* clone dgram socket */
-newfd = net_dgram_mcast_create(, NULL, errp);
+newfd = net_dgram_mcast_create(saddr, NULL, errp);
 if (newfd < 0) {
 goto err;
 }
 /* clone newfd to fd, close newfd */
 dup2(newfd, fd);
 close(newfd);
-
 }
 
 nc = qemu_new_net_client(_dgram_socket_info, peer, model, name);
@@ -359,16 +360,13 @@ static NetDgramState 
*net_dgram_fd_init_dgram(NetClientState *peer,
 net_dgram_read_poll(s, true);
 
 /* mcast: save bound address as dst */
-if (is_fd && mcast != NULL) {
-s->dgram_dst = saddr;
+if (saddr) {
+g_assert(s->dgram_dst == NULL);
+s->dgram_dst = (struct sockaddr *)saddr;
 snprintf(nc->info_str, sizeof(nc->info_str),
  "fd=%d (cloned mcast=%s:%d)",
- fd, inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ fd, inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port));
 } else {
-if (sa_type == SOCKET_ADDRESS_TYPE_UNIX) {
-s->dgram_dst.sin_family = AF_UNIX;
-}
-
 snprintf(nc->info_str, sizeof(nc->info_str), "fd=%d %s", fd,
  SocketAddressType_str(sa_type));
 }
@@ -376,6 +374,7 @@ static NetDgramState 
*net_dgram_fd_init_dgram(NetClientState *peer,
 return s;
 
 err:
+g_free(saddr);
 closesocket(fd);
 return NULL;
 }
@@ -421,21 +420,24 @@ static int net_dgram_mcast_init(NetClientState *peer,
 {
 NetDgramState *s;
 int fd, ret;
-struct sockaddr_in saddr;
+struct sockaddr_in *saddr;
 
 if (remote->type != SOCKET_ADDRESS_TYPE_INET) {
 error_setg(errp, "multicast only support inet type");
 return -1;
 }
 
-if (convert_host_port(, remote->u.inet.host, remote->u.inet.port,
+saddr = g_new(struct sockaddr_in, 1);
+if (convert_host_port(saddr, remote->u.inet.host, remote->u.inet.port,
   errp) < 0) {
+g_free(saddr);
 return -1;
 }
 
 if (!local) {
-fd = net_dgram_mcast_create(, NULL, errp);
+   

Re: [PATCH v3 04/24] disas/nanomips: Delete NMD class second field

2022-09-13 Thread Richard Henderson

On 9/12/22 13:26, Milica Lazarevic wrote:

We're deleting the m_pc field of the NMD class. It's now part of the
Dis_info struct that this patch introduces. Currently, the Dis_info
struct has just one field, m_pc, which we need for address calculation
in the ADDRESS function.

We're filling Dis_info at the entrance of the nanoMIPS disassembler.
I.e. print_insn_nanomips. Next, we're adding that information as an
argument wherever we need to.

Since NMD class now has no more fields, the NMD constructor is
also deleted.

Signed-off-by: Milica Lazarevic
---
  disas/nanomips.cpp | 1368 ++--
  disas/nanomips.h   | 1292 +
  2 files changed, 1331 insertions(+), 1329 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v4 09/15] vhost: expose vhost_virtqueue_stop()

2022-09-13 Thread Jason Wang
On Mon, Sep 12, 2022 at 1:22 AM Kangjie Xu  wrote:
>
> Expose vhost_virtqueue_stop(), we need to use it when resetting a
> virtqueue.
>
> Signed-off-by: Kangjie Xu 
> Signed-off-by: Xuan Zhuo 

Acked-by: Jason Wang 

> ---
>  hw/virtio/vhost.c | 8 
>  include/hw/virtio/vhost.h | 2 ++
>  2 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
> index 7900bc81ab..5407f60226 100644
> --- a/hw/virtio/vhost.c
> +++ b/hw/virtio/vhost.c
> @@ -1201,10 +1201,10 @@ fail_alloc_desc:
>  return r;
>  }
>
> -static void vhost_virtqueue_stop(struct vhost_dev *dev,
> -struct VirtIODevice *vdev,
> -struct vhost_virtqueue *vq,
> -unsigned idx)
> +void vhost_virtqueue_stop(struct vhost_dev *dev,
> +  struct VirtIODevice *vdev,
> +  struct vhost_virtqueue *vq,
> +  unsigned idx)
>  {
>  int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, idx);
>  struct vhost_vring_state state = {
> diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
> index b092f57d98..2b168b2269 100644
> --- a/include/hw/virtio/vhost.h
> +++ b/include/hw/virtio/vhost.h
> @@ -281,6 +281,8 @@ int vhost_device_iotlb_miss(struct vhost_dev *dev, 
> uint64_t iova, int write);
>
>  int vhost_virtqueue_start(struct vhost_dev *dev, struct VirtIODevice *vdev,
>struct vhost_virtqueue *vq, unsigned idx);
> +void vhost_virtqueue_stop(struct vhost_dev *dev, struct VirtIODevice *vdev,
> +  struct vhost_virtqueue *vq, unsigned idx);
>
>  void vhost_dev_reset_inflight(struct vhost_inflight *inflight);
>  void vhost_dev_free_inflight(struct vhost_inflight *inflight);
> --
> 2.32.0
>




[PATCH v8 00/14] qapi: net: add unix socket type support to netdev backend

2022-09-13 Thread Laurent Vivier
"-netdev socket" only supports inet sockets.

It's not a complex task to add support for unix sockets, but
the socket netdev parameters are not defined to manage well unix
socket parameters.

As discussed in:

  "socket.c added support for unix domain socket datagram transport"
  
https://lore.kernel.org/qemu-devel/1c0e1bc5-904f-46b0-8044-68e43e67b...@gmail.com/

This series adds support of unix socket type using SocketAddress QAPI structure.

Two new netdev backends, "stream" and "dgram" are added, that are barely a copy 
of "socket"
backend but they use the SocketAddress QAPI to provide socket parameters.
And then they also implement unix sockets (TCP and UDP).

Some examples of CLI syntax:

  for TCP:

  -netdev stream,id=socket0,addr.type=inet,addr.host=localhost,addr.port=1234
  -netdev 
stream,id=socket0,server=off,addr.type=inet,addr.host=localhost,addr.port=1234

  -netdev dgram,id=socket0,\
  local.type=inet,local.host=localhost,local.port=1234,\
  remote.type=inet,remote.host=localhost,remote.port=1235

  for UNIX:

  -netdev stream,id=socket0,addr.type=unix,addr.path=/tmp/qemu0
  -netdev stream,id=socket0,server=off,addr.type=unix,addr.path=/tmp/qemu0

  -netdev dgram,id=socket0,\
  local.type=unix,local.path=/tmp/qemu0,\
  remote.type=unix,remote.path=/tmp/qemu1

  for FD:

  -netdev stream,id=socket0,addr.type=fd,addr.str=4
  -netdev stream,id=socket0,server=off,addr.type=fd,addr.str=5

  -netdev dgram,id=socket0,local.type=fd,addr.str=4

v8:
  - test ipv4 and ipv6 parameters (stream inet)
  - test abstract parameter (stream unix)
  - add SocketAddressInet supported parameters in qemu-options.hx
(only stream, supported by the move to QIO)
  - with qio_channel_writev() replace (ret == -1 && errno == EAGAIN)
by (ret == QIO_CHANNEL_ERR_BLOCK)

v7:
  - add qtests
  - update parameters table in net.json
  - update socket_uri() and socket_parse()

v6:
  - s/netdev option/-netdev option/ PATCH 4
  - s/ / /
  - update @NetdevStreamOptions and @NetdevDgramOptions comments
  - update PATCH 4 description message
  - add missing return in error case for unix stream socket
  - split socket_uri() patch: move and rename, then change content

v5:
  - remove RFC prefix
  - put the change of net_client_parse() into its own patch (exit() in the
function)
  - update comments regarding netdev_is_modern() and netdev_parse_modern()
  - update error case in net_stream_server_init()
  - update qemu-options.hx with unix type
  - fix HMP "info network" with unix protocol/server side.

v4:
  - net_client_parse() fails with exit() rather than with return.
  - keep "{ 'name': 'vmnet-host', 'if': 'CONFIG_VMNET' }" on its
own line in qapi/net.json
  - add a comment in qapi/net.json about parameters usage
  - move netdev_is_modern() check to qemu_init()
  - in netdev_is_modern(), check for JSON and use qemu_opts_do_parse()
to parse parameters and detect type value.
  - add a blank line after copyright comment

v3:
  - remove support of "-net" for dgram and stream. They are only
supported with "-netdev" option.
  - use _fatal directly in net_client_inits()
  - update qemu-options.hx
  - move to QIO for stream socket

v2:
  - use "stream" and "dgram" rather than "socket-ng,mode=stream"
and ""socket-ng,mode=dgram"
  - extract code to bypass qemu_opts_parse_noisily() to
a new patch
  - do not ignore EINVAL (Stefano)
  - fix "-net" option

CC: Ralph Schmieder 
CC: Stefano Brivio 
CC: Daniel P. Berrangé 
CC: Markus Armbruster 

Laurent Vivier (13):
  net: introduce convert_host_port()
  net: remove the @errp argument of net_client_inits()
  net: simplify net_client_parse() error management
  qapi: net: introduce a way to bypass qemu_opts_parse_noisily()
  qapi: net: add stream and dgram netdevs
  net: stream: add unix socket
  net: dgram: make dgram_dst generic
  net: dgram: move mcast specific code from net_socket_fd_init_dgram()
  net: dgram: add unix socket
  qemu-sockets: move and rename SocketAddress_to_str()
  qemu-sockets: update socket_uri() and socket_parse()  to be consistent
  net: stream: move to QIO
  tests/qtest: netdev: test stream and dgram backends

Stefano Brivio (1):
  net: stream: Don't ignore EINVAL on netdev socket connection

 hmp-commands.hx |   2 +-
 include/net/net.h   |   6 +-
 include/qemu/sockets.h  |   4 +-
 monitor/hmp-cmds.c  |  23 +-
 net/clients.h   |   6 +
 net/dgram.c | 707 
 net/hub.c   |   2 +
 net/meson.build |   2 +
 net/net.c   | 169 ++---
 net/stream.c| 376 +++
 qapi/net.json   |  63 +++-
 qemu-options.hx |  14 +
 softmmu/vl.c|  16 +-
 tests/qtest/meson.build |   1 +
 tests/qtest/netdev-socket.c | 391 
 util/qemu-sockets.c |  25 ++
 16 files changed, 1725 insertions(+), 82 

Re: Any interest in a QEMU emulation BoF at KVM Forum?

2022-09-13 Thread Cédric Le Goater

On 9/13/22 09:12, Alex Bennée wrote:

The BoF session will be in Lifey A (the big hall) this afternoon. I thought 
being able to sit around tables while we discuss things would make things a bit 
easier. We can share note taking on the etherpad:

https://etherpad.opendev.org/p/qemu-emulation-bof%40kvmforum2022 


I'll run a HO at: https://meet.google.com/rac-axef-xvv 



Thanks for that. I will try to join. What time approximately ?

C.




On Wed, 31 Aug 2022 at 16:19, Alex Bennée mailto:alex.ben...@linaro.org>> wrote:

Hi,

Given our slowly growing range of TCG emulations and the evident
interest in keeping up with modern processor architectures is it worth
having an emulation focused BoF at the up-coming KVM Forum?

Some potential topics for discussion I could think of might include:

  * Progress towards heterogeneous vCPU emulation

  We've been making slow progress in removing assumptions from the
  various front-ends about their global nature and adding accel:TCG
  abstractions and support for the translator loop. We can already have
  CPUs from the same architecture family in a model. What else do we need
  to do so we can have those funky ARM+RiscV+Tricore heterogeneous
  models? Is it library or something else?

  * External Device Models

  I know this is a contentious topic given the potential for GPL
  end-runs. However there are also good arguments for enabling the
  testing of open source designs without having forcing the
  implementation of a separate C model to test software. For example if
  we hypothetically modelled a Pi Pico would it make sense to model the
  PIO in C if we could just compile the Verilog for it into a SystemC
  model? Would a plethora of closed device models be the inevitable
  consequence of such an approach? Would it matter if we just
  concentrated on supporting useful open source solutions?

  * Dynamic Machine Models

  While we try and avoid modelling bespoke virtual HW in QEMU
  (virt/goldfish not withstanding ;-) there is obviously a desire in the
  EDA space to allow such experimentation. Is this something we can
  provide so aspiring HW engineers can experiment with system
  architectures without having to form QEMU and learn QOM. There have
  been suggestions about consuming device trees or maybe translating to
  QMP calls and adding support for wiring devices together. Given the
  number of forks that exist is this something that could be better
  supported upstream without degenerating into messy hacks?

  * A sense of time

  Currently we have the fairly limited support for -icount in QEMU. At
  the same time we have no desire to start expanding frontends with
  the details cost models required for a more realistic sense of time to
  be presented. One suggestion is to expand the TCG plugin interface to
  allow for the plugin to control time allowing as much or little logic
  to be pushed there as we like and freeing up frontends from ever having
  to consider it.

Are any of these topics of interest? Are there any other emulation
topics people would like to discuss?

-- 
Alex Bennée




--
Alex Bennée
KVM/QEMU Hacker for Linaro





Re: [PATCH v3 14/24] disas/nanomips: Delete wrapper functions

2022-09-13 Thread Richard Henderson

On 9/12/22 13:26, Milica Lazarevic wrote:

Following functions just wrap the decode_gpr_gpr3() function:
- encode_rs3_and_check_rs3_ge_rt3()
- encode_rs3_and_check_rs3_lt_rt3()
Therefore those have been deleted. Calls to these two functions have
been replaced with calls to decode_gpr_gpr3.

Signed-off-by: Milica Lazarevic
---
  disas/nanomips.cpp | 18 ++
  1 file changed, 2 insertions(+), 16 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v3 13/24] disas/nanomips: Delete copy functions

2022-09-13 Thread Richard Henderson

On 9/12/22 13:26, Milica Lazarevic wrote:

Functions that have just one parameter and simply return it have been
deleted. Calls to these functions have been replaced with the argument
itself.

We're deleting following functions:
- both versions of copy()
- encode_s_from_address()
- encode_u_from_address()
- encode_lsb_from_pos_and_size()

Signed-off-by: Milica Lazarevic
---
  disas/nanomips.cpp | 3151 ++--
  1 file changed, 1559 insertions(+), 1592 deletions(-)


Reviewed-by: Richard Henderson 


r~



Re: [PATCH v3 15/24] disas/nanomips: Replace std::string type

2022-09-13 Thread Richard Henderson

On 9/12/22 13:26, Milica Lazarevic wrote:

The return type of typedef disassembly_function is changed to char *
instead of std::string. Therefore, for every particular
disassembly_function function signature is changed.
For example:
- static std::string ABS_D(uint64 instruction, img_address m_pc) {...}
is replaced with
- static char *ABS_D(uint64 instruction, img_address m_pc) {...}

Every helper function used to return std::string is changed to return
const char * or char *. Where the return value points to a static string
that the caller must not free, the return type is const char *. If a
function allocates memory and the caller is required to free it, the
return type is a char *. This applies to the following functions:
img_format, to_string, GPR, save_restore_list, FPR, etc.

Now that we replaced every std::string for const char * or char *, it is
possible to delete multiple versions of the img_format function. The
general version:
- static char *img_format(const char *format, ...) {...}
can handle all string formatting, so others have been deleted.

Where necessary, strings are dynamically allocated with g_strjoinv,
g_strdup, g_strdup_vprintf, and g_strdup_printf. Memory leaking will be
prevented later.

String concatenation in the save_restore_list() function is handled
using g_strjoinv() function instead of += operator.

The type of the "dis" parameter in the Disassemble function is changed
- from std::string &
- to char **

Without applying all of these changes, the nanomips disassembler may be
buildable but can't produce the appropriate output, so all of them are
made together.

Signed-off-by: Milica Lazarevic
---
  disas/nanomips.cpp | 4776 ++--
  1 file changed, 2337 insertions(+), 2439 deletions(-)


Reviewed-by: Richard Henderson 

r~



[PATCH v8 07/14] net: stream: add unix socket

2022-09-13 Thread Laurent Vivier
Signed-off-by: Laurent Vivier 
Reviewed-by: Stefano Brivio 
---
 net/stream.c| 108 +---
 qapi/net.json   |   2 +-
 qemu-options.hx |   1 +
 3 files changed, 105 insertions(+), 6 deletions(-)

diff --git a/net/stream.c b/net/stream.c
index e8afbaca50b6..0f91ff20df61 100644
--- a/net/stream.c
+++ b/net/stream.c
@@ -235,7 +235,7 @@ static NetStreamState 
*net_stream_fd_init_stream(NetClientState *peer,
 static void net_stream_accept(void *opaque)
 {
 NetStreamState *s = opaque;
-struct sockaddr_in saddr;
+struct sockaddr_storage saddr;
 socklen_t len;
 int fd;
 
@@ -253,9 +253,27 @@ static void net_stream_accept(void *opaque)
 s->fd = fd;
 s->nc.link_down = false;
 net_stream_connect(s);
-snprintf(s->nc.info_str, sizeof(s->nc.info_str),
- "connection from %s:%d",
- inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+switch (saddr.ss_family) {
+case AF_INET: {
+struct sockaddr_in *saddr_in = (struct sockaddr_in *)
+
+snprintf(s->nc.info_str, sizeof(s->nc.info_str),
+ "connection from %s:%d",
+ inet_ntoa(saddr_in->sin_addr), ntohs(saddr_in->sin_port));
+break;
+}
+case AF_UNIX: {
+struct sockaddr_un saddr_un;
+
+len = sizeof(saddr_un);
+getsockname(s->listen_fd, (struct sockaddr *)_un, );
+snprintf(s->nc.info_str, sizeof(s->nc.info_str),
+ "connect from %s", saddr_un.sun_path);
+break;
+}
+default:
+g_assert_not_reached();
+}
 }
 
 static int net_stream_server_init(NetClientState *peer,
@@ -295,6 +313,43 @@ static int net_stream_server_init(NetClientState *peer,
 }
 break;
 }
+case SOCKET_ADDRESS_TYPE_UNIX: {
+struct sockaddr_un saddr_un;
+
+ret = unlink(addr->u.q_unix.path);
+if (ret < 0 && errno != ENOENT) {
+error_setg_errno(errp, errno, "failed to unlink socket %s",
+ addr->u.q_unix.path);
+return -1;
+}
+
+saddr_un.sun_family = PF_UNIX;
+ret = snprintf(saddr_un.sun_path, sizeof(saddr_un.sun_path), "%s",
+   addr->u.q_unix.path);
+if (ret < 0 || ret >= sizeof(saddr_un.sun_path)) {
+error_setg(errp, "UNIX socket path '%s' is too long",
+   addr->u.q_unix.path);
+error_append_hint(errp, "Path must be less than %zu bytes\n",
+  sizeof(saddr_un.sun_path));
+return -1;
+}
+
+fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
+if (fd < 0) {
+error_setg_errno(errp, errno, "can't create stream socket");
+return -1;
+}
+qemu_socket_set_nonblock(fd);
+
+ret = bind(fd, (struct sockaddr *)_un, sizeof(saddr_un));
+if (ret < 0) {
+error_setg_errno(errp, errno, "can't create socket with path: %s",
+ saddr_un.sun_path);
+closesocket(fd);
+return -1;
+}
+break;
+}
 case SOCKET_ADDRESS_TYPE_FD:
 fd = monitor_fd_param(monitor_cur(), addr->u.fd.str, errp);
 if (fd == -1) {
@@ -380,6 +435,49 @@ static int net_stream_client_init(NetClientState *peer,
ntohs(saddr_in.sin_port));
 break;
 }
+case SOCKET_ADDRESS_TYPE_UNIX: {
+struct sockaddr_un saddr_un;
+
+saddr_un.sun_family = PF_UNIX;
+ret = snprintf(saddr_un.sun_path, sizeof(saddr_un.sun_path), "%s",
+   addr->u.q_unix.path);
+if (ret < 0 || ret >= sizeof(saddr_un.sun_path)) {
+error_setg(errp, "UNIX socket path '%s' is too long",
+   addr->u.q_unix.path);
+error_append_hint(errp, "Path must be less than %zu bytes\n",
+  sizeof(saddr_un.sun_path));
+return -1;
+}
+
+fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
+if (fd < 0) {
+error_setg_errno(errp, errno, "can't create stream socket");
+return -1;
+}
+qemu_socket_set_nonblock(fd);
+
+connected = 0;
+for (;;) {
+ret = connect(fd, (struct sockaddr *)_un, sizeof(saddr_un));
+if (ret < 0) {
+if (errno == EINTR || errno == EWOULDBLOCK) {
+/* continue */
+} else if (errno == EAGAIN ||
+   errno == EALREADY) {
+break;
+} else {
+error_setg_errno(errp, errno, "can't connect socket");
+closesocket(fd);
+return -1;
+}
+} else {
+connected = 1;
+break;
+}
+}
+info_str = g_strdup_printf(" connect to %s", saddr_un.sun_path);
+break;
+

[PATCH v8 12/14] qemu-sockets: update socket_uri() and socket_parse() to be consistent

2022-09-13 Thread Laurent Vivier
To be consistent with socket_uri(), add 'tcp:' prefix for inet type in
socket_parse(), by default socket_parse() use tcp when no prefix is
provided (format is host:port).

In socket_uri(), use 'vsock:' prefix for vsock type rather than 'tcp:'
because it makes a vsock address look like an inet address with CID
misinterpreted as host.
Goes back to commit 9aca82ba31 "migration: Create socket-address parameter"

Signed-off-by: Laurent Vivier 
---
 util/qemu-sockets.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 9f6f655fd526..a9926af714c4 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -1090,7 +1090,7 @@ char *socket_uri(SocketAddress *addr)
 case SOCKET_ADDRESS_TYPE_FD:
 return g_strdup_printf("fd:%s", addr->u.fd.str);
 case SOCKET_ADDRESS_TYPE_VSOCK:
-return g_strdup_printf("tcp:%s:%s",
+return g_strdup_printf("vsock:%s:%s",
addr->u.vsock.cid,
addr->u.vsock.port);
 default:
@@ -1124,6 +1124,11 @@ SocketAddress *socket_parse(const char *str, Error 
**errp)
 if (vsock_parse(>u.vsock, str + strlen("vsock:"), errp)) {
 goto fail;
 }
+} else if (strstart(str, "tcp:", NULL)) {
+addr->type = SOCKET_ADDRESS_TYPE_INET;
+if (inet_parse(>u.inet, str + strlen("tcp:"), errp)) {
+goto fail;
+}
 } else {
 addr->type = SOCKET_ADDRESS_TYPE_INET;
 if (inet_parse(>u.inet, str, errp)) {
-- 
2.37.3




Re: [PATCH v3 16/24] disas/nanomips: Remove IMMEDIATE functions

2022-09-13 Thread Richard Henderson

On 9/12/22 13:26, Milica Lazarevic wrote:

Both versions of IMMEDIATE functions have been removed.

Before this patch, we'd been calling img_format twice, the first time
through the IMMEDIATE to get an appropriate string and the second time
to print that string. There's no more need for that. Therefore, calls to
IMMEDIATE are removed, and now we're directly printing the integer
values instead.

Signed-off-by: Milica Lazarevic
---
  disas/nanomips.cpp | 756 -
  1 file changed, 265 insertions(+), 491 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v3 19/24] disas/nanomips: Remove function overloading

2022-09-13 Thread Richard Henderson

On 9/12/22 13:26, Milica Lazarevic wrote:

Disassemble function that calls the other variant of it is deleted.
Where it is called, now we're directly calling the other implementation.

Signed-off-by: Milica Lazarevic
---
  disas/nanomips.cpp | 7 +--
  1 file changed, 1 insertion(+), 6 deletions(-)


Reviewed-by: Richard Henderson 


r~



Re: [PATCH 27/37] target/i386: Use tcg gvec ops for pmovmskb

2022-09-13 Thread Richard Henderson

On 9/12/22 00:04, Paolo Bonzini wrote:

+while (vec_len > 8) {
+vec_len -= 8;
+tcg_gen_shli_tl(s->T0, s->T0, 8);
+tcg_gen_ld8u_tl(t, cpu_env, offsetof(CPUX86State, xmm_t0.ZMM_B(vec_len 
- 1)));
+tcg_gen_or_tl(s->T0, s->T0, t);
  }


The shl + or is deposit, for those hosts that have it,
and will be re-expanded to shl + or for those that don't:

tcg_gen_ld8u_tl(t, ...);
tcg_gen_deposit_tl(s->T0, t, s->T0, 8, TARGET_LONG_BITS - 8);


r~



Re: [PATCH v7 00/14] KVM: mm: fd-based approach for supporting KVM guest private memory

2022-09-13 Thread Sean Christopherson
On Thu, Sep 08, 2022, Kirill A. Shutemov wrote:
> On Wed, Aug 31, 2022 at 05:24:39PM +0300, Kirill A . Shutemov wrote:
> > On Sat, Aug 20, 2022 at 10:15:32PM -0700, Hugh Dickins wrote:
> > > > I will try next week to rework it as shim to top of shmem. Does it work
> > > > for you?
> > > 
> > > Yes, please do, thanks.  It's a compromise between us: the initial TDX
> > > case has no justification to use shmem at all, but doing it that way
> > > will help you with some of the infrastructure, and will probably be
> > > easiest for KVM to extend to other more relaxed fd cases later.
> > 
> > Okay, below is my take on the shim approach.
> > 
> > I don't hate how it turned out. It is easier to understand without
> > callback exchange thing.
> > 
> > The only caveat is I had to introduce external lock to protect against
> > race between lookup and truncate.

As before, I think this lock is unnecessary.  Or at least it's unnessary to hold
the lock across get/put.  The ->invalidate() call will ensure that the pfn is
never actually used if get() races with truncation.

Switching topics, what actually prevents mmapp() on the shim?  I tried to 
follow,
but I don't know these areas well enough.



Re: [PATCH 33/37] target/i386: Enable AVX cpuid bits when using TCG

2022-09-13 Thread Richard Henderson

On 9/12/22 00:04, Paolo Bonzini wrote:

From: Paul Brook

Include AVX, AVX2 and VAES in the guest cpuid features supported by TCG.

Signed-off-by: Paul Brook
Message-Id:<20220424220204.2493824-40-p...@nowt.org>
Signed-off-by: Paolo Bonzini
---
  target/i386/cpu.c | 10 +-
  1 file changed, 5 insertions(+), 5 deletions(-)


Reviewed-by: Richard Henderson 


r~



Re: [RFC PATCH 00/37] target/i386: new decoder + AVX implementation

2022-09-13 Thread Richard Henderson

On 9/12/22 00:03, Paolo Bonzini wrote:

   target/i386: remove old SSE decoder


Patch 37 never arrived, but I can imagine what it looked like.  :-)

The series is looking good.  All of the nits were minor.


r~



[PATCH v2 0/4] virtio-gpu: Blob resources

2022-09-13 Thread Antonio Caggiano
Add shared memory and support blob resource creation, mapping and
unmapping through virglrenderer new stable APIs[0] when available.

[0] https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/891

Antonio Caggiano (1):
  virtio-gpu: Handle resource blob commands

Dmitry Osipenko (1):
  virtio-gpu: Don't require udmabuf when blob support is enabled

Dr. David Alan Gilbert (1):
  virtio: Add shared memory capability

Gerd Hoffmann (1):
  virtio-gpu: hostmem

 hw/display/virtio-gpu-pci.c  |  15 +++
 hw/display/virtio-gpu-virgl.c| 171 +++
 hw/display/virtio-gpu.c  |  29 ++---
 hw/display/virtio-vga.c  |  33 --
 hw/virtio/virtio-pci.c   |  18 +++
 include/hw/virtio/virtio-gpu-bswap.h |  18 +++
 include/hw/virtio/virtio-gpu.h   |  13 ++
 include/hw/virtio/virtio-pci.h   |   4 +
 meson.build  |   5 +
 9 files changed, 283 insertions(+), 23 deletions(-)

-- 
2.34.1




[PATCH v2 1/4] virtio: Add shared memory capability

2022-09-13 Thread Antonio Caggiano
From: "Dr. David Alan Gilbert" 

Define a new capability type 'VIRTIO_PCI_CAP_SHARED_MEMORY_CFG'
and the data structure 'virtio_pci_shm_cap' to go with it.
They allow defining shared memory regions with sizes and offsets
of 2^32 and more.
Multiple instances of the capability are allowed and distinguished
by a device-specific 'id'.

v2: Remove virtio_pci_shm_cap as virtio_pci_cap64 is used instead.
v3: No need for mask32 as cpu_to_le32 truncates the value.

Signed-off-by: Dr. David Alan Gilbert 
Signed-off-by: Antonio Caggiano 
---
 hw/virtio/virtio-pci.c | 18 ++
 include/hw/virtio/virtio-pci.h |  4 
 2 files changed, 22 insertions(+)

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index a50c5a57d7..377bb06fec 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1169,6 +1169,24 @@ static int virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy,
 return offset;
 }
 
+int virtio_pci_add_shm_cap(VirtIOPCIProxy *proxy,
+   uint8_t bar, uint64_t offset, uint64_t length,
+   uint8_t id)
+{
+struct virtio_pci_cap64 cap = {
+.cap.cap_len = sizeof cap,
+.cap.cfg_type = VIRTIO_PCI_CAP_SHARED_MEMORY_CFG,
+};
+
+cap.cap.bar = bar;
+cap.cap.length = cpu_to_le32(length);
+cap.length_hi = cpu_to_le32(length >> 32);
+cap.cap.offset = cpu_to_le32(offset);
+cap.offset_hi = cpu_to_le32(offset >> 32);
+cap.cap.id = id;
+return virtio_pci_add_mem_cap(proxy, );
+}
+
 static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr,
unsigned size)
 {
diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h
index 2446dcd9ae..5e5c4a4c6d 100644
--- a/include/hw/virtio/virtio-pci.h
+++ b/include/hw/virtio/virtio-pci.h
@@ -252,4 +252,8 @@ void virtio_pci_types_register(const 
VirtioPCIDeviceTypeInfo *t);
  */
 unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues);
 
+int virtio_pci_add_shm_cap(VirtIOPCIProxy *proxy,
+   uint8_t bar, uint64_t offset, uint64_t length,
+   uint8_t id);
+
 #endif
-- 
2.34.1




Re: [PATCH v3 1/3] util/main-loop: Fix maximum number of wait objects for win32

2022-09-13 Thread Marc-André Lureau
Hi

On Wed, Aug 24, 2022 at 12:52 PM Bin Meng  wrote:

> From: Bin Meng 
>
> The maximum number of wait objects for win32 should be
> MAXIMUM_WAIT_OBJECTS, not MAXIMUM_WAIT_OBJECTS + 1.
>
> Signed-off-by: Bin Meng 
> ---
>
> Changes in v3:
> - move the check of adding the same HANDLE twice to a separete patch
>
> Changes in v2:
> - fix the logic in qemu_add_wait_object() to avoid adding
>   the same HANDLE twice
>
>  util/main-loop.c | 11 +++
>  1 file changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/util/main-loop.c b/util/main-loop.c
> index f00a25451b..cb018dc33c 100644
> --- a/util/main-loop.c
> +++ b/util/main-loop.c
> @@ -363,10 +363,10 @@ void qemu_del_polling_cb(PollingFunc *func, void
> *opaque)
>  /* Wait objects support */
>  typedef struct WaitObjects {
>  int num;
> -int revents[MAXIMUM_WAIT_OBJECTS + 1];
> -HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
> -WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
> -void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
> +int revents[MAXIMUM_WAIT_OBJECTS];
> +HANDLE events[MAXIMUM_WAIT_OBJECTS];
> +WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS];
> +void *opaque[MAXIMUM_WAIT_OBJECTS];
>  } WaitObjects;
>
>  static WaitObjects wait_objects = {0};
> @@ -395,6 +395,9 @@ void qemu_del_wait_object(HANDLE handle,
> WaitObjectFunc *func, void *opaque)
>  if (w->events[i] == handle) {
>  found = 1;
>  }
> +if (i == MAXIMUM_WAIT_OBJECTS - 1) {
> +break;
> +}
>

hmm


>  if (found) {
>  w->events[i] = w->events[i + 1];
>  w->func[i] = w->func[i + 1];
>

The way deletion works is by moving the i+1 element (which is always zeroed
for i == MAXIMUM_WAIT_OBJECTS) to i.

After your patch, for i == MAXIMUM_WAIT_OBJECTS, we no longer clear the
last value, and instead rely simply on updated w->num:

if (found) {
w->num--;
}

 So your patch looks ok to me, but I prefer the current code.

Paolo, what do you say?


  1   2   >