[Bug 1868221] Re: /usr/share/applications/qemu.desktop should have an "Exec=" key.

2020-05-08 Thread Frédéric Brière
Thank you Lockywolf for this bug report.  Have you filed one against KDE
as you previously mentioned?  If so, could you provide us with a link?
Thanks in advance!

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1868221

Title:
  /usr/share/applications/qemu.desktop should have an "Exec=" key.

Status in QEMU:
  New

Bug description:
  According to the www.freedesktop.org .desktop-file specification, all
  "Application" desktop files should have an "Exec=" key. The one in
  qemu doesn't.

  This can be easily verified by running kbuildsycoca4 if KDE4 is
  present, but the issue is not DE-dependent.

  Which binary exactly should be assigned as the default one, I don't
  know.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1868221/+subscriptions



Re: [PATCH v16 QEMU 09/16] vfio: Add save state functions to SaveVMHandlers

2020-05-08 Thread Yan Zhao
On Wed, Mar 25, 2020 at 05:09:07AM +0800, Kirti Wankhede wrote:
> Added .save_live_pending, .save_live_iterate and .save_live_complete_precopy
> functions. These functions handles pre-copy and stop-and-copy phase.
> 
> In _SAVING|_RUNNING device state or pre-copy phase:
> - read pending_bytes. If pending_bytes > 0, go through below steps.
> - read data_offset - indicates kernel driver to write data to staging
>   buffer.
> - read data_size - amount of data in bytes written by vendor driver in
>   migration region.
I think we should change the sequence of reading data_size and
data_offset. see the next comment below.

> - read data_size bytes of data from data_offset in the migration region.
> - Write data packet to file stream as below:
> {VFIO_MIG_FLAG_DEV_DATA_STATE, data_size, actual data,
> VFIO_MIG_FLAG_END_OF_STATE }
> 
> In _SAVING device state or stop-and-copy phase
> a. read config space of device and save to migration file stream. This
>doesn't need to be from vendor driver. Any other special config state
>from driver can be saved as data in following iteration.
> b. read pending_bytes. If pending_bytes > 0, go through below steps.
> c. read data_offset - indicates kernel driver to write data to staging
>buffer.
> d. read data_size - amount of data in bytes written by vendor driver in
>migration region.
> e. read data_size bytes of data from data_offset in the migration region.
> f. Write data packet as below:
>{VFIO_MIG_FLAG_DEV_DATA_STATE, data_size, actual data}
> g. iterate through steps b to f while (pending_bytes > 0)
> h. Write {VFIO_MIG_FLAG_END_OF_STATE}
> 
> When data region is mapped, its user's responsibility to read data from
> data_offset of data_size before moving to next steps.
> 
> Signed-off-by: Kirti Wankhede 
> Reviewed-by: Neo Jia 
> ---
>  hw/vfio/migration.c   | 245 
> +-
>  hw/vfio/trace-events  |   6 ++
>  include/hw/vfio/vfio-common.h |   1 +
>  3 files changed, 251 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c
> index 033f76526e49..ecbeed5182c2 100644
> --- a/hw/vfio/migration.c
> +++ b/hw/vfio/migration.c
> @@ -138,6 +138,137 @@ static int vfio_migration_set_state(VFIODevice 
> *vbasedev, uint32_t mask,
>  return 0;
>  }
>  
> +static void *find_data_region(VFIORegion *region,
> +  uint64_t data_offset,
> +  uint64_t data_size)
> +{
> +void *ptr = NULL;
> +int i;
> +
> +for (i = 0; i < region->nr_mmaps; i++) {
> +if ((data_offset >= region->mmaps[i].offset) &&
> +(data_offset < region->mmaps[i].offset + region->mmaps[i].size) 
> &&
> +(data_size <= region->mmaps[i].size)) {
> +ptr = region->mmaps[i].mmap + (data_offset -
> +   region->mmaps[i].offset);
> +break;
> +}
> +}
> +return ptr;
> +}
> +
> +static int vfio_save_buffer(QEMUFile *f, VFIODevice *vbasedev)
> +{
> +VFIOMigration *migration = vbasedev->migration;
> +VFIORegion *region = >region;
> +uint64_t data_offset = 0, data_size = 0;
> +int ret;
> +
> +ret = pread(vbasedev->fd, _offset, sizeof(data_offset),
> +region->fd_offset + offsetof(struct 
> vfio_device_migration_info,
> + data_offset));
> +if (ret != sizeof(data_offset)) {
> +error_report("%s: Failed to get migration buffer data offset %d",
> + vbasedev->name, ret);
> +return -EINVAL;
> +}
> +
> +ret = pread(vbasedev->fd, _size, sizeof(data_size),
> +region->fd_offset + offsetof(struct 
> vfio_device_migration_info,
> + data_size));
> +if (ret != sizeof(data_size)) {
> +error_report("%s: Failed to get migration buffer data size %d",
> + vbasedev->name, ret);
> +return -EINVAL;
> +}
data_size should be read first, and if it's 0, data_offset will not
be read further.

the reasons are below:
1. if there's no data region provided by vendor driver, there's no
reason to get a valid data_offset, so reading/writing of data_offset
should fail. And this should not be treated as a migration error.

2. even if pending_bytes is 0, vfio_save_iterate() is still possible to be
called and therefore vfio_save_buffer() is called.

Thanks
Yan
> +
> +if (data_size > 0) {
> +void *buf = NULL;
> +bool buffer_mmaped;
> +
> +if (region->mmaps) {
> +buf = find_data_region(region, data_offset, data_size);
> +}
> +
> +buffer_mmaped = (buf != NULL) ? true : false;
> +
> +if (!buffer_mmaped) {
> +buf = g_try_malloc0(data_size);
> +if (!buf) {
> +error_report("%s: Error allocating buffer ", __func__);
> +return -ENOMEM;
> +}
> +

Re: [PATCH V3 00/14] KVM: MIPS: Add Loongson-3 support (Host Side)

2020-05-08 Thread Huacai Chen
Hi, Aleksandar,

On Fri, May 8, 2020 at 7:43 PM Aleksandar Markovic
 wrote:
>
> нед, 3. мај 2020. у 12:06 Huacai Chen  је написао/ла:
> >
> > We are preparing to add KVM support for Loongson-3. VZ extension is
> > fully supported in Loongson-3A R4+, and we will not care about old CPUs
> > (at least now). We already have a full functional Linux kernel (based
> > on Linux-5.4.x LTS) and QEMU (based on 5.0.0-rc2) and their git
> > repositories are here:
> >
> > QEMU: https://github.com/chenhuacai/qemu
> > Kernel: https://github.com/chenhuacai/linux
> >
> > Of course these two repositories need to be rework and not suitable for
> > upstream (especially the commits need to be splitted). We show them here
> > is just to tell others what we have done, and how KVM/Loongson will look
> > like.
> >
> > Our plan is make the KVM host side be upstream first, and after that,
> > we will make the KVM guest side and QEMU emulator be upstream.
> >
>
> Huacei, I absolutely salute this series, as it is, in my opinion, of
> tremendous significance not only for Loongson, but also for KVM for
> MIPS in general.
>
> As you probably know, James Hogan left KVM for MIPS kernel
> maintainership some time ago. It was really too bad, as he was and
> still is, from my direct experience, an excellent colleague and
> engineer.
>
> KVM for MIPS kernel maintainership left orphaned put me (as the
> maintainer for KVM for MIPS in QEMU) in an awkward position.
>
> May I ask that you and me jointly assume KVM for MIPS kernel
> maintainership? For me, it makes perfect sense, and I would certainly
> enjoy working with you. If you agree, please add such patch at the end
> of this series, in its next version.
I'm very glad to join maintainership with you, thank you for your invitation.

Regards,
Huacai

>
> Yours,
> Aleksandar
>
>
> > V1 -> V2:
> > 1, Remove "mips: define pud_index() regardless of page table folding"
> >because it has been applied.
> > 2, Make Loongson-specific code be guarded by CONFIG_CPU_LOONGSON64.
> >
> > V2 -> V3:
> > 1, Emulate a reduced feature list of CPUCFG.
> > 2, Fix all possible checkpatch.pl errors and warnings.
> >
> > Xing Li(2):
> >  KVM: MIPS: Define KVM_ENTRYHI_ASID to cpu_asid_mask(_cpu_data)
> >  KVM: MIPS: Fix VPN2_MASK definition for variable cpu_vmbits
> >
> > Huacai Chen(12):
> >  KVM: MIPS: Increase KVM_MAX_VCPUS and KVM_USER_MEM_SLOTS to 16
> >  KVM: MIPS: Add EVENTFD support which is needed by VHOST
> >  KVM: MIPS: Use lddir/ldpte instructions to lookup gpa_mm.pgd
> >  KVM: MIPS: Introduce and use cpu_guest_has_ldpte
> >  KVM: MIPS: Use root tlb to control guest's CCA for Loongson-3
> >  KVM: MIPS: Let indexed cacheops cause guest exit on Loongson-3
> >  KVM: MIPS: Add more types of virtual interrupts
> >  KVM: MIPS: Add Loongson-3 Virtual IPI interrupt support
> >  KVM: MIPS: Add CPUCFG emulation for Loongson-3
> >  KVM: MIPS: Add CONFIG6 and DIAG registers emulation
> >  KVM: MIPS: Add more MMIO load/store instructions emulation
> >  KVM: MIPS: Enable KVM support for Loongson-3
> >
> > Signed-off-by: Huacai Chen 
> > ---
> >  arch/mips/Kconfig|   1 +
> >  arch/mips/include/asm/cpu-features.h |   3 +
> >  arch/mips/include/asm/kvm_host.h |  52 +++-
> >  arch/mips/include/asm/mipsregs.h |   7 +
> >  arch/mips/include/uapi/asm/inst.h|  11 +
> >  arch/mips/kernel/cpu-probe.c |   2 +
> >  arch/mips/kvm/Kconfig|   1 +
> >  arch/mips/kvm/Makefile   |   5 +-
> >  arch/mips/kvm/emulate.c  | 503 
> > ++-
> >  arch/mips/kvm/entry.c|  19 +-
> >  arch/mips/kvm/interrupt.c|  93 +--
> >  arch/mips/kvm/interrupt.h|  14 +-
> >  arch/mips/kvm/loongson_ipi.c | 214 +++
> >  arch/mips/kvm/mips.c |  49 +++-
> >  arch/mips/kvm/tlb.c  |  41 +++
> >  arch/mips/kvm/trap_emul.c|   3 +
> >  arch/mips/kvm/vz.c   | 235 +++-
> >  17 files changed, 1087 insertions(+), 166 deletions(-)
> >  create mode 100644 arch/mips/kvm/loongson_ipi.c
> > --
> > 2.7.0



[Bug 1877706] [NEW] [Feature request] qemu does not support for Octeon MIPS64 on X86

2020-05-08 Thread Lu Haocong
Public bug reported:

Description of problem:

I use mips64-octeon-linux-gnu-gcc cross toolchain on X86,and generate
binary file.

> mips64-octeon-linux-gnu-gcc hello.c -static
> file a.out
> a.out: ELF 32-bit MSB executable, MIPS, N32 MIPS64 rel2 version 1 (SYSV), 
> statically linked, for GNU/Linux 2.4.0, not stripped

I execute it with mips64-linux-user mode in qemu, it is invalid.

> ./qemu-5.0.0/mips64-linux-user/qemu-mips64 a.out
> a.out: Invalid ELF image for this architecture

when I choose mips-linux-user mode, it regards as illegal instruction.

> ./qemu-5.0.0/mips-linux-user/qemu-mips a.out
> qemu: uncaught target signal 4 (Illegal instruction) - core dumped
> Illegal instruction (core dumped)

I would like to know, is this due to my problem or does qemu not support
Octeon MIPS64 on X86?

if qemu has supported Octeon MIPS64 on X86, how can I emulate it.

** Affects: qemu
 Importance: Undecided
 Status: New

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1877706

Title:
   [Feature request] qemu does not support for Octeon MIPS64 on X86

Status in QEMU:
  New

Bug description:
  Description of problem:

  I use mips64-octeon-linux-gnu-gcc cross toolchain on X86,and generate
  binary file.

  > mips64-octeon-linux-gnu-gcc hello.c -static
  > file a.out
  > a.out: ELF 32-bit MSB executable, MIPS, N32 MIPS64 rel2 version 1 (SYSV), 
statically linked, for GNU/Linux 2.4.0, not stripped

  I execute it with mips64-linux-user mode in qemu, it is invalid.

  > ./qemu-5.0.0/mips64-linux-user/qemu-mips64 a.out
  > a.out: Invalid ELF image for this architecture

  when I choose mips-linux-user mode, it regards as illegal instruction.

  > ./qemu-5.0.0/mips-linux-user/qemu-mips a.out
  > qemu: uncaught target signal 4 (Illegal instruction) - core dumped
  > Illegal instruction (core dumped)

  I would like to know, is this due to my problem or does qemu not
  support Octeon MIPS64 on X86?

  if qemu has supported Octeon MIPS64 on X86, how can I emulate it.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1877706/+subscriptions



Re: [PATCH V2] hax: Dynamic allocate vcpu state structure

2020-05-08 Thread Colin Xu

Bowen is no longer working on the project so continue the revising.

Sorry for the delayed reply.

On 2020-05-09 11:59, Colin Xu wrote:

From: WangBowen 

Dynamic allocating vcpu state structure according to smp value to be
more precise and safe. Previously it will alloccate array of fixed size
HAX_MAX_VCPU.

This is achieved by using g_new0 to dynamic allocate the array. The
allocated size is obtained from smp.max_cpus in MachineState. Also, the
size is compared with HAX_MAX_VCPU when creating the vm. The reason for
choosing dynamic array over linked list is because the status is visited
by index all the time.

This will lead to QEMU checking whether the smp value is larger than the
HAX_MAX_VCPU when creating vm, if larger, the process will terminate,
otherwise it will allocate array of size smp to store the status.

V2: Check max_cpus before open vm. (Philippe)

Signed-off-by: WangBowen 
Signed-off-by: Colin Xu 
---
  target/i386/hax-all.c  | 25 +++--
  target/i386/hax-i386.h |  5 +++--
  2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c
index f9c83fff2547..c93bb23a446a 100644
--- a/target/i386/hax-all.c
+++ b/target/i386/hax-all.c
@@ -232,10 +232,10 @@ int hax_init_vcpu(CPUState *cpu)
  return ret;
  }
  
-struct hax_vm *hax_vm_create(struct hax_state *hax)

+struct hax_vm *hax_vm_create(struct hax_state *hax, int max_cpus)
  {
  struct hax_vm *vm;
-int vm_id = 0, ret;
+int vm_id = 0, ret, i;
  
  if (hax_invalid_fd(hax->fd)) {

  return NULL;
@@ -245,6 +245,11 @@ struct hax_vm *hax_vm_create(struct hax_state *hax)
  return hax->vm;
  }
  
+if (max_cpus > HAX_MAX_VCPU) {

+fprintf(stderr, "Maximum VCPU number QEMU supported is %d\n", 
HAX_MAX_VCPU);
+return NULL;
+}
+
  vm = g_new0(struct hax_vm, 1);
  
  ret = hax_host_create_vm(hax, _id);

@@ -259,6 +264,12 @@ struct hax_vm *hax_vm_create(struct hax_state *hax)
  goto error;
  }
  
+vm->numvcpus = max_cpus;

+vm->vcpus = g_new0(struct hax_vcpu_state *, vm->numvcpus);
+for (i = 0; i < vm->numvcpus; i++) {
+vm->vcpus[i] = NULL;
+}
+
  hax->vm = vm;
  return vm;
  
@@ -272,12 +283,14 @@ int hax_vm_destroy(struct hax_vm *vm)

  {
  int i;
  
-for (i = 0; i < HAX_MAX_VCPU; i++)

+for (i = 0; i < vm->numvcpus; i++)
  if (vm->vcpus[i]) {
  fprintf(stderr, "VCPU should be cleaned before vm clean\n");
  return -1;
  }
  hax_close_fd(vm->fd);
+vm->numvcpus = 0;
+g_free(vm->vcpus);
  g_free(vm);
  hax_global.vm = NULL;
  return 0;
@@ -292,7 +305,7 @@ static void hax_handle_interrupt(CPUState *cpu, int mask)
  }
  }
  
-static int hax_init(ram_addr_t ram_size)

+static int hax_init(ram_addr_t ram_size, int max_cpus)
  {
  struct hax_state *hax = NULL;
  struct hax_qemu_version qversion;
@@ -324,7 +337,7 @@ static int hax_init(ram_addr_t ram_size)
  goto error;
  }
  
-hax->vm = hax_vm_create(hax);

+hax->vm = hax_vm_create(hax, max_cpus);
  if (!hax->vm) {
  fprintf(stderr, "Failed to create HAX VM\n");
  ret = -EINVAL;
@@ -352,7 +365,7 @@ static int hax_init(ram_addr_t ram_size)
  
  static int hax_accel_init(MachineState *ms)

  {
-int ret = hax_init(ms->ram_size);
+int ret = hax_init(ms->ram_size, (int)ms->smp.max_cpus);
  
  if (ret && (ret != -ENOSPC)) {

  fprintf(stderr, "No accelerator found.\n");
diff --git a/target/i386/hax-i386.h b/target/i386/hax-i386.h
index 54e9d8b057f3..7d988f81da05 100644
--- a/target/i386/hax-i386.h
+++ b/target/i386/hax-i386.h
@@ -47,7 +47,8 @@ struct hax_state {
  struct hax_vm {
  hax_fd fd;
  int id;
-struct hax_vcpu_state *vcpus[HAX_MAX_VCPU];
+int numvcpus;
+struct hax_vcpu_state **vcpus;
  };
  
  #ifdef NEED_CPU_H

@@ -58,7 +59,7 @@ int valid_hax_tunnel_size(uint16_t size);
  /* Host specific functions */
  int hax_mod_version(struct hax_state *hax, struct hax_module_version 
*version);
  int hax_inject_interrupt(CPUArchState *env, int vector);
-struct hax_vm *hax_vm_create(struct hax_state *hax);
+struct hax_vm *hax_vm_create(struct hax_state *hax, int max_cpus);
  int hax_vcpu_run(struct hax_vcpu_state *vcpu);
  int hax_vcpu_create(int id);
  int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state,


--
Best Regards,
Colin Xu




[PATCH V2] hax: Dynamic allocate vcpu state structure

2020-05-08 Thread Colin Xu
From: WangBowen 

Dynamic allocating vcpu state structure according to smp value to be
more precise and safe. Previously it will alloccate array of fixed size
HAX_MAX_VCPU.

This is achieved by using g_new0 to dynamic allocate the array. The
allocated size is obtained from smp.max_cpus in MachineState. Also, the
size is compared with HAX_MAX_VCPU when creating the vm. The reason for
choosing dynamic array over linked list is because the status is visited
by index all the time.

This will lead to QEMU checking whether the smp value is larger than the
HAX_MAX_VCPU when creating vm, if larger, the process will terminate,
otherwise it will allocate array of size smp to store the status.

V2: Check max_cpus before open vm. (Philippe)

Signed-off-by: WangBowen 
Signed-off-by: Colin Xu 
---
 target/i386/hax-all.c  | 25 +++--
 target/i386/hax-i386.h |  5 +++--
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c
index f9c83fff2547..c93bb23a446a 100644
--- a/target/i386/hax-all.c
+++ b/target/i386/hax-all.c
@@ -232,10 +232,10 @@ int hax_init_vcpu(CPUState *cpu)
 return ret;
 }
 
-struct hax_vm *hax_vm_create(struct hax_state *hax)
+struct hax_vm *hax_vm_create(struct hax_state *hax, int max_cpus)
 {
 struct hax_vm *vm;
-int vm_id = 0, ret;
+int vm_id = 0, ret, i;
 
 if (hax_invalid_fd(hax->fd)) {
 return NULL;
@@ -245,6 +245,11 @@ struct hax_vm *hax_vm_create(struct hax_state *hax)
 return hax->vm;
 }
 
+if (max_cpus > HAX_MAX_VCPU) {
+fprintf(stderr, "Maximum VCPU number QEMU supported is %d\n", 
HAX_MAX_VCPU);
+return NULL;
+}
+
 vm = g_new0(struct hax_vm, 1);
 
 ret = hax_host_create_vm(hax, _id);
@@ -259,6 +264,12 @@ struct hax_vm *hax_vm_create(struct hax_state *hax)
 goto error;
 }
 
+vm->numvcpus = max_cpus;
+vm->vcpus = g_new0(struct hax_vcpu_state *, vm->numvcpus);
+for (i = 0; i < vm->numvcpus; i++) {
+vm->vcpus[i] = NULL;
+}
+
 hax->vm = vm;
 return vm;
 
@@ -272,12 +283,14 @@ int hax_vm_destroy(struct hax_vm *vm)
 {
 int i;
 
-for (i = 0; i < HAX_MAX_VCPU; i++)
+for (i = 0; i < vm->numvcpus; i++)
 if (vm->vcpus[i]) {
 fprintf(stderr, "VCPU should be cleaned before vm clean\n");
 return -1;
 }
 hax_close_fd(vm->fd);
+vm->numvcpus = 0;
+g_free(vm->vcpus);
 g_free(vm);
 hax_global.vm = NULL;
 return 0;
@@ -292,7 +305,7 @@ static void hax_handle_interrupt(CPUState *cpu, int mask)
 }
 }
 
-static int hax_init(ram_addr_t ram_size)
+static int hax_init(ram_addr_t ram_size, int max_cpus)
 {
 struct hax_state *hax = NULL;
 struct hax_qemu_version qversion;
@@ -324,7 +337,7 @@ static int hax_init(ram_addr_t ram_size)
 goto error;
 }
 
-hax->vm = hax_vm_create(hax);
+hax->vm = hax_vm_create(hax, max_cpus);
 if (!hax->vm) {
 fprintf(stderr, "Failed to create HAX VM\n");
 ret = -EINVAL;
@@ -352,7 +365,7 @@ static int hax_init(ram_addr_t ram_size)
 
 static int hax_accel_init(MachineState *ms)
 {
-int ret = hax_init(ms->ram_size);
+int ret = hax_init(ms->ram_size, (int)ms->smp.max_cpus);
 
 if (ret && (ret != -ENOSPC)) {
 fprintf(stderr, "No accelerator found.\n");
diff --git a/target/i386/hax-i386.h b/target/i386/hax-i386.h
index 54e9d8b057f3..7d988f81da05 100644
--- a/target/i386/hax-i386.h
+++ b/target/i386/hax-i386.h
@@ -47,7 +47,8 @@ struct hax_state {
 struct hax_vm {
 hax_fd fd;
 int id;
-struct hax_vcpu_state *vcpus[HAX_MAX_VCPU];
+int numvcpus;
+struct hax_vcpu_state **vcpus;
 };
 
 #ifdef NEED_CPU_H
@@ -58,7 +59,7 @@ int valid_hax_tunnel_size(uint16_t size);
 /* Host specific functions */
 int hax_mod_version(struct hax_state *hax, struct hax_module_version *version);
 int hax_inject_interrupt(CPUArchState *env, int vector);
-struct hax_vm *hax_vm_create(struct hax_state *hax);
+struct hax_vm *hax_vm_create(struct hax_state *hax, int max_cpus);
 int hax_vcpu_run(struct hax_vcpu_state *vcpu);
 int hax_vcpu_create(int id);
 int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state,
-- 
2.26.2




Re: [RFC v2 0/9] vDPA support in qemu

2020-05-08 Thread Jason Wang



On 2020/5/9 上午12:32, Cindy Lu wrote:

vDPA device is a device that uses a datapath which complies with the
virtio specifications with vendor specific control path. vDPA devices
can be both physically located on the hardware or emulated by software.
This RFC introduce the vDPA support in qemu

change from v1
separe the patch of introduce vhost_set_vring_ready method



I think you meant "separate"?

May worth to mention TODO:

1) vIOMMU support
2) live migration support

And it might be helpful if you can publish a github repo for people to try.

Thanks



separe the patch of qemu_get_peer
separe the patch  of vhost_set_state
intorduce the new macro specific for vDPA in configure
intorduce the fuction to pass the fd from cmdline
introduce the docmation in qemu-options.hx
the other comments form last version


Cindy Lu (3):
   net: introduce qemu_get_peer
   net: use the function qemu_get_peer
   virtio_net: introduce vhost_set_state

Jason Wang (4):
   virtio-bus: introduce queue_enabled method
   virito-pci: implement queue_enabled method
   vhost_net: set vq ready during start if necessary
   vhost: introduce vhost_set_vring_ready method

Tiwei Bie (2):
   vhost-vdpa: introduce vhost-vdpa net client
   vhost-vdpa: implement vhost-vdpa backend

  configure |  21 ++
  hw/net/vhost_net-stub.c   |   4 +
  hw/net/vhost_net.c|  77 -
  hw/net/virtio-net.c   |   9 +
  hw/virtio/Makefile.objs   |   1 +
  hw/virtio/vhost-backend.c |   5 +
  hw/virtio/vhost-vdpa.c| 447 ++
  hw/virtio/vhost.c |  14 +
  hw/virtio/virtio-pci.c|  13 +
  hw/virtio/virtio.c|   6 +
  include/hw/virtio/vhost-backend.h |  10 +-
  include/hw/virtio/vhost-vdpa.h|  25 ++
  include/hw/virtio/vhost.h |   1 +
  include/hw/virtio/virtio-bus.h|   4 +
  include/net/net.h |   1 +
  include/net/vhost-vdpa.h  |  19 ++
  include/net/vhost_net.h   |   4 +-
  net/Makefile.objs |   2 +-
  net/clients.h |   2 +
  net/net.c |   9 +
  net/vhost-vdpa.c  | 227 +++
  qapi/net.json |  22 +-
  qemu-options.hx   |  19 ++
  23 files changed, 930 insertions(+), 12 deletions(-)
  create mode 100644 hw/virtio/vhost-vdpa.c
  create mode 100644 include/hw/virtio/vhost-vdpa.h
  create mode 100644 include/net/vhost-vdpa.h
  create mode 100644 net/vhost-vdpa.c






Re: [RFC v2 5/9] vhost-vdpa: implement vhost-vdpa backend

2020-05-08 Thread Jason Wang



On 2020/5/9 上午11:00, Jason Wang wrote:


+    .vhost_get_config  = vhost_vdpa_get_config,
+    .vhost_set_config = vhost_vdpa_set_config, 



Btw, I don't see the actual user of those two helpers?

Thanks




Re: [RFC v2 9/9] vhost: introduce vhost_set_vring_ready method

2020-05-08 Thread Jason Wang



On 2020/5/9 上午12:32, Cindy Lu wrote:

From: Jason Wang 

Vhost-vdpa introduces VHOST_VDPA_SET_VRING_ENABLE which complies the
semantic of queue_enable defined in virtio spec. This method can be
used for preventing device from executing request for a specific
virtqueue. This patch introduces the vhost_ops for this.

Note that, we've already had vhost_set_vring_enable which has different
semantic which allows to enable or disable a specific virtqueue for
some kinds of vhost backends. E.g vhost-user use this to changes the
number of active queue pairs.

Signed-off-by: Jason Wang 



Similarly, please place this patch before vhost-vdpa patches.

Thanks



---
  hw/net/vhost_net-stub.c |  4 
  hw/net/vhost_net.c  | 11 ++-
  include/net/vhost_net.h |  1 +
  3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/hw/net/vhost_net-stub.c b/hw/net/vhost_net-stub.c
index aac0e98228..43e93e1a9a 100644
--- a/hw/net/vhost_net-stub.c
+++ b/hw/net/vhost_net-stub.c
@@ -86,6 +86,10 @@ int vhost_set_vring_enable(NetClientState *nc, int enable)
  return 0;
  }
  
+int vhost_set_vring_ready(NetClientState *nc)

+{
+return 0;
+}
  int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
  {
  return 0;
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index eff9ec9177..6911282a0a 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -375,7 +375,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
  goto err_start;
  }
  
-if (ncs[i].peer->vring_enable) {

+if (peer->vring_enable) {
  /* restore vring enable state */
  r = vhost_set_vring_enable(peer, peer->vring_enable);
  
@@ -496,6 +496,15 @@ int vhost_set_vring_enable(NetClientState *nc, int enable)

  return 0;
  }
  
+int vhost_set_vring_ready(NetClientState *nc)

+{
+VHostNetState *net = get_vhost_net(nc);
+const VhostOps *vhost_ops = net->dev.vhost_ops;
+if (vhost_ops && vhost_ops->vhost_set_vring_ready) {
+return vhost_ops->vhost_set_vring_ready(>dev);
+}
+return 0;
+}
  int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
  {
  const VhostOps *vhost_ops = net->dev.vhost_ops;
diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index b47844bf29..247432a3b2 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -35,6 +35,7 @@ int vhost_net_notify_migration_done(VHostNetState *net, char* 
mac_addr);
  VHostNetState *get_vhost_net(NetClientState *nc);
  
  int vhost_set_vring_enable(NetClientState * nc, int enable);

+int vhost_set_vring_ready(NetClientState *nc);
  
  uint64_t vhost_net_get_acked_features(VHostNetState *net);
  





Re: [RFC v2 8/9] vhost_net: set vq ready during start if necessary

2020-05-08 Thread Jason Wang



On 2020/5/9 上午12:32, Cindy Lu wrote:

From: Jason Wang 

Signed-off-by: Jason Wang 
---
  hw/net/vhost_net.c | 4 
  1 file changed, 4 insertions(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 1af39abaf3..eff9ec9177 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -383,6 +383,10 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
  goto err_start;
  }
  }
+
+if (virtio_queue_enabled(dev, i)) {
+vhost_set_vring_ready(peer);
+}
  }
  
  return 0;



Please place the patch before vhost-vdpa.

Thanks




Re: [RFC v2 7/9] virito-pci: implement queue_enabled method

2020-05-08 Thread Jason Wang



On 2020/5/9 上午12:32, Cindy Lu wrote:

From: Jason Wang 

With version 1, we can detect whether a queue is enabled via
queue_enabled.

Signed-off-by: Jason Wang 



This patch should come before any vhost-vdpa patch.

Thanks



---
  hw/virtio/virtio-pci.c | 13 +
  1 file changed, 13 insertions(+)

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index c6b47a9c73..4aaf5d953e 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1103,6 +1103,18 @@ static AddressSpace *virtio_pci_get_dma_as(DeviceState 
*d)
  return pci_get_address_space(dev);
  }
  
+static bool virtio_pci_queue_enabled(DeviceState *d, int n)

+{
+VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
+VirtIODevice *vdev = virtio_bus_get_device(>bus);
+
+if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
+return proxy->vqs[vdev->queue_sel].enabled;
+}
+
+return virtio_queue_get_desc_addr(vdev, n) != 0;
+}
+
  static int virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy,
 struct virtio_pci_cap *cap)
  {
@@ -2053,6 +2065,7 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, 
void *data)
  k->ioeventfd_enabled = virtio_pci_ioeventfd_enabled;
  k->ioeventfd_assign = virtio_pci_ioeventfd_assign;
  k->get_dma_as = virtio_pci_get_dma_as;
+k->queue_enabled = virtio_pci_queue_enabled;
  }
  
  static const TypeInfo virtio_pci_bus_info = {





Re: [RFC v2 6/9] virtio-bus: introduce queue_enabled method

2020-05-08 Thread Jason Wang



On 2020/5/9 上午12:32, Cindy Lu wrote:

From: Jason Wang 

This patch introduces queue_enabled() method which allows the
transport to implement its own way to report whether or not a queue is
enabled.

Signed-off-by: Jason Wang 



This patch should come before any of the vhost-vpda patch.

Thanks



---
  hw/virtio/virtio.c | 6 ++
  include/hw/virtio/virtio-bus.h | 4 
  2 files changed, 10 insertions(+)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 04716b5f6c..09732a8836 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -3169,6 +3169,12 @@ hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, 
int n)
  
  bool virtio_queue_enabled(VirtIODevice *vdev, int n)

  {
+BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
+VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+
+if (k->queue_enabled)
+return k->queue_enabled(qbus->parent, n);
+
  return virtio_queue_get_desc_addr(vdev, n) != 0;
  }
  
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h

index 38c9399cd4..0f6f215925 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -83,6 +83,10 @@ typedef struct VirtioBusClass {
   */
  int (*ioeventfd_assign)(DeviceState *d, EventNotifier *notifier,
  int n, bool assign);
+/*
+ * Whether queue number n is enabled.
+ */
+bool (*queue_enabled)(DeviceState *d, int n);
  /*
   * Does the transport have variable vring alignment?
   * (ie can it ever call virtio_queue_set_align()?)





Re: [RFC v2 5/9] vhost-vdpa: implement vhost-vdpa backend

2020-05-08 Thread Jason Wang



On 2020/5/9 上午12:32, Cindy Lu wrote:

From: Tiwei Bie 

Currently we have 2 types of vhost backends in QEMU: vhost kernel and
vhost-user. The above patch provides a generic device for vDPA purpose,
this vDPA device exposes to user space a non-vendor-specific configuration
interface for setting up a vhost HW accelerator, this patch set introduces
a third vhost backend called vhost-vdpa based on the vDPA interface.

Vhost-vdpa usage:

   qemu-system-x86_64 -cpu host -enable-kvm \
 ..
   -netdev type=vhost-vdpa,vhostdev=/dev/vhost-vdpa-id,id=vhost-vdpa0 \
   -device virtio-net-pci,netdev=vhost-vdpa0,page-per-vq=on \

Co-Authored-By: Lingshan zhu 
Signed-off-by: Cindy Lu 



Signed-off-by: Jason Wang 



---
  hw/net/vhost_net.c|  39 ++-
  hw/virtio/Makefile.objs   |   1 +
  hw/virtio/vhost-backend.c |   5 +
  hw/virtio/vhost-vdpa.c| 447 ++
  hw/virtio/vhost.c |  14 +
  include/hw/virtio/vhost-backend.h |   8 +-
  include/hw/virtio/vhost-vdpa.h|  25 ++
  include/hw/virtio/vhost.h |   1 +
  8 files changed, 538 insertions(+), 2 deletions(-)
  create mode 100644 hw/virtio/vhost-vdpa.c
  create mode 100644 include/hw/virtio/vhost-vdpa.h

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 63b2a85d6e..1af39abaf3 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -17,8 +17,10 @@
  #include "net/net.h"
  #include "net/tap.h"
  #include "net/vhost-user.h"
+#include "net/vhost-vdpa.h"
  
  #include "standard-headers/linux/vhost_types.h"

+#include "linux-headers/linux/vhost.h"
  #include "hw/virtio/virtio-net.h"
  #include "net/vhost_net.h"
  #include "qemu/error-report.h"
@@ -85,6 +87,29 @@ static const int user_feature_bits[] = {
  VHOST_INVALID_FEATURE_BIT
  };
  
+static const int vdpa_feature_bits[] = {

+VIRTIO_F_NOTIFY_ON_EMPTY,
+VIRTIO_RING_F_INDIRECT_DESC,
+VIRTIO_RING_F_EVENT_IDX,
+VIRTIO_F_ANY_LAYOUT,
+VIRTIO_F_VERSION_1,
+VIRTIO_NET_F_CSUM,
+VIRTIO_NET_F_GUEST_CSUM,
+VIRTIO_NET_F_GSO,
+VIRTIO_NET_F_GUEST_TSO4,
+VIRTIO_NET_F_GUEST_TSO6,
+VIRTIO_NET_F_GUEST_ECN,
+VIRTIO_NET_F_GUEST_UFO,
+VIRTIO_NET_F_HOST_TSO4,
+VIRTIO_NET_F_HOST_TSO6,
+VIRTIO_NET_F_HOST_ECN,
+VIRTIO_NET_F_HOST_UFO,
+VIRTIO_NET_F_MRG_RXBUF,
+VIRTIO_NET_F_MTU,
+VIRTIO_F_IOMMU_PLATFORM,
+VIRTIO_NET_F_GUEST_ANNOUNCE,
+VHOST_INVALID_FEATURE_BIT
+};



The framework should be ready for packed ring, let's add that.



  static const int *vhost_net_get_feature_bits(struct vhost_net *net)
  {
  const int *feature_bits = 0;
@@ -96,6 +121,9 @@ static const int *vhost_net_get_feature_bits(struct 
vhost_net *net)
  case NET_CLIENT_DRIVER_VHOST_USER:
  feature_bits = user_feature_bits;
  break;
+case NET_CLIENT_DRIVER_VHOST_VDPA:
+feature_bits = vdpa_feature_bits;
+break;
  default:
  error_report("Feature bits not defined for this type: %d",
  net->nc->info->type);
@@ -110,7 +138,10 @@ uint64_t vhost_net_get_features(struct vhost_net *net, 
uint64_t features)
  return vhost_get_features(>dev, vhost_net_get_feature_bits(net),
  features);
  }
-
+int vhost_net_get_device_id(struct vhost_net *net, uint32_t * device_id)
+{
+return vhost_dev_get_device_id(>dev, device_id);
+}
  void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
  {
  net->dev.acked_features = net->dev.backend_features;
@@ -433,6 +464,12 @@ VHostNetState *get_vhost_net(NetClientState *nc)
  vhost_net = vhost_user_get_vhost_net(nc);
  assert(vhost_net);
  break;
+#endif
+#ifdef CONFIG_VHOST_NET_VDPA
+case NET_CLIENT_DRIVER_VHOST_VDPA:
+vhost_net = vhost_vdpa_get_vhost_net(nc);
+assert(vhost_net);
+break;
  #endif
  default:
  break;
diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs
index e2f70fbb89..e7c5d4a862 100644
--- a/hw/virtio/Makefile.objs
+++ b/hw/virtio/Makefile.objs
@@ -5,6 +5,7 @@ obj-y += virtio.o
  obj-$(call lor,$(CONFIG_VHOST_USER),$(CONFIG_VHOST_KERNEL)) += vhost.o 
vhost-backend.o
  common-obj-$(call lnot,$(call 
lor,$(CONFIG_VHOST_USER),$(CONFIG_VHOST_KERNEL))) += vhost-stub.o
  obj-$(CONFIG_VHOST_USER) += vhost-user.o
+obj-$(CONFIG_VHOST_VDPA) += vhost-vdpa.o
  
  common-obj-$(CONFIG_VIRTIO_RNG) += virtio-rng.o

  common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
index 48905383f8..069ddb423d 100644
--- a/hw/virtio/vhost-backend.c
+++ b/hw/virtio/vhost-backend.c
@@ -285,6 +285,11 @@ int vhost_set_backend_type(struct vhost_dev *dev, 
VhostBackendType backend_type)
  case VHOST_BACKEND_TYPE_USER:
  dev->vhost_ops = _ops;
  break;
+#endif
+#ifdef CONFIG_VHOST_VDPA
+case VHOST_BACKEND_TYPE_VDPA:
+dev->vhost_ops = _ops;
+break;
  #endif
  default:
  

Re: [PATCH for-5.1 V3 0/7] mips: Add Loongson-3 machine support (with KVM)

2020-05-08 Thread chen huacai
Hi, Aleksandar,

On Sat, May 9, 2020 at 12:55 AM Aleksandar Markovic
 wrote:
>
> нед, 3. мај 2020. у 12:21 Huacai Chen  је написао/ла:
> >
> > Loongson-3 CPU family include Loongson-3A R1/R2/R3/R4 and Loongson-3B
> > R1/R2. Loongson-3A R1 is the oldest and its ISA is the smallest, while
> > Loongson-3A R4 is the newest and its ISA is almost the superset of all
> > others. To reduce complexity, in QEMU we just define two CPU types:
> >
> > 1, "Loongson-3A1000" CPU which is corresponding to Loongson-3A R1. It is
> >suitable for TCG because Loongson-3A R1 has fewest ASE.
> > 2, "Loongson-3A4000" CPU which is corresponding to Loongson-3A R4. It is
> >suitable for KVM because Loongson-3A R4 has the VZ ASE.
> >
>
> Hi, Huacei,
>
> Just a couple of practicalities. As you know, we can't upstream this
> series until correspondent kernel support is upstreamed into kernel.
> This is my advice, timing-wise:
>
> - I think it is too late (and not good from testing/risk perspective)
> to shoot for integrating your kernel series into kernel 5.7;
> - My advice is to try to upstream your kernel series at the beginning
> of 5.8 development cycle (which should not be too far)
> - Once this is done, it will open the door for integrating this series
> into QEMU upstream
> - This means that combination of kernel 5.8 and QEMU 5.1 will
> hopefully be a working system from Loongson KVM point of view
> - This will also mean we will have relatively sufficient time to test,
> and possibly fix some new bugs before QEMU 5.1 release.
>
> I hope this tentative plan sounds good to you.
OK, I will try to upstream kernel series at first, and send a V4 of
qemu series after that.
>
> Sincerely,
> Aleksandar



-- 
Huacai Chen



Re: Parameter 'driver' expects pluggable device type

2020-05-08 Thread Priyamvad Acharya
Hi,
I have set user_creatable to true in class_init function of pl061 source
code.
Now when I run qemu via command line with *-device *option it gives below
output

> qemu-system-arm: Device pl061 can not be dynamically instantiated
>


I request community members to reply asap!!!



On Fri, 8 May 2020 at 07:40, Priyamvad Acharya 
wrote:

> Hi,
> Thanks for providing relevant information.
> FYI
> I am using Qemu version *4.2.94 (v5.0.0-rc4-dirty).*
> I am using *virt* board.
>
> Where we need to set *user creatable *to true?
> Any other modification is needed to allow sysbus device support?
>
> Below is the script which I am using  to boot linux image with pl061
> device on virt board.
>
> #!/bin/bash
>>
>> KERNEL="/lhome/priyamvad/debian_qemu_arm32/vmlinuz-3.16.0-6-armmp-lpae"
>>
>> INIT_IMAGE="/lhome/priyamvad/debian_qemu_arm32/initrd.img-3.16.0-6-armmp-lpae"
>> DISK="/lhome/priyamvad/debian_qemu_arm32/hda30.qcow2"
>>
>> ./qemu-system-arm \
>> -M virt \
>> -m 1024 \
>> -smp 4 \
>> -kernel $KERNEL \
>> -object rng-random,filename=/dev/urandom,id=rng0 \
>> -device virtio-rng-device,rng=rng0 \
>> -initrd $INIT_IMAGE \
>> -append 'root=/dev/vda2' \
>> -drive if=none,file=$DISK,format=qcow2,id=hd \
>> -device pl061 \
>> -device virtio-blk-device,drive=hd \
>> -device virtio-net-device,netdev=usernet \
>> -netdev user,id=usernet,hostfwd=tcp::-:22 \
>> -nographic
>>
>
> Is the above script  correct  to boot linux image with pl061 device on
> virt board?
>
> On Fri, 8 May 2020 at 02:32, John Snow  wrote:
>
>>
>>
>> On 5/6/20 8:56 AM, Priyamvad Acharya wrote:
>> >
>> > Hello developer community,
>> > I want to allow a *sysbus *type device to boot with kernel image(arm
>> > architecture) via Qemu command line .
>> >
>> > When I run qemu arm system executable with *-device *option via qemu
>> > command line,I get following error message
>> >
>> >> qemu-system-arm: -device pl061: Parameter 'driver' expects pluggable
>> > device type
>> >
>> > So, how to allow a sysbus device via command line?
>> > Is there any working patch?
>>
>> Hi, it looks like the pl061 device is not declared "user creatable" so
>> it is unavailable from the CLI. As a sysbus device, QEMU is not aware,
>> in the abstract, of how to "connect" the device to other devices.
>>
>> See the sysbus class initialization code for more detail:
>> https://github.com/qemu/qemu/blob/master/hw/core/sysbus.c#L301
>>
>>
>> However, It looks like these boards/devices create such a device:
>>
>> hw/arm/highbank
>> hw/arm/realview
>> hw/arm/sbsa-ref
>> hw/arm/stellaris
>> hw/arm/versatilepb
>> hw/arm/virt
>>
>> If you want one on some other kind of machine, you'll need to write it
>> up yourself in the machine board code, but you didn't tell us what
>> version of QEMU you're using, what machine type you are trying to use,
>> etc.
>>
>> --js
>>
>>


Re: [RFC v2 4/9] vhost-vdpa: introduce vhost-vdpa net client

2020-05-08 Thread Jason Wang



On 2020/5/9 上午12:32, Cindy Lu wrote:

From: Tiwei Bie 



If you think you've done a huge refactor on the code, you can change the 
author but need to keep the sob of Tiwei.





This patch set introduces a new net client type: vhost-vdpa.
vhost-vdpa net client will set up a vDPA device which is specified
by a "vhostdev" parameter.

Co-authored-by: Lingshan Zhu 
Signed-off-by: Cindy Lu 
---
  configure|  21 
  include/net/vhost-vdpa.h |  19 
  include/net/vhost_net.h  |   1 +



Patch 5 which is the infrastructure of vhost-vpda should come first. 
Please re-order the patch in next version.




  net/Makefile.objs|   2 +-
  net/clients.h|   2 +
  net/net.c|   3 +
  net/vhost-vdpa.c | 227 +++
  qapi/net.json|  22 +++-
  qemu-options.hx  |  19 
  9 files changed, 313 insertions(+), 3 deletions(-)
  create mode 100644 include/net/vhost-vdpa.h
  create mode 100644 net/vhost-vdpa.c

diff --git a/configure b/configure
index 6099be1d84..bdd732e3bb 100755
--- a/configure
+++ b/configure
@@ -1505,6 +1505,10 @@ for opt do
;;
--enable-vhost-user) vhost_user="yes"
;;
+  --disable-vhost-vdpa) vhost_vdpa="no"
+  ;;
+  --enable-vhost-vdpa) vhost_vdpa="yes"
+  ;;
--disable-vhost-kernel) vhost_kernel="no"
;;
--enable-vhost-kernel) vhost_kernel="yes"
@@ -1780,6 +1784,7 @@ disabled with --disable-FEATURE, default is enabled if 
available:
vhost-cryptovhost-user-crypto backend support
vhost-kernelvhost kernel backend support
vhost-user  vhost-user backend support
+  vhost-vdpa  vhost-vdpa backend support



Maybe "vhost-vdpa kernel backend support" is better.



spice   spice
rbd rados block device (rbd)
libiscsiiscsi support
@@ -2241,6 +2246,10 @@ test "$vhost_user" = "" && vhost_user=yes
  if test "$vhost_user" = "yes" && test "$mingw32" = "yes"; then
error_exit "vhost-user isn't available on win32"
  fi
+test "$vhost_vdpa" = "" && vhost_vdpa=yes
+if test "$vhost_vdpa" = "yes" && test "$mingw32" = "yes"; then
+  error_exit "vhost-vdpa isn't available on win32"
+fi



Let's add a check for Linux like vhost kernel below.



  test "$vhost_kernel" = "" && vhost_kernel=$linux
  if test "$vhost_kernel" = "yes" && test "$linux" != "yes"; then
error_exit "vhost-kernel is only available on Linux"
@@ -2269,6 +2278,11 @@ test "$vhost_user_fs" = "" && vhost_user_fs=$vhost_user
  if test "$vhost_user_fs" = "yes" && test "$vhost_user" = "no"; then
error_exit "--enable-vhost-user-fs requires --enable-vhost-user"
  fi
+#vhost-vdpa backends
+test "$vhost_net_vdpa" = "" && vhost_net_vdpa=$vhost_vdpa
+if test "$vhost_net_vdpa" = "yes" && test "$vhost_vdpa" = "no"; then
+  error_exit "--enable-vhost-net-vdpa requires --enable-vhost-vdpa"
+fi
  
  # OR the vhost-kernel and vhost-user values for simplicity

  if test "$vhost_net" = ""; then
@@ -6543,6 +6557,7 @@ echo "vhost-scsi support $vhost_scsi"
  echo "vhost-vsock support $vhost_vsock"
  echo "vhost-user support $vhost_user"
  echo "vhost-user-fs support $vhost_user_fs"
+echo "vhost-vdpa support $vhost_vdpa"
  echo "Trace backends$trace_backends"
  if have_backend "simple"; then
  echo "Trace output file $trace_file-"
@@ -7031,6 +7046,9 @@ fi
  if test "$vhost_net_user" = "yes" ; then
echo "CONFIG_VHOST_NET_USER=y" >> $config_host_mak
  fi
+if test "$vhost_net_vdpa" = "yes" ; then
+  echo "CONFIG_VHOST_NET_VDPA=y" >> $config_host_mak
+fi
  if test "$vhost_crypto" = "yes" ; then
echo "CONFIG_VHOST_CRYPTO=y" >> $config_host_mak
  fi
@@ -7043,6 +7061,9 @@ fi
  if test "$vhost_user" = "yes" ; then
echo "CONFIG_VHOST_USER=y" >> $config_host_mak
  fi
+if test "$vhost_vdpa" = "yes" ; then
+  echo "CONFIG_VHOST_VDPA=y" >> $config_host_mak
+fi
  if test "$vhost_user_fs" = "yes" ; then
echo "CONFIG_VHOST_USER_FS=y" >> $config_host_mak
  fi
diff --git a/include/net/vhost-vdpa.h b/include/net/vhost-vdpa.h
new file mode 100644
index 00..6ce0d04f72
--- /dev/null
+++ b/include/net/vhost-vdpa.h
@@ -0,0 +1,19 @@
+/*
+ * vhost-vdpa.h
+ *
+ * Copyright(c) 2017-2018 Intel Corporation.
+ * Copyright(c) 2020 Red Hat, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef VHOST_VDPA_H
+#define VHOST_VDPA_H
+
+struct vhost_net;
+struct vhost_net *vhost_vdpa_get_vhost_net(NetClientState *nc);
+uint64_t vhost_vdpa_get_acked_features(NetClientState *nc);
+
+#endif /* VHOST_VDPA_H */
diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index 6548a5a105..b47844bf29 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -40,4 +40,5 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net);
  
  int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);

  int vhost_set_state(NetClientState *nc, uint8_t state);
+int 

Re: [RFC v2 3/9] virtio_net: introduce vhost_set_state

2020-05-08 Thread Jason Wang



On 2020/5/9 上午12:32, Cindy Lu wrote:

Introduce a function to set the state to the vhost driver.
vDPA need to sync the driver's state to NIC



Let's split this patch into two.

1) introduce vhost_set_state
2) make virtio-net use of vhost_set_state




Signed-off-by: Cindy Lu 
---
  hw/net/vhost_net.c| 9 +
  hw/net/virtio-net.c   | 9 +
  include/hw/virtio/vhost-backend.h | 2 ++
  include/net/vhost_net.h   | 2 +-
  4 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index d1d421e3d9..63b2a85d6e 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -465,3 +465,12 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
  
  return vhost_ops->vhost_net_set_mtu(>dev, mtu);

  }
+int vhost_set_state(NetClientState *nc, uint8_t state)
+{
+struct vhost_net *net = get_vhost_net(nc);
+struct vhost_dev *hdev = >dev;
+if (hdev->vhost_ops->vhost_set_state) {



Indentation looks wrong.



+return hdev->vhost_ops->vhost_set_state(hdev, state);
+}
+return 0;
+}
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index db3d7c38e6..1bddb4b4af 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -206,6 +206,9 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t 
status)
  VirtIODevice *vdev = VIRTIO_DEVICE(n);
  NetClientState *nc = qemu_get_queue(n->nic);
  int queues = n->multiqueue ? n->max_queues : 1;
+NetClientState *peer = qemu_get_peer(nc, 0);
+uint8_t status_set  = vdev->status ;
+uint8_t vhost_started_pre = n->vhost_started;
  
  if (!get_vhost_net(nc->peer)) {

  return;
@@ -245,6 +248,7 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t 
status)
  return;
  }
  }
+status_set = status_set | VIRTIO_CONFIG_S_DRIVER_OK;
  
  n->vhost_started = 1;

  r = vhost_net_start(vdev, n->nic->ncs, queues);
@@ -252,11 +256,16 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t 
status)
  error_report("unable to start vhost net: %d: "
   "falling back on userspace virtio", -r);
  n->vhost_started = 0;
+status_set = status_set & ~VIRTIO_CONFIG_S_DRIVER_OK;
  }
  } else {
  vhost_net_stop(vdev, n->nic->ncs, queues);
+status_set = status_set & ~VIRTIO_CONFIG_S_DRIVER_OK;
  n->vhost_started = 0;
  }
+if (vhost_started_pre != n->vhost_started) {
+vhost_set_state(peer, status_set);



Any reason why not just passing virtio device status to vhost-vdpa?



+}
  }
  
  static int virtio_net_set_vnet_endian_one(VirtIODevice *vdev,

diff --git a/include/hw/virtio/vhost-backend.h 
b/include/hw/virtio/vhost-backend.h
index 6f6670783f..f823055167 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -112,6 +112,7 @@ typedef int (*vhost_get_inflight_fd_op)(struct vhost_dev 
*dev,
  typedef int (*vhost_set_inflight_fd_op)(struct vhost_dev *dev,
  struct vhost_inflight *inflight);
  
+typedef int (*vhost_set_state_op)(struct vhost_dev *dev, uint8_t state);



Need document what's the meaning of state here, is it e.g virtio device 
status? If yes, is it better to rename it to vhost_set_status()?


Thanks



  typedef struct VhostOps {
  VhostBackendType backend_type;
  vhost_backend_init vhost_backend_init;
@@ -152,6 +153,7 @@ typedef struct VhostOps {
  vhost_backend_mem_section_filter_op vhost_backend_mem_section_filter;
  vhost_get_inflight_fd_op vhost_get_inflight_fd;
  vhost_set_inflight_fd_op vhost_set_inflight_fd;
+vhost_set_state_op vhost_set_state;
  } VhostOps;
  
  extern const VhostOps user_ops;

diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index 77e47398c4..6548a5a105 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -39,5 +39,5 @@ int vhost_set_vring_enable(NetClientState * nc, int enable);
  uint64_t vhost_net_get_acked_features(VHostNetState *net);
  
  int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);

-
+int vhost_set_state(NetClientState *nc, uint8_t state);
  #endif





Re: [RFC v2 2/9] net: use the function qemu_get_peer

2020-05-08 Thread Jason Wang



On 2020/5/9 上午12:32, Cindy Lu wrote:

user the qemu_get_peer to replace the old process



The title should be "vhost_net: use the function qemu_get_peer".

Thanks




Signed-off-by: Cindy Lu 
---
  hw/net/vhost_net.c | 14 +-
  1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 6b82803fa7..d1d421e3d9 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -306,7 +306,9 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
  BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
  VirtioBusState *vbus = VIRTIO_BUS(qbus);
  VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
+struct vhost_net *net;
  int r, e, i;
+NetClientState *peer;
  
  if (!k->set_guest_notifiers) {

  error_report("binding does not support guest notifiers");
@@ -314,9 +316,9 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
  }
  
  for (i = 0; i < total_queues; i++) {

-struct vhost_net *net;
  
-net = get_vhost_net(ncs[i].peer);

+peer = qemu_get_peer(ncs, i);
+net = get_vhost_net(peer);
  vhost_net_set_vq_index(net, i * 2);
  
  /* Suppress the masking guest notifiers on vhost user

@@ -335,7 +337,8 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
  }
  
  for (i = 0; i < total_queues; i++) {

-r = vhost_net_start_one(get_vhost_net(ncs[i].peer), dev);
+peer = qemu_get_peer(ncs, i);
+r = vhost_net_start_one(get_vhost_net(peer), dev);
  
  if (r < 0) {

  goto err_start;
@@ -343,7 +346,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
  
  if (ncs[i].peer->vring_enable) {

  /* restore vring enable state */
-r = vhost_set_vring_enable(ncs[i].peer, ncs[i].peer->vring_enable);
+r = vhost_set_vring_enable(peer, peer->vring_enable);
  
  if (r < 0) {

  goto err_start;
@@ -355,7 +358,8 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
  
  err_start:

  while (--i >= 0) {
-vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev);
+peer = qemu_get_peer(ncs , i);
+vhost_net_stop_one(get_vhost_net(peer), dev);
  }
  e = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
  if (e < 0) {





[Bug 1877688] Re: 9p virtfs device reports error when opening certain files

2020-05-08 Thread A A
Here's a C program to trigger this behavior. I don't think it matters
what the contents of "file" or its size is.

** Description changed:

  Reading certain files on a 9p mounted FS produces this error message:
  
  qemu-system-x86_64: VirtFS reply type 117 needs 12 bytes, buffer has 12,
  less than minimum
  
  After this error message is generated, further accesses to the 9p FS
  hangs whatever tries to access it. The Arch Linux guest system is
  otherwise usable. This happens with QEMU 5.0.0 and guest kernel version
  5.6.11, hosted on an Arch Linux distro. I use the following command to
  launch QEMU:
  
  exec qemu-system-x86_64 -enable-kvm -display gtk -vga virtio -cpu host
  -m 4G -netdev tap,ifname=vmtap0,id=vn0,script=no,downscript=no -device
  virtio-net-pci,netdev=vn0 -kernel kernel.img -drive
  file=file.img,format=raw,if=virtio -virtfs
  local,path=mnt,mount_tag=host0,security_model=passthrough,id=host0
  -append "console=ttyS0 root=/dev/vda rw"
  
  There's nothing relevant in the guest kernel logs as far as I'm aware of
  with loglevel set to 7.
  
- Aha, I found the cursed file. See this strace log:
- 
- openat(AT_FDCWD, "/home/user/.local/share/nvim/shada/main.shada", 
O_RDONLY|O_CLOEXEC) = 25
- mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab8427000
- mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab835
- mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab8279000
- mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab81a2000
- mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab80cb000
- readv(25,
+ I tracked down the issue to readv() with a small buffer(<=12 bytes) and
+ then a large buffer(>= 1024 bytes). A C program is provided to trigger
+ this behavior.

** Attachment added: "readv.c"
   
https://bugs.launchpad.net/qemu/+bug/1877688/+attachment/5368749/+files/readv.c

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1877688

Title:
  9p virtfs device reports error when opening certain files

Status in QEMU:
  New

Bug description:
  Reading certain files on a 9p mounted FS produces this error message:

  qemu-system-x86_64: VirtFS reply type 117 needs 12 bytes, buffer has
  12, less than minimum

  After this error message is generated, further accesses to the 9p FS
  hangs whatever tries to access it. The Arch Linux guest system is
  otherwise usable. This happens with QEMU 5.0.0 and guest kernel
  version 5.6.11, hosted on an Arch Linux distro. I use the following
  command to launch QEMU:

  exec qemu-system-x86_64 -enable-kvm -display gtk -vga virtio -cpu host
  -m 4G -netdev tap,ifname=vmtap0,id=vn0,script=no,downscript=no -device
  virtio-net-pci,netdev=vn0 -kernel kernel.img -drive
  file=file.img,format=raw,if=virtio -virtfs
  local,path=mnt,mount_tag=host0,security_model=passthrough,id=host0
  -append "console=ttyS0 root=/dev/vda rw"

  There's nothing relevant in the guest kernel logs as far as I'm aware
  of with loglevel set to 7.

  I tracked down the issue to readv() with a small buffer(<=12 bytes)
  and then a large buffer(>= 1024 bytes). A C program is provided to
  trigger this behavior.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1877688/+subscriptions



Re: [PATCH v5 00/19] target/arm: sve load/store improvements

2020-05-08 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200508154359.7494-1-richard.hender...@linaro.org/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Message-id: 20200508154359.7494-1-richard.hender...@linaro.org
Subject: [PATCH v5 00/19] target/arm: sve load/store improvements
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Switched to a new branch 'test'
5531df6 target/arm: Remove sve_memopidx
32fcdbe target/arm: Reuse sve_probe_page for gather loads
18e6634 target/arm: Reuse sve_probe_page for scatter stores
1ed3f4e target/arm: Reuse sve_probe_page for gather first-fault loads
c8c5809 target/arm: Use SVEContLdSt for contiguous stores
ff13c74 target/arm: Update contiguous first-fault and no-fault loads
7a4fc9f target/arm: Use SVEContLdSt for multi-register contiguous loads
e162663 target/arm: Handle watchpoints in sve_ld1_r
0a4a70e target/arm: Use SVEContLdSt in sve_ld1_r
6bc90b5 target/arm: Adjust interface of sve_ld1_host_fn
17db59e target/arm: Add sve infrastructure for page lookup
b9da291 target/arm: Drop manual handling of set/clear_helper_retaddr
8fd1eb2 target/arm: Use cpu_*_data_ra for sve_ldst_tlb_fn
474601a accel/tcg: Add endian-specific cpu_{ld, st}* operations
bdf03c8 accel/tcg: Add probe_access_flags
0c484ed accel/tcg: Adjust probe_access call to page_check_range
8a9847f accel/tcg: Add block comment for probe_access
7ae56c8 exec: Fix cpu_watchpoint_address_matches address length
3f79d9a exec: Add block comments for watchpoint routines

=== OUTPUT BEGIN ===
1/19 Checking commit 3f79d9ad401d (exec: Add block comments for watchpoint 
routines)
2/19 Checking commit 7ae56c835cf0 (exec: Fix cpu_watchpoint_address_matches 
address length)
3/19 Checking commit 8a9847f53fbc (accel/tcg: Add block comment for 
probe_access)
4/19 Checking commit 0c484ed7b14e (accel/tcg: Adjust probe_access call to 
page_check_range)
5/19 Checking commit bdf03c877b12 (accel/tcg: Add probe_access_flags)
6/19 Checking commit 474601a95614 (accel/tcg: Add endian-specific cpu_{ld, st}* 
operations)
7/19 Checking commit 8fd1eb2928fa (target/arm: Use cpu_*_data_ra for 
sve_ldst_tlb_fn)
ERROR: spaces required around that '*' (ctx:VxV)
#63: FILE: target/arm/sve_helper.c:4029:
+TLB(env, addr, (TYPEM)*(TYPEE *)(vd + H(reg_off)), ra); \
   ^

ERROR: spaces required around that '*' (ctx:WxV)
#153: FILE: target/arm/sve_helper.c:4162:
+  sve_ldst1_tlb_fn *tlb_fn)
^

total: 2 errors, 0 warnings, 455 lines checked

Patch 7/19 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

8/19 Checking commit b9da291f2b6c (target/arm: Drop manual handling of 
set/clear_helper_retaddr)
9/19 Checking commit 17db59e78016 (target/arm: Add sve infrastructure for page 
lookup)
WARNING: Block comments use a leading /* on a separate line
#32: FILE: target/arm/sve_helper.c:1633:
+/* Big-endian hosts need to frob the byte indices.  If the copy

total: 0 errors, 1 warnings, 281 lines checked

Patch 9/19 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
10/19 Checking commit 6bc90b548569 (target/arm: Adjust interface of 
sve_ld1_host_fn)
11/19 Checking commit 0a4a70e7e0ea (target/arm: Use SVEContLdSt in sve_ld1_r)
12/19 Checking commit e162663bddd0 (target/arm: Handle watchpoints in sve_ld1_r)
13/19 Checking commit 7a4fc9f72f73 (target/arm: Use SVEContLdSt for 
multi-register contiguous loads)
14/19 Checking commit ff13c741c638 (target/arm: Update contiguous first-fault 
and no-fault loads)
15/19 Checking commit c8c58097770c (target/arm: Use SVEContLdSt for contiguous 
stores)
16/19 Checking commit 1ed3f4ec9df2 (target/arm: Reuse sve_probe_page for gather 
first-fault loads)
17/19 Checking commit 18e66342e1c1 (target/arm: Reuse sve_probe_page for 
scatter stores)
18/19 Checking commit 32fcdbe6e7eb (target/arm: Reuse sve_probe_page for gather 
loads)
19/19 Checking commit 5531df6852bc (target/arm: Remove sve_memopidx)
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20200508154359.7494-1-richard.hender...@linaro.org/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

[Bug 1877688] Re: 9p virtfs device reports error when opening certain files

2020-05-08 Thread A A
** Description changed:

  Reading certain files on a 9p mounted FS produces this error message:
  
  qemu-system-x86_64: VirtFS reply type 117 needs 12 bytes, buffer has 12,
  less than minimum
  
  After this error message is generated, further accesses to the 9p FS
  hangs whatever tries to access it. The Arch Linux guest system is
  otherwise usable. This happens with QEMU 5.0.0 and guest kernel version
  5.6.11, hosted on an Arch Linux distro. I use the following command to
  launch QEMU:
  
  exec qemu-system-x86_64 -enable-kvm -display gtk -vga virtio -cpu host
  -m 4G -netdev tap,ifname=vmtap0,id=vn0,script=no,downscript=no -device
  virtio-net-pci,netdev=vn0 -kernel kernel.img -drive
  file=file.img,format=raw,if=virtio -virtfs
  local,path=mnt,mount_tag=host0,security_model=passthrough,id=host0
  -append "console=ttyS0 root=/dev/vda rw"
  
  There's nothing relevant in the guest kernel logs as far as I'm aware of
  with loglevel set to 7.
+ 
+ Aha, I found the cursed file. See this strace log:
+ 
+ openat(AT_FDCWD, "/home/user/.local/share/nvim/shada/main.shada", 
O_RDONLY|O_CLOEXEC) = 25
+ mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab8427000
+ mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab835
+ mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab8279000
+ mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab81a2000
+ mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab80cb000
+ readv(25,

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1877688

Title:
  9p virtfs device reports error when opening certain files

Status in QEMU:
  New

Bug description:
  Reading certain files on a 9p mounted FS produces this error message:

  qemu-system-x86_64: VirtFS reply type 117 needs 12 bytes, buffer has
  12, less than minimum

  After this error message is generated, further accesses to the 9p FS
  hangs whatever tries to access it. The Arch Linux guest system is
  otherwise usable. This happens with QEMU 5.0.0 and guest kernel
  version 5.6.11, hosted on an Arch Linux distro. I use the following
  command to launch QEMU:

  exec qemu-system-x86_64 -enable-kvm -display gtk -vga virtio -cpu host
  -m 4G -netdev tap,ifname=vmtap0,id=vn0,script=no,downscript=no -device
  virtio-net-pci,netdev=vn0 -kernel kernel.img -drive
  file=file.img,format=raw,if=virtio -virtfs
  local,path=mnt,mount_tag=host0,security_model=passthrough,id=host0
  -append "console=ttyS0 root=/dev/vda rw"

  There's nothing relevant in the guest kernel logs as far as I'm aware
  of with loglevel set to 7.

  Aha, I found the cursed file. See this strace log:

  openat(AT_FDCWD, "/home/user/.local/share/nvim/shada/main.shada", 
O_RDONLY|O_CLOEXEC) = 25
  mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab8427000
  mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab835
  mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab8279000
  mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab81a2000
  mmap(NULL, 880640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f3ab80cb000
  readv(25,

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1877688/+subscriptions



[Bug 1877688] [NEW] 9p virtfs device reports error when opening certain files

2020-05-08 Thread A A
Public bug reported:

Reading certain files on a 9p mounted FS produces this error message:

qemu-system-x86_64: VirtFS reply type 117 needs 12 bytes, buffer has 12,
less than minimum

After this error message is generated, further accesses to the 9p FS
hangs whatever tries to access it. The Arch Linux guest system is
otherwise usable. This happens with QEMU 5.0.0 and guest kernel version
5.6.11, hosted on an Arch Linux distro. I use the following command to
launch QEMU:

exec qemu-system-x86_64 -enable-kvm -display gtk -vga virtio -cpu host
-m 4G -netdev tap,ifname=vmtap0,id=vn0,script=no,downscript=no -device
virtio-net-pci,netdev=vn0 -kernel kernel.img -drive
file=file.img,format=raw,if=virtio -virtfs
local,path=mnt,mount_tag=host0,security_model=passthrough,id=host0
-append "console=ttyS0 root=/dev/vda rw"

There's nothing relevant in the guest kernel logs as far as I'm aware of
with loglevel set to 7.

** Affects: qemu
 Importance: Undecided
 Status: New


** Tags: 9p virtfs

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1877688

Title:
  9p virtfs device reports error when opening certain files

Status in QEMU:
  New

Bug description:
  Reading certain files on a 9p mounted FS produces this error message:

  qemu-system-x86_64: VirtFS reply type 117 needs 12 bytes, buffer has
  12, less than minimum

  After this error message is generated, further accesses to the 9p FS
  hangs whatever tries to access it. The Arch Linux guest system is
  otherwise usable. This happens with QEMU 5.0.0 and guest kernel
  version 5.6.11, hosted on an Arch Linux distro. I use the following
  command to launch QEMU:

  exec qemu-system-x86_64 -enable-kvm -display gtk -vga virtio -cpu host
  -m 4G -netdev tap,ifname=vmtap0,id=vn0,script=no,downscript=no -device
  virtio-net-pci,netdev=vn0 -kernel kernel.img -drive
  file=file.img,format=raw,if=virtio -virtfs
  local,path=mnt,mount_tag=host0,security_model=passthrough,id=host0
  -append "console=ttyS0 root=/dev/vda rw"

  There's nothing relevant in the guest kernel logs as far as I'm aware
  of with loglevel set to 7.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1877688/+subscriptions



Qemu Support for Virtio Video V4L2 driver

2020-05-08 Thread Saket Sinha
Hi ,

This is to inquire about Qemu support for Virtio Video V4L2 driver
posted in [1].
I am currently not aware of any upstream effort for Qemu reference
implementation and would like to discuss how to proceed with the same.

[1]: https://patchwork.linuxtv.org/patch/61717/

Regards,
Saket Sinha



[PATCH v1 7/8] s390/kvm: header sync for diag318

2020-05-08 Thread Collin Walling
Signed-off-by: Collin Walling 
---
 linux-headers/asm-s390/kvm.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h
index 0138ccb0d8..b661feafdc 100644
--- a/linux-headers/asm-s390/kvm.h
+++ b/linux-headers/asm-s390/kvm.h
@@ -74,6 +74,7 @@ struct kvm_s390_io_adapter_req {
 #define KVM_S390_VM_CRYPTO 2
 #define KVM_S390_VM_CPU_MODEL  3
 #define KVM_S390_VM_MIGRATION  4
+#define KVM_S390_VM_MISC   5
 
 /* kvm attributes for mem_ctrl */
 #define KVM_S390_VM_MEM_ENABLE_CMMA0
@@ -171,6 +172,10 @@ struct kvm_s390_vm_cpu_subfunc {
 #define KVM_S390_VM_MIGRATION_START1
 #define KVM_S390_VM_MIGRATION_STATUS   2
 
+/* kvm attributes for KVM_S390_VM_MISC */
+#define KVM_S390_VM_MISC_ENABLE_DIAG3180
+#define KVM_S390_VM_MISC_DIAG318   1
+
 /* for KVM_GET_REGS and KVM_SET_REGS */
 struct kvm_regs {
/* general purpose regs for s390 */
-- 
2.21.1




[PATCH v1 3/8] s390/sclp: rework sclp boundary and length checks

2020-05-08 Thread Collin Walling
Let's factor out the SCLP boundary and length checks
into separate functions.

Signed-off-by: Collin Walling 
---
 hw/s390x/sclp.c | 41 +++--
 1 file changed, 35 insertions(+), 6 deletions(-)

diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index d08a291e40..470d5da7a2 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -49,6 +49,34 @@ static inline bool sclp_command_code_valid(uint32_t code)
 return false;
 }
 
+static bool check_sccb_boundary_valid(uint64_t sccb_addr, uint32_t code,
+  SCCB *sccb)
+{
+uint64_t current_len = sccb_addr + be16_to_cpu(sccb->h.length);
+uint64_t allowed_len = (sccb_addr & PAGE_MASK) + PAGE_SIZE;
+
+switch (code & SCLP_CMD_CODE_MASK) {
+default:
+if (current_len <= allowed_len) {
+return true;
+}
+}
+sccb->h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
+return false;
+}
+
+static bool check_sufficient_sccb_len(SCCB *sccb, int size)
+{
+MachineState *ms = MACHINE(qdev_get_machine());
+int required_len = size + ms->possible_cpus->len * sizeof(CPUEntry);
+
+if (be16_to_cpu(sccb->h.length) < required_len) {
+sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
+return false;
+}
+return true;
+}
+
 static void prepare_cpu_entries(CPUEntry *entry, int *count)
 {
 MachineState *ms = MACHINE(qdev_get_machine());
@@ -76,8 +104,7 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
 int rnsize, rnmax;
 IplParameterBlock *ipib = s390_ipl_get_iplb();
 
-if (be16_to_cpu(sccb->h.length) < (sizeof(ReadInfo) + cpu_count * 
sizeof(CPUEntry))) {
-sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
+if (!check_sufficient_sccb_len(sccb, sizeof(ReadInfo))) {
 return;
 }
 
@@ -134,8 +161,7 @@ static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
 ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb;
 int cpu_count;
 
-if (be16_to_cpu(sccb->h.length) < (sizeof(ReadCpuInfo) + cpu_count * 
sizeof(CPUEntry))) {
-sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
+if (!check_sufficient_sccb_len(sccb, sizeof(ReadCpuInfo))) {
 return;
 }
 
@@ -227,6 +253,10 @@ int sclp_service_call_protected(CPUS390XState *env, 
uint64_t sccb,
 goto out_write;
 }
 
+if (!check_sccb_boundary_valid(sccb, code, _sccb)) {
+goto out_write;
+}
+
 sclp_c->execute(sclp, _sccb, code);
 out_write:
 s390_cpu_pv_mem_write(env_archcpu(env), 0, _sccb,
@@ -272,8 +302,7 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, 
uint32_t code)
 goto out_write;
 }
 
-if ((sccb + be16_to_cpu(work_sccb.h.length)) > ((sccb & PAGE_MASK) + 
PAGE_SIZE)) {
-work_sccb.h.response_code = 
cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
+if (!check_sccb_boundary_valid(sccb, code, _sccb)) {
 goto out_write;
 }
 
-- 
2.21.1




[PATCH v1 2/8] s390/sclp: check sccb len before filling in data

2020-05-08 Thread Collin Walling
The SCCB must be checked for a sufficient length before it is filled
with any data. If the length is insufficient, then the SCLP command
is suppressed and the proper response code is set in the SCCB header.

Signed-off-by: Collin Walling 
---
 hw/s390x/sclp.c | 22 ++
 smp.max_cpus|  0
 2 files changed, 10 insertions(+), 12 deletions(-)
 create mode 100644 smp.max_cpus

diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 156ffe3223..d08a291e40 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -76,6 +76,11 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
 int rnsize, rnmax;
 IplParameterBlock *ipib = s390_ipl_get_iplb();
 
+if (be16_to_cpu(sccb->h.length) < (sizeof(ReadInfo) + cpu_count * 
sizeof(CPUEntry))) {
+sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
+return;
+}
+
 /* CPU information */
 prepare_cpu_entries(read_info->entries, _count);
 read_info->entries_cpu = cpu_to_be16(cpu_count);
@@ -84,12 +89,6 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
 
 read_info->ibc_val = cpu_to_be32(s390_get_ibc_val());
 
-if (be16_to_cpu(sccb->h.length) <
-(sizeof(ReadInfo) + cpu_count * sizeof(CPUEntry))) {
-sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
-return;
-}
-
 /* Configuration Characteristic (Extension) */
 s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR,
  read_info->conf_char);
@@ -135,17 +134,16 @@ static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB 
*sccb)
 ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb;
 int cpu_count;
 
+if (be16_to_cpu(sccb->h.length) < (sizeof(ReadCpuInfo) + cpu_count * 
sizeof(CPUEntry))) {
+sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
+return;
+}
+
 prepare_cpu_entries(cpu_info->entries, _count);
 cpu_info->nr_configured = cpu_to_be16(cpu_count);
 cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo, entries));
 cpu_info->nr_standby = cpu_to_be16(0);
 
-if (be16_to_cpu(sccb->h.length) <
-(sizeof(ReadCpuInfo) + cpu_count * sizeof(CPUEntry))) {
-sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
-return;
-}
-
 /* The standby offset is 16-byte for each CPU */
 cpu_info->offset_standby = cpu_to_be16(cpu_info->offset_configured
 + cpu_info->nr_configured*sizeof(CPUEntry));
diff --git a/smp.max_cpus b/smp.max_cpus
new file mode 100644
index 00..e69de29bb2
-- 
2.21.1




[PATCH v1 8/8] s390: diagnose 318 info reset and migration support

2020-05-08 Thread Collin Walling
The DIAGNOSE 318 (diag318) instruction allows the guest to store
diagnostic data that is collected by the firmware in the case of
hardware/firmware service events. The instruction is invoked in the
Linux kernel and intercepted in KVM. QEMU needs to collect this data
for migration so that it is consistent on the destination machine.

Availability of this instruction is determined by byte 134, bit 0
of the SCLP Read Info block. This coincidentally expands into the
space used for CPU entries, which means VMs running with the diag318
capability will not be able to read information regarding all CPUs.

This feature depends on the Extended-Length SCCB (els) feature.

Diag318 is set to 0 during modified clear and load normal resets.

This feature is not supported in protected virtualization mode.

Signed-off-by: Collin Walling 
---
 hw/s390x/s390-virtio-ccw.c  | 45 +++
 hw/s390x/sclp.c |  5 +++
 include/hw/s390x/s390-virtio-ccw.h  |  1 +
 include/hw/s390x/sclp.h |  3 ++
 target/s390x/cpu.c  | 19 
 target/s390x/cpu.h  |  4 +++
 target/s390x/cpu_features.h |  1 +
 target/s390x/cpu_features_def.inc.h |  3 ++
 target/s390x/cpu_models.c   |  1 +
 target/s390x/gen-features.c |  1 +
 target/s390x/kvm-stub.c | 10 ++
 target/s390x/kvm.c  | 48 +
 target/s390x/kvm_s390x.h|  3 ++
 13 files changed, 144 insertions(+)

diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 45292fb5a8..dc4eb20ec8 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -242,6 +242,40 @@ static void s390_create_sclpconsole(const char *type, 
Chardev *chardev)
 qdev_init_nofail(dev);
 }
 
+static int diag318_post_load(void *opaque, int version_id)
+{
+S390CcwMachineState *d = opaque;
+
+s390_set_diag318_info(d->diag318_info);
+return 0;
+}
+
+static int diag318_pre_save(void *opaque)
+{
+S390CcwMachineState *d = opaque;
+
+s390_get_diag318_info(>diag318_info);
+return 0;
+}
+
+static bool diag318_needed(void *opaque)
+{
+return s390_diag318_is_allowed();
+}
+
+const VMStateDescription vmstate_diag318 = {
+.name = "vmstate_diag318",
+.post_load = diag318_post_load,
+.pre_save = diag318_pre_save,
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = diag318_needed,
+.fields = (VMStateField[]) {
+VMSTATE_UINT64(diag318_info, S390CcwMachineState),
+VMSTATE_END_OF_LIST()
+}
+};
+
 static void ccw_init(MachineState *machine)
 {
 int ret;
@@ -299,6 +333,8 @@ static void ccw_init(MachineState *machine)
 
 /* init the TOD clock */
 s390_init_tod();
+
+vmstate_register(NULL, 0, _diag318, machine);
 }
 
 static void s390_cpu_plug(HotplugHandler *hotplug_dev,
@@ -404,6 +440,13 @@ static void s390_pv_prepare_reset(S390CcwMachineState *ms)
 s390_pv_perf_clear_reset();
 }
 
+static void s390_diag318_reset(void)
+{
+if (s390_diag318_is_allowed()) {
+s390_set_diag318_info(0);
+}
+}
+
 static void s390_machine_reset(MachineState *machine)
 {
 S390CcwMachineState *ms = S390_CCW_MACHINE(machine);
@@ -440,6 +483,7 @@ static void s390_machine_reset(MachineState *machine)
 subsystem_reset();
 s390_crypto_reset();
 s390_pv_prepare_reset(ms);
+s390_diag318_reset();
 CPU_FOREACH(t) {
 run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL);
 }
@@ -452,6 +496,7 @@ static void s390_machine_reset(MachineState *machine)
  */
 subsystem_reset();
 s390_pv_prepare_reset(ms);
+s390_diag318_reset();
 CPU_FOREACH(t) {
 if (t == cs) {
 continue;
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index b5c89760e7..ae3de14e63 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -143,6 +143,11 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
 s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT,
  read_info->conf_char_ext);
 
+if (s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB)) {
+s390_get_feat_block(S390_FEAT_TYPE_SCLP_BYTE_134,
+_info->byte_134);
+}
+
 read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO |
 SCLP_HAS_IOA_RECONFIG);
 
diff --git a/include/hw/s390x/s390-virtio-ccw.h 
b/include/hw/s390x/s390-virtio-ccw.h
index cd1dccc6e3..1134da4d75 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -30,6 +30,7 @@ typedef struct S390CcwMachineState {
 bool dea_key_wrap;
 bool pv;
 uint8_t loadparm[8];
+uint64_t diag318_info;
 } S390CcwMachineState;
 
 typedef struct S390CcwMachineClass {
diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h
index ef2d63eae9..b42a6b6f5a 100644
--- a/include/hw/s390x/sclp.h
+++ 

[PATCH v1 5/8] s390/sclp: use cpu offset to locate cpu entries

2020-05-08 Thread Collin Walling
The start of the CPU entry region in the Read SCP Info
response data is denoted by the offset_cpu field. As such,
QEMU needs to begin creating entries at this address.

This is in preparation for when Read SCP Info inevitably
introduces new bytes that push the start of its CPUEntry
field further away.

Read CPU Info is unlikely to ever change, so let's not
bother accounting for the offset there.

Signed-off-by: Collin Walling 
---
 hw/s390x/sclp.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 748d04a0e2..c47bd3b5ab 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -103,15 +103,17 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
 int cpu_count;
 int rnsize, rnmax;
 IplParameterBlock *ipib = s390_ipl_get_iplb();
+int offset_cpu = offsetof(ReadInfo, entries);
+CPUEntry *entries_start = (void *)sccb + offset_cpu;
 
 if (!check_sufficient_sccb_len(sccb, sizeof(ReadInfo))) {
 return;
 }
 
 /* CPU information */
-prepare_cpu_entries(read_info->entries, _count);
+prepare_cpu_entries(entries_start, _count);
 read_info->entries_cpu = cpu_to_be16(cpu_count);
-read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries));
+read_info->offset_cpu = cpu_to_be16(offset_cpu);
 read_info->highest_cpu = cpu_to_be16(machine->smp.max_cpus - 1);
 
 read_info->ibc_val = cpu_to_be32(s390_get_ibc_val());
-- 
2.21.1




[PATCH v1 6/8] s390/sclp: add extended-length sccb support for kvm guest

2020-05-08 Thread Collin Walling
As more features and facilities are added to the Read SCP Info (RSCPI)
response, more space is required to store them. The space used to store
these new features intrudes on the space originally used to store CPU
entries. This means as more features and facilities are added to the
RSCPI response, less space can be used to store CPU entries.

With the Extended-Length SCCB (ELS) facility, a KVM guest can execute
the RSCPI command and determine if the SCCB is large enough to store a
complete reponse. If it is not large enough, then the required length
will be set in the SCCB header.

The caller of the SCLP command is responsible for creating a
large-enough SCCB to store a complete response. Proper checking should
be in place, and the caller should execute the command once-more with
the large-enough SCCB.

This facility also enables an extended SCCB for the Read CPU Info
(RCPUI) command.

When this facility is enabled, the boundary violation response cannot
be a result from the RSCPI, RSCPI Forced, or RCPUI commands.

In order to tolerate kernels that do not yet have full support for this
feature, a "fixed" offset to the start of the CPU Entries within the
Read SCP Info struct is set to allow for the original 248 max entries.

Additionally, this is introduced as a CPU feature to protect the guest
from migrating to a machine that does not support storing an extended
SCCB. This could otherwise hinder the VM from being able to read all
available CPU entries after migration.

Signed-off-by: Collin Walling 
---
 hw/s390x/sclp.c | 23 +--
 include/hw/s390x/sclp.h |  1 +
 target/s390x/cpu_features_def.inc.h |  1 +
 target/s390x/gen-features.c |  1 +
 target/s390x/kvm.c  |  4 
 5 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index c47bd3b5ab..b5c89760e7 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -56,6 +56,18 @@ static bool check_sccb_boundary_valid(uint64_t sccb_addr, 
uint32_t code,
 uint64_t allowed_len = (sccb_addr & PAGE_MASK) + PAGE_SIZE;
 
 switch (code & SCLP_CMD_CODE_MASK) {
+case SCLP_CMDW_READ_SCP_INFO:
+case SCLP_CMDW_READ_SCP_INFO_FORCED:
+case SCLP_CMDW_READ_CPU_INFO:
+/*
+ * An extended-length SCCB is only allowed for RSCPI and RSCPU and is
+ * allowed to exceed the 4k boundary. The respective commands will
+ * set the length field to the required length if an insufficient
+ * SCCB length is provided.
+ */
+if (s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB)) {
+return true;
+}
 default:
 if (current_len <= allowed_len) {
 return true;
@@ -72,6 +84,10 @@ static bool check_sufficient_sccb_len(SCCB *sccb, int size)
 
 if (be16_to_cpu(sccb->h.length) < required_len) {
 sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
+if (s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) &&
+sccb->h.control_mask[2] & SCLP_VARIABLE_LENGTH_RESPONSE) {
+sccb->h.length = required_len;
+}
 return false;
 }
 return true;
@@ -103,10 +119,13 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
 int cpu_count;
 int rnsize, rnmax;
 IplParameterBlock *ipib = s390_ipl_get_iplb();
-int offset_cpu = offsetof(ReadInfo, entries);
+int offset_cpu = s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) ?
+ offsetof(ReadInfo, entries) :
+ SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET;
 CPUEntry *entries_start = (void *)sccb + offset_cpu;
 
-if (!check_sufficient_sccb_len(sccb, sizeof(ReadInfo))) {
+if (!check_sufficient_sccb_len(sccb, offset_cpu)) {
+warn_report("insufficient sccb size to store full read scp info 
response");
 return;
 }
 
diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h
index 822eff4396..ef2d63eae9 100644
--- a/include/hw/s390x/sclp.h
+++ b/include/hw/s390x/sclp.h
@@ -110,6 +110,7 @@ typedef struct CPUEntry {
 uint8_t reserved1;
 } QEMU_PACKED CPUEntry;
 
+#define SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET 128
 typedef struct ReadInfo {
 SCCBHeader h;
 uint16_t rnmax;
diff --git a/target/s390x/cpu_features_def.inc.h 
b/target/s390x/cpu_features_def.inc.h
index 60db28351d..3548d65a69 100644
--- a/target/s390x/cpu_features_def.inc.h
+++ b/target/s390x/cpu_features_def.inc.h
@@ -97,6 +97,7 @@ DEF_FEAT(GUARDED_STORAGE, "gs", STFL, 133, "Guarded-storage 
facility")
 DEF_FEAT(VECTOR_PACKED_DECIMAL, "vxpd", STFL, 134, "Vector packed decimal 
facility")
 DEF_FEAT(VECTOR_ENH, "vxeh", STFL, 135, "Vector enhancements facility")
 DEF_FEAT(MULTIPLE_EPOCH, "mepoch", STFL, 139, "Multiple-epoch facility")
+DEF_FEAT(EXTENDED_LENGTH_SCCB, "els", STFL, 140, "Extended-length SCCB 
facility")
 DEF_FEAT(TEST_PENDING_EXT_INTERRUPTION, "tpei", STFL, 144, 
"Test-pending-external-interruption facility")
 

[PATCH v1 1/8] s390/sclp: remove SCLPDevice param from prepare_cpu_entries

2020-05-08 Thread Collin Walling
It was never used in this function, so let's remove it.

Signed-off-by: Collin Walling 
---
 hw/s390x/sclp.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index ede056b3ef..156ffe3223 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -49,7 +49,7 @@ static inline bool sclp_command_code_valid(uint32_t code)
 return false;
 }
 
-static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int *count)
+static void prepare_cpu_entries(CPUEntry *entry, int *count)
 {
 MachineState *ms = MACHINE(qdev_get_machine());
 uint8_t features[SCCB_CPU_FEATURE_LEN] = { 0 };
@@ -77,7 +77,7 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
 IplParameterBlock *ipib = s390_ipl_get_iplb();
 
 /* CPU information */
-prepare_cpu_entries(sclp, read_info->entries, _count);
+prepare_cpu_entries(read_info->entries, _count);
 read_info->entries_cpu = cpu_to_be16(cpu_count);
 read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries));
 read_info->highest_cpu = cpu_to_be16(machine->smp.max_cpus - 1);
@@ -135,7 +135,7 @@ static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
 ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb;
 int cpu_count;
 
-prepare_cpu_entries(sclp, cpu_info->entries, _count);
+prepare_cpu_entries(cpu_info->entries, _count);
 cpu_info->nr_configured = cpu_to_be16(cpu_count);
 cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo, entries));
 cpu_info->nr_standby = cpu_to_be16(0);
-- 
2.21.1




[PATCH v1 4/8] s390/sclp: read sccb from mem based on sccb length

2020-05-08 Thread Collin Walling
The header of the SCCB contains the actual length of the
SCCB. Instead of using a static 4K size, let's allow
for a variable size determined by the value set in the
header. The proper checks are already in place to ensure
the SCCB length is sufficent to store a full response,
and that the length does not cross any explicitly-set
boundaries.

Signed-off-by: Collin Walling 
---
 hw/s390x/sclp.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 470d5da7a2..748d04a0e2 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -244,15 +244,16 @@ int sclp_service_call_protected(CPUS390XState *env, 
uint64_t sccb,
 SCLPDevice *sclp = get_sclp_device();
 SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
 SCCB work_sccb;
-hwaddr sccb_len = sizeof(SCCB);
 
-s390_cpu_pv_mem_read(env_archcpu(env), 0, _sccb, sccb_len);
+s390_cpu_pv_mem_read(env_archcpu(env), 0, _sccb, sizeof(SCCBHeader));
 
 if (!sclp_command_code_valid(code)) {
 work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
 goto out_write;
 }
 
+s390_cpu_pv_mem_read(env_archcpu(env), 0, _sccb, work_sccb.h.length);
+
 if (!check_sccb_boundary_valid(sccb, code, _sccb)) {
 goto out_write;
 }
@@ -271,8 +272,6 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, 
uint32_t code)
 SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
 SCCB work_sccb;
 
-hwaddr sccb_len = sizeof(SCCB);
-
 /* first some basic checks on program checks */
 if (env->psw.mask & PSW_MASK_PSTATE) {
 return -PGM_PRIVILEGED;
@@ -290,13 +289,16 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, 
uint32_t code)
  * from playing dirty tricks by modifying the memory content after
  * the host has checked the values
  */
-cpu_physical_memory_read(sccb, _sccb, sccb_len);
+cpu_physical_memory_read(sccb, _sccb, sizeof(SCCBHeader));
 
 /* Valid sccb sizes */
 if (be16_to_cpu(work_sccb.h.length) < sizeof(SCCBHeader)) {
 return -PGM_SPECIFICATION;
 }
 
+/* the header contains the actual length of the sccb */
+cpu_physical_memory_read(sccb, _sccb, work_sccb.h.length);
+
 if (!sclp_command_code_valid(code)) {
 work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
 goto out_write;
-- 
2.21.1




[PATCH v1 0/8] s390: Extended-Length SCCB & DIAGNOSE 0x318

2020-05-08 Thread Collin Walling
This patch series introduces two features for an s390 KVM quest:
- Extended-Length SCCB (els) for the Read SCP/CPU Info SCLP 
commands
- DIAGNOSE 0x318 (diag318) enabling / migration handling

The diag318 feature depends on els and KVM support.

The els feature is handled entirely with QEMU, and does not require 
KVM support.

These patches are introduced together for two main reasons:
- els allows diag318 to exist while retaining the original 248 
VCPU max
- diag318 is presented to show how els is useful

Full els support is dependant on the Linux kernel, which must react
to the SCLP response code and set an appropriate-length SCCB. 

A user should take care when tuning the CPU model for a VM.
If a user defines a VM with els support and specifies 248 CPUs, but
the guest Linux kernel cannot react to the SCLP response code, then
the guest will crash immediately upon kernel startup.

Since it has been some time since the last review and a few things
have changed, I've removed all ack's and set this submission to v1.

Collin L. Walling (8):
  s390/sclp: remove SCLPDevice param from prepare_cpu_entries
  s390/sclp: check sccb len before filling in data
  s390/sclp: rework sclp boundary and length checks
  s390/sclp: read sccb from mem based on sccb length
  s390/sclp: use cpu offset to locate cpu entries
  s390/sclp: add extended-length sccb support for kvm guest
  s390/kvm: header sync for diag318
  s390: diagnose 318 info reset and migration support

 hw/s390x/s390-virtio-ccw.c  |  45 +
 hw/s390x/sclp.c | 101 +---
 include/hw/s390x/s390-virtio-ccw.h  |   1 +
 include/hw/s390x/sclp.h |   4 ++
 linux-headers/asm-s390/kvm.h|   5 ++
 smp.max_cpus|   0
 target/s390x/cpu.c  |  19 ++
 target/s390x/cpu.h  |   4 ++
 target/s390x/cpu_features.h |   1 +
 target/s390x/cpu_features_def.inc.h |   4 ++
 target/s390x/cpu_models.c   |   1 +
 target/s390x/gen-features.c |   2 +
 target/s390x/kvm-stub.c |  10 +++
 target/s390x/kvm.c  |  52 ++
 target/s390x/kvm_s390x.h|   3 +
 15 files changed, 229 insertions(+), 23 deletions(-)
 create mode 100644 smp.max_cpus

-- 
2.21.1




[PATCH v24 QEMU 1/3] virtio-balloon: Replace free page hinting references to 'report' with 'hint'

2020-05-08 Thread Alexander Duyck
From: Alexander Duyck 

In an upcoming patch a feature named Free Page Reporting is about to be
added. In order to avoid any confusion we should drop the use of the word
'report' when referring to Free Page Hinting. So what this patch does is go
through and replace all instances of 'report' with 'hint" when we are
referring to free page hinting.

Acked-by: David Hildenbrand 
Signed-off-by: Alexander Duyck 
---
 hw/virtio/virtio-balloon.c |   78 ++--
 include/hw/virtio/virtio-balloon.h |   20 +
 2 files changed, 49 insertions(+), 49 deletions(-)

diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index a4729f7fc930..a209706b4d8d 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -466,21 +466,21 @@ static bool get_free_page_hints(VirtIOBalloon *dev)
 ret = false;
 goto out;
 }
-if (id == dev->free_page_report_cmd_id) {
-dev->free_page_report_status = FREE_PAGE_REPORT_S_START;
+if (id == dev->free_page_hint_cmd_id) {
+dev->free_page_hint_status = FREE_PAGE_HINT_S_START;
 } else {
 /*
  * Stop the optimization only when it has started. This
  * avoids a stale stop sign for the previous command.
  */
-if (dev->free_page_report_status == FREE_PAGE_REPORT_S_START) {
-dev->free_page_report_status = FREE_PAGE_REPORT_S_STOP;
+if (dev->free_page_hint_status == FREE_PAGE_HINT_S_START) {
+dev->free_page_hint_status = FREE_PAGE_HINT_S_STOP;
 }
 }
 }
 
 if (elem->in_num) {
-if (dev->free_page_report_status == FREE_PAGE_REPORT_S_START) {
+if (dev->free_page_hint_status == FREE_PAGE_HINT_S_START) {
 qemu_guest_free_page_hint(elem->in_sg[0].iov_base,
   elem->in_sg[0].iov_len);
 }
@@ -506,11 +506,11 @@ static void virtio_ballloon_get_free_page_hints(void 
*opaque)
 qemu_mutex_unlock(>free_page_lock);
 virtio_notify(vdev, vq);
   /*
-   * Start to poll the vq once the reporting started. Otherwise, continue
+   * Start to poll the vq once the hinting started. Otherwise, continue
* only when there are entries on the vq, which need to be given back.
*/
 } while (continue_to_get_hints ||
- dev->free_page_report_status == FREE_PAGE_REPORT_S_START);
+ dev->free_page_hint_status == FREE_PAGE_HINT_S_START);
 virtio_queue_set_notification(vq, 1);
 }
 
@@ -531,14 +531,14 @@ static void virtio_balloon_free_page_start(VirtIOBalloon 
*s)
 return;
 }
 
-if (s->free_page_report_cmd_id == UINT_MAX) {
-s->free_page_report_cmd_id =
-   VIRTIO_BALLOON_FREE_PAGE_REPORT_CMD_ID_MIN;
+if (s->free_page_hint_cmd_id == UINT_MAX) {
+s->free_page_hint_cmd_id =
+   VIRTIO_BALLOON_FREE_PAGE_HINT_CMD_ID_MIN;
 } else {
-s->free_page_report_cmd_id++;
+s->free_page_hint_cmd_id++;
 }
 
-s->free_page_report_status = FREE_PAGE_REPORT_S_REQUESTED;
+s->free_page_hint_status = FREE_PAGE_HINT_S_REQUESTED;
 virtio_notify_config(vdev);
 }
 
@@ -546,18 +546,18 @@ static void virtio_balloon_free_page_stop(VirtIOBalloon 
*s)
 {
 VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
-if (s->free_page_report_status != FREE_PAGE_REPORT_S_STOP) {
+if (s->free_page_hint_status != FREE_PAGE_HINT_S_STOP) {
 /*
  * The lock also guarantees us that the
  * virtio_ballloon_get_free_page_hints exits after the
- * free_page_report_status is set to S_STOP.
+ * free_page_hint_status is set to S_STOP.
  */
 qemu_mutex_lock(>free_page_lock);
 /*
- * The guest hasn't done the reporting, so host sends a notification
- * to the guest to actively stop the reporting.
+ * The guest isn't done hinting, so send a notification
+ * to the guest to actively stop the hinting.
  */
-s->free_page_report_status = FREE_PAGE_REPORT_S_STOP;
+s->free_page_hint_status = FREE_PAGE_HINT_S_STOP;
 qemu_mutex_unlock(>free_page_lock);
 virtio_notify_config(vdev);
 }
@@ -567,15 +567,15 @@ static void virtio_balloon_free_page_done(VirtIOBalloon 
*s)
 {
 VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
-s->free_page_report_status = FREE_PAGE_REPORT_S_DONE;
+s->free_page_hint_status = FREE_PAGE_HINT_S_DONE;
 virtio_notify_config(vdev);
 }
 
 static int
-virtio_balloon_free_page_report_notify(NotifierWithReturn *n, void *data)
+virtio_balloon_free_page_hint_notify(NotifierWithReturn *n, void *data)
 {
 VirtIOBalloon *dev = container_of(n, VirtIOBalloon,
-  free_page_report_notify);
+  free_page_hint_notify);
 VirtIODevice *vdev = 

[PATCH v24 QEMU 3/3] virtio-balloon: Provide an interface for free page reporting

2020-05-08 Thread Alexander Duyck
From: Alexander Duyck 

Add support for free page reporting. The idea is to function very similar
to how the balloon works in that we basically end up madvising the page as
not being used. However we don't really need to bother with any deflate
type logic since the page will be faulted back into the guest when it is
read or written to.

This provides a new way of letting the guest proactively report free
pages to the hypervisor, so the hypervisor can reuse them. In contrast to
inflate/deflate that is triggered via the hypervisor explicitly.

Acked-by: David Hildenbrand 
Signed-off-by: Alexander Duyck 
---
 hw/virtio/virtio-balloon.c |   69 
 include/hw/virtio/virtio-balloon.h |2 +
 2 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 1666132a24c1..53abba290274 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -321,6 +321,67 @@ static void balloon_stats_set_poll_interval(Object *obj, 
Visitor *v,
 balloon_stats_change_timer(s, 0);
 }
 
+static void virtio_balloon_handle_report(VirtIODevice *vdev, VirtQueue *vq)
+{
+VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
+VirtQueueElement *elem;
+
+while ((elem = virtqueue_pop(vq, sizeof(VirtQueueElement {
+unsigned int i;
+
+/*
+ * When we discard the page it has the effect of removing the page
+ * from the hypervisor itself and causing it to be zeroed when it
+ * is returned to us. So we must not discard the page if it is
+ * accessible by another device or process, or if the guest is
+ * expecting it to retain a non-zero value.
+ */
+if (qemu_balloon_is_inhibited() || dev->poison_val) {
+goto skip_element;
+}
+
+for (i = 0; i < elem->in_num; i++) {
+void *addr = elem->in_sg[i].iov_base;
+size_t size = elem->in_sg[i].iov_len;
+ram_addr_t ram_offset;
+RAMBlock *rb;
+
+/*
+ * There is no need to check the memory section to see if
+ * it is ram/readonly/romd like there is for handle_output
+ * below. If the region is not meant to be written to then
+ * address_space_map will have allocated a bounce buffer
+ * and it will be freed in address_space_unmap and trigger
+ * and unassigned_mem_write before failing to copy over the
+ * buffer. If more than one bad descriptor is provided it
+ * will return NULL after the first bounce buffer and fail
+ * to map any resources.
+ */
+rb = qemu_ram_block_from_host(addr, false, _offset);
+if (!rb) {
+trace_virtio_balloon_bad_addr(elem->in_addr[i]);
+continue;
+}
+
+/*
+ * For now we will simply ignore unaligned memory regions, or
+ * regions that overrun the end of the RAMBlock.
+ */
+if (!QEMU_IS_ALIGNED(ram_offset | size, qemu_ram_pagesize(rb)) ||
+(ram_offset + size) > qemu_ram_get_used_length(rb)) {
+continue;
+}
+
+ram_block_discard_range(rb, ram_offset, size);
+}
+
+skip_element:
+virtqueue_push(vq, elem, 0);
+virtio_notify(vdev, vq);
+g_free(elem);
+}
+}
+
 static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
 {
 VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
@@ -841,6 +902,12 @@ static void virtio_balloon_device_realize(DeviceState 
*dev, Error **errp)
 virtio_error(vdev, "iothread is missing");
 }
 }
+
+if (virtio_has_feature(s->host_features, VIRTIO_BALLOON_F_REPORTING)) {
+s->reporting_vq = virtio_add_queue(vdev, 32,
+   virtio_balloon_handle_report);
+}
+
 reset_stats(s);
 }
 
@@ -945,6 +1012,8 @@ static Property virtio_balloon_properties[] = {
 VIRTIO_BALLOON_F_FREE_PAGE_HINT, false),
 DEFINE_PROP_BIT("page-poison", VirtIOBalloon, host_features,
 VIRTIO_BALLOON_F_PAGE_POISON, true),
+DEFINE_PROP_BIT("free-page-reporting", VirtIOBalloon, host_features,
+VIRTIO_BALLOON_F_REPORTING, false),
 /* QEMU 4.0 accidentally changed the config size even when free-page-hint
  * is disabled, resulting in QEMU 3.1 migration incompatibility.  This
  * property retains this quirk for QEMU 4.1 machine types.
diff --git a/include/hw/virtio/virtio-balloon.h 
b/include/hw/virtio/virtio-balloon.h
index 3ca2a78e1aca..28fd2b396087 100644
--- a/include/hw/virtio/virtio-balloon.h
+++ b/include/hw/virtio/virtio-balloon.h
@@ -42,7 +42,7 @@ enum virtio_balloon_free_page_hint_status {
 
 typedef struct VirtIOBalloon {
 VirtIODevice parent_obj;
-VirtQueue *ivq, *dvq, *svq, *free_page_vq;
+VirtQueue *ivq, 

[PATCH v24 QEMU 2/3] virtio-balloon: Implement support for page poison reporting feature

2020-05-08 Thread Alexander Duyck
From: Alexander Duyck 

We need to make certain to advertise support for page poison reporting if
we want to actually get data on if the guest will be poisoning pages.

Add a value for reporting the poison value being used if page poisoning is
enabled in the guest. With this we can determine if we will need to skip
free page reporting when it is enabled in the future.

The value currently has no impact on existing balloon interfaces. In the
case of existing balloon interfaces the onus is on the guest driver to
reapply whatever poison is in place.

When we add free page reporting the poison value is used to determine if
we can perform in-place page reporting. The expectation is that a reported
page will already contain the value specified by the poison, and the
reporting of the page should not change that value.

Acked-by: David Hildenbrand 
Signed-off-by: Alexander Duyck 
---
 hw/core/machine.c  |4 +++-
 hw/virtio/virtio-balloon.c |   29 +
 include/hw/virtio/virtio-balloon.h |1 +
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 7a50dd518f4c..da26d58634dc 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -28,7 +28,9 @@
 #include "hw/mem/nvdimm.h"
 #include "migration/vmstate.h"
 
-GlobalProperty hw_compat_5_0[] = {};
+GlobalProperty hw_compat_5_0[] = {
+{ "virtio-balloon-device", "page-poison", "false" },
+};
 const size_t hw_compat_5_0_len = G_N_ELEMENTS(hw_compat_5_0);
 
 GlobalProperty hw_compat_4_2[] = {
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index a209706b4d8d..1666132a24c1 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -634,6 +634,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, 
uint8_t *config_data)
 
 config.num_pages = cpu_to_le32(dev->num_pages);
 config.actual = cpu_to_le32(dev->actual);
+config.poison_val = cpu_to_le32(dev->poison_val);
 
 if (dev->free_page_hint_status == FREE_PAGE_HINT_S_REQUESTED) {
 config.free_page_hint_cmd_id =
@@ -683,6 +684,14 @@ static ram_addr_t get_current_ram_size(void)
 return size;
 }
 
+static bool virtio_balloon_page_poison_support(void *opaque)
+{
+VirtIOBalloon *s = opaque;
+VirtIODevice *vdev = VIRTIO_DEVICE(s);
+
+return virtio_vdev_has_feature(vdev, VIRTIO_BALLOON_F_PAGE_POISON);
+}
+
 static void virtio_balloon_set_config(VirtIODevice *vdev,
   const uint8_t *config_data)
 {
@@ -697,6 +706,10 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
 qapi_event_send_balloon_change(vm_ram_size -
 ((ram_addr_t) dev->actual << 
VIRTIO_BALLOON_PFN_SHIFT));
 }
+dev->poison_val = 0;
+if (virtio_balloon_page_poison_support(dev)) {
+dev->poison_val = le32_to_cpu(config.poison_val);
+}
 trace_virtio_balloon_set_config(dev->actual, oldactual);
 }
 
@@ -755,6 +768,17 @@ static const VMStateDescription 
vmstate_virtio_balloon_free_page_hint = {
 }
 };
 
+static const VMStateDescription vmstate_virtio_balloon_page_poison = {
+.name = "vitio-balloon-device/page-poison",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = virtio_balloon_page_poison_support,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32(poison_val, VirtIOBalloon),
+VMSTATE_END_OF_LIST()
+}
+};
+
 static const VMStateDescription vmstate_virtio_balloon_device = {
 .name = "virtio-balloon-device",
 .version_id = 1,
@@ -767,6 +791,7 @@ static const VMStateDescription 
vmstate_virtio_balloon_device = {
 },
 .subsections = (const VMStateDescription * []) {
 _virtio_balloon_free_page_hint,
+_virtio_balloon_page_poison,
 NULL
 }
 };
@@ -854,6 +879,8 @@ static void virtio_balloon_device_reset(VirtIODevice *vdev)
 g_free(s->stats_vq_elem);
 s->stats_vq_elem = NULL;
 }
+
+s->poison_val = 0;
 }
 
 static void virtio_balloon_set_status(VirtIODevice *vdev, uint8_t status)
@@ -916,6 +943,8 @@ static Property virtio_balloon_properties[] = {
 VIRTIO_BALLOON_F_DEFLATE_ON_OOM, false),
 DEFINE_PROP_BIT("free-page-hint", VirtIOBalloon, host_features,
 VIRTIO_BALLOON_F_FREE_PAGE_HINT, false),
+DEFINE_PROP_BIT("page-poison", VirtIOBalloon, host_features,
+VIRTIO_BALLOON_F_PAGE_POISON, true),
 /* QEMU 4.0 accidentally changed the config size even when free-page-hint
  * is disabled, resulting in QEMU 3.1 migration incompatibility.  This
  * property retains this quirk for QEMU 4.1 machine types.
diff --git a/include/hw/virtio/virtio-balloon.h 
b/include/hw/virtio/virtio-balloon.h
index 108cff97e71a..3ca2a78e1aca 100644
--- a/include/hw/virtio/virtio-balloon.h
+++ b/include/hw/virtio/virtio-balloon.h
@@ -70,6 +70,7 @@ typedef struct VirtIOBalloon {
 uint32_t host_features;
 
 bool 

[PATCH v24 QEMU 0/3] virtio-balloon: add support for page poison reporting and free page reporting

2020-05-08 Thread Alexander Duyck
This series provides an asynchronous means of reporting free guest pages
to QEMU through virtio-balloon so that the memory associated with those
pages can be dropped and reused by other processes and/or guests on the
host. Using this it is possible to avoid unnecessary I/O to disk and
greatly improve performance in the case of memory overcommit on the host.

I originally submitted this patch series back on February 11th 2020[1],
but at that time I was focused primarily on the kernel portion of this
patch set. However as of April 7th those patches are now included in
Linus's kernel tree[2] and so I am submitting the QEMU pieces for
inclusion.

[1]: 
https://lore.kernel.org/lkml/20200211224416.29318.44077.stgit@localhost.localdomain/
[2]: 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b0c504f154718904ae49349147e3b7e6ae91ffdc

Changes from v17:
Fixed typo in patch 1 title
Addressed white-space issues reported via checkpatch
Added braces {} for two if statements to match expected coding style

Changes from v18:
Updated patches 2 and 3 based on input from dhildenb
Added comment to patch 2 describing what keeps us from reporting a bad page
Added patch to address issue with ROM devices being directly writable

Changes from v19:
Added std-headers change to match changes pushed for linux kernel headers
Added patch to remove "report" from page hinting code paths
Updated comment to better explain why we disable hints w/ page poisoning
Removed code that was modifying config size for poison vs hinting
Dropped x-page-poison property
Added code to bounds check the reported region vs the RAM block
Dropped patch for ROM devices as that was already pulled in by Paolo

Changes from v20:
Rearranged patches to push Linux header sync patches to front
Removed association between free page hinting and VIRTIO_BALLOON_F_PAGE_POISON
Added code to enable VIRTIO_BALLOON_F_PAGE_POISON if page reporting is enabled
Fixed possible resource leak if poison or qemu_balloon_is_inhibited return true

Changes from v21:
Added ack for patch 3
Rewrote patch description for page poison reporting feature
Made page-poison independent property and set to enabled by default
Added logic to migrate poison_val
Added several comments in code to better explain features
Switched free-page-reporting property to disabled by default

Changes from v22:
Added ack for patches 4 & 5
Added additional comment fixes in patch 3 to remove "reporting" reference
Renamed rvq in patch 5 to reporting_vq to better match linux kernel
Moved call adding reporting_vq to after free_page_vq

Changes from v23:
Rebased on latest QEMU
Dropped patches 1 & 2 as Linux kernel headers were synced
Added compat machine bits for page-poison feature

---

Alexander Duyck (3):
  virtio-balloon: Replace free page hinting references to 'report' with 
'hint'
  virtio-balloon: Implement support for page poison reporting feature
  virtio-balloon: Provide an interface for free page reporting


 hw/core/machine.c  |4 +
 hw/virtio/virtio-balloon.c |  176 
 include/hw/virtio/virtio-balloon.h |   23 ++---
 3 files changed, 152 insertions(+), 51 deletions(-)

--



[PULL v2 1/1] hw/tpm: fix usage of bool in tpm-tis.c

2020-05-08 Thread Stefan Berger
From: Jafar Abdi 

Clean up wrong usage of FALSE and TRUE in places that use "bool" from stdbool.h.

FALSE and TRUE (with capital letters) are the constants defined by glib for
being used with the "gboolean" type of glib. But some parts of the code also use
TRUE and FALSE for variables that are declared as "bool" (the type from 
).

Signed-off-by: Jafar Abdi 
Reviewed-by: Thomas Huth 
Reviewed-by: Stefan Berger 
---
 hw/tpm/tpm_tis_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c
index 9ce64d4836..1af4bce139 100644
--- a/hw/tpm/tpm_tis_common.c
+++ b/hw/tpm/tpm_tis_common.c
@@ -536,7 +536,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
 while ((TPM_TIS_IS_VALID_LOCTY(s->active_locty) &&
 locty > s->active_locty) ||
 !TPM_TIS_IS_VALID_LOCTY(s->active_locty)) {
-bool higher_seize = FALSE;
+bool higher_seize = false;
 
 /* already a pending SEIZE ? */
 if ((s->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) {
@@ -546,7 +546,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
 /* check for ongoing seize by a higher locality */
 for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) {
 if ((s->loc[l].access & TPM_TIS_ACCESS_SEIZE)) {
-higher_seize = TRUE;
+higher_seize = true;
 break;
 }
 }
-- 
2.24.1




[PULL v2 0/1] Merge tpm 2020/05/08 v2

2020-05-08 Thread Stefan Berger
This PR submits a fix that changes improperly used 'FALSE' to 'false'.

The following changes since commit c88f1ffc19e38008a1c33ae039482a860aa7418c:

  Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging 
(2020-05-08 14:29:18 +0100)

are available in the Git repository at:

  git://github.com/stefanberger/qemu-tpm.git tags/pull-tpm-2020-05-08-1

for you to fetch changes up to 441adbb4540423c90e4628a3c553e61d38445d73:

  hw/tpm: fix usage of bool in tpm-tis.c (2020-05-08 16:40:45 -0400)


Jafar Abdi (1):
  hw/tpm: fix usage of bool in tpm-tis.c

 hw/tpm/tpm_tis_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

-- 
2.24.1




Re: [PATCH v3 06/17] block/io: support int64_t bytes in bdrv_aligned_pwritev()

2020-05-08 Thread Eric Blake

On 4/30/20 6:10 AM, Vladimir Sementsov-Ogievskiy wrote:

We are generally moving to int64_t for both offset and bytes parameters
on all io paths.

Main motivation is realization of 64-bit write_zeroes operation for
fast zeroing large disk chunks, up to the whole disk.

We chose signed type, to be consistent with off_t (which is signed) and
with possibility for signed return type (where negative value means
error).

So, prepare bdrv_aligned_pwritev() now and convert the dependencies:
bdrv_co_write_req_prepare() and bdrv_co_write_req_finish() to signed
type bytes.

Series: 64bit-block-status
Signed-off-by: Vladimir Sementsov-Ogievskiy 
---
  block/io.c | 17 ++---
  1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/block/io.c b/block/io.c
index b83749cc50..8bb4ea6285 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1686,12 +1686,11 @@ fail:
  }
  
  static inline int coroutine_fn

-bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
+bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, int64_t bytes,
BdrvTrackedRequest *req, int flags)


Changes from unsigned to signed.  Audit of callers:

bdrv_aligned_pwritev() - adjusted this patch, safe
bdrv_do_pdiscard() - passes int64_t, safe
bdrv_co_copy_range_internal() - passes int64_t, safe
bdrv_do_truncate() - passes int64_t, safe

Internal usage:


  {
  BlockDriverState *bs = child->bs;
  bool waited;
-int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);


Drops an old sector calculation, and replaces it with:

  
  if (bs->read_only) {

  return -EPERM;
@@ -1716,8 +1715,10 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t 
offset, uint64_t bytes,
  }
  
  assert(req->overlap_offset <= offset);

+assert(offset <= INT64_MAX - bytes);
  assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
-assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
+assert(offset + bytes <= bs->total_sectors * BDRV_SECTOR_SIZE ||
+   child->perm & BLK_PERM_RESIZE);


assertions that things fit within 63 bits.  Safe

[The req->overlap_offset+ req->overlap_bytes calculation used to be 
unsigned, but was changed to be signed earlier in this series]


  
  switch (req->type) {

  case BDRV_TRACKED_WRITE:
@@ -1738,7 +1739,7 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t 
offset, uint64_t bytes,
  }
  
  static inline void coroutine_fn

-bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes,
+bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, int64_t bytes,
   BdrvTrackedRequest *req, int ret)
  {


Similar to the above; same four callers, all pass int64_t.



  int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);


This computation needs analysis.  Previously, we had:

DIV_ROUND_UP(int64_t + uint64_t, unsigned long long)
which expands to:
(((uint64_t) + (ull) - int) / (ull))
which simplifies to uint64_t.

Now we have:
DIV_ROUND_UP(int64_t + int64_t, ull)
Okay, in spite of our argument changing type, the macro still results in 
a 64-bit unsigned answer.  Either way, that answer fits within 63 bits, 
so it is safe when assigned to int64_t.


Also in this function:
stat64_max(>wr_highest_offset, offset + bytes);
in include/qemu/stats64.h, takes uint64_t parameter, but we're passing a 
positive 63-bit number - safe

bdrv_set_dirty(bs, offset, bytes);
in block/dirty-bitmap.c, takes int64_t parameter - safe


@@ -1780,14 +1781,14 @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t 
offset, uint64_t bytes,
   * after possibly fragmenting it.
   */
  static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
-BdrvTrackedRequest *req, int64_t offset, unsigned int bytes,
+BdrvTrackedRequest *req, int64_t offset, int64_t bytes,
  int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags)
  {


changes signature from unsigned 32-bit to signed 64-bit.  callers:

bdrv_co_do_zero_pwritev() - passes int64_t, but that was clamped to 
either pad.buf_len [BdrvRequestPadding uses 'size_t buf_len', but 
initializes it in bdrv_init_padding() to at most 2*align] or align set 
from BlockLimits.request_alignment (naturally uint32_t, but documented 
as 'a power of 2 less than INT_MAX' which is at most 1G), so the old 
code never overflowed, and the new code introduces no change


Perhaps we should separately fix BdrvRequestPadding to use a saner type 
than size_t for continuity between 32- and 64-bit platforms (perhaps 
uint32_t rather than int64_t, since we know our padding is bounded by 
request_alignment), but it doesn't impact this patch


bdrv_do_pwritev_part() - still passes unsigned int at this point in the 
series, safe


Usage within the function:


  BlockDriverState *bs = child->bs;
  BlockDriver *drv = bs->drv;
  int ret;
  
-uint64_t bytes_remaining = bytes;

+

Re: [PULL v1 1/1] hw/tpm: fix usage of bool in tpm-tis.c

2020-05-08 Thread Stefan Berger

On 5/8/20 4:04 PM, Stefan Berger wrote:

Clean up wrong usage of FALSE and TRUE in places that use "bool" from stdbool.h.

FALSE and TRUE (with capital letters) are the constants defined by glib for
being used with the "gboolean" type of glib. But some parts of the code also use
TRUE and FALSE for variables that are declared as "bool" (the type from 
).


Scratch this one. Wrong author of patch. Need to fix attribution.




Signed-off-by: Jafar Abdi 
Reviewed-by: Thomas Huth 
Reviewed-by: Stefan Berger 
---
  hw/tpm/tpm_tis_common.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c
index 9ce64d4836..5cd4006d2f 100644
--- a/hw/tpm/tpm_tis_common.c
+++ b/hw/tpm/tpm_tis_common.c
@@ -536,7 +536,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
  while ((TPM_TIS_IS_VALID_LOCTY(s->active_locty) &&
  locty > s->active_locty) ||
  !TPM_TIS_IS_VALID_LOCTY(s->active_locty)) {
-bool higher_seize = FALSE;
+bool higher_seize = false;
  
  /* already a pending SEIZE ? */

  if ((s->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) {
@@ -546,7 +546,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
  /* check for ongoing seize by a higher locality */
  for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) {
  if ((s->loc[l].access & TPM_TIS_ACCESS_SEIZE)) {
-higher_seize = TRUE;
+higher_seize = false;
  break;
  }
  }






Re: [PATCH 4/4] exec: Rename qemu_ram_writeback() as qemu_ram_msync()

2020-05-08 Thread Richard Henderson
On 5/7/20 11:24 PM, Philippe Mathieu-Daudé wrote:
> Rename qemu_ram_writeback() as qemu_ram_msync() to better
> match what it does.
> 
> Suggested-by: Stefan Hajnoczi 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  include/exec/ram_addr.h | 4 ++--
>  exec.c  | 2 +-
>  memory.c| 2 +-
>  3 files changed, 4 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson 


r~



Re: [PATCH 3/4] hw/block: Let the NVMe emulated device be target-agnostic

2020-05-08 Thread Richard Henderson
On 5/7/20 11:24 PM, Philippe Mathieu-Daudé wrote:
> Now than the non-target specific memory_region_msync() function
> is available, use it to make this device target-agnostic.
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  hw/block/nvme.c| 6 ++
>  hw/block/Makefile.objs | 2 +-
>  2 files changed, 3 insertions(+), 5 deletions(-)

Reviewed-by: Richard Henderson 


r~



[Bug 1868116] Re: QEMU monitor no longer works

2020-05-08 Thread Bug Watch Updater
** Changed in: qemu (Debian)
   Status: New => Fix Released

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1868116

Title:
  QEMU monitor no longer works

Status in QEMU:
  New
Status in qemu package in Ubuntu:
  Triaged
Status in vte2.91 package in Ubuntu:
  Fix Released
Status in qemu package in Debian:
  Fix Released

Bug description:
  Repro:
  VTE
  $ meson _build && ninja -C _build && ninja -C _build install

  qemu:
  $ ../configure --python=/usr/bin/python3 --disable-werror --disable-user 
--disable-linux-user --disable-docs --disable-guest-agent --disable-sdl 
--enable-gtk --disable-vnc --disable-xen --disable-brlapi --disable-fdt 
--disable-hax --disable-vde --disable-netmap --disable-rbd --disable-libiscsi 
--disable-libnfs --disable-smartcard --disable-libusb --disable-usb-redir 
--disable-seccomp --disable-glusterfs --disable-tpm --disable-numa 
--disable-opengl --disable-virglrenderer --disable-xfsctl --disable-vxhs 
--disable-slirp --disable-blobs --target-list=x86_64-softmmu --disable-rdma 
--disable-pvrdma --disable-attr --disable-vhost-net --disable-vhost-vsock 
--disable-vhost-scsi --disable-vhost-crypto --disable-vhost-user 
--disable-spice --disable-qom-cast-debug --disable-vxhs --disable-bochs 
--disable-cloop --disable-dmg --disable-qcow1 --disable-vdi --disable-vvfat 
--disable-qed --disable-parallels --disable-sheepdog --disable-avx2 
--disable-nettle --disable-gnutls --disable-capstone --disable-tools 
--disable-libpmem --disable-iconv --disable-cap-ng
  $ make

  Test:
  $ LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu/:$LD_LIBRARY_PATH 
./build/x86_64-softmmu/qemu-system-x86_64 -enable-kvm --drive 
media=cdrom,file=http://archive.ubuntu.com/ubuntu/dists/bionic/main/installer-amd64/current/images/netboot/mini.iso
  - switch to monitor with CTRL+ALT+2
  - try to enter something

  Affects head of both usptream git repos.

  
  --- original bug ---

  It was observed that the QEMU console (normally accessible using
  Ctrl+Alt+2) accepts no input, so it can't be used. This is being
  problematic because there are cases where it's required to send
  commands to the guest, or key combinations that the host would grab
  (as Ctrl-Alt-F1 or Alt-F4).

  ProblemType: Bug
  DistroRelease: Ubuntu 20.04
  Package: qemu 1:4.2-3ubuntu2
  Uname: Linux 5.6.0-rc6+ x86_64
  ApportVersion: 2.20.11-0ubuntu20
  Architecture: amd64
  CurrentDesktop: XFCE
  Date: Thu Mar 19 12:16:31 2020
  Dependencies:

  InstallationDate: Installed on 2017-06-13 (1009 days ago)
  InstallationMedia: Xubuntu 17.04 "Zesty Zapus" - Release amd64 (20170412)
  KvmCmdLine:
   COMMAND STAT  EUID  RUID PIDPPID %CPU COMMAND
   qemu-system-x86 Sl+   1000  1000   34275   25235 29.2 qemu-system-x86_64 -m 
4G -cpu Skylake-Client -device virtio-vga,virgl=true,xres=1280,yres=720 -accel 
kvm -device nec-usb-xhci -serial vc -serial stdio -hda 
/home/usuario/Sistemas/androidx86.img -display gtk,gl=on -device usb-audio
   kvm-nx-lpage-re S0 0   34284   2  0.0 [kvm-nx-lpage-re]
   kvm-pit/34275   S0 0   34286   2  0.0 [kvm-pit/34275]
  MachineType: LENOVO 80UG
  ProcKernelCmdLine: BOOT_IMAGE=/boot/vmlinuz-5.6.0-rc6+ 
root=UUID=6b4ae5c0-c78c-49a6-a1ba-029192618a7a ro quiet ro kvm.ignore_msrs=1 
kvm.report_ignored_msrs=0 kvm.halt_poll_ns=0 kvm.halt_poll_ns_grow=0 
i915.enable_gvt=1 i915.fastboot=1 cgroup_enable=memory swapaccount=1 
zswap.enabled=1 zswap.zpool=z3fold 
resume=UUID=a82e38a0-8d20-49dd-9cbd-de7216b589fc log_buf_len=16M 
usbhid.quirks=0x0079:0x0006:0x10 config_scsi_mq_default=y 
scsi_mod.use_blk_mq=1 mtrr_gran_size=64M mtrr_chunk_size=64M nbd.nbds_max=2 
nbd.max_part=63
  SourcePackage: qemu
  UpgradeStatus: Upgraded to focal on 2019-12-22 (87 days ago)
  dmi.bios.date: 08/09/2018
  dmi.bios.vendor: LENOVO
  dmi.bios.version: 0XCN45WW
  dmi.board.asset.tag: NO Asset Tag
  dmi.board.name: Toronto 4A2
  dmi.board.vendor: LENOVO
  dmi.board.version: SDK0J40679 WIN
  dmi.chassis.asset.tag: NO Asset Tag
  dmi.chassis.type: 10
  dmi.chassis.vendor: LENOVO
  dmi.chassis.version: Lenovo ideapad 310-14ISK
  dmi.modalias: 
dmi:bvnLENOVO:bvr0XCN45WW:bd08/09/2018:svnLENOVO:pn80UG:pvrLenovoideapad310-14ISK:rvnLENOVO:rnToronto4A2:rvrSDK0J40679WIN:cvnLENOVO:ct10:cvrLenovoideapad310-14ISK:
  dmi.product.family: IDEAPAD
  dmi.product.name: 80UG
  dmi.product.sku: LENOVO_MT_80UG_BU_idea_FM_Lenovo ideapad 310-14ISK
  dmi.product.version: Lenovo ideapad 310-14ISK
  dmi.sys.vendor: LENOVO
  mtime.conffile..etc.apport.crashdb.conf: 2019-08-29T08:39:36.787240

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1868116/+subscriptions



Re: [PATCH 1/4] memory: Rename memory_region_do_writeback -> memory_region_writeback

2020-05-08 Thread Richard Henderson
On 5/7/20 11:24 PM, Philippe Mathieu-Daudé wrote:
> We usually use '_do_' for internal functions. Rename
> memory_region_do_writeback() as memory_region_writeback().
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  include/exec/memory.h | 4 ++--
>  memory.c  | 2 +-
>  target/arm/helper.c   | 2 +-
>  3 files changed, 4 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson 


r~



[PULL v1 1/1] hw/tpm: fix usage of bool in tpm-tis.c

2020-05-08 Thread Stefan Berger
Clean up wrong usage of FALSE and TRUE in places that use "bool" from stdbool.h.

FALSE and TRUE (with capital letters) are the constants defined by glib for
being used with the "gboolean" type of glib. But some parts of the code also use
TRUE and FALSE for variables that are declared as "bool" (the type from 
).

Signed-off-by: Jafar Abdi 
Reviewed-by: Thomas Huth 
Reviewed-by: Stefan Berger 
---
 hw/tpm/tpm_tis_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c
index 9ce64d4836..5cd4006d2f 100644
--- a/hw/tpm/tpm_tis_common.c
+++ b/hw/tpm/tpm_tis_common.c
@@ -536,7 +536,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
 while ((TPM_TIS_IS_VALID_LOCTY(s->active_locty) &&
 locty > s->active_locty) ||
 !TPM_TIS_IS_VALID_LOCTY(s->active_locty)) {
-bool higher_seize = FALSE;
+bool higher_seize = false;
 
 /* already a pending SEIZE ? */
 if ((s->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) {
@@ -546,7 +546,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
 /* check for ongoing seize by a higher locality */
 for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) {
 if ((s->loc[l].access & TPM_TIS_ACCESS_SEIZE)) {
-higher_seize = TRUE;
+higher_seize = false;
 break;
 }
 }
-- 
2.24.1




[PULL v1 0/1] Merge tpm 2020/05/08 v1

2020-05-08 Thread Stefan Berger
This PR submits a fix that changes improperly used 'FALSE' to 'false'.

The following changes since commit c88f1ffc19e38008a1c33ae039482a860aa7418c:

  Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging 
(2020-05-08 14:29:18 +0100)

are available in the Git repository at:

  git://github.com/stefanberger/qemu-tpm.git tags/pull-tpm-2020-05-08-1

for you to fetch changes up to e91b6ad279f38f231ee9298b6ec2ba0a26a81994:

  hw/tpm: fix usage of bool in tpm-tis.c (2020-05-08 15:54:37 -0400)


Stefan Berger (1):
  hw/tpm: fix usage of bool in tpm-tis.c

 hw/tpm/tpm_tis_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

-- 
2.24.1




Re: [Qemu-devel] [PATCH V2 4/4] hw/tpm: fix usage of bool in tpm-tis.c

2020-05-08 Thread Stefan Berger

On 5/7/20 7:52 AM, Daniel P. Berrangé wrote:

ping, again, for either qemu-trivial or TPM maintainers to take this
patch.

The other three in this series are merged, but this TPM patch is
still pending.



I'll send a PR with it tonight.





RE: [PATCH v3 06/11] net: cadence_gem: Move tx/rx packet buffert to CadenceGEMState

2020-05-08 Thread Sai Pavan Boddu
Hi Edgar,

> -Original Message-
> From: Edgar E. Iglesias 
> Sent: Friday, May 8, 2020 5:00 PM
> To: Sai Pavan Boddu 
> Cc: Alistair Francis ; Peter Maydell
> ; Jason Wang ; Markus
> Armbruster ; Philippe Mathieu-Daudé
> ; Tong Ho ; Ramon Fried
> ; qemu-...@nongnu.org; qemu-
> de...@nongnu.org
> Subject: Re: [PATCH v3 06/11] net: cadence_gem: Move tx/rx packet buffert
> to CadenceGEMState
> 
> On Fri, May 08, 2020 at 04:30:40PM +0530, Sai Pavan Boddu wrote:
> > Moving this buffers to CadenceGEMState, as their size will be
> > increased more when JUMBO frames support is added.
> >
> > Signed-off-by: Sai Pavan Boddu 
> > ---
> >  hw/net/cadence_gem.c | 52 ++-
> -
> >  include/hw/net/cadence_gem.h |  2 ++
> >  2 files changed, 33 insertions(+), 21 deletions(-)
> >
> > diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index
> > 77a0588..5ccec1a 100644
> > --- a/hw/net/cadence_gem.c
> > +++ b/hw/net/cadence_gem.c
> > @@ -314,6 +314,8 @@
> >
> >  #define GEM_MODID_VALUE 0x00020118
> >
> > +#define MAX_FRAME_SIZE 2048
> > +
> >  static inline uint64_t tx_desc_get_buffer(CadenceGEMState *s,
> > uint32_t *desc)  {
> >  uint64_t ret = desc[0];
> > @@ -928,17 +930,14 @@ static void gem_get_rx_desc(CadenceGEMState
> *s, int q)
> >   */
> >  static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf,
> > size_t size)  {
> > -CadenceGEMState *s;
> > +CadenceGEMState *s = qemu_get_nic_opaque(nc);
> >  unsigned   rxbufsize, bytes_to_copy;
> >  unsigned   rxbuf_offset;
> > -uint8_trxbuf[2048];
> >  uint8_t   *rxbuf_ptr;
> >  bool first_desc = true;
> >  int maf;
> >  int q = 0;
> >
> > -s = qemu_get_nic_opaque(nc);
> > -
> >  /* Is this destination MAC address "for us" ? */
> >  maf = gem_mac_address_filter(s, buf);
> >  if (maf == GEM_RX_REJECT) {
> > @@ -994,19 +993,19 @@ static ssize_t gem_receive(NetClientState *nc,
> const uint8_t *buf, size_t size)
> >  } else {
> >  unsigned crc_val;
> >
> > -if (size > sizeof(rxbuf) - sizeof(crc_val)) {
> > -size = sizeof(rxbuf) - sizeof(crc_val);
> > +if (size > MAX_FRAME_SIZE - sizeof(crc_val)) {
> > +size = MAX_FRAME_SIZE - sizeof(crc_val);
> >  }
> >  bytes_to_copy = size;
> >  /* The application wants the FCS field, which QEMU does not 
> > provide.
> >   * We must try and calculate one.
> >   */
> >
> > -memcpy(rxbuf, buf, size);
> > -memset(rxbuf + size, 0, sizeof(rxbuf) - size);
> > -rxbuf_ptr = rxbuf;
> > -crc_val = cpu_to_le32(crc32(0, rxbuf, MAX(size, 60)));
> > -memcpy(rxbuf + size, _val, sizeof(crc_val));
> > +memcpy(s->rx_packet, buf, size);
> > +memset(s->rx_packet + size, 0, MAX_FRAME_SIZE - size);
> > +rxbuf_ptr = s->rx_packet;
> > +crc_val = cpu_to_le32(crc32(0, s->rx_packet, MAX(size, 60)));
> > +memcpy(s->rx_packet + size, _val, sizeof(crc_val));
> >
> >  bytes_to_copy += 4;
> >  size += 4;
> > @@ -1152,7 +1151,6 @@ static void gem_transmit(CadenceGEMState *s)  {
> >  uint32_t desc[DESC_MAX_NUM_WORDS];
> >  hwaddr packet_desc_addr;
> > -uint8_t tx_packet[2048];
> >  uint8_t *p;
> >  unsignedtotal_bytes;
> >  int q = 0;
> > @@ -1168,7 +1166,7 @@ static void gem_transmit(CadenceGEMState *s)
> >   * Packets scattered across multiple descriptors are gathered to this
> >   * one contiguous buffer first.
> >   */
> > -p = tx_packet;
> > +p = s->tx_packet;
> >  total_bytes = 0;
> >
> >  for (q = s->num_priority_queues - 1; q >= 0; q--) { @@ -1198,12
> > +1196,12 @@ static void gem_transmit(CadenceGEMState *s)
> >  break;
> >  }
> >
> > -if (tx_desc_get_length(desc) > sizeof(tx_packet) -
> > -   (p - tx_packet)) {
> > +if (tx_desc_get_length(desc) > MAX_FRAME_SIZE -
> > +   (p - s->tx_packet)) {
> >  DB_PRINT("TX descriptor @ 0x%" HWADDR_PRIx \
> >   " too large: size 0x%x space 0x%zx\n",
> >   packet_desc_addr, tx_desc_get_length(desc),
> > - sizeof(tx_packet) - (p - tx_packet));
> > + MAX_FRAME_SIZE - (p - s->tx_packet));
> >  break;
> >  }
> >
> > @@ -1248,24 +1246,24 @@ static void gem_transmit(CadenceGEMState
> *s)
> >
> >  /* Is checksum offload enabled? */
> >  if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) {
> > -net_checksum_calculate(tx_packet, total_bytes);
> > +net_checksum_calculate(s->tx_packet,
> > + total_bytes);
> >  }
> >
> >  /* Update MAC statistics */
> > -

RE: [PATCH v3 07/11] net: cadence_gem: Add support for jumbo frames

2020-05-08 Thread Sai Pavan Boddu
Hi Edgar,

> -Original Message-
> From: Edgar E. Iglesias 
> Sent: Friday, May 8, 2020 5:14 PM
> To: Sai Pavan Boddu 
> Cc: Alistair Francis ; Peter Maydell
> ; Jason Wang ; Markus
> Armbruster ; Philippe Mathieu-Daudé
> ; Tong Ho ; Ramon Fried
> ; qemu-...@nongnu.org; qemu-
> de...@nongnu.org
> Subject: Re: [PATCH v3 07/11] net: cadence_gem: Add support for jumbo
> frames
> 
> On Fri, May 08, 2020 at 04:30:41PM +0530, Sai Pavan Boddu wrote:
> > Add a property "jumbo-max-len", which can be configured for jumbo
> > frame size up to 16,383 bytes, and also introduce new register
> GEM_JUMBO_MAX_LEN.
> >
> > Signed-off-by: Sai Pavan Boddu 
> > ---
> >  hw/net/cadence_gem.c | 21 +++--
> >  include/hw/net/cadence_gem.h |  1 +
> >  2 files changed, 20 insertions(+), 2 deletions(-)
> >
> > diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index
> > 5ccec1a..45c50ab 100644
> > --- a/hw/net/cadence_gem.c
> > +++ b/hw/net/cadence_gem.c
> > @@ -61,6 +61,7 @@
> >  #define GEM_TXPAUSE   (0x003C/4) /* TX Pause Time reg */
> >  #define GEM_TXPARTIALSF   (0x0040/4) /* TX Partial Store and
> Forward */
> >  #define GEM_RXPARTIALSF   (0x0044/4) /* RX Partial Store and
> Forward */
> > +#define GEM_JUMBO_MAX_LEN (0x0048 / 4) /* Max Jumbo Frame
> Size */
> 
> Would be nice to align this in the same way as all the others...
> 
> 
> 
> >  #define GEM_HASHLO(0x0080/4) /* Hash Low address reg */
> >  #define GEM_HASHHI(0x0084/4) /* Hash High address reg */
> >  #define GEM_SPADDR1LO (0x0088/4) /* Specific addr 1 low reg */
> > @@ -314,7 +315,8 @@
> >
> >  #define GEM_MODID_VALUE 0x00020118
> >
> > -#define MAX_FRAME_SIZE 2048
> > +#define MAX_JUMBO_FRAME_SIZE_MASK 0x3FFF #define
> MAX_FRAME_SIZE
> > +MAX_JUMBO_FRAME_SIZE_MASK
> >
> >  static inline uint64_t tx_desc_get_buffer(CadenceGEMState *s,
> > uint32_t *desc)  { @@ -1343,9 +1345,10 @@ static void
> > gem_reset(DeviceState *d)
> >  s->regs[GEM_RXPARTIALSF] = 0x03ff;
> >  s->regs[GEM_MODID] = s->revision;
> >  s->regs[GEM_DESCONF] = 0x02500111;
> > -s->regs[GEM_DESCONF2] = 0x2ab13fff;
> > +s->regs[GEM_DESCONF2] = 0x2ab1 | s->jumbo_max_len;
> >  s->regs[GEM_DESCONF5] = 0x002f2045;
> >  s->regs[GEM_DESCONF6] = GEM_DESCONF6_64B_MASK;
> > +s->regs[GEM_JUMBO_MAX_LEN] = s->jumbo_max_len;
> >
> >  if (s->num_priority_queues > 1) {
> >  queues_mask = MAKE_64BIT_MASK(1, s->num_priority_queues - 1);
> > @@ -1420,6 +1423,9 @@ static uint64_t gem_read(void *opaque, hwaddr
> offset, unsigned size)
> >  DB_PRINT("lowering irqs on ISR read\n");
> >  /* The interrupts get updated at the end of the function. */
> >  break;
> > +case GEM_JUMBO_MAX_LEN:
> > +retval = s->jumbo_max_len;
> > +break;
> >  case GEM_PHYMNTNC:
> >  if (retval & GEM_PHYMNTNC_OP_R) {
> >  uint32_t phy_addr, reg_num; @@ -1516,6 +1522,9 @@ static
> > void gem_write(void *opaque, hwaddr offset, uint64_t val,
> >  s->regs[GEM_IMR] &= ~val;
> >  gem_update_int_status(s);
> >  break;
> > +case GEM_JUMBO_MAX_LEN:
> > +s->jumbo_max_len = val & MAX_JUMBO_FRAME_SIZE_MASK;
> 
> I don't think writing to this register may increase the max len beyond the
> max-len selected at design time (the property).
> TBH I'm surprised this register is RW in the spec.
> 
> We may need two variables here, one for the design-time configured max
> and another for the runtime configurable max.
[Sai Pavan Boddu] Better way is to, use new created property  to set the reset 
value of  this register. Which can be overwritten by guest on runtime by 
writing to regs[GEM_JUMBO_MAX_LEN].

I would add few checks, so that frames does not cross JUMBO max length 
configured.

Thanks,
Sai Pavan
> 
> 
> > +break;
> >  case GEM_INT_Q1_ENABLE ... GEM_INT_Q7_ENABLE:
> >  s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_ENABLE] &=
> ~val;
> >  gem_update_int_status(s);
> > @@ -1611,6 +1620,12 @@ static void gem_realize(DeviceState *dev, Error
> **errp)
> >  s->nic = qemu_new_nic(_gem_info, >conf,
> >object_get_typename(OBJECT(dev)), dev->id,
> > s);
> >
> > +if (s->jumbo_max_len > MAX_FRAME_SIZE) {
> > +g_warning("jumbo-max-len is grater than %d",
> 
> 
> You've got a typo here "grater".
> 
> I also think we could error out here if wrong values are chosen.
> 
> Best regards,
> Edgar



Re: [PATCH v4 07/19] tcg: Use tcg_constant_{i32,i64,vec} with tcg gvec expanders

2020-05-08 Thread Richard Henderson
On 5/8/20 11:26 AM, Richard Henderson wrote:
> @@ -1647,16 +1632,14 @@ static void gen_addv_mask(TCGv_i64 d, TCGv_i64 a, 
> TCGv_i64 b, TCGv_i64 m)
>  
>  void tcg_gen_vec_add8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
>  {
> -TCGv_i64 m = tcg_const_i64(dup_const(MO_8, 0x80));
> +TCGv_i64 m = tcg_constant_i64(dup_const(MO_8, 0x80));
>  gen_addv_mask(d, a, b, m);
> -tcg_temp_free_i64(m);
>  }
>  

These unconditional uses of tcg_constant_i64 break 32-bit builds.
I'll have to find another way to handle these.

For now I am dropping this patch.


r~



Re: [PATCH v2 3/3] arm/acpi: Add the TPM2.0 device under the DSDT

2020-05-08 Thread Stefan Berger

On 5/8/20 11:25 AM, Ard Biesheuvel wrote:

On Fri, 8 May 2020 at 17:24, Shannon Zhao  wrote:

Hi,

On 2020/5/5 22:44, Eric Auger wrote:

+static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
+{
+hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
+PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
+MemoryRegion *sbdev_mr;
+SysBusDevice *sbdev;
+hwaddr tpm_base;
+
+sbdev = (SysBusDevice *)object_dynamic_cast(OBJECT(tpm_find()),
+TYPE_SYS_BUS_DEVICE);

Does it need to check the tpm version like you do in previous patch?

tpm_get_version(tpm_find()) == TPM_VERSION_2_0


I don't think so. The device node could in theory be used to describe
a TPM 1.2/1.3 as well, even though we never actually do that.


There is no TPM 1.3. There may be a TIS v1.3.




Re: [PATCH v4 01/19] tcg: Consolidate 3 bits into enum TCGTempKind

2020-05-08 Thread Philippe Mathieu-Daudé

On 5/8/20 8:25 PM, Richard Henderson wrote:

The temp_fixed, temp_global, temp_local bits are all related.
Combine them into a single enumeration.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
  include/tcg/tcg.h |  20 +---
  tcg/optimize.c|   8 +--
  tcg/tcg.c | 122 --
  3 files changed, 90 insertions(+), 60 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 



Re: [PATCH v3 01/19] tcg: Consolidate 3 bits into enum TCGTempKind

2020-05-08 Thread Philippe Mathieu-Daudé

On 5/8/20 5:17 PM, Richard Henderson wrote:

The temp_fixed, temp_global, temp_local bits are all related.
Combine them into a single enumeration.

Signed-off-by: Richard Henderson 
---
  include/tcg/tcg.h |  20 +---
  tcg/optimize.c|   8 +--
  tcg/tcg.c | 122 --
  3 files changed, 90 insertions(+), 60 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 380014ed80..06486635e6 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -483,23 +483,27 @@ typedef enum TCGTempVal {
  TEMP_VAL_CONST,
  } TCGTempVal;
  
+typedef enum TCGTempKind {

+/* Temp is dead at the end of all basic blocks. */
+TEMP_NORMAL,
+/* Temp is saved across basic blocks but dead at the end of TBs. */
+TEMP_LOCAL,
+/* Temp is saved across both basic blocks and translation blocks. */
+TEMP_GLOBAL,
+/* Temp is in a fixed register. */
+TEMP_FIXED,
+} TCGTempKind;
+
  typedef struct TCGTemp {
  TCGReg reg:8;
  TCGTempVal val_type:8;
  TCGType base_type:8;
  TCGType type:8;
-unsigned int fixed_reg:1;
+TCGTempKind kind:3;
  unsigned int indirect_reg:1;
  unsigned int indirect_base:1;
  unsigned int mem_coherent:1;
  unsigned int mem_allocated:1;
-/* If true, the temp is saved across both basic blocks and
-   translation blocks.  */
-unsigned int temp_global:1;
-/* If true, the temp is saved across basic blocks but dead
-   at the end of translation blocks.  If false, the temp is
-   dead at the end of basic blocks.  */
-unsigned int temp_local:1;
  unsigned int temp_allocated:1;
  
  tcg_target_long val;

diff --git a/tcg/optimize.c b/tcg/optimize.c
index 53aa8e5329..afb4a9a5a9 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -116,21 +116,21 @@ static TCGTemp *find_better_copy(TCGContext *s, TCGTemp 
*ts)
  TCGTemp *i;
  
  /* If this is already a global, we can't do better. */

-if (ts->temp_global) {
+if (ts->kind >= TEMP_GLOBAL) {
  return ts;
  }
  
  /* Search for a global first. */

  for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (i->temp_global) {
+if (i->kind >= TEMP_GLOBAL) {
  return i;
  }
  }
  
  /* If it is a temp, search for a temp local. */

-if (!ts->temp_local) {
+if (ts->kind == TEMP_NORMAL) {
  for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (ts->temp_local) {
+if (i->kind >= TEMP_LOCAL) {
  return i;
  }
  }
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 216a6963b3..2c022c9621 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1155,7 +1155,7 @@ static inline TCGTemp *tcg_global_alloc(TCGContext *s)
  tcg_debug_assert(s->nb_globals == s->nb_temps);
  s->nb_globals++;
  ts = tcg_temp_alloc(s);
-ts->temp_global = 1;
+ts->kind = TEMP_GLOBAL;
  
  return ts;

  }
@@ -1172,7 +1172,7 @@ static TCGTemp *tcg_global_reg_new_internal(TCGContext 
*s, TCGType type,
  ts = tcg_global_alloc(s);
  ts->base_type = type;
  ts->type = type;
-ts->fixed_reg = 1;
+ts->kind = TEMP_FIXED;
  ts->reg = reg;
  ts->name = name;
  tcg_regset_set_reg(s->reserved_regs, reg);
@@ -1199,7 +1199,7 @@ TCGTemp *tcg_global_mem_new_internal(TCGType type, 
TCGv_ptr base,
  bigendian = 1;
  #endif
  
-if (!base_ts->fixed_reg) {

+if (base_ts->kind != TEMP_FIXED) {
  /* We do not support double-indirect registers.  */
  tcg_debug_assert(!base_ts->indirect_reg);
  base_ts->indirect_base = 1;
@@ -1247,6 +1247,7 @@ TCGTemp *tcg_global_mem_new_internal(TCGType type, 
TCGv_ptr base,
  TCGTemp *tcg_temp_new_internal(TCGType type, bool temp_local)
  {
  TCGContext *s = tcg_ctx;
+TCGTempKind kind = temp_local ? TEMP_LOCAL : TEMP_NORMAL;
  TCGTemp *ts;
  int idx, k;
  
@@ -1259,7 +1260,7 @@ TCGTemp *tcg_temp_new_internal(TCGType type, bool temp_local)

  ts = >temps[idx];
  ts->temp_allocated = 1;
  tcg_debug_assert(ts->base_type == type);
-tcg_debug_assert(ts->temp_local == temp_local);
+tcg_debug_assert(ts->kind == kind);
  } else {
  ts = tcg_temp_alloc(s);
  if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
@@ -1268,18 +1269,18 @@ TCGTemp *tcg_temp_new_internal(TCGType type, bool 
temp_local)
  ts->base_type = type;
  ts->type = TCG_TYPE_I32;
  ts->temp_allocated = 1;
-ts->temp_local = temp_local;
+ts->kind = kind;
  
  tcg_debug_assert(ts2 == ts + 1);

  ts2->base_type = TCG_TYPE_I64;
  ts2->type = TCG_TYPE_I32;
  ts2->temp_allocated = 1;
-ts2->temp_local = temp_local;
+ts2->kind = kind;
  } else {
  ts->base_type = type;
  ts->type = type;
 

Re: [PATCH 2/2] hw/display/edid: Add missing 'qdev-properties.h' header

2020-05-08 Thread Philippe Mathieu-Daudé
On Mon, May 4, 2020 at 8:38 PM Richard Henderson
 wrote:
>
> On 5/4/20 1:20 AM, Philippe Mathieu-Daudé wrote:
> > To use the DEFINE_EDID_PROPERTIES() macro we need the
> > definitions from "hw/qdev-properties.h".
> >
> > Signed-off-by: Philippe Mathieu-Daudé 
> > ---
> >  include/hw/display/edid.h | 1 +
> >  1 file changed, 1 insertion(+)
>
> Does this not currently build?  I'm not sure what you're fixing.

Because when trying to use this header once included, I get when building:

include/hw/display/edid.h:24:5: error: implicit declaration of
function ‘DEFINE_PROP_UINT32’ [-Werror=implicit-function-declaration]
   24 | DEFINE_PROP_UINT32("xres", _state, _edid_info.prefx, 0),\
  | ^~

Then I've to grep for this macro and figure out I need to include
"hw/qdev-properties.h".
I am expecting a header providing a macro to also include the
pre-requisites, so I fixed in case someone else run into the same
problem.
Does it make sense? I can reword the patch description to better explain.

>
> r~
>



Re: [PATCH v3 3/3] target/arm: Use clear_vec_high more effectively

2020-05-08 Thread Philippe Mathieu-Daudé
On Tue, May 5, 2020 at 4:22 PM Richard Henderson
 wrote:
>
> On 5/4/20 11:09 PM, Philippe Mathieu-Daudé wrote:
> >> @@ -7111,7 +7121,7 @@ static void disas_simd_zip_trn
> >>   }
> >> tcg_resl = tcg_const_i64(0);
> >> -tcg_resh = tcg_const_i64(0);
> >> +tcg_resh = is_q ? tcg_const_i64(0) : NULL;
> >>   tcg_res = tcg_temp_new_i64();
> >> for (i = 0; i < elements; i++) {
> >> @@ -7162,9 +7172,12 @@ static void disas_simd_zip_trn(DisasContext *s,
> >> uint32_t insn)
> >
> > More context:
> >
> >...
> >ofs = i * esize;
> >if (ofs < 64) {
> >tcg_gen_shli_i64(tcg_res, tcg_res, ofs);
> >tcg_gen_or_i64(tcg_resl, tcg_resl, tcg_res);
> >} else {
> >tcg_gen_shli_i64(tcg_res, tcg_res, ofs - 64);
> >tcg_gen_or_i64(tcg_resh, tcg_resh, tcg_res);
> >
> >  here  tcg_resh is NULL too.
> >
> >}
> >}
>
> When is_q is false, the vector length is 64.  Thus that line is not reachable.

OK.

>
>
> r~



[PATCH v4 18/19] tcg/i386: Use tcg_constant_vec with tcg vec expanders

2020-05-08 Thread Richard Henderson
Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 tcg/i386/tcg-target.inc.c | 26 +-
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.inc.c
index 5e73e5d02b..cce28c81d7 100644
--- a/tcg/i386/tcg-target.inc.c
+++ b/tcg/i386/tcg-target.inc.c
@@ -3519,7 +3519,7 @@ static void expand_vec_rotv(TCGType type, unsigned vece, 
TCGv_vec v0,
 static void expand_vec_mul(TCGType type, unsigned vece,
TCGv_vec v0, TCGv_vec v1, TCGv_vec v2)
 {
-TCGv_vec t1, t2, t3, t4;
+TCGv_vec t1, t2, t3, t4, zero;
 
 tcg_debug_assert(vece == MO_8);
 
@@ -3537,11 +3537,11 @@ static void expand_vec_mul(TCGType type, unsigned vece,
 case TCG_TYPE_V64:
 t1 = tcg_temp_new_vec(TCG_TYPE_V128);
 t2 = tcg_temp_new_vec(TCG_TYPE_V128);
-tcg_gen_dup16i_vec(t2, 0);
+zero = tcg_constant_vec(TCG_TYPE_V128, MO_8, 0);
 vec_gen_3(INDEX_op_x86_punpckl_vec, TCG_TYPE_V128, MO_8,
-  tcgv_vec_arg(t1), tcgv_vec_arg(v1), tcgv_vec_arg(t2));
+  tcgv_vec_arg(t1), tcgv_vec_arg(v1), tcgv_vec_arg(zero));
 vec_gen_3(INDEX_op_x86_punpckl_vec, TCG_TYPE_V128, MO_8,
-  tcgv_vec_arg(t2), tcgv_vec_arg(t2), tcgv_vec_arg(v2));
+  tcgv_vec_arg(t2), tcgv_vec_arg(zero), tcgv_vec_arg(v2));
 tcg_gen_mul_vec(MO_16, t1, t1, t2);
 tcg_gen_shri_vec(MO_16, t1, t1, 8);
 vec_gen_3(INDEX_op_x86_packus_vec, TCG_TYPE_V128, MO_8,
@@ -3556,15 +3556,15 @@ static void expand_vec_mul(TCGType type, unsigned vece,
 t2 = tcg_temp_new_vec(type);
 t3 = tcg_temp_new_vec(type);
 t4 = tcg_temp_new_vec(type);
-tcg_gen_dup16i_vec(t4, 0);
+zero = tcg_constant_vec(TCG_TYPE_V128, MO_8, 0);
 vec_gen_3(INDEX_op_x86_punpckl_vec, type, MO_8,
-  tcgv_vec_arg(t1), tcgv_vec_arg(v1), tcgv_vec_arg(t4));
+  tcgv_vec_arg(t1), tcgv_vec_arg(v1), tcgv_vec_arg(zero));
 vec_gen_3(INDEX_op_x86_punpckl_vec, type, MO_8,
-  tcgv_vec_arg(t2), tcgv_vec_arg(t4), tcgv_vec_arg(v2));
+  tcgv_vec_arg(t2), tcgv_vec_arg(zero), tcgv_vec_arg(v2));
 vec_gen_3(INDEX_op_x86_punpckh_vec, type, MO_8,
-  tcgv_vec_arg(t3), tcgv_vec_arg(v1), tcgv_vec_arg(t4));
+  tcgv_vec_arg(t3), tcgv_vec_arg(v1), tcgv_vec_arg(zero));
 vec_gen_3(INDEX_op_x86_punpckh_vec, type, MO_8,
-  tcgv_vec_arg(t4), tcgv_vec_arg(t4), tcgv_vec_arg(v2));
+  tcgv_vec_arg(t4), tcgv_vec_arg(zero), tcgv_vec_arg(v2));
 tcg_gen_mul_vec(MO_16, t1, t1, t2);
 tcg_gen_mul_vec(MO_16, t3, t3, t4);
 tcg_gen_shri_vec(MO_16, t1, t1, 8);
@@ -3592,7 +3592,7 @@ static bool expand_vec_cmp_noinv(TCGType type, unsigned 
vece, TCGv_vec v0,
 NEED_UMIN = 8,
 NEED_UMAX = 16,
 };
-TCGv_vec t1, t2;
+TCGv_vec t1, t2, t3;
 uint8_t fixup;
 
 switch (cond) {
@@ -3663,9 +3663,9 @@ static bool expand_vec_cmp_noinv(TCGType type, unsigned 
vece, TCGv_vec v0,
 } else if (fixup & NEED_BIAS) {
 t1 = tcg_temp_new_vec(type);
 t2 = tcg_temp_new_vec(type);
-tcg_gen_dupi_vec(vece, t2, 1ull << ((8 << vece) - 1));
-tcg_gen_sub_vec(vece, t1, v1, t2);
-tcg_gen_sub_vec(vece, t2, v2, t2);
+t3 = tcg_constant_vec(type, vece, 1ull << ((8 << vece) - 1));
+tcg_gen_sub_vec(vece, t1, v1, t3);
+tcg_gen_sub_vec(vece, t2, v2, t3);
 v1 = t1;
 v2 = t2;
 cond = tcg_signed_cond(cond);
-- 
2.20.1




[PATCH v4 19/19] tcg: Remove tcg_gen_dup{8,16,32,64}i_vec

2020-05-08 Thread Richard Henderson
These interfaces have been replaced by tcg_gen_dupi_vec
and tcg_constant_vec.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-op.h |  4 
 tcg/tcg-op-vec.c | 20 
 2 files changed, 24 deletions(-)

diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h
index b4fba35e87..d0319692ec 100644
--- a/include/tcg/tcg-op.h
+++ b/include/tcg/tcg-op.h
@@ -959,10 +959,6 @@ void tcg_gen_mov_vec(TCGv_vec, TCGv_vec);
 void tcg_gen_dup_i32_vec(unsigned vece, TCGv_vec, TCGv_i32);
 void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec, TCGv_i64);
 void tcg_gen_dup_mem_vec(unsigned vece, TCGv_vec, TCGv_ptr, tcg_target_long);
-void tcg_gen_dup8i_vec(TCGv_vec, uint32_t);
-void tcg_gen_dup16i_vec(TCGv_vec, uint32_t);
-void tcg_gen_dup32i_vec(TCGv_vec, uint32_t);
-void tcg_gen_dup64i_vec(TCGv_vec, uint64_t);
 void tcg_gen_dupi_vec(unsigned vece, TCGv_vec, uint64_t);
 void tcg_gen_add_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
 void tcg_gen_sub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c
index 4681d26973..9c5deafd5f 100644
--- a/tcg/tcg-op-vec.c
+++ b/tcg/tcg-op-vec.c
@@ -284,26 +284,6 @@ void tcg_gen_dupi_vec(unsigned vece, TCGv_vec dest, 
uint64_t val)
 tcg_gen_mov_vec(dest, tcg_constant_vec(type, vece, val));
 }
 
-void tcg_gen_dup64i_vec(TCGv_vec dest, uint64_t val)
-{
-tcg_gen_dupi_vec(MO_64, dest, val);
-}
-
-void tcg_gen_dup32i_vec(TCGv_vec dest, uint32_t val)
-{
-tcg_gen_dupi_vec(MO_32, dest, val);
-}
-
-void tcg_gen_dup16i_vec(TCGv_vec dest, uint32_t val)
-{
-tcg_gen_dupi_vec(MO_16, dest, val);
-}
-
-void tcg_gen_dup8i_vec(TCGv_vec dest, uint32_t val)
-{
-tcg_gen_dupi_vec(MO_8, dest, val);
-}
-
 void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec r, TCGv_i64 a)
 {
 TCGArg ri = tcgv_vec_arg(r);
-- 
2.20.1




[PATCH v4 16/19] tcg: Increase tcg_out_dupi_vec immediate to int64_t

2020-05-08 Thread Richard Henderson
While we don't store more than tcg_target_long in TCGTemp,
we shouldn't be limited to that for code generation.  We will
be able to use this for INDEX_op_dup2_vec with 2 constants.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 tcg/aarch64/tcg-target.inc.c |  2 +-
 tcg/i386/tcg-target.inc.c| 20 
 tcg/ppc/tcg-target.inc.c | 15 ---
 tcg/tcg.c|  4 ++--
 4 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/tcg/aarch64/tcg-target.inc.c b/tcg/aarch64/tcg-target.inc.c
index a7b1d36494..82b409ca7d 100644
--- a/tcg/aarch64/tcg-target.inc.c
+++ b/tcg/aarch64/tcg-target.inc.c
@@ -857,7 +857,7 @@ static void tcg_out_logicali(TCGContext *s, AArch64Insn 
insn, TCGType ext,
 }
 
 static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
- TCGReg rd, tcg_target_long v64)
+ TCGReg rd, int64_t v64)
 {
 bool q = type == TCG_TYPE_V128;
 int cmode, imm8, i;
diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.inc.c
index 4118071dd9..5e73e5d02b 100644
--- a/tcg/i386/tcg-target.inc.c
+++ b/tcg/i386/tcg-target.inc.c
@@ -945,7 +945,7 @@ static bool tcg_out_dupm_vec(TCGContext *s, TCGType type, 
unsigned vece,
 }
 
 static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
- TCGReg ret, tcg_target_long arg)
+ TCGReg ret, int64_t arg)
 {
 int vex_l = (type == TCG_TYPE_V256 ? P_VEXL : 0);
 
@@ -958,7 +958,14 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
 return;
 }
 
-if (TCG_TARGET_REG_BITS == 64) {
+if (TCG_TARGET_REG_BITS == 32 && arg == dup_const(MO_32, arg)) {
+if (have_avx2) {
+tcg_out_vex_modrm_pool(s, OPC_VPBROADCASTW + vex_l, ret);
+} else {
+tcg_out_vex_modrm_pool(s, OPC_VBROADCASTSS, ret);
+}
+new_pool_label(s, arg, R_386_32, s->code_ptr - 4, 0);
+} else {
 if (type == TCG_TYPE_V64) {
 tcg_out_vex_modrm_pool(s, OPC_MOVQ_VqWq, ret);
 } else if (have_avx2) {
@@ -966,14 +973,11 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
 } else {
 tcg_out_vex_modrm_pool(s, OPC_MOVDDUP, ret);
 }
-new_pool_label(s, arg, R_386_PC32, s->code_ptr - 4, -4);
-} else {
-if (have_avx2) {
-tcg_out_vex_modrm_pool(s, OPC_VPBROADCASTW + vex_l, ret);
+if (TCG_TARGET_REG_BITS == 64) {
+new_pool_label(s, arg, R_386_PC32, s->code_ptr - 4, -4);
 } else {
-tcg_out_vex_modrm_pool(s, OPC_VBROADCASTSS, ret);
+new_pool_l2(s, R_386_32, s->code_ptr - 4, 0, arg, arg >> 32);
 }
-new_pool_label(s, arg, R_386_32, s->code_ptr - 4, 0);
 }
 }
 
diff --git a/tcg/ppc/tcg-target.inc.c b/tcg/ppc/tcg-target.inc.c
index 7111da34dd..3f9690418f 100644
--- a/tcg/ppc/tcg-target.inc.c
+++ b/tcg/ppc/tcg-target.inc.c
@@ -913,7 +913,7 @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, 
TCGReg ret,
 }
 
 static void tcg_out_dupi_vec(TCGContext *s, TCGType type, TCGReg ret,
- tcg_target_long val)
+ int64_t val)
 {
 uint32_t load_insn;
 int rel, low;
@@ -921,20 +921,20 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type, 
TCGReg ret,
 
 low = (int8_t)val;
 if (low >= -16 && low < 16) {
-if (val == (tcg_target_long)dup_const(MO_8, low)) {
+if (val == dup_const(MO_8, low)) {
 tcg_out32(s, VSPLTISB | VRT(ret) | ((val & 31) << 16));
 return;
 }
-if (val == (tcg_target_long)dup_const(MO_16, low)) {
+if (val == dup_const(MO_16, low)) {
 tcg_out32(s, VSPLTISH | VRT(ret) | ((val & 31) << 16));
 return;
 }
-if (val == (tcg_target_long)dup_const(MO_32, low)) {
+if (val == dup_const(MO_32, low)) {
 tcg_out32(s, VSPLTISW | VRT(ret) | ((val & 31) << 16));
 return;
 }
 }
-if (have_isa_3_00 && val == (tcg_target_long)dup_const(MO_8, val)) {
+if (have_isa_3_00 && val == dup_const(MO_8, val)) {
 tcg_out32(s, XXSPLTIB | VRT(ret) | ((val & 0xff) << 11));
 return;
 }
@@ -956,14 +956,15 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type, 
TCGReg ret,
 if (TCG_TARGET_REG_BITS == 64) {
 new_pool_label(s, val, rel, s->code_ptr, add);
 } else {
-new_pool_l2(s, rel, s->code_ptr, add, val, val);
+new_pool_l2(s, rel, s->code_ptr, add, val >> 32, val);
 }
 } else {
 load_insn = LVX | VRT(ret) | RB(TCG_REG_TMP1);
 if (TCG_TARGET_REG_BITS == 64) {
 new_pool_l2(s, rel, s->code_ptr, add, val, val);
 } else {
-new_pool_l4(s, rel, s->code_ptr, add, val, val, val, val);
+new_pool_l4(s, rel, s->code_ptr, add,
+val >> 32, 

[PATCH v4 17/19] tcg: Add tcg_reg_alloc_dup2

2020-05-08 Thread Richard Henderson
There are several ways we can expand a vector dup of a 64-bit
element on a 32-bit host.

Signed-off-by: Richard Henderson 
---
 tcg/tcg.c | 88 +++
 1 file changed, 88 insertions(+)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 18ebcc98f6..e8fe2d580b 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -3908,6 +3908,91 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 }
 }
 
+static void tcg_reg_alloc_dup2(TCGContext *s, const TCGOp *op)
+{
+const TCGLifeData arg_life = op->life;
+TCGTemp *ots, *itsl, *itsh;
+TCGType vtype = TCGOP_VECL(op) + TCG_TYPE_V64;
+
+/* This opcode is only valid for 32-bit hosts, for 64-bit elements. */
+tcg_debug_assert(TCG_TARGET_REG_BITS == 32);
+tcg_debug_assert(TCGOP_VECE(op) == MO_64);
+
+ots = arg_temp(op->args[0]);
+itsl = arg_temp(op->args[1]);
+itsh = arg_temp(op->args[2]);
+
+/* ENV should not be modified.  */
+tcg_debug_assert(!temp_readonly(ots));
+
+/* Allocate the output register now.  */
+if (ots->val_type != TEMP_VAL_REG) {
+TCGRegSet allocated_regs = s->reserved_regs;
+TCGRegSet dup_out_regs =
+tcg_op_defs[INDEX_op_dup_vec].args_ct[0].u.regs;
+
+/* Make sure to not spill the input registers. */
+if (!IS_DEAD_ARG(1) && itsl->val_type == TEMP_VAL_REG) {
+tcg_regset_set_reg(allocated_regs, itsl->reg);
+}
+if (!IS_DEAD_ARG(2) && itsh->val_type == TEMP_VAL_REG) {
+tcg_regset_set_reg(allocated_regs, itsh->reg);
+}
+
+ots->reg = tcg_reg_alloc(s, dup_out_regs, allocated_regs,
+ op->output_pref[0], ots->indirect_base);
+ots->val_type = TEMP_VAL_REG;
+ots->mem_coherent = 0;
+s->reg_to_temp[ots->reg] = ots;
+}
+
+/* Promote dup2 of immediates to dupi_vec. */
+if (itsl->val_type == TEMP_VAL_CONST &&
+itsh->val_type == TEMP_VAL_CONST) {
+tcg_out_dupi_vec(s, vtype, ots->reg,
+ (uint32_t)itsl->val | ((uint64_t)itsh->val << 32));
+goto done;
+}
+
+/* If the two inputs form one 64-bit value, try dupm_vec. */
+if (itsl + 1 == itsh &&
+itsl->base_type == TCG_TYPE_I64 &&
+itsh->base_type == TCG_TYPE_I64) {
+if (!itsl->mem_coherent) {
+temp_sync(s, itsl, s->reserved_regs, 0, 0);
+}
+if (!itsl->mem_coherent) {
+temp_sync(s, itsl, s->reserved_regs, 0, 0);
+}
+#ifdef HOST_WORDS_BIGENDIAN
+TCGTemp *its = itsh;
+#else
+TCGTemp *its = itsl;
+#endif
+if (tcg_out_dupm_vec(s, vtype, MO_64, ots->reg,
+ its->mem_base->reg, its->mem_offset)) {
+goto done;
+}
+}
+
+/* Fall back to generic expansion. */
+tcg_reg_alloc_op(s, op);
+return;
+
+ done:
+if (IS_DEAD_ARG(1)) {
+temp_dead(s, itsl);
+}
+if (IS_DEAD_ARG(2)) {
+temp_dead(s, itsh);
+}
+if (NEED_SYNC_ARG(0)) {
+temp_sync(s, ots, s->reserved_regs, 0, IS_DEAD_ARG(0));
+} else if (IS_DEAD_ARG(0)) {
+temp_dead(s, ots);
+}
+}
+
 #ifdef TCG_TARGET_STACK_GROWSUP
 #define STACK_DIR(x) (-(x))
 #else
@@ -4299,6 +4384,9 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
 case INDEX_op_dup_vec:
 tcg_reg_alloc_dup(s, op);
 break;
+case INDEX_op_dup2_vec:
+tcg_reg_alloc_dup2(s, op);
+break;
 case INDEX_op_insn_start:
 if (num_insns >= 0) {
 size_t off = tcg_current_code_size(s);
-- 
2.20.1




[PATCH v4 13/19] tcg/tci: Add special tci_movi_{i32,i64} opcodes

2020-05-08 Thread Richard Henderson
The normal movi opcodes are going away.  We need something
for TCI to use internally.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-opc.h| 8 
 tcg/tci.c| 4 ++--
 tcg/tci/tcg-target.inc.c | 4 ++--
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
index e3929b80d2..5a941eaa07 100644
--- a/include/tcg/tcg-opc.h
+++ b/include/tcg/tcg-opc.h
@@ -272,6 +272,14 @@ DEF(last_generic, 0, 0, 0, TCG_OPF_NOT_PRESENT)
 #include "tcg-target.opc.h"
 #endif
 
+#ifdef TCG_TARGET_INTERPRETER
+/* These opcodes are only for use between the tci generator and interpreter. */
+DEF(tci_movi_i32, 1, 0, 1, TCG_OPF_NOT_PRESENT)
+#if TCG_TARGET_REG_BITS == 64
+DEF(tci_movi_i64, 1, 0, 1, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
+#endif
+#endif
+
 #undef TLADDR_ARGS
 #undef DATA64_ARGS
 #undef IMPL
diff --git a/tcg/tci.c b/tcg/tci.c
index 46fe9ce63f..a6c1aaf5af 100644
--- a/tcg/tci.c
+++ b/tcg/tci.c
@@ -576,7 +576,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t 
*tb_ptr)
 t1 = tci_read_r32(regs, _ptr);
 tci_write_reg32(regs, t0, t1);
 break;
-case INDEX_op_movi_i32:
+case INDEX_op_tci_movi_i32:
 t0 = *tb_ptr++;
 t1 = tci_read_i32(_ptr);
 tci_write_reg32(regs, t0, t1);
@@ -847,7 +847,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t 
*tb_ptr)
 t1 = tci_read_r64(regs, _ptr);
 tci_write_reg64(regs, t0, t1);
 break;
-case INDEX_op_movi_i64:
+case INDEX_op_tci_movi_i64:
 t0 = *tb_ptr++;
 t1 = tci_read_i64(_ptr);
 tci_write_reg64(regs, t0, t1);
diff --git a/tcg/tci/tcg-target.inc.c b/tcg/tci/tcg-target.inc.c
index 992d50cb1e..1f1639df0d 100644
--- a/tcg/tci/tcg-target.inc.c
+++ b/tcg/tci/tcg-target.inc.c
@@ -530,13 +530,13 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
 uint8_t *old_code_ptr = s->code_ptr;
 uint32_t arg32 = arg;
 if (type == TCG_TYPE_I32 || arg == arg32) {
-tcg_out_op_t(s, INDEX_op_movi_i32);
+tcg_out_op_t(s, INDEX_op_tci_movi_i32);
 tcg_out_r(s, t0);
 tcg_out32(s, arg32);
 } else {
 tcg_debug_assert(type == TCG_TYPE_I64);
 #if TCG_TARGET_REG_BITS == 64
-tcg_out_op_t(s, INDEX_op_movi_i64);
+tcg_out_op_t(s, INDEX_op_tci_movi_i64);
 tcg_out_r(s, t0);
 tcg_out64(s, arg);
 #else
-- 
2.20.1




[PATCH v4 15/19] tcg: Use tcg_out_dupi_vec from temp_load

2020-05-08 Thread Richard Henderson
Having dupi pass though movi is confusing and arguably wrong.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 tcg/aarch64/tcg-target.inc.c |  7 
 tcg/i386/tcg-target.inc.c| 63 
 tcg/ppc/tcg-target.inc.c |  6 
 tcg/tcg.c|  8 -
 4 files changed, 49 insertions(+), 35 deletions(-)

diff --git a/tcg/aarch64/tcg-target.inc.c b/tcg/aarch64/tcg-target.inc.c
index d065fd600b..a7b1d36494 100644
--- a/tcg/aarch64/tcg-target.inc.c
+++ b/tcg/aarch64/tcg-target.inc.c
@@ -1010,13 +1010,6 @@ static void tcg_out_movi(TCGContext *s, TCGType type, 
TCGReg rd,
 case TCG_TYPE_I64:
 tcg_debug_assert(rd < 32);
 break;
-
-case TCG_TYPE_V64:
-case TCG_TYPE_V128:
-tcg_debug_assert(rd >= 32);
-tcg_out_dupi_vec(s, type, rd, value);
-return;
-
 default:
 g_assert_not_reached();
 }
diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.inc.c
index bc957e7bed..4118071dd9 100644
--- a/tcg/i386/tcg-target.inc.c
+++ b/tcg/i386/tcg-target.inc.c
@@ -977,30 +977,32 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
 }
 }
 
-static void tcg_out_movi(TCGContext *s, TCGType type,
- TCGReg ret, tcg_target_long arg)
+static void tcg_out_movi_vec(TCGContext *s, TCGType type,
+ TCGReg ret, tcg_target_long arg)
+{
+if (arg == 0) {
+tcg_out_vex_modrm(s, OPC_PXOR, ret, ret, ret);
+return;
+}
+if (arg == -1) {
+tcg_out_vex_modrm(s, OPC_PCMPEQB, ret, ret, ret);
+return;
+}
+
+int rexw = (type == TCG_TYPE_I32 ? 0 : P_REXW);
+tcg_out_vex_modrm_pool(s, OPC_MOVD_VyEy + rexw, ret);
+if (TCG_TARGET_REG_BITS == 64) {
+new_pool_label(s, arg, R_386_PC32, s->code_ptr - 4, -4);
+} else {
+new_pool_label(s, arg, R_386_32, s->code_ptr - 4, 0);
+}
+}
+
+static void tcg_out_movi_int(TCGContext *s, TCGType type,
+ TCGReg ret, tcg_target_long arg)
 {
 tcg_target_long diff;
 
-switch (type) {
-case TCG_TYPE_I32:
-#if TCG_TARGET_REG_BITS == 64
-case TCG_TYPE_I64:
-#endif
-if (ret < 16) {
-break;
-}
-/* fallthru */
-case TCG_TYPE_V64:
-case TCG_TYPE_V128:
-case TCG_TYPE_V256:
-tcg_debug_assert(ret >= 16);
-tcg_out_dupi_vec(s, type, ret, arg);
-return;
-default:
-g_assert_not_reached();
-}
-
 if (arg == 0) {
 tgen_arithr(s, ARITH_XOR, ret, ret);
 return;
@@ -1029,6 +1031,25 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
 tcg_out64(s, arg);
 }
 
+static void tcg_out_movi(TCGContext *s, TCGType type,
+ TCGReg ret, tcg_target_long arg)
+{
+switch (type) {
+case TCG_TYPE_I32:
+#if TCG_TARGET_REG_BITS == 64
+case TCG_TYPE_I64:
+#endif
+if (ret < 16) {
+tcg_out_movi_int(s, type, ret, arg);
+} else {
+tcg_out_movi_vec(s, type, ret, arg);
+}
+break;
+default:
+g_assert_not_reached();
+}
+}
+
 static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
 {
 if (val == (int8_t)val) {
diff --git a/tcg/ppc/tcg-target.inc.c b/tcg/ppc/tcg-target.inc.c
index c525439b62..7111da34dd 100644
--- a/tcg/ppc/tcg-target.inc.c
+++ b/tcg/ppc/tcg-target.inc.c
@@ -987,12 +987,6 @@ static void tcg_out_movi(TCGContext *s, TCGType type, 
TCGReg ret,
 tcg_out_movi_int(s, type, ret, arg, false);
 break;
 
-case TCG_TYPE_V64:
-case TCG_TYPE_V128:
-tcg_debug_assert(ret >= TCG_REG_V0);
-tcg_out_dupi_vec(s, type, ret, arg);
-break;
-
 default:
 g_assert_not_reached();
 }
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 7a23ccb017..a84a9d3d63 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -3400,7 +3400,13 @@ static void temp_load(TCGContext *s, TCGTemp *ts, 
TCGRegSet desired_regs,
 case TEMP_VAL_CONST:
 reg = tcg_reg_alloc(s, desired_regs, allocated_regs,
 preferred_regs, ts->indirect_base);
-tcg_out_movi(s, ts->type, reg, ts->val);
+if (ts->type <= TCG_TYPE_I64) {
+tcg_out_movi(s, ts->type, reg, ts->val);
+} else if (TCG_TARGET_REG_BITS == 64) {
+tcg_out_dupi_vec(s, ts->type, reg, ts->val);
+} else {
+tcg_out_dupi_vec(s, ts->type, reg, dup_const(MO_32, ts->val));
+}
 ts->mem_coherent = 0;
 break;
 case TEMP_VAL_MEM:
-- 
2.20.1




[PATCH v4 12/19] tcg/optimize: Use tcg_constant_internal with constant folding

2020-05-08 Thread Richard Henderson
Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 106 ++---
 1 file changed, 48 insertions(+), 58 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index d36d7e1d7f..dd5187be31 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -178,37 +178,6 @@ static bool args_are_copies(TCGArg arg1, TCGArg arg2)
 return ts_are_copies(arg_temp(arg1), arg_temp(arg2));
 }
 
-static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg val)
-{
-const TCGOpDef *def;
-TCGOpcode new_op;
-tcg_target_ulong mask;
-TempOptInfo *di = arg_info(dst);
-
-def = _op_defs[op->opc];
-if (def->flags & TCG_OPF_VECTOR) {
-new_op = INDEX_op_dupi_vec;
-} else if (def->flags & TCG_OPF_64BIT) {
-new_op = INDEX_op_movi_i64;
-} else {
-new_op = INDEX_op_movi_i32;
-}
-op->opc = new_op;
-/* TCGOP_VECL and TCGOP_VECE remain unchanged.  */
-op->args[0] = dst;
-op->args[1] = val;
-
-reset_temp(dst);
-di->is_const = true;
-di->val = val;
-mask = val;
-if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_movi_i32) {
-/* High bits of the destination are now garbage.  */
-mask |= ~0xull;
-}
-di->mask = mask;
-}
-
 static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg src)
 {
 TCGTemp *dst_ts = arg_temp(dst);
@@ -259,6 +228,27 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg src)
 }
 }
 
+static void tcg_opt_gen_movi(TCGContext *s, TCGTempSet *temps_used,
+ TCGOp *op, TCGArg dst, TCGArg val)
+{
+const TCGOpDef *def = _op_defs[op->opc];
+TCGType type;
+TCGTemp *tv;
+
+if (def->flags & TCG_OPF_VECTOR) {
+type = TCGOP_VECL(op) + TCG_TYPE_V64;
+} else if (def->flags & TCG_OPF_64BIT) {
+type = TCG_TYPE_I64;
+} else {
+type = TCG_TYPE_I32;
+}
+
+/* Convert movi to mov with constant temp. */
+tv = tcg_constant_internal(type, val);
+init_ts_info(temps_used, tv);
+tcg_opt_gen_mov(s, op, dst, temp_arg(tv));
+}
+
 static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
 {
 uint64_t l64, h64;
@@ -621,7 +611,7 @@ void tcg_optimize(TCGContext *s)
 nb_temps = s->nb_temps;
 nb_globals = s->nb_globals;
 
-bitmap_zero(temps_used.l, nb_temps);
+memset(_used, 0, sizeof(temps_used));
 for (i = 0; i < nb_temps; ++i) {
 s->temps[i].state_ptr = NULL;
 }
@@ -727,7 +717,7 @@ void tcg_optimize(TCGContext *s)
 CASE_OP_32_64(rotr):
 if (arg_is_const(op->args[1])
 && arg_info(op->args[1])->val == 0) {
-tcg_opt_gen_movi(s, op, op->args[0], 0);
+tcg_opt_gen_movi(s, _used, op, op->args[0], 0);
 continue;
 }
 break;
@@ -1050,7 +1040,7 @@ void tcg_optimize(TCGContext *s)
 
 if (partmask == 0) {
 tcg_debug_assert(nb_oargs == 1);
-tcg_opt_gen_movi(s, op, op->args[0], 0);
+tcg_opt_gen_movi(s, _used, op, op->args[0], 0);
 continue;
 }
 if (affected == 0) {
@@ -1067,7 +1057,7 @@ void tcg_optimize(TCGContext *s)
 CASE_OP_32_64(mulsh):
 if (arg_is_const(op->args[2])
 && arg_info(op->args[2])->val == 0) {
-tcg_opt_gen_movi(s, op, op->args[0], 0);
+tcg_opt_gen_movi(s, _used, op, op->args[0], 0);
 continue;
 }
 break;
@@ -1094,7 +1084,7 @@ void tcg_optimize(TCGContext *s)
 CASE_OP_32_64_VEC(sub):
 CASE_OP_32_64_VEC(xor):
 if (args_are_copies(op->args[1], op->args[2])) {
-tcg_opt_gen_movi(s, op, op->args[0], 0);
+tcg_opt_gen_movi(s, _used, op, op->args[0], 0);
 continue;
 }
 break;
@@ -,14 +1101,14 @@ void tcg_optimize(TCGContext *s)
 break;
 CASE_OP_32_64(movi):
 case INDEX_op_dupi_vec:
-tcg_opt_gen_movi(s, op, op->args[0], op->args[1]);
+tcg_opt_gen_movi(s, _used, op, op->args[0], op->args[1]);
 break;
 
 case INDEX_op_dup_vec:
 if (arg_is_const(op->args[1])) {
 tmp = arg_info(op->args[1])->val;
 tmp = dup_const(TCGOP_VECE(op), tmp);
-tcg_opt_gen_movi(s, op, op->args[0], tmp);
+tcg_opt_gen_movi(s, _used, op, op->args[0], tmp);
 break;
 }
 goto do_default;
@@ -1141,7 +1131,7 @@ void tcg_optimize(TCGContext *s)
 case INDEX_op_extrh_i64_i32:
 if (arg_is_const(op->args[1])) {
 tmp = do_constant_folding(opc, arg_info(op->args[1])->val, 0);
-tcg_opt_gen_movi(s, op, op->args[0], tmp);
+tcg_opt_gen_movi(s, _used, op, op->args[0], tmp);
   

[PATCH v4 10/19] tcg/optimize: Improve find_better_copy

2020-05-08 Thread Richard Henderson
Prefer TEMP_CONST over anything else.

Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 27 ---
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index c0fc5e3da6..b86bf3d707 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -122,31 +122,28 @@ static void init_arg_info(TempOptInfo *infos,
 
 static TCGTemp *find_better_copy(TCGContext *s, TCGTemp *ts)
 {
-TCGTemp *i;
+TCGTemp *i, *g, *l;
 
-/* If this is already a global, we can't do better. */
-if (ts->kind >= TEMP_GLOBAL) {
+/* If this is already readonly, we can't do better. */
+if (temp_readonly(ts)) {
 return ts;
 }
 
-/* Search for a global first. */
+g = l = NULL;
 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (i->kind >= TEMP_GLOBAL) {
+if (temp_readonly(i)) {
 return i;
-}
-}
-
-/* If it is a temp, search for a temp local. */
-if (ts->kind == TEMP_NORMAL) {
-for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (i->kind >= TEMP_LOCAL) {
-return i;
+} else if (i->kind > ts->kind) {
+if (i->kind == TEMP_GLOBAL) {
+g = i;
+} else if (i->kind == TEMP_LOCAL) {
+l = i;
 }
 }
 }
 
-/* Failure to find a better representation, return the same temp. */
-return ts;
+/* If we didn't find a better representation, return the same temp. */
+return g ? g : l ? l : ts;
 }
 
 static bool ts_are_copies(TCGTemp *ts1, TCGTemp *ts2)
-- 
2.20.1




[PATCH v4 11/19] tcg/optimize: Adjust TempOptInfo allocation

2020-05-08 Thread Richard Henderson
Do not allocate a large block for indexing.  Instead, allocate
for each temporary as they are seen.

In general, this will use less memory, if we consider that most
TBs do not touch every target register.  This also allows us to
allocate TempOptInfo for new temps created during optimization.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 60 --
 1 file changed, 34 insertions(+), 26 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index b86bf3d707..d36d7e1d7f 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -89,35 +89,41 @@ static void reset_temp(TCGArg arg)
 }
 
 /* Initialize and activate a temporary.  */
-static void init_ts_info(TempOptInfo *infos,
- TCGTempSet *temps_used, TCGTemp *ts)
+static void init_ts_info(TCGTempSet *temps_used, TCGTemp *ts)
 {
 size_t idx = temp_idx(ts);
-if (!test_bit(idx, temps_used->l)) {
-TempOptInfo *ti = [idx];
+TempOptInfo *ti;
 
+if (test_bit(idx, temps_used->l)) {
+return;
+}
+set_bit(idx, temps_used->l);
+
+ti = ts->state_ptr;
+if (ti == NULL) {
+ti = tcg_malloc(sizeof(TempOptInfo));
 ts->state_ptr = ti;
-ti->next_copy = ts;
-ti->prev_copy = ts;
-if (ts->kind == TEMP_CONST) {
-ti->is_const = true;
-ti->val = ti->mask = ts->val;
-if (TCG_TARGET_REG_BITS > 32 && ts->type == TCG_TYPE_I32) {
-/* High bits of a 32-bit quantity are garbage.  */
-ti->mask |= ~0xull;
-}
-} else {
-ti->is_const = false;
-ti->mask = -1;
+}
+
+ti->next_copy = ts;
+ti->prev_copy = ts;
+if (ts->kind == TEMP_CONST) {
+ti->is_const = true;
+ti->val = ts->val;
+ti->mask = ts->val;
+if (TCG_TARGET_REG_BITS > 32 && ts->type == TCG_TYPE_I32) {
+/* High bits of a 32-bit quantity are garbage.  */
+ti->mask |= ~0xull;
 }
-set_bit(idx, temps_used->l);
+} else {
+ti->is_const = false;
+ti->mask = -1;
 }
 }
 
-static void init_arg_info(TempOptInfo *infos,
-  TCGTempSet *temps_used, TCGArg arg)
+static void init_arg_info(TCGTempSet *temps_used, TCGArg arg)
 {
-init_ts_info(infos, temps_used, arg_temp(arg));
+init_ts_info(temps_used, arg_temp(arg));
 }
 
 static TCGTemp *find_better_copy(TCGContext *s, TCGTemp *ts)
@@ -603,9 +609,8 @@ static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
 /* Propagate constants and copies, fold constant expressions. */
 void tcg_optimize(TCGContext *s)
 {
-int nb_temps, nb_globals;
+int nb_temps, nb_globals, i;
 TCGOp *op, *op_next, *prev_mb = NULL;
-TempOptInfo *infos;
 TCGTempSet temps_used;
 
 /* Array VALS has an element for each temp.
@@ -615,12 +620,15 @@ void tcg_optimize(TCGContext *s)
 
 nb_temps = s->nb_temps;
 nb_globals = s->nb_globals;
+
 bitmap_zero(temps_used.l, nb_temps);
-infos = tcg_malloc(sizeof(TempOptInfo) * nb_temps);
+for (i = 0; i < nb_temps; ++i) {
+s->temps[i].state_ptr = NULL;
+}
 
 QTAILQ_FOREACH_SAFE(op, >ops, link, op_next) {
 tcg_target_ulong mask, partmask, affected;
-int nb_oargs, nb_iargs, i;
+int nb_oargs, nb_iargs;
 TCGArg tmp;
 TCGOpcode opc = op->opc;
 const TCGOpDef *def = _op_defs[opc];
@@ -633,14 +641,14 @@ void tcg_optimize(TCGContext *s)
 for (i = 0; i < nb_oargs + nb_iargs; i++) {
 TCGTemp *ts = arg_temp(op->args[i]);
 if (ts) {
-init_ts_info(infos, _used, ts);
+init_ts_info(_used, ts);
 }
 }
 } else {
 nb_oargs = def->nb_oargs;
 nb_iargs = def->nb_iargs;
 for (i = 0; i < nb_oargs + nb_iargs; i++) {
-init_arg_info(infos, _used, op->args[i]);
+init_arg_info(_used, op->args[i]);
 }
 }
 
-- 
2.20.1




[PATCH v4 09/19] tcg: Rename struct tcg_temp_info to TempOptInfo

2020-05-08 Thread Richard Henderson
Fix this name vs our coding style.

Reviewed-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 32 
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index 8f3bd99ff4..c0fc5e3da6 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -35,20 +35,20 @@
 glue(glue(case INDEX_op_, x), _i64):\
 glue(glue(case INDEX_op_, x), _vec)
 
-struct tcg_temp_info {
+typedef struct TempOptInfo {
 bool is_const;
 TCGTemp *prev_copy;
 TCGTemp *next_copy;
 tcg_target_ulong val;
 tcg_target_ulong mask;
-};
+} TempOptInfo;
 
-static inline struct tcg_temp_info *ts_info(TCGTemp *ts)
+static inline TempOptInfo *ts_info(TCGTemp *ts)
 {
 return ts->state_ptr;
 }
 
-static inline struct tcg_temp_info *arg_info(TCGArg arg)
+static inline TempOptInfo *arg_info(TCGArg arg)
 {
 return ts_info(arg_temp(arg));
 }
@@ -71,9 +71,9 @@ static inline bool ts_is_copy(TCGTemp *ts)
 /* Reset TEMP's state, possibly removing the temp for the list of copies.  */
 static void reset_ts(TCGTemp *ts)
 {
-struct tcg_temp_info *ti = ts_info(ts);
-struct tcg_temp_info *pi = ts_info(ti->prev_copy);
-struct tcg_temp_info *ni = ts_info(ti->next_copy);
+TempOptInfo *ti = ts_info(ts);
+TempOptInfo *pi = ts_info(ti->prev_copy);
+TempOptInfo *ni = ts_info(ti->next_copy);
 
 ni->prev_copy = ti->prev_copy;
 pi->next_copy = ti->next_copy;
@@ -89,12 +89,12 @@ static void reset_temp(TCGArg arg)
 }
 
 /* Initialize and activate a temporary.  */
-static void init_ts_info(struct tcg_temp_info *infos,
+static void init_ts_info(TempOptInfo *infos,
  TCGTempSet *temps_used, TCGTemp *ts)
 {
 size_t idx = temp_idx(ts);
 if (!test_bit(idx, temps_used->l)) {
-struct tcg_temp_info *ti = [idx];
+TempOptInfo *ti = [idx];
 
 ts->state_ptr = ti;
 ti->next_copy = ts;
@@ -114,7 +114,7 @@ static void init_ts_info(struct tcg_temp_info *infos,
 }
 }
 
-static void init_arg_info(struct tcg_temp_info *infos,
+static void init_arg_info(TempOptInfo *infos,
   TCGTempSet *temps_used, TCGArg arg)
 {
 init_ts_info(infos, temps_used, arg_temp(arg));
@@ -180,7 +180,7 @@ static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg val)
 const TCGOpDef *def;
 TCGOpcode new_op;
 tcg_target_ulong mask;
-struct tcg_temp_info *di = arg_info(dst);
+TempOptInfo *di = arg_info(dst);
 
 def = _op_defs[op->opc];
 if (def->flags & TCG_OPF_VECTOR) {
@@ -211,8 +211,8 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg src)
 TCGTemp *dst_ts = arg_temp(dst);
 TCGTemp *src_ts = arg_temp(src);
 const TCGOpDef *def;
-struct tcg_temp_info *di;
-struct tcg_temp_info *si;
+TempOptInfo *di;
+TempOptInfo *si;
 tcg_target_ulong mask;
 TCGOpcode new_op;
 
@@ -245,7 +245,7 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg src)
 di->mask = mask;
 
 if (src_ts->type == dst_ts->type) {
-struct tcg_temp_info *ni = ts_info(si->next_copy);
+TempOptInfo *ni = ts_info(si->next_copy);
 
 di->next_copy = si->next_copy;
 di->prev_copy = src_ts;
@@ -608,7 +608,7 @@ void tcg_optimize(TCGContext *s)
 {
 int nb_temps, nb_globals;
 TCGOp *op, *op_next, *prev_mb = NULL;
-struct tcg_temp_info *infos;
+TempOptInfo *infos;
 TCGTempSet temps_used;
 
 /* Array VALS has an element for each temp.
@@ -619,7 +619,7 @@ void tcg_optimize(TCGContext *s)
 nb_temps = s->nb_temps;
 nb_globals = s->nb_globals;
 bitmap_zero(temps_used.l, nb_temps);
-infos = tcg_malloc(sizeof(struct tcg_temp_info) * nb_temps);
+infos = tcg_malloc(sizeof(TempOptInfo) * nb_temps);
 
 QTAILQ_FOREACH_SAFE(op, >ops, link, op_next) {
 tcg_target_ulong mask, partmask, affected;
-- 
2.20.1




[PATCH v4 05/19] tcg: Use tcg_constant_{i32, i64} with tcg int expanders

2020-05-08 Thread Richard Henderson
Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-op.h |  13 +--
 tcg/tcg-op.c | 216 ---
 2 files changed, 100 insertions(+), 129 deletions(-)

diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h
index 5abf17fecc..b4fba35e87 100644
--- a/include/tcg/tcg-op.h
+++ b/include/tcg/tcg-op.h
@@ -271,6 +271,7 @@ void tcg_gen_mb(TCGBar);
 
 /* 32 bit ops */
 
+void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg);
 void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
 void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2);
 void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
@@ -349,11 +350,6 @@ static inline void tcg_gen_mov_i32(TCGv_i32 ret, TCGv_i32 
arg)
 }
 }
 
-static inline void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg)
-{
-tcg_gen_op2i_i32(INDEX_op_movi_i32, ret, arg);
-}
-
 static inline void tcg_gen_ld8u_i32(TCGv_i32 ret, TCGv_ptr arg2,
 tcg_target_long offset)
 {
@@ -467,6 +463,7 @@ static inline void tcg_gen_not_i32(TCGv_i32 ret, TCGv_i32 
arg)
 
 /* 64 bit ops */
 
+void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg);
 void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
 void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2);
 void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
@@ -550,11 +547,6 @@ static inline void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 
arg)
 }
 }
 
-static inline void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
-{
-tcg_gen_op2i_i64(INDEX_op_movi_i64, ret, arg);
-}
-
 static inline void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2,
 tcg_target_long offset)
 {
@@ -698,7 +690,6 @@ static inline void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 
arg1, TCGv_i64 arg2)
 
 void tcg_gen_discard_i64(TCGv_i64 arg);
 void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg);
-void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg);
 void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
 void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
 void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index e60b74fb82..202d8057c5 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -104,15 +104,18 @@ void tcg_gen_mb(TCGBar mb_type)
 
 /* 32 bit ops */
 
+void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg)
+{
+tcg_gen_mov_i32(ret, tcg_constant_i32(arg));
+}
+
 void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
 {
 /* some cases can be optimized here */
 if (arg2 == 0) {
 tcg_gen_mov_i32(ret, arg1);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg2);
-tcg_gen_add_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+tcg_gen_add_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 }
 
@@ -122,9 +125,7 @@ void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 
arg2)
 /* Don't recurse with tcg_gen_neg_i32.  */
 tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg1);
-tcg_gen_sub_i32(ret, t0, arg2);
-tcg_temp_free_i32(t0);
+tcg_gen_sub_i32(ret, tcg_constant_i32(arg1), arg2);
 }
 }
 
@@ -134,15 +135,12 @@ void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, 
int32_t arg2)
 if (arg2 == 0) {
 tcg_gen_mov_i32(ret, arg1);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg2);
-tcg_gen_sub_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+tcg_gen_sub_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 }
 
 void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
 {
-TCGv_i32 t0;
 /* Some cases can be optimized here.  */
 switch (arg2) {
 case 0:
@@ -165,9 +163,8 @@ void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t 
arg2)
 }
 break;
 }
-t0 = tcg_const_i32(arg2);
-tcg_gen_and_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+
+tcg_gen_and_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 
 void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
@@ -178,9 +175,7 @@ void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t 
arg2)
 } else if (arg2 == 0) {
 tcg_gen_mov_i32(ret, arg1);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg2);
-tcg_gen_or_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+tcg_gen_or_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 }
 
@@ -193,9 +188,7 @@ void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t 
arg2)
 /* Don't recurse with tcg_gen_not_i32.  */
 tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg2);
-tcg_gen_xor_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+tcg_gen_xor_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 }
 
@@ -205,9 +198,7 @@ void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t 

[PATCH v4 08/19] tcg: Use tcg_constant_{i32,i64} with tcg plugins

2020-05-08 Thread Richard Henderson
Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 accel/tcg/plugin-gen.c | 49 +++---
 1 file changed, 22 insertions(+), 27 deletions(-)

diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
index 51580d51a0..e5dc9d0ca9 100644
--- a/accel/tcg/plugin-gen.c
+++ b/accel/tcg/plugin-gen.c
@@ -284,8 +284,8 @@ static TCGOp *copy_extu_i32_i64(TCGOp **begin_op, TCGOp *op)
 if (TCG_TARGET_REG_BITS == 32) {
 /* mov_i32 */
 op = copy_op(begin_op, op, INDEX_op_mov_i32);
-/* movi_i32 */
-op = copy_op(begin_op, op, INDEX_op_movi_i32);
+/* mov_i32 w/ $0 */
+op = copy_op(begin_op, op, INDEX_op_mov_i32);
 } else {
 /* extu_i32_i64 */
 op = copy_op(begin_op, op, INDEX_op_extu_i32_i64);
@@ -306,39 +306,34 @@ static TCGOp *copy_mov_i64(TCGOp **begin_op, TCGOp *op)
 return op;
 }
 
-static TCGOp *copy_movi_i64(TCGOp **begin_op, TCGOp *op, uint64_t v)
-{
-if (TCG_TARGET_REG_BITS == 32) {
-/* 2x movi_i32 */
-op = copy_op(begin_op, op, INDEX_op_movi_i32);
-op->args[1] = v;
-
-op = copy_op(begin_op, op, INDEX_op_movi_i32);
-op->args[1] = v >> 32;
-} else {
-/* movi_i64 */
-op = copy_op(begin_op, op, INDEX_op_movi_i64);
-op->args[1] = v;
-}
-return op;
-}
-
 static TCGOp *copy_const_ptr(TCGOp **begin_op, TCGOp *op, void *ptr)
 {
 if (UINTPTR_MAX == UINT32_MAX) {
-/* movi_i32 */
-op = copy_op(begin_op, op, INDEX_op_movi_i32);
-op->args[1] = (uintptr_t)ptr;
+/* mov_i32 */
+op = copy_op(begin_op, op, INDEX_op_mov_i32);
+op->args[1] = tcgv_i32_arg(tcg_constant_i32((uintptr_t)ptr));
 } else {
-/* movi_i64 */
-op = copy_movi_i64(begin_op, op, (uint64_t)(uintptr_t)ptr);
+/* mov_i64 */
+op = copy_op(begin_op, op, INDEX_op_mov_i64);
+op->args[1] = tcgv_i64_arg(tcg_constant_i64((uintptr_t)ptr));
 }
 return op;
 }
 
 static TCGOp *copy_const_i64(TCGOp **begin_op, TCGOp *op, uint64_t v)
 {
-return copy_movi_i64(begin_op, op, v);
+if (TCG_TARGET_REG_BITS == 32) {
+/* 2x mov_i32 */
+op = copy_op(begin_op, op, INDEX_op_mov_i32);
+op->args[1] = tcgv_i32_arg(tcg_constant_i32(v));
+op = copy_op(begin_op, op, INDEX_op_mov_i32);
+op->args[1] = tcgv_i32_arg(tcg_constant_i32(v >> 32));
+} else {
+/* mov_i64 */
+op = copy_op(begin_op, op, INDEX_op_mov_i64);
+op->args[1] = tcgv_i64_arg(tcg_constant_i64(v));
+}
+return op;
 }
 
 static TCGOp *copy_extu_tl_i64(TCGOp **begin_op, TCGOp *op)
@@ -486,8 +481,8 @@ static TCGOp *append_mem_cb(const struct qemu_plugin_dyn_cb 
*cb,
 
 tcg_debug_assert(type == PLUGIN_GEN_CB_MEM);
 
-/* const_i32 == movi_i32 ("info", so it remains as is) */
-op = copy_op(_op, op, INDEX_op_movi_i32);
+/* const_i32 == mov_i32 ("info", so it remains as is) */
+op = copy_op(_op, op, INDEX_op_mov_i32);
 
 /* const_ptr */
 op = copy_const_ptr(_op, op, cb->userp);
-- 
2.20.1




[PATCH v4 06/19] tcg: Use tcg_constant_{i32, vec} with tcg vec expanders

2020-05-08 Thread Richard Henderson
Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 tcg/tcg-op-vec.c | 63 ++--
 1 file changed, 34 insertions(+), 29 deletions(-)

diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c
index 43101defe4..0e3e80a612 100644
--- a/tcg/tcg-op-vec.c
+++ b/tcg/tcg-op-vec.c
@@ -233,25 +233,17 @@ void tcg_gen_mov_vec(TCGv_vec r, TCGv_vec a)
 }
 }
 
-#define MO_REG  (TCG_TARGET_REG_BITS == 64 ? MO_64 : MO_32)
-
-static void do_dupi_vec(TCGv_vec r, unsigned vece, TCGArg a)
-{
-TCGTemp *rt = tcgv_vec_temp(r);
-vec_gen_2(INDEX_op_dupi_vec, rt->base_type, vece, temp_arg(rt), a);
-}
-
 TCGv_vec tcg_const_zeros_vec(TCGType type)
 {
 TCGv_vec ret = tcg_temp_new_vec(type);
-do_dupi_vec(ret, MO_REG, 0);
+tcg_gen_mov_vec(ret, tcg_constant_vec(type, MO_8, 0));
 return ret;
 }
 
 TCGv_vec tcg_const_ones_vec(TCGType type)
 {
 TCGv_vec ret = tcg_temp_new_vec(type);
-do_dupi_vec(ret, MO_REG, -1);
+tcg_gen_mov_vec(ret, tcg_constant_vec(type, MO_8, -1));
 return ret;
 }
 
@@ -267,37 +259,50 @@ TCGv_vec tcg_const_ones_vec_matching(TCGv_vec m)
 return tcg_const_ones_vec(t->base_type);
 }
 
-void tcg_gen_dup64i_vec(TCGv_vec r, uint64_t a)
+void tcg_gen_dupi_vec(unsigned vece, TCGv_vec dest, uint64_t val)
 {
-if (TCG_TARGET_REG_BITS == 32 && a == deposit64(a, 32, 32, a)) {
-do_dupi_vec(r, MO_32, a);
-} else if (TCG_TARGET_REG_BITS == 64 || a == (uint64_t)(int32_t)a) {
-do_dupi_vec(r, MO_64, a);
-} else {
-TCGv_i64 c = tcg_const_i64(a);
-tcg_gen_dup_i64_vec(MO_64, r, c);
-tcg_temp_free_i64(c);
+TCGType type = tcgv_vec_temp(dest)->base_type;
+
+/*
+ * For MO_64 constants that can't be represented in tcg_target_long,
+ * we must use INDEX_op_dup2_vec.
+ */
+if (TCG_TARGET_REG_BITS == 32) {
+val = dup_const(vece, val);
+if (val != deposit64(val, 32, 32, val) &&
+val != (uint64_t)(int32_t)val) {
+uint32_t vl = extract64(val, 0, 32);
+uint32_t vh = extract64(val, 32, 32);
+TCGArg al = tcgv_i32_arg(tcg_constant_i32(vl));
+TCGArg ah = tcgv_i32_arg(tcg_constant_i32(vh));
+TCGArg di = tcgv_vec_arg(dest);
+
+vec_gen_3(INDEX_op_dup2_vec, type, MO_64, di, al, ah);
+return;
+}
 }
+
+tcg_gen_mov_vec(dest, tcg_constant_vec(type, vece, val));
 }
 
-void tcg_gen_dup32i_vec(TCGv_vec r, uint32_t a)
+void tcg_gen_dup64i_vec(TCGv_vec dest, uint64_t val)
 {
-do_dupi_vec(r, MO_REG, dup_const(MO_32, a));
+tcg_gen_dupi_vec(MO_64, dest, val);
 }
 
-void tcg_gen_dup16i_vec(TCGv_vec r, uint32_t a)
+void tcg_gen_dup32i_vec(TCGv_vec dest, uint32_t val)
 {
-do_dupi_vec(r, MO_REG, dup_const(MO_16, a));
+tcg_gen_dupi_vec(MO_32, dest, val);
 }
 
-void tcg_gen_dup8i_vec(TCGv_vec r, uint32_t a)
+void tcg_gen_dup16i_vec(TCGv_vec dest, uint32_t val)
 {
-do_dupi_vec(r, MO_REG, dup_const(MO_8, a));
+tcg_gen_dupi_vec(MO_16, dest, val);
 }
 
-void tcg_gen_dupi_vec(unsigned vece, TCGv_vec r, uint64_t a)
+void tcg_gen_dup8i_vec(TCGv_vec dest, uint32_t val)
 {
-do_dupi_vec(r, MO_REG, dup_const(vece, a));
+tcg_gen_dupi_vec(MO_8, dest, val);
 }
 
 void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec r, TCGv_i64 a)
@@ -502,8 +507,8 @@ void tcg_gen_abs_vec(unsigned vece, TCGv_vec r, TCGv_vec a)
 if (tcg_can_emit_vec_op(INDEX_op_sari_vec, type, vece) > 0) {
 tcg_gen_sari_vec(vece, t, a, (8 << vece) - 1);
 } else {
-do_dupi_vec(t, MO_REG, 0);
-tcg_gen_cmp_vec(TCG_COND_LT, vece, t, a, t);
+tcg_gen_cmp_vec(TCG_COND_LT, vece, t, a,
+tcg_constant_vec(type, vece, 0));
 }
 tcg_gen_xor_vec(vece, r, a, t);
 tcg_gen_sub_vec(vece, r, r, t);
-- 
2.20.1




[PATCH v4 07/19] tcg: Use tcg_constant_{i32, i64, vec} with tcg gvec expanders

2020-05-08 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/tcg-op-gvec.c | 125 +++---
 1 file changed, 50 insertions(+), 75 deletions(-)

diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
index 3707c0effb..8ecaf4d67e 100644
--- a/tcg/tcg-op-gvec.c
+++ b/tcg/tcg-op-gvec.c
@@ -96,7 +96,7 @@ void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs,
 gen_helper_gvec_2 *fn)
 {
 TCGv_ptr a0, a1;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -108,7 +108,6 @@ void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs,
 
 tcg_temp_free_ptr(a0);
 tcg_temp_free_ptr(a1);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with two vector operands
@@ -118,7 +117,7 @@ void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, 
TCGv_i64 c,
  gen_helper_gvec_2i *fn)
 {
 TCGv_ptr a0, a1;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -130,7 +129,6 @@ void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, 
TCGv_i64 c,
 
 tcg_temp_free_ptr(a0);
 tcg_temp_free_ptr(a1);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with three vector operands.  */
@@ -139,7 +137,7 @@ void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 gen_helper_gvec_3 *fn)
 {
 TCGv_ptr a0, a1, a2;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -154,7 +152,6 @@ void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 tcg_temp_free_ptr(a0);
 tcg_temp_free_ptr(a1);
 tcg_temp_free_ptr(a2);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with four vector operands.  */
@@ -163,7 +160,7 @@ void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 int32_t data, gen_helper_gvec_4 *fn)
 {
 TCGv_ptr a0, a1, a2, a3;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -181,7 +178,6 @@ void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 tcg_temp_free_ptr(a1);
 tcg_temp_free_ptr(a2);
 tcg_temp_free_ptr(a3);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with five vector operands.  */
@@ -190,7 +186,7 @@ void tcg_gen_gvec_5_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 uint32_t maxsz, int32_t data, gen_helper_gvec_5 *fn)
 {
 TCGv_ptr a0, a1, a2, a3, a4;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -211,7 +207,6 @@ void tcg_gen_gvec_5_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 tcg_temp_free_ptr(a2);
 tcg_temp_free_ptr(a3);
 tcg_temp_free_ptr(a4);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with three vector operands
@@ -221,7 +216,7 @@ void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs,
 int32_t data, gen_helper_gvec_2_ptr *fn)
 {
 TCGv_ptr a0, a1;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -233,7 +228,6 @@ void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs,
 
 tcg_temp_free_ptr(a0);
 tcg_temp_free_ptr(a1);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with three vector operands
@@ -243,7 +237,7 @@ void tcg_gen_gvec_3_ptr(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 int32_t data, gen_helper_gvec_3_ptr *fn)
 {
 TCGv_ptr a0, a1, a2;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -258,7 +252,6 @@ void tcg_gen_gvec_3_ptr(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 tcg_temp_free_ptr(a0);
 tcg_temp_free_ptr(a1);
 tcg_temp_free_ptr(a2);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with four vector operands
@@ -269,7 +262,7 @@ void tcg_gen_gvec_4_ptr(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 gen_helper_gvec_4_ptr *fn)
 {
 TCGv_ptr a0, a1, a2, a3;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));

[PATCH v4 03/19] tcg: Introduce TYPE_CONST temporaries

2020-05-08 Thread Richard Henderson
These will hold a single constant for the duration of the TB.
They are hashed, so that each value has one temp across the TB.

Not used yet, this is all infrastructure.

Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h |  27 +++-
 tcg/optimize.c|  13 +++-
 tcg/tcg-op-vec.c  |  17 +
 tcg/tcg.c | 170 ++
 4 files changed, 182 insertions(+), 45 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 0d09ea7822..57d6b0216c 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -492,6 +492,8 @@ typedef enum TCGTempKind {
 TEMP_GLOBAL,
 /* Temp is in a fixed register. */
 TEMP_FIXED,
+/* Temp is a fixed constant. */
+TEMP_CONST,
 } TCGTempKind;
 
 typedef struct TCGTemp {
@@ -667,6 +669,7 @@ struct TCGContext {
 QSIMPLEQ_HEAD(, TCGOp) plugin_ops;
 #endif
 
+GHashTable *const_table[TCG_TYPE_COUNT];
 TCGTempSet free_temps[TCG_TYPE_COUNT * 2];
 TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
 
@@ -683,7 +686,7 @@ struct TCGContext {
 
 static inline bool temp_readonly(TCGTemp *ts)
 {
-return ts->kind == TEMP_FIXED;
+return ts->kind >= TEMP_FIXED;
 }
 
 extern TCGContext tcg_init_ctx;
@@ -1041,6 +1044,7 @@ TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, 
TCGOpcode opc);
 
 void tcg_optimize(TCGContext *s);
 
+/* Allocate a new temporary and initialize it with a constant. */
 TCGv_i32 tcg_const_i32(int32_t val);
 TCGv_i64 tcg_const_i64(int64_t val);
 TCGv_i32 tcg_const_local_i32(int32_t val);
@@ -1050,6 +1054,27 @@ TCGv_vec tcg_const_ones_vec(TCGType);
 TCGv_vec tcg_const_zeros_vec_matching(TCGv_vec);
 TCGv_vec tcg_const_ones_vec_matching(TCGv_vec);
 
+/*
+ * Locate or create a read-only temporary that is a constant.
+ * This kind of temporary need not and should not be freed.
+ */
+TCGTemp *tcg_constant_internal(TCGType type, tcg_target_long val);
+
+static inline TCGv_i32 tcg_constant_i32(int32_t val)
+{
+return temp_tcgv_i32(tcg_constant_internal(TCG_TYPE_I32, val));
+}
+
+static inline TCGv_i64 tcg_constant_i64(int64_t val)
+{
+if (TCG_TARGET_REG_BITS == 32) {
+qemu_build_not_reached();
+}
+return temp_tcgv_i64(tcg_constant_internal(TCG_TYPE_I64, val));
+}
+
+TCGv_vec tcg_constant_vec(TCGType type, unsigned vece, int64_t val);
+
 #if UINTPTR_MAX == UINT32_MAX
 # define tcg_const_ptr(x)((TCGv_ptr)tcg_const_i32((intptr_t)(x)))
 # define tcg_const_local_ptr(x)  ((TCGv_ptr)tcg_const_local_i32((intptr_t)(x)))
diff --git a/tcg/optimize.c b/tcg/optimize.c
index afb4a9a5a9..8f3bd99ff4 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -99,8 +99,17 @@ static void init_ts_info(struct tcg_temp_info *infos,
 ts->state_ptr = ti;
 ti->next_copy = ts;
 ti->prev_copy = ts;
-ti->is_const = false;
-ti->mask = -1;
+if (ts->kind == TEMP_CONST) {
+ti->is_const = true;
+ti->val = ti->mask = ts->val;
+if (TCG_TARGET_REG_BITS > 32 && ts->type == TCG_TYPE_I32) {
+/* High bits of a 32-bit quantity are garbage.  */
+ti->mask |= ~0xull;
+}
+} else {
+ti->is_const = false;
+ti->mask = -1;
+}
 set_bit(idx, temps_used->l);
 }
 }
diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c
index f784517d84..43101defe4 100644
--- a/tcg/tcg-op-vec.c
+++ b/tcg/tcg-op-vec.c
@@ -209,6 +209,23 @@ static void vec_gen_op3(TCGOpcode opc, unsigned vece,
 vec_gen_3(opc, type, vece, temp_arg(rt), temp_arg(at), temp_arg(bt));
 }
 
+TCGv_vec tcg_constant_vec(TCGType type, unsigned vece, int64_t val)
+{
+val = dup_const(vece, val);
+
+/*
+ * For MO_64 constants that can't be represented in tcg_target_long,
+ * we must use INDEX_op_dup2_vec, which requires a non-const temporary.
+ */
+if (TCG_TARGET_REG_BITS == 32 &&
+val != deposit64(val, 32, 32, val) &&
+val != (uint64_t)(int32_t)val) {
+g_assert_not_reached();
+}
+
+return temp_tcgv_vec(tcg_constant_internal(type, val));
+}
+
 void tcg_gen_mov_vec(TCGv_vec r, TCGv_vec a)
 {
 if (r != a) {
diff --git a/tcg/tcg.c b/tcg/tcg.c
index a529166026..94f7898317 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1127,6 +1127,7 @@ void tcg_func_start(TCGContext *s)
 
 /* No temps have been previously allocated for size or locality.  */
 memset(s->free_temps, 0, sizeof(s->free_temps));
+memset(s->const_table, 0, sizeof(s->const_table));
 
 s->nb_ops = 0;
 s->nb_labels = 0;
@@ -1199,13 +1200,19 @@ TCGTemp *tcg_global_mem_new_internal(TCGType type, 
TCGv_ptr base,
 bigendian = 1;
 #endif
 
-if (base_ts->kind != TEMP_FIXED) {
+switch (base_ts->kind) {
+case TEMP_FIXED:
+break;
+case TEMP_GLOBAL:
 /* We do not support double-indirect registers.  */
 tcg_debug_assert(!base_ts->indirect_reg);
 base_ts->indirect_base = 1;
 

[PATCH v4 01/19] tcg: Consolidate 3 bits into enum TCGTempKind

2020-05-08 Thread Richard Henderson
The temp_fixed, temp_global, temp_local bits are all related.
Combine them into a single enumeration.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h |  20 +---
 tcg/optimize.c|   8 +--
 tcg/tcg.c | 122 --
 3 files changed, 90 insertions(+), 60 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 380014ed80..06486635e6 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -483,23 +483,27 @@ typedef enum TCGTempVal {
 TEMP_VAL_CONST,
 } TCGTempVal;
 
+typedef enum TCGTempKind {
+/* Temp is dead at the end of all basic blocks. */
+TEMP_NORMAL,
+/* Temp is saved across basic blocks but dead at the end of TBs. */
+TEMP_LOCAL,
+/* Temp is saved across both basic blocks and translation blocks. */
+TEMP_GLOBAL,
+/* Temp is in a fixed register. */
+TEMP_FIXED,
+} TCGTempKind;
+
 typedef struct TCGTemp {
 TCGReg reg:8;
 TCGTempVal val_type:8;
 TCGType base_type:8;
 TCGType type:8;
-unsigned int fixed_reg:1;
+TCGTempKind kind:3;
 unsigned int indirect_reg:1;
 unsigned int indirect_base:1;
 unsigned int mem_coherent:1;
 unsigned int mem_allocated:1;
-/* If true, the temp is saved across both basic blocks and
-   translation blocks.  */
-unsigned int temp_global:1;
-/* If true, the temp is saved across basic blocks but dead
-   at the end of translation blocks.  If false, the temp is
-   dead at the end of basic blocks.  */
-unsigned int temp_local:1;
 unsigned int temp_allocated:1;
 
 tcg_target_long val;
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 53aa8e5329..afb4a9a5a9 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -116,21 +116,21 @@ static TCGTemp *find_better_copy(TCGContext *s, TCGTemp 
*ts)
 TCGTemp *i;
 
 /* If this is already a global, we can't do better. */
-if (ts->temp_global) {
+if (ts->kind >= TEMP_GLOBAL) {
 return ts;
 }
 
 /* Search for a global first. */
 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (i->temp_global) {
+if (i->kind >= TEMP_GLOBAL) {
 return i;
 }
 }
 
 /* If it is a temp, search for a temp local. */
-if (!ts->temp_local) {
+if (ts->kind == TEMP_NORMAL) {
 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (ts->temp_local) {
+if (i->kind >= TEMP_LOCAL) {
 return i;
 }
 }
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 216a6963b3..2c022c9621 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1155,7 +1155,7 @@ static inline TCGTemp *tcg_global_alloc(TCGContext *s)
 tcg_debug_assert(s->nb_globals == s->nb_temps);
 s->nb_globals++;
 ts = tcg_temp_alloc(s);
-ts->temp_global = 1;
+ts->kind = TEMP_GLOBAL;
 
 return ts;
 }
@@ -1172,7 +1172,7 @@ static TCGTemp *tcg_global_reg_new_internal(TCGContext 
*s, TCGType type,
 ts = tcg_global_alloc(s);
 ts->base_type = type;
 ts->type = type;
-ts->fixed_reg = 1;
+ts->kind = TEMP_FIXED;
 ts->reg = reg;
 ts->name = name;
 tcg_regset_set_reg(s->reserved_regs, reg);
@@ -1199,7 +1199,7 @@ TCGTemp *tcg_global_mem_new_internal(TCGType type, 
TCGv_ptr base,
 bigendian = 1;
 #endif
 
-if (!base_ts->fixed_reg) {
+if (base_ts->kind != TEMP_FIXED) {
 /* We do not support double-indirect registers.  */
 tcg_debug_assert(!base_ts->indirect_reg);
 base_ts->indirect_base = 1;
@@ -1247,6 +1247,7 @@ TCGTemp *tcg_global_mem_new_internal(TCGType type, 
TCGv_ptr base,
 TCGTemp *tcg_temp_new_internal(TCGType type, bool temp_local)
 {
 TCGContext *s = tcg_ctx;
+TCGTempKind kind = temp_local ? TEMP_LOCAL : TEMP_NORMAL;
 TCGTemp *ts;
 int idx, k;
 
@@ -1259,7 +1260,7 @@ TCGTemp *tcg_temp_new_internal(TCGType type, bool 
temp_local)
 ts = >temps[idx];
 ts->temp_allocated = 1;
 tcg_debug_assert(ts->base_type == type);
-tcg_debug_assert(ts->temp_local == temp_local);
+tcg_debug_assert(ts->kind == kind);
 } else {
 ts = tcg_temp_alloc(s);
 if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
@@ -1268,18 +1269,18 @@ TCGTemp *tcg_temp_new_internal(TCGType type, bool 
temp_local)
 ts->base_type = type;
 ts->type = TCG_TYPE_I32;
 ts->temp_allocated = 1;
-ts->temp_local = temp_local;
+ts->kind = kind;
 
 tcg_debug_assert(ts2 == ts + 1);
 ts2->base_type = TCG_TYPE_I64;
 ts2->type = TCG_TYPE_I32;
 ts2->temp_allocated = 1;
-ts2->temp_local = temp_local;
+ts2->kind = kind;
 } else {
 ts->base_type = type;
 ts->type = type;
 ts->temp_allocated = 1;
-ts->temp_local = temp_local;
+ts->kind = kind;
 

[PATCH v4 14/19] tcg: Remove movi and dupi opcodes

2020-05-08 Thread Richard Henderson
These are now completely covered by mov from a
TYPE_CONST temporary.

Reviewed-by: Alex Bennée 
Reviewed-by: Aleksandar Markovic 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-opc.h|  3 ---
 tcg/aarch64/tcg-target.inc.c |  3 ---
 tcg/arm/tcg-target.inc.c |  1 -
 tcg/i386/tcg-target.inc.c|  3 ---
 tcg/mips/tcg-target.inc.c|  2 --
 tcg/optimize.c   |  4 
 tcg/ppc/tcg-target.inc.c |  3 ---
 tcg/riscv/tcg-target.inc.c   |  2 --
 tcg/s390/tcg-target.inc.c|  2 --
 tcg/sparc/tcg-target.inc.c   |  2 --
 tcg/tcg-op-vec.c |  1 -
 tcg/tcg.c| 18 +-
 tcg/tci/tcg-target.inc.c |  2 --
 13 files changed, 1 insertion(+), 45 deletions(-)

diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
index 5a941eaa07..d63c6bcb3d 100644
--- a/include/tcg/tcg-opc.h
+++ b/include/tcg/tcg-opc.h
@@ -45,7 +45,6 @@ DEF(br, 0, 0, 1, TCG_OPF_BB_END)
 DEF(mb, 0, 0, 1, 0)
 
 DEF(mov_i32, 1, 1, 0, TCG_OPF_NOT_PRESENT)
-DEF(movi_i32, 1, 0, 1, TCG_OPF_NOT_PRESENT)
 DEF(setcond_i32, 1, 2, 1, 0)
 DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32))
 /* load/store */
@@ -110,7 +109,6 @@ DEF(ctz_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_ctz_i32))
 DEF(ctpop_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ctpop_i32))
 
 DEF(mov_i64, 1, 1, 0, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
-DEF(movi_i64, 1, 0, 1, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
 DEF(setcond_i64, 1, 2, 1, IMPL64)
 DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64))
 /* load/store */
@@ -215,7 +213,6 @@ DEF(qemu_st_i64, 0, TLADDR_ARGS + DATA64_ARGS, 1,
 #define IMPLVEC  TCG_OPF_VECTOR | IMPL(TCG_TARGET_MAYBE_vec)
 
 DEF(mov_vec, 1, 1, 0, TCG_OPF_VECTOR | TCG_OPF_NOT_PRESENT)
-DEF(dupi_vec, 1, 0, 1, TCG_OPF_VECTOR | TCG_OPF_NOT_PRESENT)
 
 DEF(dup_vec, 1, 1, 0, IMPLVEC)
 DEF(dup2_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_REG_BITS == 32))
diff --git a/tcg/aarch64/tcg-target.inc.c b/tcg/aarch64/tcg-target.inc.c
index 760b0e742d..d065fd600b 100644
--- a/tcg/aarch64/tcg-target.inc.c
+++ b/tcg/aarch64/tcg-target.inc.c
@@ -2262,8 +2262,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
-case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi.  */
-case INDEX_op_movi_i64:
 case INDEX_op_call: /* Always emitted via tcg_out_call.  */
 default:
 g_assert_not_reached();
@@ -2471,7 +2469,6 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 break;
 
 case INDEX_op_mov_vec:  /* Always emitted via tcg_out_mov.  */
-case INDEX_op_dupi_vec: /* Always emitted via tcg_out_movi.  */
 case INDEX_op_dup_vec:  /* Always emitted via tcg_out_dup_vec.  */
 default:
 g_assert_not_reached();
diff --git a/tcg/arm/tcg-target.inc.c b/tcg/arm/tcg-target.inc.c
index 6aa7757aac..b967499fa4 100644
--- a/tcg/arm/tcg-target.inc.c
+++ b/tcg/arm/tcg-target.inc.c
@@ -2068,7 +2068,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
 break;
 
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
-case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi.  */
 case INDEX_op_call: /* Always emitted via tcg_out_call.  */
 default:
 tcg_abort();
diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.inc.c
index ae0228238b..bc957e7bed 100644
--- a/tcg/i386/tcg-target.inc.c
+++ b/tcg/i386/tcg-target.inc.c
@@ -2678,8 +2678,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
 break;
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
-case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi.  */
-case INDEX_op_movi_i64:
 case INDEX_op_call: /* Always emitted via tcg_out_call.  */
 default:
 tcg_abort();
@@ -2965,7 +2963,6 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 break;
 
 case INDEX_op_mov_vec:  /* Always emitted via tcg_out_mov.  */
-case INDEX_op_dupi_vec: /* Always emitted via tcg_out_movi.  */
 case INDEX_op_dup_vec:  /* Always emitted via tcg_out_dup_vec.  */
 default:
 g_assert_not_reached();
diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index 4d32ebc1df..09dc5a94fa 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -2155,8 +2155,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
 break;
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
-case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi.  */
-case INDEX_op_movi_i64:
 case INDEX_op_call: /* Always emitted via tcg_out_call.  */
 default:
 tcg_abort();
diff --git a/tcg/optimize.c b/tcg/optimize.c
index dd5187be31..9a2c945dbe 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -1099,10 +1099,6 @@ void tcg_optimize(TCGContext *s)
 

[PATCH v4 04/19] tcg: Use tcg_constant_i32 with icount expander

2020-05-08 Thread Richard Henderson
We must do this before we adjust how tcg_out_movi_i32,
lest the under-the-hood poking that we do be broken.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 include/exec/gen-icount.h | 25 +
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
index 822c43cfd3..404732518a 100644
--- a/include/exec/gen-icount.h
+++ b/include/exec/gen-icount.h
@@ -34,7 +34,7 @@ static inline void gen_io_end(void)
 
 static inline void gen_tb_start(TranslationBlock *tb)
 {
-TCGv_i32 count, imm;
+TCGv_i32 count;
 
 tcg_ctx->exitreq_label = gen_new_label();
 if (tb_cflags(tb) & CF_USE_ICOUNT) {
@@ -48,15 +48,13 @@ static inline void gen_tb_start(TranslationBlock *tb)
offsetof(ArchCPU, env));
 
 if (tb_cflags(tb) & CF_USE_ICOUNT) {
-imm = tcg_temp_new_i32();
-/* We emit a movi with a dummy immediate argument. Keep the insn index
- * of the movi so that we later (when we know the actual insn count)
- * can update the immediate argument with the actual insn count.  */
-tcg_gen_movi_i32(imm, 0xdeadbeef);
+/*
+ * We emit a sub with a dummy immediate argument. Keep the insn index
+ * of the sub so that we later (when we know the actual insn count)
+ * can update the argument with the actual insn count.
+ */
+tcg_gen_sub_i32(count, count, tcg_constant_i32(0));
 icount_start_insn = tcg_last_op();
-
-tcg_gen_sub_i32(count, count, imm);
-tcg_temp_free_i32(imm);
 }
 
 tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label);
@@ -74,9 +72,12 @@ static inline void gen_tb_start(TranslationBlock *tb)
 static inline void gen_tb_end(TranslationBlock *tb, int num_insns)
 {
 if (tb_cflags(tb) & CF_USE_ICOUNT) {
-/* Update the num_insn immediate parameter now that we know
- * the actual insn count.  */
-tcg_set_insn_param(icount_start_insn, 1, num_insns);
+/*
+ * Update the num_insn immediate parameter now that we know
+ * the actual insn count.
+ */
+tcg_set_insn_param(icount_start_insn, 2,
+   tcgv_i32_arg(tcg_constant_i32(num_insns)));
 }
 
 gen_set_label(tcg_ctx->exitreq_label);
-- 
2.20.1




[PATCH v4 00/19] tcg: Better handling of constants

2020-05-08 Thread Richard Henderson
V4 adds the r-b against v2 that I forgot to go back and add.

Re patch 17, Alex asked if I could ifdef tcg_reg_alloc_dup2
instead of assert within it.  Answer: No, not without adding
still more ifdefs to compensate.  In the end I prefer the assert.

V3 fixes the target/sparc regression during register allocation.

V1 blurb:

This promotes constants to full-fledged temporaries, which are then
hashed so we have only a single copy across the TB.  If an opcode
requires forcing one into a register, then we will only do this
once -- at least until the register is killed, e.g. by a function call.

While this is probably an modest improvement for integer code, it is
significant for SVE vector code.  In particular, where a generator function
loads a constant for the operation, and then the generator function is
called N times for the N x 128-bit vector.  Previously we'd be loading
up the same constant N times and now we do so only once.

The existing tcg_const_{type}() functions are unchanged, allocating
a new temporary and initializing it.  The constant propagation pass
of the optimizer will generally remove the temporary when it turns
out not to be modified further.

This adds new tcg_constant_{type}() functions which produce a read-only
temporary containing the constant which need not be freed.  I have
updated the generic expanders to take advantage of this, but have not
touched the target front ends.

This also, in the end, allows the complete removal of the tcg opcodes
that create a constant: INDEX_op_movi_{i32,i64} and INDEX_op_dupi_vec.
Loading of constants into hard registers is completely controlled by
the register allocator.


r~


Richard Henderson (19):
  tcg: Consolidate 3 bits into enum TCGTempKind
  tcg: Add temp_readonly
  tcg: Introduce TYPE_CONST temporaries
  tcg: Use tcg_constant_i32 with icount expander
  tcg: Use tcg_constant_{i32,i64} with tcg int expanders
  tcg: Use tcg_constant_{i32,vec} with tcg vec expanders
  tcg: Use tcg_constant_{i32,i64,vec} with tcg gvec expanders
  tcg: Use tcg_constant_{i32,i64} with tcg plugins
  tcg: Rename struct tcg_temp_info to TempOptInfo
  tcg/optimize: Improve find_better_copy
  tcg/optimize: Adjust TempOptInfo allocation
  tcg/optimize: Use tcg_constant_internal with constant folding
  tcg/tci: Add special tci_movi_{i32,i64} opcodes
  tcg: Remove movi and dupi opcodes
  tcg: Use tcg_out_dupi_vec from temp_load
  tcg: Increase tcg_out_dupi_vec immediate to int64_t
  tcg: Add tcg_reg_alloc_dup2
  tcg/i386: Use tcg_constant_vec with tcg vec expanders
  tcg: Remove tcg_gen_dup{8,16,32,64}i_vec

 include/exec/gen-icount.h|  25 +--
 include/tcg/tcg-op.h |  17 +-
 include/tcg/tcg-opc.h|  11 +-
 include/tcg/tcg.h|  50 -
 accel/tcg/plugin-gen.c   |  49 ++---
 tcg/aarch64/tcg-target.inc.c |  12 +-
 tcg/arm/tcg-target.inc.c |   1 -
 tcg/i386/tcg-target.inc.c| 110 ++
 tcg/mips/tcg-target.inc.c|   2 -
 tcg/optimize.c   | 204 +-
 tcg/ppc/tcg-target.inc.c |  24 +--
 tcg/riscv/tcg-target.inc.c   |   2 -
 tcg/s390/tcg-target.inc.c|   2 -
 tcg/sparc/tcg-target.inc.c   |   2 -
 tcg/tcg-op-gvec.c| 125 +--
 tcg/tcg-op-vec.c |  83 
 tcg/tcg-op.c | 216 +--
 tcg/tcg.c| 397 ++-
 tcg/tci.c|   4 +-
 tcg/tci/tcg-target.inc.c |   6 +-
 20 files changed, 751 insertions(+), 591 deletions(-)

-- 
2.20.1




[PATCH v4 02/19] tcg: Add temp_readonly

2020-05-08 Thread Richard Henderson
In most, but not all, places that we check for TEMP_FIXED,
we are really testing that we do not modify the temporary.

Reviewed-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h |  5 +
 tcg/tcg.c | 21 ++---
 2 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 06486635e6..0d09ea7822 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -681,6 +681,11 @@ struct TCGContext {
 target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS];
 };
 
+static inline bool temp_readonly(TCGTemp *ts)
+{
+return ts->kind == TEMP_FIXED;
+}
+
 extern TCGContext tcg_init_ctx;
 extern __thread TCGContext *tcg_ctx;
 extern TCGv_env cpu_env;
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 2c022c9621..a529166026 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -3173,7 +3173,7 @@ static void temp_load(TCGContext *, TCGTemp *, TCGRegSet, 
TCGRegSet, TCGRegSet);
mark it free; otherwise mark it dead.  */
 static void temp_free_or_dead(TCGContext *s, TCGTemp *ts, int free_or_dead)
 {
-if (ts->kind == TEMP_FIXED) {
+if (temp_readonly(ts)) {
 return;
 }
 if (ts->val_type == TEMP_VAL_REG) {
@@ -3197,7 +3197,7 @@ static inline void temp_dead(TCGContext *s, TCGTemp *ts)
 static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs,
   TCGRegSet preferred_regs, int free_or_dead)
 {
-if (ts->kind == TEMP_FIXED) {
+if (temp_readonly(ts)) {
 return;
 }
 if (!ts->mem_coherent) {
@@ -3355,8 +3355,7 @@ static void temp_save(TCGContext *s, TCGTemp *ts, 
TCGRegSet allocated_regs)
 {
 /* The liveness analysis already ensures that globals are back
in memory. Keep an tcg_debug_assert for safety. */
-tcg_debug_assert(ts->val_type == TEMP_VAL_MEM
- || ts->kind == TEMP_FIXED);
+tcg_debug_assert(ts->val_type == TEMP_VAL_MEM || temp_readonly(ts));
 }
 
 /* save globals to their canonical location and assume they can be
@@ -3414,7 +3413,7 @@ static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp 
*ots,
   TCGRegSet preferred_regs)
 {
 /* ENV should not be modified.  */
-tcg_debug_assert(ots->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ots));
 
 /* The movi is not explicitly generated here.  */
 if (ots->val_type == TEMP_VAL_REG) {
@@ -3454,7 +3453,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp 
*op)
 ts = arg_temp(op->args[1]);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ots->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ots));
 
 /* Note that otype != itype for no-op truncation.  */
 otype = ots->type;
@@ -3515,7 +3514,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp 
*op)
  * Store the source register into the destination slot
  * and leave the destination temp as TEMP_VAL_MEM.
  */
-assert(ots->kind != TEMP_FIXED);
+assert(!temp_readonly(ots));
 if (!ts->mem_allocated) {
 temp_allocate_frame(s, ots);
 }
@@ -3552,7 +3551,7 @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp 
*op)
 its = arg_temp(op->args[1]);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ots->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ots));
 
 itype = its->type;
 vece = TCGOP_VECE(op);
@@ -3783,7 +3782,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 ts = arg_temp(arg);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ts->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ts));
 
 if ((arg_ct->ct & TCG_CT_ALIAS)
 && !const_args[arg_ct->alias_index]) {
@@ -3825,7 +3824,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 ts = arg_temp(op->args[i]);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ts->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ts));
 
 if (NEED_SYNC_ARG(i)) {
 temp_sync(s, ts, o_allocated_regs, 0, IS_DEAD_ARG(i));
@@ -3957,7 +3956,7 @@ static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op)
 ts = arg_temp(arg);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ts->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ts));
 
 reg = tcg_target_call_oarg_regs[i];
 tcg_debug_assert(s->reg_to_temp[reg] == NULL);
-- 
2.20.1




[PATCH] spapr: Add a new level of NUMA for GPUs

2020-05-08 Thread Reza Arbab
NUMA nodes corresponding to GPU memory currently have the same
affinity/distance as normal memory nodes. Add a third NUMA associativity
reference point enabling us to give GPU nodes more distance.

Before, `numactl -H` output in a guest with 4 GPUs (nodes 2-5):

node distances:
node   0   1   2   3   4   5
  0:  10  40  40  40  40  40
  1:  40  10  40  40  40  40
  2:  40  40  10  40  40  40
  3:  40  40  40  10  40  40
  4:  40  40  40  40  10  40
  5:  40  40  40  40  40  10

After:

node distances:
node   0   1   2   3   4   5
  0:  10  40  80  80  80  80
  1:  40  10  80  80  80  80
  2:  80  80  10  80  80  80
  3:  80  80  80  10  80  80
  4:  80  80  80  80  10  80
  5:  80  80  80  80  80  10

These are the same distances as on the host, mirroring the change made
to host firmware in skiboot commit f845a648b8cb ("numa/associativity:
Add a new level of NUMA for GPU's").

Signed-off-by: Reza Arbab 
---
 hw/ppc/spapr.c | 6 +-
 hw/ppc/spapr_pci_nvlink2.c | 8 +++-
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index c18eab0a2305..53567f98f0c6 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -892,7 +892,11 @@ static void spapr_dt_rtas(SpaprMachineState *spapr, void 
*fdt)
 int rtas;
 GString *hypertas = g_string_sized_new(256);
 GString *qemu_hypertas = g_string_sized_new(256);
-uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) };
+uint32_t refpoints[] = {
+cpu_to_be32(0x4),
+cpu_to_be32(0x4),
+cpu_to_be32(0x2),
+};
 uint64_t max_device_addr = MACHINE(spapr)->device_memory->base +
 memory_region_size((spapr)->device_memory->mr);
 uint32_t lrdr_capacity[] = {
diff --git a/hw/ppc/spapr_pci_nvlink2.c b/hw/ppc/spapr_pci_nvlink2.c
index 8332d5694e46..f2cb26019e88 100644
--- a/hw/ppc/spapr_pci_nvlink2.c
+++ b/hw/ppc/spapr_pci_nvlink2.c
@@ -37,8 +37,6 @@
 #define PHANDLE_NVLINK(phb, gn, nn)  (0x0013 | (((phb)->index) << 8) | \
  ((gn) << 4) | (nn))
 
-#define SPAPR_GPU_NUMA_ID   (cpu_to_be32(1))
-
 typedef struct SpaprPhbPciNvGpuSlot {
 uint64_t tgt;
 uint64_t gpa;
@@ -361,9 +359,9 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, 
void *fdt)
 "nvlink2-mr[0]", NULL);
 uint32_t associativity[] = {
 cpu_to_be32(0x4),
-SPAPR_GPU_NUMA_ID,
-SPAPR_GPU_NUMA_ID,
-SPAPR_GPU_NUMA_ID,
+cpu_to_be32(nvslot->numa_id),
+cpu_to_be32(nvslot->numa_id),
+cpu_to_be32(nvslot->numa_id),
 cpu_to_be32(nvslot->numa_id)
 };
 uint64_t size = object_property_get_uint(nv_mrobj, "size", NULL);
-- 
2.18.1




Re: [PATCH v3 05/17] block/io: support int64_t bytes in bdrv_co_do_pwrite_zeroes()

2020-05-08 Thread Eric Blake

On 4/30/20 6:10 AM, Vladimir Sementsov-Ogievskiy wrote:

We are generally moving to int64_t for both offset and bytes parameters
on all io paths.

Main motivation is realization of 64-bit write_zeroes operation for
fast zeroing large disk chunks, up to the whole disk.

We chose signed type, to be consistent with off_t (which is signed) and
with possibility for signed return type (where negative value means
error).

So, prepare bdrv_co_do_pwrite_zeroes() now.

Patch-correctness audit by Eric Blake:





 use of 'num' within the loop
 compute 'int head' via % 'int alignment' - safe
 clamp size by 'int max_write_zeroes' - safe
 drv->bdrv_co_pwrite_zeroes(int) - safe because of clamping
 clamp size by 'int max_transfer' - safe
 qemu_iovec_init_buf(size_t) - safe because of clamping
 bdrv_driver_pwritev(uint64_t) [well, int64_t after 4/17] - safe


I know you were quoting me, but the [comment] can be dropped (I wrote my 
audit on patches in isolation while reviewing the pre-series state of 
the tree, but when this commit is finally applied, the previous patch 
will already be in place)




 So even with the wider type, we aren't exceeding the contract of
 anything we pass it on to.  Later patches may improve
 drv->bdrv_co_pwrite_zeroes and qemu_iovec_init_buf to be 64-bit
 clean, at which point we would want to revisit this function to use
 64-bit clamping rather than 32-bit clamping, but it does not have
 to happen here.

Series: 64bit-block-status
Signed-off-by: Vladimir Sementsov-Ogievskiy 
Reviewed-by: Eric Blake 
---
  block/io.c | 6 +++---
  1 file changed, 3 insertions(+), 3 deletions(-)



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




Re: [PATCH v23 QEMU 0/5] virtio-balloon: add support for page poison reporting and free page reporting

2020-05-08 Thread David Hildenbrand



> Am 08.05.2020 um 19:31 schrieb Alexander Duyck :
> 
> I just wanted to follow up since it has been a little over a week
> since I submitted this and I haven't heard anything back. It looks
> like the linux-headers patches can be dropped since the headers appear
> to have been synced. I was wondering if I should resubmit with just
> the 3 patches that are adding the functionality, or if this patch-set
> is good as-is?

Should be good as-is. However, if the new compat machines are already upstream, 
you might want to tackle that right away.

Cheers and have a nice weekend!

> 
> Thanks.
> 
> - Alex
> 
>> On Mon, Apr 27, 2020 at 5:53 PM Alexander Duyck
>>  wrote:
>> 
>> This series provides an asynchronous means of reporting free guest pages
>> to QEMU through virtio-balloon so that the memory associated with those
>> pages can be dropped and reused by other processes and/or guests on the
>> host. Using this it is possible to avoid unnecessary I/O to disk and
>> greatly improve performance in the case of memory overcommit on the host.
>> 
>> I originally submitted this patch series back on February 11th 2020[1],
>> but at that time I was focused primarily on the kernel portion of this
>> patch set. However as of April 7th those patches are now included in
>> Linus's kernel tree[2] and so I am submitting the QEMU pieces for
>> inclusion.
>> 
>> [1]: 
>> https://lore.kernel.org/lkml/20200211224416.29318.44077.stgit@localhost.localdomain/
>> [2]: 
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b0c504f154718904ae49349147e3b7e6ae91ffdc
>> 
>> Changes from v17:
>> Fixed typo in patch 1 title
>> Addressed white-space issues reported via checkpatch
>> Added braces {} for two if statements to match expected coding style
>> 
>> Changes from v18:
>> Updated patches 2 and 3 based on input from dhildenb
>> Added comment to patch 2 describing what keeps us from reporting a bad page
>> Added patch to address issue with ROM devices being directly writable
>> 
>> Changes from v19:
>> Added std-headers change to match changes pushed for linux kernel headers
>> Added patch to remove "report" from page hinting code paths
>> Updated comment to better explain why we disable hints w/ page poisoning
>> Removed code that was modifying config size for poison vs hinting
>> Dropped x-page-poison property
>> Added code to bounds check the reported region vs the RAM block
>> Dropped patch for ROM devices as that was already pulled in by Paolo
>> 
>> Changes from v20:
>> Rearranged patches to push Linux header sync patches to front
>> Removed association between free page hinting and 
>> VIRTIO_BALLOON_F_PAGE_POISON
>> Added code to enable VIRTIO_BALLOON_F_PAGE_POISON if page reporting is 
>> enabled
>> Fixed possible resource leak if poison or qemu_balloon_is_inhibited return 
>> true
>> 
>> Changes from v21:
>> Added ack for patch 3
>> Rewrote patch description for page poison reporting feature
>> Made page-poison independent property and set to enabled by default
>> Added logic to migrate poison_val
>> Added several comments in code to better explain features
>> Switched free-page-reporting property to disabled by default
>> 
>> Changes from v22:
>> Added ack for patches 4 & 5
>> Added additional comment fixes in patch 3 to remove "reporting" reference
>> Renamed rvq in patch 5 to reporting_vq to improve readability
>> Moved call adding reporting_vq to after free_page_vq to fix VQ ordering
>> 
>> ---
>> 
>> Alexander Duyck (5):
>>  linux-headers: Update to allow renaming of free_page_report_cmd_id
>>  linux-headers: update to contain virito-balloon free page reporting
>>  virtio-balloon: Replace free page hinting references to 'report' with 
>> 'hint'
>>  virtio-balloon: Implement support for page poison reporting feature
>>  virtio-balloon: Provide an interface for free page reporting
>> 
>> 
>> hw/virtio/virtio-balloon.c  |  176 
>> ++-
>> include/hw/virtio/virtio-balloon.h  |   23 ++-
>> include/standard-headers/linux/virtio_balloon.h |   12 +-
>> 3 files changed, 159 insertions(+), 52 deletions(-)
>> 
>> --
> 




[PATCH v3 5/9] blockdev: Split off basic bitmap operations for qemu-img

2020-05-08 Thread Eric Blake
Upcoming patches want to add some basic bitmap manipulation abilities
to qemu-img.  But blockdev.o is too heavyweight to link into qemu-img
(among other things, it would drag in block jobs and transaction
support - qemu-img does offline manipulation, where atomicity is less
important because there are no concurrent modifications to compete
with), so it's time to split off the bare bones of what we will need
into a new file block/monitor/bitmap-qmp-cmds.o.

This is sufficient to expose 6 QMP commands for use by qemu-img (add,
remove, clear, enable, disable, merge), as well as move the three
helper functions touched in the previous patch.  Regarding
MAINTAINERS, the new file is automatically part of block core, but
also makes sense as related to other dirty bitmap files.

Signed-off-by: Eric Blake 
---
 Makefile.objs   |   3 +-
 block/monitor/bitmap-qmp-cmds.c | 323 
 blockdev.c  | 284 
 MAINTAINERS |   1 +
 block/monitor/Makefile.objs |   1 +
 5 files changed, 326 insertions(+), 286 deletions(-)
 create mode 100644 block/monitor/bitmap-qmp-cmds.c

diff --git a/Makefile.objs b/Makefile.objs
index a7c967633acf..99774cfd2545 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -13,9 +13,8 @@ chardev-obj-y = chardev/

 authz-obj-y = authz/

-block-obj-y = nbd/
+block-obj-y = block/ block/monitor/ nbd/ scsi/
 block-obj-y += block.o blockjob.o job.o
-block-obj-y += block/ scsi/
 block-obj-y += qemu-io-cmds.o
 block-obj-$(CONFIG_REPLICATION) += replication.o

diff --git a/block/monitor/bitmap-qmp-cmds.c b/block/monitor/bitmap-qmp-cmds.c
new file mode 100644
index ..748e1e682483
--- /dev/null
+++ b/block/monitor/bitmap-qmp-cmds.c
@@ -0,0 +1,323 @@
+/*
+ * QEMU host block device bitmaps
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * 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 "sysemu/blockdev.h"
+#include "block/block.h"
+#include "block/block_int.h"
+#include "qapi/qapi-commands-block.h"
+#include "qapi/error.h"
+
+/**
+ * block_dirty_bitmap_lookup:
+ * Return a dirty bitmap (if present), after validating
+ * the node reference and bitmap names.
+ *
+ * @node: The name of the BDS node to search for bitmaps
+ * @name: The name of the bitmap to search for
+ * @pbs: Output pointer for BDS lookup, if desired. Can be NULL.
+ * @errp: Output pointer for error information. Can be NULL.
+ *
+ * @return: A bitmap object on success, or NULL on failure.
+ */
+BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
+   const char *name,
+   BlockDriverState **pbs,
+   Error **errp)
+{
+BlockDriverState *bs;
+BdrvDirtyBitmap *bitmap;
+
+if (!node) {
+error_setg(errp, "Node cannot be NULL");
+return NULL;
+}
+if (!name) {
+error_setg(errp, "Bitmap name cannot be NULL");
+return NULL;
+}
+bs = bdrv_lookup_bs(node, node, NULL);
+if (!bs) {
+error_setg(errp, "Node '%s' not found", node);
+return NULL;
+}
+
+bitmap = bdrv_find_dirty_bitmap(bs, name);
+if (!bitmap) {
+error_setg(errp, "Dirty bitmap '%s' not found", name);
+return NULL;
+}
+
+if (pbs) {
+*pbs = bs;
+}
+
+return bitmap;
+}
+
+void qmp_block_dirty_bitmap_add(const char *node, const char *name,
+bool has_granularity, uint32_t granularity,
+bool has_persistent, bool persistent,

[PATCH v3 9/9] iotests: Add test 291 to for qemu-img bitmap coverage

2020-05-08 Thread Eric Blake
Add a new test covering the 'qemu-img bitmap' subcommand, as well as
'qemu-img convert --bitmaps', both added in recent patches.

Signed-off-by: Eric Blake 
---
 tests/qemu-iotests/291 | 112 +
 tests/qemu-iotests/291.out |  78 ++
 tests/qemu-iotests/group   |   1 +
 3 files changed, 191 insertions(+)
 create mode 100755 tests/qemu-iotests/291
 create mode 100644 tests/qemu-iotests/291.out

diff --git a/tests/qemu-iotests/291 b/tests/qemu-iotests/291
new file mode 100755
index ..3ca83b9cd1f7
--- /dev/null
+++ b/tests/qemu-iotests/291
@@ -0,0 +1,112 @@
+#!/usr/bin/env bash
+#
+# Test qemu-img bitmap handling
+#
+# Copyright (C) 2018-2020 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see .
+#
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+status=1 # failure is the default!
+
+_cleanup()
+{
+_cleanup_test_img
+nbd_server_stop
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.nbd
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+_require_command QEMU_NBD
+
+echo
+echo "=== Initial image setup ==="
+echo
+
+# Create backing image with one bitmap
+TEST_IMG="$TEST_IMG.base" _make_test_img 10M
+$QEMU_IMG bitmap --add -f $IMGFMT "$TEST_IMG.base" b0
+$QEMU_IO -c 'w 3M 1M' -f $IMGFMT "$TEST_IMG.base" | _filter_qemu_io
+
+# Create initial image and populate two bitmaps: one active, one inactive.
+ORIG_IMG=$TEST_IMG
+TEST_IMG=$TEST_IMG.orig
+_make_test_img -b "$ORIG_IMG.base" -F $IMGFMT 10M
+$QEMU_IO -c 'w 0 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG bitmap --add -g 512k -f $IMGFMT "$TEST_IMG" b1
+$QEMU_IMG bitmap --add --disable -f $IMGFMT "$TEST_IMG" b2
+$QEMU_IO -c 'w 3M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG bitmap --clear -f $IMGFMT "$TEST_IMG" b1
+$QEMU_IO -c 'w 1M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG bitmap --disable -f $IMGFMT "$TEST_IMG" b1
+$QEMU_IMG bitmap --enable -f $IMGFMT "$TEST_IMG" b2
+$QEMU_IO -c 'w 2M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "=== Bitmap preservation not possible to non-qcow2 ==="
+echo
+
+TEST_IMG=$ORIG_IMG
+$QEMU_IMG convert --bitmaps -O raw "$TEST_IMG.orig" "$TEST_IMG" &&
+echo "unexpected success"
+
+echo
+echo "=== Convert with bitmap preservation ==="
+echo
+
+# Only bitmaps from the active layer are copied
+$QEMU_IMG convert --bitmaps -O qcow2 "$TEST_IMG.orig" "$TEST_IMG"
+$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific
+# But we can also merge in bitmaps from other layers.  This test is a bit
+# contrived to cover more code paths, in reality, you could merge directly
+# into b0 without going through tmp
+$QEMU_IMG bitmap --add --disable -f $IMGFMT "$TEST_IMG" b0
+$QEMU_IMG bitmap --add --merge b0 -b "$TEST_IMG.base" -F $IMGFMT \
+ -f $IMGFMT "$TEST_IMG" tmp
+$QEMU_IMG bitmap --merge tmp -f $IMGFMT "$TEST_IMG" b0
+$QEMU_IMG bitmap --remove --image-opts \
+driver=$IMGFMT,file.driver=file,file.filename="$TEST_IMG" tmp
+$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific
+
+echo
+echo "=== Check bitmap contents ==="
+echo
+
+# x-dirty-bitmap is a hack for reading bitmaps; it abuses block status to
+# report "data":false for portions of the bitmap which are set
+IMG="driver=nbd,server.type=unix,server.path=$nbd_unix_socket"
+nbd_server_start_unix_socket -r -f qcow2 -B b0 "$TEST_IMG"
+$QEMU_IMG map --output=json --image-opts \
+"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b0" | _filter_qemu_img_map
+nbd_server_start_unix_socket -r -f qcow2 -B b1 "$TEST_IMG"
+$QEMU_IMG map --output=json --image-opts \
+"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b1" | _filter_qemu_img_map
+nbd_server_start_unix_socket -r -f qcow2 -B b2 "$TEST_IMG"
+$QEMU_IMG map --output=json --image-opts \
+"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map
+
+# success, all done
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/291.out b/tests/qemu-iotests/291.out
new file mode 100644
index ..14e5cfc96589
--- /dev/null
+++ b/tests/qemu-iotests/291.out
@@ -0,0 +1,78 @@
+QA output created by 291
+
+=== Initial image setup ===
+
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=10485760
+wrote 1048576/1048576 bytes at offset 3145728
+1 MiB, X ops; 

[PATCH v3 7/9] qcow2: Expose bitmaps' size during measure

2020-05-08 Thread Eric Blake
It's useful to know how much space can be occupied by qcow2 persistent
bitmaps, even though such metadata is unrelated to the guest-visible
data.  Report this value as an additional field, present when
measuring an existing image and the output format supports bitmaps.
Update iotest 178 and 190 to updated output, as well as new coverage
in 190 demonstrating non-zero values made possible with the
recently-added qemu-img bitmap command.

The addition of a new field demonstrates why we should always
zero-initialize qapi C structs; while the qcow2 driver still fully
populates all fields, the raw and crypto drivers had to be tweaked to
avoid uninitialized data.

See also: https://bugzilla.redhat.com/1779904

Reported-by: Nir Soffer 
Signed-off-by: Eric Blake 
---
 qapi/block-core.json | 15 +++
 block/crypto.c   |  2 +-
 block/qcow2.c| 37 ---
 block/raw-format.c   |  2 +-
 qemu-img.c   |  3 +++
 tests/qemu-iotests/178.out.qcow2 | 16 
 tests/qemu-iotests/190   | 43 ++--
 tests/qemu-iotests/190.out   | 23 -
 8 files changed, 128 insertions(+), 13 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 943df1926a91..9a7a388c7ad3 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -633,18 +633,23 @@
 # efficiently so file size may be smaller than virtual disk size.
 #
 # The values are upper bounds that are guaranteed to fit the new image file.
-# Subsequent modification, such as internal snapshot or bitmap creation, may
-# require additional space and is not covered here.
+# Subsequent modification, such as internal snapshot or further bitmap
+# creation, may require additional space and is not covered here.
 #
-# @required: Size required for a new image file, in bytes.
+# @required: Size required for a new image file, in bytes, when copying just
+#guest-visible contents.
 #
 # @fully-allocated: Image file size, in bytes, once data has been written
-#   to all sectors.
+#   to all sectors, when copying just guest-visible contents.
+#
+# @bitmaps: Additional size required for bitmap metadata in a source image,
+#   if that bitmap metadata can be copied in addition to guest
+#   contents. (since 5.1)
 #
 # Since: 2.10
 ##
 { 'struct': 'BlockMeasureInfo',
-  'data': {'required': 'int', 'fully-allocated': 'int'} }
+  'data': {'required': 'int', 'fully-allocated': 'int', '*bitmaps': 'int'} }

 ##
 # @query-block:
diff --git a/block/crypto.c b/block/crypto.c
index 6b21d6bf6c01..eadbcb248563 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -552,7 +552,7 @@ static BlockMeasureInfo *block_crypto_measure(QemuOpts 
*opts,
  * Unallocated blocks are still encrypted so allocation status makes no
  * difference to the file size.
  */
-info = g_new(BlockMeasureInfo, 1);
+info = g_new0(BlockMeasureInfo, 1);
 info->fully_allocated = luks_payload_size + size;
 info->required = luks_payload_size + size;
 return info;
diff --git a/block/qcow2.c b/block/qcow2.c
index 838d810ca5ec..f836a6047879 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -4721,6 +4721,7 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, 
BlockDriverState *in_bs,
 PreallocMode prealloc;
 bool has_backing_file;
 bool has_luks;
+uint64_t bitmaps_size = 0; /* size occupied by bitmaps in in_bs */

 /* Parse image creation options */
 cluster_size = qcow2_opt_get_cluster_size_del(opts, _err);
@@ -4796,13 +4797,38 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, 
BlockDriverState *in_bs,

 /* Account for input image */
 if (in_bs) {
+BdrvDirtyBitmap *bm;
+size_t bitmap_dir_size = 0;
 int64_t ssize = bdrv_getlength(in_bs);
+
 if (ssize < 0) {
 error_setg_errno(_err, -ssize,
  "Unable to get image virtual_size");
 goto err;
 }

+FOR_EACH_DIRTY_BITMAP(in_bs, bm) {
+if (bdrv_dirty_bitmap_get_persistence(bm)) {
+const char *name = bdrv_dirty_bitmap_name(bm);
+uint32_t granularity = bdrv_dirty_bitmap_granularity(bm);
+uint64_t bmbits = DIV_ROUND_UP(bdrv_dirty_bitmap_size(bm),
+   granularity);
+uint64_t bmclusters = DIV_ROUND_UP(DIV_ROUND_UP(bmbits,
+CHAR_BIT),
+   cluster_size);
+
+/* Assume the entire bitmap is allocated */
+bitmaps_size += bmclusters * cluster_size;
+/* Also reserve space for the bitmap table entries */
+bitmaps_size += ROUND_UP(bmclusters * sizeof(uint64_t),
+ cluster_size);
+   

[PATCH v3 3/9] block: Make it easier to learn which BDS support bitmaps

2020-05-08 Thread Eric Blake
Upcoming patches will enhance bitmap support in qemu-img, but in doing
so, it turns out to be nice to suppress output when bitmaps make no
sense (such as on a qcow2 v2 image).  Add a hook to make this easier
to query.

In the future, when we improve the ability to look up bitmaps through
a filter, we will probably also want to teach the block layer to
automatically let filters pass this request on through.

Signed-off-by: Eric Blake 
---
 block/qcow2.h| 1 +
 include/block/block_int.h| 1 +
 include/block/dirty-bitmap.h | 1 +
 block/dirty-bitmap.c | 9 +
 block/qcow2-bitmap.c | 7 +++
 block/qcow2.c| 1 +
 6 files changed, 20 insertions(+)

diff --git a/block/qcow2.h b/block/qcow2.h
index f4de0a27d5c3..fb2b2b5a7b4d 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -764,6 +764,7 @@ bool qcow2_co_can_store_new_dirty_bitmap(BlockDriverState 
*bs,
 int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
 const char *name,
 Error **errp);
+bool qcow2_dirty_bitmap_supported(BlockDriverState *bs);

 ssize_t coroutine_fn
 qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index df6d0273d679..cb1082da4c43 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -560,6 +560,7 @@ struct BlockDriver {
  uint64_t parent_perm, uint64_t parent_shared,
  uint64_t *nperm, uint64_t *nshared);

+bool (*bdrv_dirty_bitmap_supported)(BlockDriverState *bs);
 bool (*bdrv_co_can_store_new_dirty_bitmap)(BlockDriverState *bs,
const char *name,
uint32_t granularity,
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index 8a1002941892..6d2e1707639f 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -16,6 +16,7 @@ typedef enum BitmapCheckFlags {

 #define BDRV_BITMAP_MAX_NAME_SIZE 1023

+bool bdrv_dirty_bitmap_supported(BlockDriverState *bs);
 BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
   uint32_t granularity,
   const char *name,
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 063793e31606..89869c483c44 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -478,6 +478,15 @@ int bdrv_remove_persistent_dirty_bitmap(BlockDriverState 
*bs, const char *name,
 }
 }

+bool
+bdrv_dirty_bitmap_supported(BlockDriverState *bs)
+{
+if (bs->drv && bs->drv->bdrv_dirty_bitmap_supported) {
+return bs->drv->bdrv_dirty_bitmap_supported(bs);
+}
+return false;
+}
+
 static bool coroutine_fn
 bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
uint32_t granularity, Error **errp)
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index cb06954b4a5a..b9889c2144cd 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -1748,3 +1748,10 @@ fail:
   name, bdrv_get_device_or_node_name(bs));
 return false;
 }
+
+bool qcow2_dirty_bitmap_supported(BlockDriverState *bs)
+{
+BDRVQcow2State *s = bs->opaque;
+
+return s->qcow_version >= 3;
+}
diff --git a/block/qcow2.c b/block/qcow2.c
index 1ad95ff04851..838d810ca5ec 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -5663,6 +5663,7 @@ BlockDriver bdrv_qcow2 = {
 .bdrv_detach_aio_context  = qcow2_detach_aio_context,
 .bdrv_attach_aio_context  = qcow2_attach_aio_context,

+.bdrv_dirty_bitmap_supported = qcow2_dirty_bitmap_supported,
 .bdrv_co_can_store_new_dirty_bitmap = qcow2_co_can_store_new_dirty_bitmap,
 .bdrv_co_remove_persistent_dirty_bitmap =
 qcow2_co_remove_persistent_dirty_bitmap,
-- 
2.26.2




[PATCH v3 6/9] qemu-img: Add bitmap sub-command

2020-05-08 Thread Eric Blake
Include actions for --add, --remove, --clear, --enable, --disable, and
--merge (note that --clear is a bit of fluff, because the same can be
accomplished by removing a bitmap and then adding a new one in its
place, but it matches what QMP commands exist).  Listing is omitted,
because it does not require a bitmap name and because it was already
possible with 'qemu-img info'.  A single command line can play one or
more bitmap commands in sequence on the same bitmap name (although all
added bitmaps share the same granularity, and and all merged bitmaps
come from the same source file).  Merge defaults to other bitmaps in
the primary image, but can also be told to merge bitmaps from a
distinct image.

While this supports --image-opts for the file being modified, I did
not think it worth the extra complexity to support that for the source
file in a cross-file merges.  Likewise, I chose to have --merge only
take a single source rather than following the QMP support for
multiple merges in one go (although you can still use more than one
--merge in the command line); in part because qemu-img is offline and
therefore atomicity is not an issue.

Upcoming patches will add iotest coverage of these commands while
also testing other features.

Signed-off-by: Eric Blake 
---
 docs/tools/qemu-img.rst |  23 
 qemu-img.c  | 254 
 qemu-img-cmds.hx|   7 ++
 3 files changed, 284 insertions(+)

diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index 7d08c48d308f..68393c357386 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -281,6 +281,29 @@ Command description:
   For write tests, by default a buffer filled with zeros is written. This can 
be
   overridden with a pattern byte specified by *PATTERN*.

+.. option:: bitmap (--merge SOURCE | --add | --remove | --clear | --enable | 
--disable)... [-b SOURCE_FILE [-F SOURCE_FMT]] [-g GRANULARITY] [--object 
OBJECTDEF] [--image-opts | -f FMT] FILENAME BITMAP
+
+  Perform one or more modifications of the persistent bitmap *BITMAP*
+  in the disk image *FILENAME*.  The various modifications are:
+
+  ``--add`` to create *BITMAP*, enabled to record future edits.
+
+  ``--remove`` to remove *BITMAP*.
+
+  ``--clear`` to clear *BITMAP*.
+
+  ``--enable`` to change *BITMAP* to start recording future edits.
+
+  ``--disable`` to change *BITMAP* to stop recording future edits.
+
+  ``--merge`` to merge the contents of *SOURCE_BITMAP* into *BITMAP*.
+
+  Additional options ``-g`` set a non-default *GRANULARITY* for
+  ``--add``, and ``-b`` and ``-F`` select an alternative source file
+  for all *SOURCE* bitmaps used by ``--merge``.
+
+  To see what bitmaps are present in an image, use ``qemu-img info``.
+
 .. option:: check [--object OBJECTDEF] [--image-opts] [-q] [-f FMT] 
[--output=OFMT] [-r [leaks | all]] [-T SRC_CACHE] [-U] FILENAME

   Perform a consistency check on the disk image *FILENAME*. The command can
diff --git a/qemu-img.c b/qemu-img.c
index b6e8af9202a5..7ad86f7b8072 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -28,6 +28,7 @@
 #include "qemu-common.h"
 #include "qemu-version.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-block-core.h"
 #include "qapi/qapi-visit-block-core.h"
 #include "qapi/qobject-output-visitor.h"
 #include "qapi/qmp/qjson.h"
@@ -71,6 +72,12 @@ enum {
 OPTION_SHRINK = 266,
 OPTION_SALVAGE = 267,
 OPTION_TARGET_IS_ZERO = 268,
+OPTION_ADD = 269,
+OPTION_REMOVE = 270,
+OPTION_CLEAR = 271,
+OPTION_ENABLE = 272,
+OPTION_DISABLE = 273,
+OPTION_MERGE = 274,
 };

 typedef enum OutputFormat {
@@ -169,6 +176,14 @@ static void QEMU_NORETURN help(void)
"  '-n' skips the target volume creation (useful if the volume is 
created\n"
"   prior to running qemu-img)\n"
"\n"
+   "Parameters to bitmap subcommand:\n"
+   "  'bitmap' is the name of the bitmap to manipulate, through one or 
more\n"
+   "   actions from '--add', '--remove', '--clear', '--enable', 
'--diable',\n"
+   "   or '--merge source'\n"
+   "  '-g granularity' sets the granularity for '--add' actions\n"
+   "  '-b source' and '-F src_fmt' tell '--merge' actions to find the 
source\n"
+   "   bitmaps from an alternative file\n"
+   "\n"
"Parameters to check subcommand:\n"
"  '-r' tries to repair any inconsistencies that are found during 
the check.\n"
"   '-r leaks' repairs only cluster leaks, whereas '-r all' 
fixes all\n"
@@ -4461,6 +4476,245 @@ out:
 return 0;
 }

+enum ImgBitmapAct {
+BITMAP_ADD,
+BITMAP_REMOVE,
+BITMAP_CLEAR,
+BITMAP_ENABLE,
+BITMAP_DISABLE,
+BITMAP_MERGE,
+};
+typedef struct ImgBitmapAction {
+enum ImgBitmapAct act;
+const char *src; /* only used for merge */
+QSIMPLEQ_ENTRY(ImgBitmapAction) next;
+} ImgBitmapAction;
+
+static int img_bitmap(int argc, char 

[PATCH v3 8/9] qemu-img: Add convert --bitmaps option

2020-05-08 Thread Eric Blake
Make it easier to copy all the persistent bitmaps of (the top layer
of) a source image along with its guest-visible contents, by adding a
boolean flag for use with qemu-img convert.  This is basically
shorthand, as the same effect could be accomplished with a series of
'qemu-img bitmap --add' and 'qemu-img bitmap --merge -b source'
commands, or by QMP commands.

See also https://bugzilla.redhat.com/show_bug.cgi?id=1779893

While touching this, clean up a couple coding issues spotted in the
same function: an extra blank line, and merging back-to-back 'if
(!skip_create)' blocks.

Signed-off-by: Eric Blake 
---
 docs/tools/qemu-img.rst |  6 ++-
 qemu-img.c  | 81 +++--
 qemu-img-cmds.hx|  4 +-
 3 files changed, 85 insertions(+), 6 deletions(-)

diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index 68393c357386..444030861cd7 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -162,6 +162,10 @@ Parameters to convert subcommand:

 .. program:: qemu-img-convert

+.. option:: --bitmaps
+
+  Additionally copy all persistent bitmaps from the top layer of the source
+
 .. option:: -n

   Skip the creation of the target volume
@@ -396,7 +400,7 @@ Command description:
   4
 Error on reading data

-.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] 
[--target-is-zero] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T 
SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] 
[-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] 
OUTPUT_FILENAME
+.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] 
[--target-is-zero] [--bitmaps] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t 
CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l 
SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 
[...]] OUTPUT_FILENAME

   Convert the disk image *FILENAME* or a snapshot *SNAPSHOT_PARAM*
   to disk image *OUTPUT_FILENAME* using format *OUTPUT_FMT*. It can
diff --git a/qemu-img.c b/qemu-img.c
index 0e747247e0c5..5c60d0fc8c39 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -78,6 +78,7 @@ enum {
 OPTION_ENABLE = 272,
 OPTION_DISABLE = 273,
 OPTION_MERGE = 274,
+OPTION_BITMAPS = 275,
 };

 typedef enum OutputFormat {
@@ -191,6 +192,7 @@ static void QEMU_NORETURN help(void)
"   hiding corruption that has already occurred.\n"
"\n"
"Parameters to convert subcommand:\n"
+   "  '--bitmaps' copies all top-level persistent bitmaps to 
destination\n"
"  '-m' specifies how many coroutines work in parallel during the 
convert\n"
"   process (defaults to 8)\n"
"  '-W' allow to write to the target out of order rather than 
sequential\n"
@@ -2108,6 +2110,47 @@ static int convert_do_copy(ImgConvertState *s)
 return s->ret;
 }

+static int convert_copy_bitmaps(BlockDriverState *src, BlockDriverState *dst)
+{
+BdrvDirtyBitmap *bm;
+Error *err = NULL;
+BlockDirtyBitmapMergeSource *merge;
+BlockDirtyBitmapMergeSourceList *list;
+
+FOR_EACH_DIRTY_BITMAP(src, bm) {
+const char *name;
+
+if (!bdrv_dirty_bitmap_get_persistence(bm)) {
+continue;
+}
+name = bdrv_dirty_bitmap_name(bm);
+qmp_block_dirty_bitmap_add(dst->node_name, name,
+   true, bdrv_dirty_bitmap_granularity(bm),
+   true, true,
+   true, !bdrv_dirty_bitmap_enabled(bm),
+   );
+if (err) {
+error_reportf_err(err, "Failed to create bitmap %s: ", name);
+return -1;
+}
+
+merge = g_new0(BlockDirtyBitmapMergeSource, 1);
+merge->type = QTYPE_QDICT;
+merge->u.external.node = g_strdup(src->node_name);
+merge->u.external.name = g_strdup(name);
+list = g_new0(BlockDirtyBitmapMergeSourceList, 1);
+list->value = merge;
+qmp_block_dirty_bitmap_merge(dst->node_name, name, list, );
+qapi_free_BlockDirtyBitmapMergeSourceList(list);
+if (err) {
+error_reportf_err(err, "Failed to populate bitmap %s: ", name);
+return -1;
+}
+}
+
+return 0;
+}
+
 #define MAX_BUF_SECTORS 32768

 static int img_convert(int argc, char **argv)
@@ -2129,6 +2172,8 @@ static int img_convert(int argc, char **argv)
 int64_t ret = -EINVAL;
 bool force_share = false;
 bool explict_min_sparse = false;
+bool bitmaps = false;
+size_t nbitmaps = 0;

 ImgConvertState s = (ImgConvertState) {
 /* Need at least 4k of zeros for sparse detection */
@@ -2148,6 +2193,7 @@ static int img_convert(int argc, char **argv)
 {"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
 {"salvage", no_argument, 0, OPTION_SALVAGE},
  

[PATCH v3 2/9] qemu-img: Fix stale comments on doc location

2020-05-08 Thread Eric Blake
Missed in commit e13c59fa.

Signed-off-by: Eric Blake 
---
 qemu-img.c   | 2 +-
 qemu-img-cmds.hx | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/qemu-img.c b/qemu-img.c
index 6a4327aaba56..b6e8af9202a5 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -108,7 +108,7 @@ static void QEMU_NORETURN unrecognized_option(const char 
*option)
 error_exit("unrecognized option '%s'", option);
 }

-/* Please keep in synch with qemu-img.texi */
+/* Please keep in synch with docs/tools/qemu-img.rst */
 static void QEMU_NORETURN help(void)
 {
 const char *help_msg =
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index c9c54de1df40..e0886437b1f2 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -7,7 +7,7 @@ HXCOMM command structures and help message.
 HXCOMM HXCOMM can be used for comments, discarded from both rST and C

 HXCOMM When amending the rST sections, please remember to copy the usage
-HXCOMM over to the per-command sections in qemu-img.texi.
+HXCOMM over to the per-command sections in docs/tools/qemu-img.rst.

 DEF("amend", img_amend,
 "amend [--object objectdef] [--image-opts] [-p] [-q] [-f fmt] [-t cache] 
-o options filename")
-- 
2.26.2




[PATCH v3 0/9] qemu-img: Add convert --bitmaps

2020-05-08 Thread Eric Blake
v2 was here, to see the original cover letter:
https://lists.gnu.org/archive/html/qemu-devel/2020-04/msg03464.html

Since then:
- patch 2 was previously posted in isolation but fits well in this series
- patch 3 is new
- patch 4 and 5 were split from v2:2/6 [Max]
- new filename chosen in patch 5 is saner [Kevin]
- patch 6 allows list of operations on one bitmap name [Max]
- patch 7 exposes 0 when measuring v3 image without bitmaps [Max]
- patch 7 and 9 iotests beefed up [Max]
- patch 8 had enough rebase churn that I dropped R-b
- compilation passes on mingw [patchew]

001/9:[] [--] 'docs: Sort sections on qemu-img subcommand parameters'
002/9:[down] 'qemu-img: Fix stale comments on doc location'
003/9:[down] 'block: Make it easier to learn which BDS support bitmaps'
004/9:[down] 'blockdev: Promote several bitmap functions to non-static'
005/9:[0076] [FC] 'blockdev: Split off basic bitmap operations for qemu-img'
006/9:[0199] [FC] 'qemu-img: Add bitmap sub-command'
007/9:[0078] [FC] 'qcow2: Expose bitmaps' size during measure'
008/9:[0017] [FC] 'qemu-img: Add convert --bitmaps option'
009/9:[0033] [FC] 'iotests: Add test 291 to for qemu-img bitmap coverage'

Series can also be downloaded at:
https://repo.or.cz/qemu/ericb.git/shortlog/refs/tags/qemu-img-bitmaps-v3

Eric Blake (9):
  docs: Sort sections on qemu-img subcommand parameters
  qemu-img: Fix stale comments on doc location
  block: Make it easier to learn which BDS support bitmaps
  blockdev: Promote several bitmap functions to non-static
  blockdev: Split off basic bitmap operations for qemu-img
  qemu-img: Add bitmap sub-command
  qcow2: Expose bitmaps' size during measure
  qemu-img: Add convert --bitmaps option
  iotests: Add test 291 to for qemu-img bitmap coverage

 docs/tools/qemu-img.rst  |  77 ---
 Makefile.objs|   3 +-
 qapi/block-core.json |  15 +-
 block/qcow2.h|   1 +
 include/block/block_int.h|  13 ++
 include/block/dirty-bitmap.h |   1 +
 block/crypto.c   |   2 +-
 block/dirty-bitmap.c |   9 +
 block/monitor/bitmap-qmp-cmds.c  | 323 +
 block/qcow2-bitmap.c |   7 +
 block/qcow2.c|  38 +++-
 block/raw-format.c   |   2 +-
 blockdev.c   | 303 +--
 qemu-img.c   | 340 ++-
 MAINTAINERS  |   1 +
 block/monitor/Makefile.objs  |   1 +
 qemu-img-cmds.hx |  13 +-
 tests/qemu-iotests/178.out.qcow2 |  16 ++
 tests/qemu-iotests/190   |  43 +++-
 tests/qemu-iotests/190.out   |  23 ++-
 tests/qemu-iotests/291   | 112 ++
 tests/qemu-iotests/291.out   |  78 +++
 tests/qemu-iotests/group |   1 +
 23 files changed, 1077 insertions(+), 345 deletions(-)
 create mode 100644 block/monitor/bitmap-qmp-cmds.c
 create mode 100755 tests/qemu-iotests/291
 create mode 100644 tests/qemu-iotests/291.out

-- 
2.26.2




[PATCH v3 1/9] docs: Sort sections on qemu-img subcommand parameters

2020-05-08 Thread Eric Blake
We already list the subcommand summaries alphabetically, we should do
the same for the documentation related to subcommand-specific
parameters.

Signed-off-by: Eric Blake 
Reviewed-by: Max Reitz 
---
 docs/tools/qemu-img.rst | 48 -
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index 0080f83a76c9..7d08c48d308f 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -142,30 +142,6 @@ by the used format or see the format descriptions below 
for details.
   the documentation of the emulator's ``-drive cache=...`` option for allowed
   values.

-Parameters to snapshot subcommand:
-
-.. program:: qemu-img-snapshot
-
-.. option:: snapshot
-
-  Is the name of the snapshot to create, apply or delete
-
-.. option:: -a
-
-  Applies a snapshot (revert disk to saved state)
-
-.. option:: -c
-
-  Creates a snapshot
-
-.. option:: -d
-
-  Deletes a snapshot
-
-.. option:: -l
-
-  Lists all snapshots in the given image
-
 Parameters to compare subcommand:

 .. program:: qemu-img-compare
@@ -245,6 +221,30 @@ Parameters to dd subcommand:

   Sets the number of input blocks to skip

+Parameters to snapshot subcommand:
+
+.. program:: qemu-img-snapshot
+
+.. option:: snapshot
+
+  Is the name of the snapshot to create, apply or delete
+
+.. option:: -a
+
+  Applies a snapshot (revert disk to saved state)
+
+.. option:: -c
+
+  Creates a snapshot
+
+.. option:: -d
+
+  Deletes a snapshot
+
+.. option:: -l
+
+  Lists all snapshots in the given image
+
 Command description:

 .. program:: qemu-img-commands
-- 
2.26.2




[PATCH v3 4/9] blockdev: Promote several bitmap functions to non-static

2020-05-08 Thread Eric Blake
The next patch will split blockdev.c, which will require accessing
some previously-static functions from more than one .c file.  But part
of promoting a function to public is picking a naming scheme that does
not reek of exposing too many internals (two of the three functions
were named starting with 'do_').  To make future code motion easier,
perform the function rename and non-static promotion into its own
patch.

Signed-off-by: Eric Blake 
---
 include/block/block_int.h | 12 +++
 blockdev.c| 45 ---
 2 files changed, 30 insertions(+), 27 deletions(-)

diff --git a/include/block/block_int.h b/include/block/block_int.h
index cb1082da4c43..e71505951d48 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -1344,4 +1344,16 @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver 
*drv,
 Error **errp);
 extern QemuOptsList bdrv_create_opts_simple;

+BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
+   const char *name,
+   BlockDriverState **pbs,
+   Error **errp);
+BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
+  BlockDirtyBitmapMergeSourceList *bms,
+  HBitmap **backup, Error **errp);
+BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
+   bool release,
+   BlockDriverState **bitmap_bs,
+   Error **errp);
+
 #endif /* BLOCK_INT_H */
diff --git a/blockdev.c b/blockdev.c
index b3c840ec0312..fbeb38437869 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1197,10 +1197,10 @@ out_aio_context:
  *
  * @return: A bitmap object on success, or NULL on failure.
  */
-static BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
-  const char *name,
-  BlockDriverState **pbs,
-  Error **errp)
+BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
+   const char *name,
+   BlockDriverState **pbs,
+   Error **errp)
 {
 BlockDriverState *bs;
 BdrvDirtyBitmap *bitmap;
@@ -2171,11 +2171,6 @@ static void 
block_dirty_bitmap_disable_abort(BlkActionState *common)
 }
 }

-static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(
-const char *node, const char *target,
-BlockDirtyBitmapMergeSourceList *bitmaps,
-HBitmap **backup, Error **errp);
-
 static void block_dirty_bitmap_merge_prepare(BlkActionState *common,
  Error **errp)
 {
@@ -2189,15 +2184,11 @@ static void 
block_dirty_bitmap_merge_prepare(BlkActionState *common,

 action = common->action->u.block_dirty_bitmap_merge.data;

-state->bitmap = do_block_dirty_bitmap_merge(action->node, action->target,
-action->bitmaps, 
>backup,
-errp);
+state->bitmap = block_dirty_bitmap_merge(action->node, action->target,
+ action->bitmaps, >backup,
+ errp);
 }

-static BdrvDirtyBitmap *do_block_dirty_bitmap_remove(
-const char *node, const char *name, bool release,
-BlockDriverState **bitmap_bs, Error **errp);
-
 static void block_dirty_bitmap_remove_prepare(BlkActionState *common,
   Error **errp)
 {
@@ -2211,8 +2202,8 @@ static void 
block_dirty_bitmap_remove_prepare(BlkActionState *common,

 action = common->action->u.block_dirty_bitmap_remove.data;

-state->bitmap = do_block_dirty_bitmap_remove(action->node, action->name,
- false, >bs, errp);
+state->bitmap = block_dirty_bitmap_remove(action->node, action->name,
+  false, >bs, errp);
 if (state->bitmap) {
 bdrv_dirty_bitmap_skip_store(state->bitmap, true);
 bdrv_dirty_bitmap_set_busy(state->bitmap, true);
@@ -2504,9 +2495,10 @@ out:
 aio_context_release(aio_context);
 }

-static BdrvDirtyBitmap *do_block_dirty_bitmap_remove(
-const char *node, const char *name, bool release,
-BlockDriverState **bitmap_bs, Error **errp)
+BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
+   bool release,
+   BlockDriverState **bitmap_bs,
+   Error **errp)
 {
  

Re: [PATCH v2] e1000e: Added ICR clearing by corresponding IMS bit.

2020-05-08 Thread Andrew Melnichenko
Yo, I've used OpenSDM_8257x-18.pdf specification.
This document was recommended by Intel guys(Also, they referenced to that
note).
I've made a fast fix and it works. Before that I had a fix for Linux e1000e
driver.
Overall, the issue was in pending interrupts that can't be cleared by
reading ICR in Linux(Windows driver clears by writing to ICR).

You can download spec for example from:
http://iweb.dl.sourceforge.net/project/e1000/8257x%20Developer%20Manual/Revision%201.8/OpenSDM_8257x-18.pdf

On Fri, May 8, 2020 at 5:21 AM Jason Wang  wrote:

>
> On 2020/5/7 上午5:26, and...@daynix.com wrote:
> > From: Andrew Melnychenko 
> >
> > Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1707441
> > Added ICR clearing if there is IMS bit - according to the note by
> > section 13.3.27 of the 8257X developers manual.
> >
> > Signed-off-by: Andrew Melnychenko 
> > ---
> >   hw/net/e1000e_core.c | 9 +
> >   hw/net/trace-events  | 1 +
> >   2 files changed, 10 insertions(+)
> >
> > diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
> > index d5676871fa..302e99ff46 100644
> > --- a/hw/net/e1000e_core.c
> > +++ b/hw/net/e1000e_core.c
> > @@ -2624,6 +2624,15 @@ e1000e_mac_icr_read(E1000ECore *core, int index)
> >   e1000e_clear_ims_bits(core, core->mac[IAM]);
> >   }
> >
> > +/*
> > + * PCIe* GbE Controllers Open Source Software Developer's Manual
> > + * 13.3.27 Interrupt Cause Read Register
> > + */
>
>
> Hi Andrew:
>
> Which version of the manual did you use? I try to use the one mentioned
> in e1000e.c which is
>
> http://www.intel.com/content/dam/doc/datasheet/82574l-gbe-controller-datasheet.pdf
> .
>
> But I couldn't find chapter 13.3.27.
>
> Thanks
>
>
> > +if (core->mac[ICR] & core->mac[IMS]) {
> > +trace_e1000e_irq_icr_clear_icr_bit_ims(core->mac[ICR],
> core->mac[IMS]);
> > +core->mac[ICR] = 0;
> > +}
> > +
> >   trace_e1000e_irq_icr_read_exit(core->mac[ICR]);
> >   e1000e_update_interrupt_state(core);
> >   return ret;
> > diff --git a/hw/net/trace-events b/hw/net/trace-events
> > index e18f883cfd..46e40fcfa9 100644
> > --- a/hw/net/trace-events
> > +++ b/hw/net/trace-events
> > @@ -237,6 +237,7 @@ e1000e_irq_icr_read_entry(uint32_t icr) "Starting
> ICR read. Current ICR: 0x%x"
> >   e1000e_irq_icr_read_exit(uint32_t icr) "Ending ICR read. Current ICR:
> 0x%x"
> >   e1000e_irq_icr_clear_zero_ims(void) "Clearing ICR on read due to zero
> IMS"
> >   e1000e_irq_icr_clear_iame(void) "Clearing ICR on read due to IAME"
> > +e1000e_irq_icr_clear_icr_bit_ims(uint32_t icr, uint32_t ims) "Clearing
> ICR on read due corresponding IMS bit: 0x%x & 0x%x"
> >   e1000e_irq_iam_clear_eiame(uint32_t iam, uint32_t cause) "Clearing IMS
> due to EIAME, IAM: 0x%X, cause: 0x%X"
> >   e1000e_irq_icr_clear_eiac(uint32_t icr, uint32_t eiac) "Clearing ICR
> bits due to EIAC, ICR: 0x%X, EIAC: 0x%X"
> >   e1000e_irq_ims_clear_set_imc(uint32_t val) "Clearing IMS bits due to
> IMC write 0x%x"
>
>


Re: [PATCH] cpus: Fix botched configure_icount() error API violation fix

2020-05-08 Thread Markus Armbruster
Markus Armbruster  writes:

> Fixes: abc9bf69a66a11499a801ff545b8fe7adbb3a04c
> Fixes: Coverity CID 1428754
> Signed-off-by: Markus Armbruster 
> ---
>  cpus.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/cpus.c b/cpus.c
> index 5670c96bcf..b9275c672d 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -813,7 +813,7 @@ void configure_icount(QemuOpts *opts, Error **errp)
>  return;
>  }
>  
> -if (strcmp(option, "auto") != 0) {
> +if (option && !strcmp(option, "auto")) {
>  if (qemu_strtol(option, NULL, 0, _shift) < 0
>  || time_shift < 0 || time_shift > MAX_ICOUNT_SHIFT) {
>  error_setg(errp, "icount: Invalid shift value");

Nonsense.  I shouldn't multi-task.




[PATCH v2 4/5] virtio-iommu-pci: Add array of Interval properties

2020-05-08 Thread Eric Auger
The machine may need to pass reserved regions to the
virtio-iommu-pci device (such as the MSI window on x86).
So let's add an array of Interval properties.

Signed-off-by: Eric Auger 
Reviewed-by: Jean-Philippe Brucker 

---

v12 -> v12:
- added Jean's R-b
---
 hw/virtio/virtio-iommu-pci.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/virtio/virtio-iommu-pci.c b/hw/virtio/virtio-iommu-pci.c
index 3dfbf55b47..44ae9ebc11 100644
--- a/hw/virtio/virtio-iommu-pci.c
+++ b/hw/virtio/virtio-iommu-pci.c
@@ -33,6 +33,9 @@ struct VirtIOIOMMUPCI {
 
 static Property virtio_iommu_pci_properties[] = {
 DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0),
+DEFINE_PROP_ARRAY("reserved-regions", VirtIOIOMMUPCI,
+  vdev.nb_reserved_regions, vdev.reserved_regions,
+  qdev_prop_reserved_region, ReservedRegion),
 DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
2.20.1




[PATCH v2 5/5] hw/arm/virt: Let the virtio-iommu bypass MSIs

2020-05-08 Thread Eric Auger
At the moment the virtio-iommu translates MSI transactions.
This behavior is inherited from ARM SMMU. The virt machine
code knows where the guest MSI doorbells are so we can easily
declare those regions as VIRTIO_IOMMU_RESV_MEM_T_MSI. With that
setting the guest will not map MSIs through the IOMMU and those
transactions will be simply bypassed.

Depending on which MSI controller is in use (ITS or GICV2M),
we declare either:
- the ITS interrupt translation space (ITS_base + 0x1),
  containing the GITS_TRANSLATOR or
- The GICV2M single frame, containing the MSI_SETSP_NS register.

Signed-off-by: Eric Auger 

---

v1 -> v2:
- Test which MSI controller is instantiated
- If GICV2M is in use, declare its doorbell as an MSI doorbell too
---
 include/hw/arm/virt.h |  6 ++
 hw/arm/virt.c | 18 ++
 2 files changed, 24 insertions(+)

diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 6d67ace76e..ad20cb6e15 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -96,6 +96,11 @@ typedef enum VirtIOMMUType {
 VIRT_IOMMU_VIRTIO,
 } VirtIOMMUType;
 
+typedef enum VirtMSIControllerType {
+VIRT_GICV2M,
+VIRT_ITS,
+} VirtMSIControllerType;
+
 typedef enum VirtGICType {
 VIRT_GIC_VERSION_MAX,
 VIRT_GIC_VERSION_HOST,
@@ -135,6 +140,7 @@ typedef struct {
 OnOffAuto acpi;
 VirtGICType gic_version;
 VirtIOMMUType iommu;
+VirtMSIControllerType msi_controller;
 uint16_t virtio_iommu_bdf;
 struct arm_boot_info bootinfo;
 MemMapEntry *memmap;
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 634db0cfe9..d2dd07885b 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -602,6 +602,7 @@ static void create_its(VirtMachineState *vms)
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_ITS].base);
 
 fdt_add_its_gic_node(vms);
+vms->msi_controller = VIRT_ITS;
 }
 
 static void create_v2m(VirtMachineState *vms)
@@ -622,6 +623,7 @@ static void create_v2m(VirtMachineState *vms)
 }
 
 fdt_add_v2m_gic_node(vms);
+vms->msi_controller = VIRT_GICV2M;
 }
 
 static void create_gic(VirtMachineState *vms)
@@ -2136,8 +2138,24 @@ out:
 static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
 DeviceState *dev, Error **errp)
 {
+VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
+
 if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
 virt_memory_pre_plug(hotplug_dev, dev, errp);
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
+/* we declare a VIRTIO_IOMMU_RESV_MEM_T_MSI region */
+
+if (vms->msi_controller == VIRT_ITS) {
+/* GITS_TRANSLATER page */
+qdev_prop_set_uint32(dev, "len-reserved-regions", 1);
+qdev_prop_set_string(dev, "reserved-regions[0]",
+ "0x809, 0x809, 1");
+} else if (vms->msi_controller == VIRT_GICV2M) {
+/* MSI_SETSPI_NS page */
+qdev_prop_set_uint32(dev, "len-reserved-regions", 1);
+qdev_prop_set_string(dev, "reserved-regions[0]",
+ "0x802, 0x8020FFF, 1");
+}
 }
 }
 
-- 
2.20.1




[PATCH v2 2/5] virtio-iommu: Implement RESV_MEM probe request

2020-05-08 Thread Eric Auger
This patch implements the PROBE request. At the moment,
only THE RESV_MEM property is handled. The first goal is
to report iommu wide reserved regions such as the MSI regions
set by the machine code. On x86 this will be the IOAPIC MSI
region, [0xFEE0 - 0xFEEF], on ARM this may be the ITS
doorbell.

In the future we may introduce per device reserved regions.
This will be useful when protecting host assigned devices
which may expose their own reserved regions

Signed-off-by: Eric Auger 

---

v1 -> v2:
- move the unlock back to the same place
- remove the push label and factorize the code after the out label
- fix a bunch of cpu_to_leX according to the latest spec revision
- do not remove sizeof(last) from free space
- check the ep exists
---
 include/hw/virtio/virtio-iommu.h |  2 +
 hw/virtio/virtio-iommu.c | 94 ++--
 hw/virtio/trace-events   |  1 +
 3 files changed, 93 insertions(+), 4 deletions(-)

diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h
index e653004d7c..49eb105cd8 100644
--- a/include/hw/virtio/virtio-iommu.h
+++ b/include/hw/virtio/virtio-iommu.h
@@ -53,6 +53,8 @@ typedef struct VirtIOIOMMU {
 GHashTable *as_by_busptr;
 IOMMUPciBus *iommu_pcibus_by_bus_num[PCI_BUS_MAX];
 PCIBus *primary_bus;
+ReservedRegion *reserved_regions;
+uint32_t nb_reserved_regions;
 GTree *domains;
 QemuMutex mutex;
 GTree *endpoints;
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index 22ba8848c2..35d772e021 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -38,6 +38,7 @@
 
 /* Max size */
 #define VIOMMU_DEFAULT_QUEUE_SIZE 256
+#define VIOMMU_PROBE_SIZE 512
 
 typedef struct VirtIOIOMMUDomain {
 uint32_t id;
@@ -378,6 +379,65 @@ static int virtio_iommu_unmap(VirtIOIOMMU *s,
 return ret;
 }
 
+static ssize_t virtio_iommu_fill_resv_mem_prop(VirtIOIOMMU *s, uint32_t ep,
+   uint8_t *buf, size_t free)
+{
+struct virtio_iommu_probe_resv_mem prop = {};
+size_t size = sizeof(prop), length = size - sizeof(prop.head), total;
+int i;
+
+total = size * s->nb_reserved_regions;
+
+if (total > free) {
+return -ENOSPC;
+}
+
+for (i = 0; i < s->nb_reserved_regions; i++) {
+prop.head.type = cpu_to_le16(VIRTIO_IOMMU_PROBE_T_RESV_MEM);
+prop.head.length = cpu_to_le16(length);
+prop.subtype = s->reserved_regions[i].type;
+prop.start = cpu_to_le64(s->reserved_regions[i].low);
+prop.end = cpu_to_le64(s->reserved_regions[i].high);
+
+memcpy(buf, , size);
+
+trace_virtio_iommu_fill_resv_property(ep, prop.subtype,
+  prop.start, prop.end);
+buf += size;
+}
+return total;
+}
+
+/**
+ * virtio_iommu_probe - Fill the probe request buffer with
+ * the properties the device is able to return and add a NONE
+ * property at the end.
+ */
+static int virtio_iommu_probe(VirtIOIOMMU *s,
+  struct virtio_iommu_req_probe *req,
+  uint8_t *buf)
+{
+uint32_t ep_id = le32_to_cpu(req->endpoint);
+size_t free = VIOMMU_PROBE_SIZE;
+ssize_t count;
+
+if (!virtio_iommu_mr(s, ep_id)) {
+return VIRTIO_IOMMU_S_NOENT;
+}
+
+count = virtio_iommu_fill_resv_mem_prop(s, ep_id, buf, free);
+if (count < 0) {
+return VIRTIO_IOMMU_S_INVAL;
+}
+buf += count;
+free -= count;
+
+/* Fill the rest with zeroes */
+memset(buf, 0, free);
+
+return VIRTIO_IOMMU_S_OK;
+}
+
 static int virtio_iommu_iov_to_req(struct iovec *iov,
unsigned int iov_cnt,
void *req, size_t req_sz)
@@ -407,15 +467,27 @@ virtio_iommu_handle_req(detach)
 virtio_iommu_handle_req(map)
 virtio_iommu_handle_req(unmap)
 
+static int virtio_iommu_handle_probe(VirtIOIOMMU *s,
+ struct iovec *iov,
+ unsigned int iov_cnt,
+ uint8_t *buf)
+{
+struct virtio_iommu_req_probe req;
+int ret = virtio_iommu_iov_to_req(iov, iov_cnt, , sizeof(req));
+
+return ret ? ret : virtio_iommu_probe(s, , buf);
+}
+
 static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq)
 {
 VirtIOIOMMU *s = VIRTIO_IOMMU(vdev);
 struct virtio_iommu_req_head head;
 struct virtio_iommu_req_tail tail = {};
+size_t output_size = sizeof(tail), sz;
 VirtQueueElement *elem;
 unsigned int iov_cnt;
 struct iovec *iov;
-size_t sz;
+void *buf = NULL;
 
 for (;;) {
 elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
@@ -452,6 +524,17 @@ static void virtio_iommu_handle_command(VirtIODevice 
*vdev, VirtQueue *vq)
 case VIRTIO_IOMMU_T_UNMAP:
 tail.status = virtio_iommu_handle_unmap(s, iov, iov_cnt);
 break;

[PATCH v2 3/5] virtio-iommu: Handle reserved regions in the translation process

2020-05-08 Thread Eric Auger
When translating an address we need to check if it belongs to
a reserved virtual address range. If it does, there are 2 cases:

- it belongs to a RESERVED region: the guest should neither use
  this address in a MAP not instruct the end-point to DMA on
  them. We report an error

- It belongs to an MSI region: we bypass the translation.

Signed-off-by: Eric Auger 

---

v1 -> v2:
- use addr when testing addr belongs to the reserved region
  and use a block local variable
---
 hw/virtio/virtio-iommu.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index 35d772e021..ba72cfaa63 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -607,6 +607,7 @@ static IOMMUTLBEntry 
virtio_iommu_translate(IOMMUMemoryRegion *mr, hwaddr addr,
 uint32_t sid, flags;
 bool bypass_allowed;
 bool found;
+int i;
 
 interval.low = addr;
 interval.high = addr + 1;
@@ -640,6 +641,25 @@ static IOMMUTLBEntry 
virtio_iommu_translate(IOMMUMemoryRegion *mr, hwaddr addr,
 goto unlock;
 }
 
+for (i = 0; i < s->nb_reserved_regions; i++) {
+ReservedRegion *reg = >reserved_regions[i];
+
+if (addr >= reg->low && addr <= reg->high) {
+switch (reg->type) {
+case VIRTIO_IOMMU_RESV_MEM_T_MSI:
+entry.perm = flag;
+break;
+case VIRTIO_IOMMU_RESV_MEM_T_RESERVED:
+default:
+virtio_iommu_report_fault(s, VIRTIO_IOMMU_FAULT_R_MAPPING,
+  VIRTIO_IOMMU_FAULT_F_ADDRESS,
+  sid, addr);
+break;
+}
+goto unlock;
+}
+}
+
 if (!ep->domain) {
 if (!bypass_allowed) {
 error_report_once("%s %02x:%02x.%01x not attached to any domain",
-- 
2.20.1




[PATCH v2 0/5] VIRTIO-IOMMU probe request support and MSI bypass on ARM

2020-05-08 Thread Eric Auger
By default the virtio-iommu translates MSI transactions. This
behavior is inherited from ARM SMMU. However the virt machine
code knows where the MSI doorbells are, so we can easily
declare those regions as VIRTIO_IOMMU_RESV_MEM_T_MSI. With that
setting the guest iommu subsystem will not need to map MSIs.
This setup will simplify the VFIO integration.

In this series, the ITS or GICV2M doorbells are declared as
HW MSI regions to be bypassed by the VIRTIO-IOMMU.

This also paves the way to the x86 integration where the MSI
region, [0xFEE0,0xFEEF], will be exposed by the q35
machine.  However this will be handled in a separate series
when not-DT support gets resolved.

Best Regards

Eric

This series can be found at:
https://github.com/eauger/qemu/tree/v5.0.0-virtio-iommu-msi-bypass-v2

History:

v1 -> v2:
- check which MSI controller is in use and advertise the
  corresponding MSI doorbell
- managed for both ITS and GICv2M
- various fixes spotted by Peter and Jean-Philippe, see
  individual logs

v1: Most of those patches were respinned from
  [PATCH for-5.0 v11 00/20] VIRTIO-IOMMU device
  except the last one which is new

Eric Auger (5):
  qdev: Introduce DEFINE_PROP_RESERVED_REGION
  virtio-iommu: Implement RESV_MEM probe request
  virtio-iommu: Handle reserved regions in the translation process
  virtio-iommu-pci: Add array of Interval properties
  hw/arm/virt: Let the virtio-iommu bypass MSIs

 include/exec/memory.h|   6 ++
 include/hw/arm/virt.h|   6 ++
 include/hw/qdev-properties.h |   3 +
 include/hw/virtio/virtio-iommu.h |   2 +
 include/qemu/typedefs.h  |   1 +
 hw/arm/virt.c|  18 +
 hw/core/qdev-properties.c|  89 
 hw/virtio/virtio-iommu-pci.c |   3 +
 hw/virtio/virtio-iommu.c | 114 +--
 hw/virtio/trace-events   |   1 +
 10 files changed, 239 insertions(+), 4 deletions(-)

-- 
2.20.1




[PATCH v2 1/5] qdev: Introduce DEFINE_PROP_RESERVED_REGION

2020-05-08 Thread Eric Auger
Introduce a new property defining a reserved region:
, , .

This will be used to encode reserved IOVA regions.

For instance, in virtio-iommu use case, reserved IOVA regions
will be passed by the machine code to the virtio-iommu-pci
device (an array of those). The type of the reserved region
will match the virtio_iommu_probe_resv_mem subtype value:
- VIRTIO_IOMMU_RESV_MEM_T_RESERVED (0)
- VIRTIO_IOMMU_RESV_MEM_T_MSI (1)

on PC/Q35 machine, this will be used to inform the
virtio-iommu-pci device it should bypass the MSI region.
The reserved region will be: 0xfee0, 0xfeef, 1.

On ARM, we can declare the ITS MSI doorbell as an MSI
region to prevent MSIs from being mapped on guest side.

Signed-off-by: Eric Auger 

---

v11 -> v12:
- rename into DEFINE_PROP_RESERVED_REGION
- do not use g_strsplit anymore, use endptr instead
- remove 0x references
---
 include/exec/memory.h|  6 +++
 include/hw/qdev-properties.h |  3 ++
 include/qemu/typedefs.h  |  1 +
 hw/core/qdev-properties.c| 89 
 4 files changed, 99 insertions(+)

diff --git a/include/exec/memory.h b/include/exec/memory.h
index e000bd2f97..7e47afabe8 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -57,6 +57,12 @@ struct MemoryRegionMmio {
 CPUWriteMemoryFunc *write[3];
 };
 
+struct ReservedRegion {
+hwaddr low;
+hwaddr high;
+unsigned int type;
+};
+
 typedef struct IOMMUTLBEntry IOMMUTLBEntry;
 
 /* See address_space_translate: bit 0 is read, bit 1 is write.  */
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index f161604fb6..03bf850a7e 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -19,6 +19,7 @@ extern const PropertyInfo qdev_prop_string;
 extern const PropertyInfo qdev_prop_chr;
 extern const PropertyInfo qdev_prop_tpm;
 extern const PropertyInfo qdev_prop_macaddr;
+extern const PropertyInfo qdev_prop_reserved_region;
 extern const PropertyInfo qdev_prop_on_off_auto;
 extern const PropertyInfo qdev_prop_multifd_compression;
 extern const PropertyInfo qdev_prop_losttickpolicy;
@@ -183,6 +184,8 @@ extern const PropertyInfo qdev_prop_pcie_link_width;
 DEFINE_PROP(_n, _s, _f, qdev_prop_drive_iothread, BlockBackend *)
 #define DEFINE_PROP_MACADDR(_n, _s, _f) \
 DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
+#define DEFINE_PROP_RESERVED_REGION(_n, _s, _f) \
+DEFINE_PROP(_n, _s, _f, qdev_prop_reserved_region, ReservedRegion)
 #define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \
 DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_on_off_auto, OnOffAuto)
 #define DEFINE_PROP_MULTIFD_COMPRESSION(_n, _s, _f, _d) \
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index ecf3cde26c..85c4f891f4 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -59,6 +59,7 @@ typedef struct ISABus ISABus;
 typedef struct ISADevice ISADevice;
 typedef struct IsaDma IsaDma;
 typedef struct MACAddr MACAddr;
+typedef struct ReservedRegion ReservedRegion;
 typedef struct MachineClass MachineClass;
 typedef struct MachineState MachineState;
 typedef struct MemoryListener MemoryListener;
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 2047114fca..c2e0cc7cda 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -14,6 +14,7 @@
 #include "qapi/visitor.h"
 #include "chardev/char.h"
 #include "qemu/uuid.h"
+#include "qemu/cutils.h"
 
 void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
   Error **errp)
@@ -577,6 +578,94 @@ const PropertyInfo qdev_prop_macaddr = {
 .set   = set_mac,
 };
 
+/* --- Reserved Region --- */
+
+/*
+ * accepted syntax version:
+ *   ,,
+ *   where low/high addresses are uint64_t in hexadecimal
+ *   and type is an unsigned integer in decimal
+ */
+static void get_reserved_region(Object *obj, Visitor *v, const char *name,
+void *opaque, Error **errp)
+{
+DeviceState *dev = DEVICE(obj);
+Property *prop = opaque;
+ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
+char buffer[64];
+char *p = buffer;
+
+snprintf(buffer, sizeof(buffer), "0x%"PRIx64",0x%"PRIx64",%u",
+ rr->low, rr->high, rr->type);
+
+visit_type_str(v, name, , errp);
+}
+
+static void set_reserved_region(Object *obj, Visitor *v, const char *name,
+void *opaque, Error **errp)
+{
+DeviceState *dev = DEVICE(obj);
+Property *prop = opaque;
+ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
+Error *local_err = NULL;
+const char *endptr;
+char *str;
+int ret;
+
+if (dev->realized) {
+qdev_prop_set_after_realize(dev, name, errp);
+return;
+}
+
+visit_type_str(v, name, , _err);
+if (local_err) {
+error_propagate(errp, local_err);
+return;
+}
+
+ret = qemu_strtou64(str, , 16, >low);
+if (ret) {
+error_setg(errp, 

Re: [PATCH v23 QEMU 0/5] virtio-balloon: add support for page poison reporting and free page reporting

2020-05-08 Thread Alexander Duyck
I just wanted to follow up since it has been a little over a week
since I submitted this and I haven't heard anything back. It looks
like the linux-headers patches can be dropped since the headers appear
to have been synced. I was wondering if I should resubmit with just
the 3 patches that are adding the functionality, or if this patch-set
is good as-is?

Thanks.

- Alex

On Mon, Apr 27, 2020 at 5:53 PM Alexander Duyck
 wrote:
>
> This series provides an asynchronous means of reporting free guest pages
> to QEMU through virtio-balloon so that the memory associated with those
> pages can be dropped and reused by other processes and/or guests on the
> host. Using this it is possible to avoid unnecessary I/O to disk and
> greatly improve performance in the case of memory overcommit on the host.
>
> I originally submitted this patch series back on February 11th 2020[1],
> but at that time I was focused primarily on the kernel portion of this
> patch set. However as of April 7th those patches are now included in
> Linus's kernel tree[2] and so I am submitting the QEMU pieces for
> inclusion.
>
> [1]: 
> https://lore.kernel.org/lkml/20200211224416.29318.44077.stgit@localhost.localdomain/
> [2]: 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b0c504f154718904ae49349147e3b7e6ae91ffdc
>
> Changes from v17:
> Fixed typo in patch 1 title
> Addressed white-space issues reported via checkpatch
> Added braces {} for two if statements to match expected coding style
>
> Changes from v18:
> Updated patches 2 and 3 based on input from dhildenb
> Added comment to patch 2 describing what keeps us from reporting a bad page
> Added patch to address issue with ROM devices being directly writable
>
> Changes from v19:
> Added std-headers change to match changes pushed for linux kernel headers
> Added patch to remove "report" from page hinting code paths
> Updated comment to better explain why we disable hints w/ page poisoning
> Removed code that was modifying config size for poison vs hinting
> Dropped x-page-poison property
> Added code to bounds check the reported region vs the RAM block
> Dropped patch for ROM devices as that was already pulled in by Paolo
>
> Changes from v20:
> Rearranged patches to push Linux header sync patches to front
> Removed association between free page hinting and VIRTIO_BALLOON_F_PAGE_POISON
> Added code to enable VIRTIO_BALLOON_F_PAGE_POISON if page reporting is enabled
> Fixed possible resource leak if poison or qemu_balloon_is_inhibited return 
> true
>
> Changes from v21:
> Added ack for patch 3
> Rewrote patch description for page poison reporting feature
> Made page-poison independent property and set to enabled by default
> Added logic to migrate poison_val
> Added several comments in code to better explain features
> Switched free-page-reporting property to disabled by default
>
> Changes from v22:
> Added ack for patches 4 & 5
> Added additional comment fixes in patch 3 to remove "reporting" reference
> Renamed rvq in patch 5 to reporting_vq to improve readability
> Moved call adding reporting_vq to after free_page_vq to fix VQ ordering
>
> ---
>
> Alexander Duyck (5):
>   linux-headers: Update to allow renaming of free_page_report_cmd_id
>   linux-headers: update to contain virito-balloon free page reporting
>   virtio-balloon: Replace free page hinting references to 'report' with 
> 'hint'
>   virtio-balloon: Implement support for page poison reporting feature
>   virtio-balloon: Provide an interface for free page reporting
>
>
>  hw/virtio/virtio-balloon.c  |  176 
> ++-
>  include/hw/virtio/virtio-balloon.h  |   23 ++-
>  include/standard-headers/linux/virtio_balloon.h |   12 +-
>  3 files changed, 159 insertions(+), 52 deletions(-)
>
> --



Re: [PATCH v3 00/19] tcg: Better handling of constants

2020-05-08 Thread Richard Henderson
On 5/8/20 9:15 AM, Alex Bennée wrote:
> 
> Richard Henderson  writes:
> 
>> V3 fixes the target/sparc regression during register allocation.
> 
> Which patch has the fix in it? I couldn't see any per-patch rev notes.

Patch 3:

> +/*
> + * If the input is readonly, then it cannot also be an
> + * output and aliased to itself.  If the input is not
> + * dead after the instruction, we must allocate a new
> + * register and move it.
> + */
> +if (temp_readonly(ts) || !IS_DEAD_ARG(i)) {
> +goto allocate_in_reg;
> +}


> Also I'm sure I reviewed a bunch of these, did they not count because I
> found a bug ;-)

Oops, you're right.  I simply missed them, having gotten distracted by the bug.


r~




Re: [PATCH v5 04/19] accel/tcg: Adjust probe_access call to page_check_range

2020-05-08 Thread Richard Henderson
On 5/8/20 9:13 AM, Peter Maydell wrote:
> On Fri, 8 May 2020 at 16:44, Richard Henderson
>  wrote:
>>
>> We have validated that addr+size does not cross a page boundary.
>> Therefore we need to validate exactly one page.  We can achieve
>> that passing any value 1 <= x <= size to page_check_range.
>>
>> Passing 1 will simplify the next patch.
> 
> It's not clear to me how it simplifies the next patch, though --
> we have the size right there in the new function which
> calls page_check_range(), don't we? So I still don't
> understand why we're using '1' -- it isn't allowing
> us to avoid passing the size into probe_access_internal(),
> because we need to pass it anyway.
> 
> We've gone round this multiple times now so I feel like
> I must be missing something here.

While probe_access() has a size parameter, probe_access_flags() does not.

For probe_access_internal(), I currently have a "fault_size" parameter that
gets passed to tlb_fill, which is "size" for probe_access() and 0 for
probe_access_flags().

I *could* add another "check_size" parameter to probe_access_internal, to be
passed on to page_check_range(). It would be "size" for probe_access() and 1
for probe_access_flags().  But what's the point?  Always passing 1 to
page_check_range() has the same effect.

I feel like I'm missing something with your objection.


r~



Re: [PATCH for-5.1 V3 0/7] mips: Add Loongson-3 machine support (with KVM)

2020-05-08 Thread Aleksandar Markovic
нед, 3. мај 2020. у 12:21 Huacai Chen  је написао/ла:
>
> Loongson-3 CPU family include Loongson-3A R1/R2/R3/R4 and Loongson-3B
> R1/R2. Loongson-3A R1 is the oldest and its ISA is the smallest, while
> Loongson-3A R4 is the newest and its ISA is almost the superset of all
> others. To reduce complexity, in QEMU we just define two CPU types:
>
> 1, "Loongson-3A1000" CPU which is corresponding to Loongson-3A R1. It is
>suitable for TCG because Loongson-3A R1 has fewest ASE.
> 2, "Loongson-3A4000" CPU which is corresponding to Loongson-3A R4. It is
>suitable for KVM because Loongson-3A R4 has the VZ ASE.
>

Hi, Huacei,

Just a couple of practicalities. As you know, we can't upstream this
series until correspondent kernel support is upstreamed into kernel.
This is my advice, timing-wise:

- I think it is too late (and not good from testing/risk perspective)
to shoot for integrating your kernel series into kernel 5.7;
- My advice is to try to upstream your kernel series at the beginning
of 5.8 development cycle (which should not be too far)
- Once this is done, it will open the door for integrating this series
into QEMU upstream
- This means that combination of kernel 5.8 and QEMU 5.1 will
hopefully be a working system from Loongson KVM point of view
- This will also mean we will have relatively sufficient time to test,
and possibly fix some new bugs before QEMU 5.1 release.

I hope this tentative plan sounds good to you.

Sincerely,
Aleksandar



  1   2   3   4   >