Re: [Qemu-devel] [Bug 1670170] [NEW] `qemu-system-sparc64 -M Niagara` Aborted (core dumped)

2017-03-05 Thread Artyom Tarasenko
There was a major rework of the Niagara platform in the upcoming 2.9 release.
Please use the new version.

On Sun, Mar 5, 2017 at 7:18 PM, Michal Nowak  wrote:
> Public bug reported:
>
>> qemu-system-sparc64 -M Niagara
> qemu: fatal: Trap 0x0064 while trap level (6) >= MAXTL (6), Error state
> pc: 4c80  npc: 4c84
> %g0-3:    
> %g4-7:    
> %o0-3:    
> %o4-7:    
> %l0-3: 07f0 01ff 01fff008 
> %l4-7:    
> %i0-3:    
> %i4-7:    
> %f00:     
> %f08:     
> %f16:     
> %f24:     
> %f32:     
> %f40:     
> %f48:     
> %f56:     
> pstate: 0414 ccr: 44 (icc: -Z-- xcc: -Z--) asi: 00 tl: 6 pil: 0
> cansave: 6 canrestore: 0 otherwin: 0 wstate: 0 cleanwin: 6 cwp: 7
> fsr:  y:  fprs: 
>
> Aborted (core dumped)
>
>> qemu-system-sparc64 -M help
> Supported machines are:
> Niagara  Sun4v platform, Niagara
> none empty machine
> sun4uSun4u platform (default)
> sun4vSun4v platform
>
>> qemu-system-sparc64 -version
> QEMU emulator version 2.8.0(Virtualization:Staging / SLE_12_SP2)
>
> from https://build.opensuse.org/package/show/Virtualization:Staging/qemu
> on openSUSE Leap 42.2.
>
> ** Affects: qemu
>  Importance: Undecided
>  Status: New
>
>
> ** Tags: sparc
>
> ** Attachment added: "coredumpctl core dump"
>
> https://bugs.launchpad.net/bugs/1670170/+attachment/4831907/+files/core.qemu-system-spa.1000.79fef1d6233b4b989c19ea5c5c809627.451.148873742600.xz
>
> --
> You received this bug notification because you are a member of qemu-
> devel-ml, which is subscribed to QEMU.
> https://bugs.launchpad.net/bugs/1670170
>
> Title:
>   `qemu-system-sparc64 -M Niagara` Aborted (core dumped)
>
> Status in QEMU:
>   New
>
> Bug description:
>   > qemu-system-sparc64 -M Niagara
>   qemu: fatal: Trap 0x0064 while trap level (6) >= MAXTL (6), Error state
>   pc: 4c80  npc: 4c84
>   %g0-3:    
>   %g4-7:    
>   %o0-3:    
>   %o4-7:    
>   %l0-3: 07f0 01ff 01fff008 
>   %l4-7:    
>   %i0-3:    
>   %i4-7:    
>   %f00:     
>   %f08:     
>   %f16:     
>   %f24:     
>   %f32:     
>   %f40:     
>   %f48:     
>   %f56:     
>   pstate: 0414 ccr: 44 (icc: -Z-- xcc: -Z--) asi: 00 tl: 6 pil: 0
>   cansave: 6 canrestore: 0 otherwin: 0 wstate: 0 cleanwin: 6 cwp: 7
>   fsr:  y:  fprs: 
>
>   Aborted (core dumped)
>
>   > qemu-system-sparc64 -M help
>   Supported machines are:
>   Niagara  Sun4v platform, Niagara
>   none empty machine
>   sun4uSun4u platform (default)
>   sun4vSun4v platform
>
>   > qemu-system-sparc64 -version
>   QEMU emulator version 2.8.0(Virtualization:Staging / SLE_12_SP2)
>
>   from
>   https://build.opensuse.org/package/show/Virtualization:Staging/qemu on
>   openSUSE Leap 42.2.
>
> To manage notifications about this bug go to:
> https://bu

Re: [Qemu-devel] [PATCH] ppc/spapr: QOM'ify sPAPRRTCState

2017-03-05 Thread Cédric Le Goater
On 03/06/2017 12:23 AM, David Gibson wrote:
> On Fri, Mar 03, 2017 at 06:23:15PM +0100, Cédric Le Goater wrote:
>> On 03/03/2017 05:54 PM, Thomas Huth wrote:
>>> On 03.03.2017 15:49, Cédric Le Goater wrote:
 On 03/03/2017 03:13 PM, Thomas Huth wrote:
> On 03.03.2017 14:37, Cédric Le Goater wrote:
>> Also use an 'Object *' under the sPAPR machine to hold the RTC
>> object.
>
> The change from TYPE_SYS_BUS_DEVICE to TYPE_DEVICE is certainly a good
> idea! But what's the advantage of using Object* instead of DeviceState*
> in sPAPRMachineState ?

 it makes spapr_rtc_create() a little simpler.  

 We could go even further and use a sPAPRRTCState under sPAPRMachineState 
 that we  would initialize with object_initialize(). 
>>>
>>> I think a sPAPRRTCState* would make more sense here - if you just see an
>>> Object* and are not familiar with the code, you wonder what this pointer
>>> is all about (and you then have to cast it to something different if you
>>> want to do anything with it) ... so IMHO either a DeviceState* or
>>> sPAPRRTCState* is the better choice here.
>>
>> I think having a non-pointer is a better for the object lifecycle 
>> but I don't have a strong opinion on that. We will see what Dave 
>> prefers.
> 
> You seem to be talking at cross purposes.  AFAICT Thomas is not
> talking about the difference between a pointer and a non-pointer, he's
> talking about the difference between a generic Object (pointer or
> otherwise) and a concrete type.
> 
> I agree with Thomas that a specific type is preferable.  I'm not
> particularly bothered by the difference between pointer and
> non-pointer.

Using a non-pointer sPAPRRTCState introduces more changes. See below.
This is going a further than just removing the dependency on SysBus. 
To remove only the dependency on SysBus, we can keep a 'DeviceState *' 
under the machine and fix the code accordingly.  

Just tell me what you prefer. I don't mind. Although I think that 
QOM'ifying sPAPR is good thing. After RTC, there is only the NVRAM
object left to handle but I am not sure we can do much about it as 
this is a drive. 
 
> In any case, this has missed the cutoff for qemu-2.9, I'm afraid.

Well, yes. it's not fixing a bug.

Thanks,

C. 


>From b061c1616cd07d04e795cb817768b3d9833d9036 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= 
Date: Fri, 3 Mar 2017 14:29:40 +0100
Subject: [PATCH] ppc/spapr: QOM'ify sPAPRRTCState
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Also use an 'sPAPRRTCState' attribute under the sPAPR machine to hold
the RTC object. Overall, these changes remove an unnecessary and
implicit dependency on SysBus.

Signed-off-by: Cédric Le Goater 
---
 hw/ppc/spapr.c | 16 
 hw/ppc/spapr_events.c  |  2 +-
 hw/ppc/spapr_rtc.c | 41 +++--
 include/hw/ppc/spapr.h | 21 -
 include/hw/ppc/xics.h  |  2 +-
 5 files changed, 33 insertions(+), 49 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index c3bb99160545..3a7868ed80da 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1333,13 +1333,13 @@ static void spapr_create_nvram(sPAPRMachineState *spapr)
 
 static void spapr_rtc_create(sPAPRMachineState *spapr)
 {
-DeviceState *dev = qdev_create(NULL, TYPE_SPAPR_RTC);
-
-qdev_init_nofail(dev);
-spapr->rtc = dev;
-
-object_property_add_alias(qdev_get_machine(), "rtc-time",
-  OBJECT(spapr->rtc), "date", NULL);
+object_initialize(&spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC);
+object_property_add_child(OBJECT(spapr), "rtc", OBJECT(&spapr->rtc),
+  &error_fatal);
+object_property_set_bool(OBJECT(&spapr->rtc), true, "realized",
+  &error_fatal);
+object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc),
+  "date", &error_fatal);
 }
 
 /* Returns whether we want to use VGA or not */
@@ -1377,7 +1377,7 @@ static int spapr_post_load(void *opaque, int version_id)
  * So when migrating from those versions, poke the incoming offset
  * value into the RTC device */
 if (version_id < 3) {
-err = spapr_rtc_import_offset(spapr->rtc, spapr->rtc_offset);
+err = spapr_rtc_import_offset(&spapr->rtc, spapr->rtc_offset);
 }
 
 return err;
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index 24a5758e6243..f0b28d811242 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -422,7 +422,7 @@ static void spapr_init_maina(struct rtas_event_log_v6_maina 
*maina,
 maina->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINA);
 maina->hdr.section_length = cpu_to_be16(sizeof(*maina));
 /* FIXME: section version, subtype and creator id? */
-spapr_rtc_read(spapr->rtc, &tm, NULL);
+spapr_rtc_read(&spapr->rtc, &tm, NULL);
 year = tm.t

Re: [Qemu-devel] [PATCH] virito: unbreak virtio device behinds IOMMU with region cache

2017-03-05 Thread Jason Wang



On 2017年03月03日 20:56, Paolo Bonzini wrote:


On 03/03/2017 10:06, Jason Wang wrote:

Commit c611c76417f5 ("virtio: add MemoryListener to cache ring
translations") registers a memory listener to dma_as. This may not
work when IOMMU is enabled: dma_as(bus_master_as) were correctly
initialized in pcibus_machine_done() after virtio_realize() where we
try to register listener and initialize address space cache.

Fixing this by:

- delay the listener register to status set
- reset dma_as before trying to initialize address spaces to make sure
   it works even IOMMU were created after virtio device

Fixes: c611c76417f5 ("virtio: add MemoryListener to cache ring translations")
Cc: Paolo Bonzini 
Signed-off-by: Jason Wang 

For virtio 0.9 it is valid to use the virtio device while the status is 0.

You can add a function virtio_set_dma_as to generic virtio that does a
MemoryListener unregister+register, then PCI can call it when the
AddressSpace is ready.

Paolo




Ok, will post a new version.

Thanks




Re: [Qemu-devel] [PATCH] linux-user: limit number of arguments to execve

2017-03-05 Thread P J P
  Hello Eric,

+-- On Fri, 3 Mar 2017, Eric Blake wrote --+
| much smaller, or you should consider using the heap instead of the stack
| (alloca should never be used for more than about 4k).  And there's still
| the possibility that even with your cap, that you are not handling E2BIG
| correctly.  You'll need to respin this patch.

  Yes, sent a revised patch set v2.

Thank you.
--
Prasad J Pandit / Red Hat Product Security Team
47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F



[Qemu-devel] [PATCH v2 2/2] linux-user: allocate heap memory for execve arguments

2017-03-05 Thread P J P
From: Prasad J Pandit 

Arguments passed to execve(2) call from user program could
be large, allocating stack memory for them via alloca(3) call
would lead to bad behaviour. Use 'g_malloc0' to allocate memory
for such arguments.

Signed-off-by: Prasad J Pandit 
---
 linux-user/syscall.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

Update per: replace alloca() with g_malloc0()
  -> https://lists.gnu.org/archive/html/qemu-devel/2017-03/msg00750.html

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 86a4a9c..404fb0b 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7800,8 +7800,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 ret = -TARGET_E2BIG;
 break;
 }
-argp = alloca((argc + 1) * sizeof(void *));
-envp = alloca((envc + 1) * sizeof(void *));
+argp = g_malloc0((argc + 1) * sizeof(void *));
+envp = g_malloc0((envc + 1) * sizeof(void *));
 
 for (gp = guest_argp, q = argp; gp;
   gp += sizeof(abi_ulong), q++) {
@@ -7862,6 +7862,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 break;
 unlock_user(*q, addr, 0);
 }
+
+g_free(argp);
+g_free(envp);
 }
 break;
 case TARGET_NR_chdir:
-- 
2.9.3




[Qemu-devel] [PATCH v2 0/2] Limit and protect execve arguments

2017-03-05 Thread P J P
From: Prasad J Pandit 

Hello,

A user program could pass large number of 'argv','env' arguments to an
execve(2) call. It could lead to bad behaviour as the TARGET_NR_execve:
allocates stack memory(via alloca) for these arguments. alloca(3) is
better for allocations of upto one page(4KB) of stack memory. As anything
more could smash stack protectors in place.

This patch(v2) set attempts to fix these issues.
  -> https://lists.gnu.org/archive/html/qemu-devel/2017-03/msg00750.html

Thank you.
--
Prasad J Pandit (2):
  linux-user: limit number of arguments to execve
  linux-user: allocate heap memory for execve arguments

 linux-user/syscall.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

--
2.9.3



[Qemu-devel] [PATCH v2 1/2] linux-user: limit number of arguments to execve

2017-03-05 Thread P J P
From: Prasad J Pandit 

Limit the number of arguments passed to execve(2) call from
a user program, as large number of them could lead to a bad
guest address error.

Reported-by: Jann Horn 
Signed-off-by: Prasad J Pandit 
---
 linux-user/syscall.c | 6 ++
 1 file changed, 6 insertions(+)

Update per: use gemu_log() to report error
  -> https://lists.gnu.org/archive/html/qemu-devel/2017-03/msg00750.html

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 9be8e95..86a4a9c 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7766,6 +7766,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 case TARGET_NR_execve:
 {
+#define ARG_MAX 65535
 char **argp, **envp;
 int argc, envc;
 abi_ulong gp;
@@ -7794,6 +7795,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
arg1,
 envc++;
 }
 
+if (argc > ARG_MAX || envc > ARG_MAX) {
+gemu_log("argc(%d), envc(%d) exceed %d\n", argc, envc, 
ARG_MAX);
+ret = -TARGET_E2BIG;
+break;
+}
 argp = alloca((argc + 1) * sizeof(void *));
 envp = alloca((envc + 1) * sizeof(void *));
 
-- 
2.9.3




Re: [Qemu-devel] [PATCH v3 13/13] ppc: Add SM501 device in config for ppc and ppcemb targets

2017-03-05 Thread Thomas Huth
On 13.12.2016 22:00, BALATON Zoltan wrote:
> This is not used by default on any emulated machine yet but it is
> still useful to have it compiled so it can be added from the command
> line for clients that can use it (e.g. MorphOS has no driver for any
> other emulated video cards but can output via SM501)
> 
> Signed-off-by: BALATON Zoltan 
> ---
>  default-configs/ppc-softmmu.mak| 1 +
>  default-configs/ppcemb-softmmu.mak | 1 +
>  2 files changed, 2 insertions(+)
> 
> diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
> index 09c1d45..1f1cd85 100644
> --- a/default-configs/ppc-softmmu.mak
> +++ b/default-configs/ppc-softmmu.mak
> @@ -45,6 +45,7 @@ CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
>  CONFIG_PLATFORM_BUS=y
>  CONFIG_ETSEC=y
>  CONFIG_LIBDECNUMBER=y
> +CONFIG_SM501=y
>  # For PReP
>  CONFIG_SERIAL_ISA=y
>  CONFIG_MC146818RTC=y
> diff --git a/default-configs/ppcemb-softmmu.mak 
> b/default-configs/ppcemb-softmmu.mak
> index 7f56004..94340de 100644
> --- a/default-configs/ppcemb-softmmu.mak
> +++ b/default-configs/ppcemb-softmmu.mak
> @@ -15,3 +15,4 @@ CONFIG_I8259=y
>  CONFIG_XILINX=y
>  CONFIG_XILINX_ETHLITE=y
>  CONFIG_LIBDECNUMBER=y
> +CONFIG_SM501=y

Looks like there are indeed embedded PPC devices that are shipped with
the SM501 controller (e.g. the TQM5200), so I think this makes sense:

Reviewed-by: Thomas Huth 

Note: In case you respin the series, you might want to add this
CONFIG_SM501 to ppc64-softmmu.mak, too, since it is a superset of the
32-bit config (i.e. it can also emulate the 32-bit embedded chips).

 Thomas




Re: [Qemu-devel] [PATCH v2] spapr_pci: allow control of BAR alignment through SLOF

2017-03-05 Thread Michael Roth
Quoting David Gibson (2017-03-05 22:16:58)
> On Fri, Mar 03, 2017 at 05:32:57PM -0600, Michael Roth wrote:
> > In certain cases, such as PCI-passthrough with VFIO, we cannot offload
> > MMIO accesses to KVM unless the BAR alignment matches the host. This
> > patch, in conjunction with a separately submitted patch for SLOF
> > which allows for control of this via the device-tree, allows us to
> > set this alignment via QEMU.
> > 
> > Cc: qemu-...@nongnu.org
> > Cc: Nikunj A Dadhania 
> > Cc: David Gibson 
> > Cc: Alexey Kardashevskiy 
> > Signed-off-by: Michael Roth 
> > ---
> > v2:
> >   * Keep natural alignment as the default in SLOF, only set DT prop if
> > different alignment is specified by QEMU (David)
> 
> Unfortunately, this has missed the cutoff for qemu-2.9.  
> 
> I'm afraid I'm still not entirely clear on the rationale here.
> 
> Why do we need a variable parameter based on the host page size?
> Couldn't we just have SLOF always align to something "big enough"
> (64kiB, IIUC)?

Is it okay for SLOF to assume 64K is sufficient? Since this is a
restriction/quirk on the QEMU/platform side it seems like it should be
controlled via the device tree.

That said, I can't think of any situation where we'd want something other
than 64K...

But even if we bake the 64k alignment into SLOF, shouldn't we still have a
way to switch it off for older machine types so assignments don't change
from one boot to the next? That could be a boolean option/property, but if
that at least is deemed necessary it might as well provide the requested
alignment as well to reduce assumptions on the SLOF side.

If neither of these is an issue it can be fixed within SLOF; just want
to make sure that's okay from a QEMU perspective. In theory guests
shouldn't care how BAR assignments are done, but they also aren't
supposed to care about things like enumeration order either...

> 
> > ---
> >  hw/ppc/spapr.c  |  7 ++-
> >  hw/ppc/spapr_pci.c  | 10 ++
> >  include/hw/pci-host/spapr.h |  1 +
> >  3 files changed, 17 insertions(+), 1 deletion(-)
> > 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index 14192ac..ef8df35 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -3166,7 +3166,12 @@ DEFINE_SPAPR_MACHINE(2_9, "2.9", true);
> >   * pseries-2.8
> >   */
> >  #define SPAPR_COMPAT_2_8\
> > -HW_COMPAT_2_8
> > +HW_COMPAT_2_8   \
> > +{   \
> > +.driver   = TYPE_SPAPR_PCI_HOST_BRIDGE, \
> > +.property = "mem_bar_min_align",\
> > +.value= "0",\
> > +},  \
> >  
> >  static void spapr_machine_2_8_instance_options(MachineState *machine)
> >  {
> > diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> > index 919d3c2..485d32d 100644
> > --- a/hw/ppc/spapr_pci.c
> > +++ b/hw/ppc/spapr_pci.c
> > @@ -1664,6 +1664,10 @@ static void spapr_phb_realize(DeviceState *dev, 
> > Error **errp)
> >  return;
> >  }
> >  
> > +if (sphb->mem_bar_min_align == (uint64_t)-1) {
> > +sphb->mem_bar_min_align = qemu_real_host_page_size;
> > +}
> > +
> >  sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid);
> >  
> >  namebuf = alloca(strlen(sphb->dtbusname) + 32);
> > @@ -1858,6 +1862,8 @@ static Property spapr_phb_properties[] = {
> >  DEFINE_PROP_UINT32("numa_node", sPAPRPHBState, numa_node, -1),
> >  DEFINE_PROP_BOOL("pre-2.8-migration", sPAPRPHBState,
> >   pre_2_8_migration, false),
> > +DEFINE_PROP_UINT64("mem_bar_min_align", sPAPRPHBState, 
> > mem_bar_min_align,
> > +   -1),
> >  DEFINE_PROP_END_OF_LIST(),
> >  };
> >  
> > @@ -2228,6 +2234,10 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
> >  if (ret) {
> >  return ret;
> >  }
> > +if (phb->mem_bar_min_align) {
> > +_FDT(fdt_setprop_cell(fdt, bus_off, "qemu,mem-bar-min-align",
> > +  phb->mem_bar_min_align));
> > +}
> >  
> >  return 0;
> >  }
> > diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
> > index dfa7614..fa33346 100644
> > --- a/include/hw/pci-host/spapr.h
> > +++ b/include/hw/pci-host/spapr.h
> > @@ -79,6 +79,7 @@ struct sPAPRPHBState {
> >  uint64_t dma64_win_addr;
> >  
> >  uint32_t numa_node;
> > +uint64_t mem_bar_min_align;
> >  
> >  /* Fields for migration compatibility hacks */
> >  bool pre_2_8_migration;
> 
> -- 
> David Gibson| I'll have my music baroque, and my code
> david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
> | _way_ _around_!
> http://www.ozlabs.org/~dgibson




[Qemu-devel] [PULL RESEND 18/19] COLO-compare: Fix icmp and udp compare different packet always dump bug

2017-03-05 Thread Jason Wang
From: Zhang Chen 

Signed-off-by: Zhang Chen 
Signed-off-by: Jason Wang 
---
 net/colo-compare.c | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/net/colo-compare.c b/net/colo-compare.c
index 9f5968d..282727b 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -279,9 +279,13 @@ static int colo_packet_compare_udp(Packet *spkt, Packet 
*ppkt)
 
 if (ret) {
 trace_colo_compare_udp_miscompare("primary pkt size", ppkt->size);
-qemu_hexdump((char *)ppkt->data, stderr, "colo-compare", ppkt->size);
 trace_colo_compare_udp_miscompare("Secondary pkt size", spkt->size);
-qemu_hexdump((char *)spkt->data, stderr, "colo-compare", spkt->size);
+if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
+qemu_hexdump((char *)ppkt->data, stderr, "colo-compare pri pkt",
+ ppkt->size);
+qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt",
+ spkt->size);
+}
 }
 
 return ret;
@@ -311,12 +315,14 @@ static int colo_packet_compare_icmp(Packet *spkt, Packet 
*ppkt)
network_header_length + ETH_HLEN)) {
 trace_colo_compare_icmp_miscompare("primary pkt size",
ppkt->size);
-qemu_hexdump((char *)ppkt->data, stderr, "colo-compare",
- ppkt->size);
 trace_colo_compare_icmp_miscompare("Secondary pkt size",
spkt->size);
-qemu_hexdump((char *)spkt->data, stderr, "colo-compare",
- spkt->size);
+if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
+qemu_hexdump((char *)ppkt->data, stderr, "colo-compare pri pkt",
+ ppkt->size);
+qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt",
+ spkt->size);
+}
 return -1;
 } else {
 return 0;
-- 
2.7.4




[Qemu-devel] [PULL RESEND 17/19] COLO-compare: Optimize compare_common and compare_tcp

2017-03-05 Thread Jason Wang
From: Zhang Chen 

Add offset args for colo_packet_compare_common, optimize
colo_packet_compare_icmp() and colo_packet_compare_udp()
just compare the IP payload. Before compare all tcp packet,
we compare tcp checksum firstly, this function can get
better performance.

Signed-off-by: Zhang Chen 
Signed-off-by: Jason Wang 
---
 net/colo-compare.c | 50 --
 1 file changed, 36 insertions(+), 14 deletions(-)

diff --git a/net/colo-compare.c b/net/colo-compare.c
index 602a758..9f5968d 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -180,7 +180,7 @@ static int packet_enqueue(CompareState *s, int mode)
  * return:0  means packet same
  *> 0 || < 0 means packet different
  */
-static int colo_packet_compare_common(Packet *ppkt, Packet *spkt)
+static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset)
 {
 trace_colo_compare_ip_info(ppkt->size, inet_ntoa(ppkt->ip->ip_src),
inet_ntoa(ppkt->ip->ip_dst), spkt->size,
@@ -188,7 +188,8 @@ static int colo_packet_compare_common(Packet *ppkt, Packet 
*spkt)
inet_ntoa(spkt->ip->ip_dst));
 
 if (ppkt->size == spkt->size) {
-return memcmp(ppkt->data, spkt->data, spkt->size);
+return memcmp(ppkt->data + offset, spkt->data + offset,
+  spkt->size - offset);
 } else {
 trace_colo_compare_main("Net packet size are not the same");
 return -1;
@@ -207,13 +208,6 @@ static int colo_packet_compare_tcp(Packet *spkt, Packet 
*ppkt)
 
 trace_colo_compare_main("compare tcp");
 
-if (ppkt->size != spkt->size) {
-if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
-trace_colo_compare_main("pkt size not same");
-}
-return -1;
-}
-
 ptcp = (struct tcphdr *)ppkt->transport_header;
 stcp = (struct tcphdr *)spkt->transport_header;
 
@@ -231,8 +225,11 @@ static int colo_packet_compare_tcp(Packet *spkt, Packet 
*ppkt)
 spkt->ip->ip_sum = ppkt->ip->ip_sum;
 }
 
-res = memcmp(ppkt->data + ETH_HLEN, spkt->data + ETH_HLEN,
-(spkt->size - ETH_HLEN));
+if (ptcp->th_sum == stcp->th_sum) {
+res = colo_packet_compare_common(ppkt, spkt, ETH_HLEN);
+} else {
+res = -1;
+}
 
 if (res != 0 && trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
 trace_colo_compare_pkt_info_src(inet_ntoa(ppkt->ip->ip_src),
@@ -263,10 +260,22 @@ static int colo_packet_compare_tcp(Packet *spkt, Packet 
*ppkt)
 static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
 {
 int ret;
+int network_header_length = ppkt->ip->ip_hl * 4;
 
 trace_colo_compare_main("compare udp");
 
-ret = colo_packet_compare_common(ppkt, spkt);
+/*
+ * Because of ppkt and spkt are both in the same connection,
+ * The ppkt's src ip, dst ip, src port, dst port, ip_proto all are
+ * same with spkt. In addition, IP header's Identification is a random
+ * field, we can handle it in IP fragmentation function later.
+ * COLO just concern the response net packet payload from primary guest
+ * and secondary guest are same or not, So we ignored all IP header include
+ * other field like TOS,TTL,IP Checksum. we only need to compare
+ * the ip payload here.
+ */
+ret = colo_packet_compare_common(ppkt, spkt,
+ network_header_length + ETH_HLEN);
 
 if (ret) {
 trace_colo_compare_udp_miscompare("primary pkt size", ppkt->size);
@@ -284,9 +293,22 @@ static int colo_packet_compare_udp(Packet *spkt, Packet 
*ppkt)
  */
 static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
 {
+int network_header_length = ppkt->ip->ip_hl * 4;
+
 trace_colo_compare_main("compare icmp");
 
-if (colo_packet_compare_common(ppkt, spkt)) {
+/*
+ * Because of ppkt and spkt are both in the same connection,
+ * The ppkt's src ip, dst ip, src port, dst port, ip_proto all are
+ * same with spkt. In addition, IP header's Identification is a random
+ * field, we can handle it in IP fragmentation function later.
+ * COLO just concern the response net packet payload from primary guest
+ * and secondary guest are same or not, So we ignored all IP header include
+ * other field like TOS,TTL,IP Checksum. we only need to compare
+ * the ip payload here.
+ */
+if (colo_packet_compare_common(ppkt, spkt,
+   network_header_length + ETH_HLEN)) {
 trace_colo_compare_icmp_miscompare("primary pkt size",
ppkt->size);
 qemu_hexdump((char *)ppkt->data, stderr, "colo-compare",
@@ -312,7 +334,7 @@ static int colo_packet_compare_other(Packet *spkt, Packet 
*ppkt)
inet_ntoa(ppkt->ip->ip_dst), spkt->size,
inet_ntoa(spkt->ip->ip_src),
   

[Qemu-devel] [PULL RESEND 16/19] COLO-compare: Rename compare function and remove duplicate codes

2017-03-05 Thread Jason Wang
From: Zhang Chen 

Rename colo_packet_compare() to colo_packet_compare_common() that
make tcp_compare udp_compare icmp_compare reuse this function.
Remove minimum packet size check in icmp_compare, because we have
check this in parse_packet_early().

Signed-off-by: Zhang Chen 
Signed-off-by: Jason Wang 
---
 net/colo-compare.c | 18 +++---
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/net/colo-compare.c b/net/colo-compare.c
index 300f017..602a758 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -180,7 +180,7 @@ static int packet_enqueue(CompareState *s, int mode)
  * return:0  means packet same
  *> 0 || < 0 means packet different
  */
-static int colo_packet_compare(Packet *ppkt, Packet *spkt)
+static int colo_packet_compare_common(Packet *ppkt, Packet *spkt)
 {
 trace_colo_compare_ip_info(ppkt->size, inet_ntoa(ppkt->ip->ip_src),
inet_ntoa(ppkt->ip->ip_dst), spkt->size,
@@ -190,6 +190,7 @@ static int colo_packet_compare(Packet *ppkt, Packet *spkt)
 if (ppkt->size == spkt->size) {
 return memcmp(ppkt->data, spkt->data, spkt->size);
 } else {
+trace_colo_compare_main("Net packet size are not the same");
 return -1;
 }
 }
@@ -205,6 +206,7 @@ static int colo_packet_compare_tcp(Packet *spkt, Packet 
*ppkt)
 int res;
 
 trace_colo_compare_main("compare tcp");
+
 if (ppkt->size != spkt->size) {
 if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) {
 trace_colo_compare_main("pkt size not same");
@@ -263,7 +265,8 @@ static int colo_packet_compare_udp(Packet *spkt, Packet 
*ppkt)
 int ret;
 
 trace_colo_compare_main("compare udp");
-ret = colo_packet_compare(ppkt, spkt);
+
+ret = colo_packet_compare_common(ppkt, spkt);
 
 if (ret) {
 trace_colo_compare_udp_miscompare("primary pkt size", ppkt->size);
@@ -281,16 +284,9 @@ static int colo_packet_compare_udp(Packet *spkt, Packet 
*ppkt)
  */
 static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
 {
-int network_length;
-
 trace_colo_compare_main("compare icmp");
-network_length = ppkt->ip->ip_hl * 4;
-if (ppkt->size != spkt->size ||
-ppkt->size < network_length + ETH_HLEN) {
-return -1;
-}
 
-if (colo_packet_compare(ppkt, spkt)) {
+if (colo_packet_compare_common(ppkt, spkt)) {
 trace_colo_compare_icmp_miscompare("primary pkt size",
ppkt->size);
 qemu_hexdump((char *)ppkt->data, stderr, "colo-compare",
@@ -316,7 +312,7 @@ static int colo_packet_compare_other(Packet *spkt, Packet 
*ppkt)
inet_ntoa(ppkt->ip->ip_dst), spkt->size,
inet_ntoa(spkt->ip->ip_src),
inet_ntoa(spkt->ip->ip_dst));
-return colo_packet_compare(ppkt, spkt);
+return colo_packet_compare_common(ppkt, spkt);
 }
 
 static int colo_old_packet_check_one(Packet *pkt, int64_t *check_time)
-- 
2.7.4




Re: [Qemu-devel] [PATCH] linux-user: limit number of arguments to execve

2017-03-05 Thread P J P
+-- On Fri, 3 Mar 2017, Jann Horn wrote --+
| On Fri, Mar 3, 2017 at 4:55 PM, Peter Maydell  
wrote:
| >> +if (argc > ARG_MAX || envc > ARG_MAX) {
| >> +fprintf(stderr,
| >> +"argc(%d), envc(%d) exceed %d\n", argc, envc, 
ARG_MAX);
| >> +ret = -TARGET_EFAULT;
| >> +break;
| >> +}
| >>  argp = alloca((argc + 1) * sizeof(void *));
| >>  envp = alloca((envc + 1) * sizeof(void *));
| >
| > This code is already supposed to handle "argument string too big",
| > see commit a6f79cc9a5e.
| >
| > What's the actual bug case we're trying to handle here?

Not argument string, but argument count too big leads to a bad address in 
get_user_ual(...), resulting in segfault.

Thank you.
--
Prasad J Pandit / Red Hat Product Security Team
47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F



[Qemu-devel] [PULL RESEND 14/19] net/colo: fix memory double free error

2017-03-05 Thread Jason Wang
From: zhanghailiang 

The 'primary_list' and 'secondary_list' members of struct Connection
is not allocated through dynamically g_queue_new(), but we free it by using
g_queue_free(), which will lead to a double-free bug.

Reviewed-by: Zhang Chen 
Signed-off-by: zhanghailiang 
Signed-off-by: Jason Wang 
---
 net/colo.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/colo.c b/net/colo.c
index 6a6eacd..8cc166b 100644
--- a/net/colo.c
+++ b/net/colo.c
@@ -147,9 +147,9 @@ void connection_destroy(void *opaque)
 Connection *conn = opaque;
 
 g_queue_foreach(&conn->primary_list, packet_destroy, NULL);
-g_queue_free(&conn->primary_list);
+g_queue_clear(&conn->primary_list);
 g_queue_foreach(&conn->secondary_list, packet_destroy, NULL);
-g_queue_free(&conn->secondary_list);
+g_queue_clear(&conn->secondary_list);
 g_slice_free(Connection, conn);
 }
 
-- 
2.7.4




[Qemu-devel] [PULL RESEND 19/19] net/filter-mirror: Follow CODING_STYLE

2017-03-05 Thread Jason Wang
From: Zhang Chen 

Signed-off-by: Zhang Chen 
Signed-off-by: Jason Wang 
---
 net/filter-mirror.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index aa0aa98..72fa7c2 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -49,7 +49,7 @@ static int filter_mirror_send(CharBackend *chr_out,
 {
 int ret = 0;
 ssize_t size = 0;
-uint32_t len =  0;
+uint32_t len = 0;
 char *buf;
 
 size = iov_size(iov, iovcnt);
@@ -77,8 +77,9 @@ err:
 return ret < 0 ? ret : -EIO;
 }
 
-static void
-redirector_to_filter(NetFilterState *nf, const uint8_t *buf, int len)
+static void redirector_to_filter(NetFilterState *nf,
+ const uint8_t *buf,
+ int len)
 {
 struct iovec iov = {
 .iov_base = (void *)buf,
-- 
2.7.4




[Qemu-devel] [PULL RESEND 11/19] net/colo-compare: Fix memory free error

2017-03-05 Thread Jason Wang
From: Zhang Chen 

We use g_queue_init() to init s->conn_list, so we should use g_queue_clear()
to instead of g_queue_free().

Signed-off-by: Zhang Chen 
Reviewed-by: zhanghailiang 
Signed-off-by: Jason Wang 
---
 net/colo-compare.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/colo-compare.c b/net/colo-compare.c
index a6fc2ff..300f017 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -729,7 +729,7 @@ static void colo_compare_finalize(Object *obj)
 /* Release all unhandled packets after compare thead exited */
 g_queue_foreach(&s->conn_list, colo_flush_packets, s);
 
-g_queue_free(&s->conn_list);
+g_queue_clear(&s->conn_list);
 
 g_hash_table_destroy(s->connection_track_table);
 g_free(s->pri_indev);
-- 
2.7.4




[Qemu-devel] [PULL RESEND 12/19] vmxnet3: Convert ring values to uint32_t's

2017-03-05 Thread Jason Wang
From: "Dr. David Alan Gilbert" 

The index's in the Vmxnet3Ring were migrated as 32bit ints
yet are declared as size_t's.  They appear to be derived
from 32bit values loaded from guest memory, so actually
store them as that.

Signed-off-by: Dr. David Alan Gilbert 
Acked-by: Dmitry Fleytman 
Signed-off-by: Jason Wang 
---
 hw/net/vmxnet3.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index e13a798..224c109 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -141,17 +141,17 @@ typedef struct VMXNET3Class {
 /* Cyclic ring abstraction */
 typedef struct {
 hwaddr pa;
-size_t size;
-size_t cell_size;
-size_t next;
+uint32_t size;
+uint32_t cell_size;
+uint32_t next;
 uint8_t gen;
 } Vmxnet3Ring;
 
 static inline void vmxnet3_ring_init(PCIDevice *d,
 Vmxnet3Ring *ring,
  hwaddr pa,
- size_t size,
- size_t cell_size,
+ uint32_t size,
+ uint32_t cell_size,
  bool zero_region)
 {
 ring->pa = pa;
@@ -166,7 +166,7 @@ static inline void vmxnet3_ring_init(PCIDevice *d,
 }
 
 #define VMXNET3_RING_DUMP(macro, ring_name, ridx, r) \
-macro("%s#%d: base %" PRIx64 " size %zu cell_size %zu gen %d next %zu",  \
+macro("%s#%d: base %" PRIx64 " size %u cell_size %u gen %d next %u",  \
   (ring_name), (ridx),   \
   (r)->pa, (r)->size, (r)->cell_size, (r)->gen, (r)->next)
 
-- 
2.7.4




[Qemu-devel] [PULL RESEND 15/19] filter-rewriter: skip net_checksum_calculate() while offset = 0

2017-03-05 Thread Jason Wang
From: zhanghailiang 

While the offset of packets's sequence for primary side and
secondary side is zero, it is unnecessary to call net_checksum_calculate()
to recalculate the checksume value of packets.

Signed-off-by: zhanghailiang 
Signed-off-by: Jason Wang 
---
 net/filter-rewriter.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
index c4ab91c..afa06e8 100644
--- a/net/filter-rewriter.c
+++ b/net/filter-rewriter.c
@@ -93,10 +93,12 @@ static int handle_primary_tcp_pkt(NetFilterState *nf,
 conn->offset -= (ntohl(tcp_pkt->th_ack) - 1);
 conn->syn_flag = 0;
 }
-/* handle packets to the secondary from the primary */
-tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset);
+if (conn->offset) {
+/* handle packets to the secondary from the primary */
+tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset);
 
-net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
+net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
+}
 }
 
 return 0;
@@ -129,10 +131,13 @@ static int handle_secondary_tcp_pkt(NetFilterState *nf,
 }
 
 if ((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == TH_ACK) {
-/* handle packets to the primary from the secondary*/
-tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset);
+/* Only need to adjust seq while offset is Non-zero */
+if (conn->offset) {
+/* handle packets to the primary from the secondary*/
+tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset);
 
-net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
+net_checksum_calculate((uint8_t *)pkt->data, pkt->size);
+}
 }
 
 return 0;
-- 
2.7.4




[Qemu-devel] [PULL RESEND 08/19] colo-compare: kick compare thread to exit after some cleanup in finalization

2017-03-05 Thread Jason Wang
From: zhanghailiang 

We should call g_main_loop_quit() to notify colo compare thread to
exit, Or it will run in g_main_loop_run() forever.

Besides, the finalizing process can't happen in context of colo thread,
it is reasonable to remove the 'if (qemu_thread_is_self(&s->thread))'
branch.

Before compare thead exits, some cleanup works need to be
done,  All unhandled packets need to be released and connection_track_table
needs to be freed, or there will be memory leak.

Signed-off-by: zhanghailiang 
Reviewed-by: Zhang Chen 
Signed-off-by: Jason Wang 
---
 net/colo-compare.c | 39 +--
 1 file changed, 29 insertions(+), 10 deletions(-)

diff --git a/net/colo-compare.c b/net/colo-compare.c
index fdde788..37ce75c 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -83,6 +83,8 @@ typedef struct CompareState {
 GHashTable *connection_track_table;
 /* compare thread, a thread for each NIC */
 QemuThread thread;
+
+GMainLoop *compare_loop;
 } CompareState;
 
 typedef struct CompareClass {
@@ -496,7 +498,6 @@ static gboolean check_old_packet_regular(void *opaque)
 static void *colo_compare_thread(void *opaque)
 {
 GMainContext *worker_context;
-GMainLoop *compare_loop;
 CompareState *s = opaque;
 GSource *timeout_source;
 
@@ -507,7 +508,7 @@ static void *colo_compare_thread(void *opaque)
 qemu_chr_fe_set_handlers(&s->chr_sec_in, compare_chr_can_read,
  compare_sec_chr_in, NULL, s, worker_context, 
true);
 
-compare_loop = g_main_loop_new(worker_context, FALSE);
+s->compare_loop = g_main_loop_new(worker_context, FALSE);
 
 /* To kick any packets that the secondary doesn't match */
 timeout_source = g_timeout_source_new(REGULAR_PACKET_CHECK_MS);
@@ -515,10 +516,10 @@ static void *colo_compare_thread(void *opaque)
   (GSourceFunc)check_old_packet_regular, s, NULL);
 g_source_attach(timeout_source, worker_context);
 
-g_main_loop_run(compare_loop);
+g_main_loop_run(s->compare_loop);
 
 g_source_unref(timeout_source);
-g_main_loop_unref(compare_loop);
+g_main_loop_unref(s->compare_loop);
 g_main_context_unref(worker_context);
 return NULL;
 }
@@ -675,6 +676,23 @@ static void colo_compare_complete(UserCreatable *uc, Error 
**errp)
 return;
 }
 
+static void colo_flush_packets(void *opaque, void *user_data)
+{
+CompareState *s = user_data;
+Connection *conn = opaque;
+Packet *pkt = NULL;
+
+while (!g_queue_is_empty(&conn->primary_list)) {
+pkt = g_queue_pop_head(&conn->primary_list);
+compare_chr_send(&s->chr_out, pkt->data, pkt->size);
+packet_destroy(pkt, NULL);
+}
+while (!g_queue_is_empty(&conn->secondary_list)) {
+pkt = g_queue_pop_head(&conn->secondary_list);
+packet_destroy(pkt, NULL);
+}
+}
+
 static void colo_compare_class_init(ObjectClass *oc, void *data)
 {
 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
@@ -703,14 +721,15 @@ static void colo_compare_finalize(Object *obj)
 qemu_chr_fe_deinit(&s->chr_sec_in);
 qemu_chr_fe_deinit(&s->chr_out);
 
-g_queue_free(&s->conn_list);
+g_main_loop_quit(s->compare_loop);
+qemu_thread_join(&s->thread);
 
-if (qemu_thread_is_self(&s->thread)) {
-/* compare connection */
-g_queue_foreach(&s->conn_list, colo_compare_connection, s);
-qemu_thread_join(&s->thread);
-}
+/* Release all unhandled packets after compare thead exited */
+g_queue_foreach(&s->conn_list, colo_flush_packets, s);
+
+g_queue_free(&s->conn_list);
 
+g_hash_table_destroy(s->connection_track_table);
 g_free(s->pri_indev);
 g_free(s->sec_indev);
 g_free(s->outdev);
-- 
2.7.4




[Qemu-devel] [PULL RESEND 10/19] colo-compare: Fix removing fds been watched incorrectly in finalization

2017-03-05 Thread Jason Wang
From: zhanghailiang 

We will catch the bellow error report while try to delete compare object
by qmp command:
chardev/char-io.c:91: io_watch_poll_finalize: Assertion `iwp->src == ((void 
*)0)' failed.

This is caused by failing to remove the right fd been watched while
call qemu_chr_fe_set_handlers();

Fix it by pass the worker_context parameter to qemu_chr_fe_set_handlers().

Signed-off-by: zhanghailiang 
Reviewed-by: Zhang Chen 
Signed-off-by: Jason Wang 
---
 net/colo-compare.c | 20 +++-
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/net/colo-compare.c b/net/colo-compare.c
index 37ce75c..a6fc2ff 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -84,6 +84,7 @@ typedef struct CompareState {
 /* compare thread, a thread for each NIC */
 QemuThread thread;
 
+GMainContext *worker_context;
 GMainLoop *compare_loop;
 } CompareState;
 
@@ -497,30 +498,29 @@ static gboolean check_old_packet_regular(void *opaque)
 
 static void *colo_compare_thread(void *opaque)
 {
-GMainContext *worker_context;
 CompareState *s = opaque;
 GSource *timeout_source;
 
-worker_context = g_main_context_new();
+s->worker_context = g_main_context_new();
 
 qemu_chr_fe_set_handlers(&s->chr_pri_in, compare_chr_can_read,
- compare_pri_chr_in, NULL, s, worker_context, 
true);
+  compare_pri_chr_in, NULL, s, s->worker_context, 
true);
 qemu_chr_fe_set_handlers(&s->chr_sec_in, compare_chr_can_read,
- compare_sec_chr_in, NULL, s, worker_context, 
true);
+  compare_sec_chr_in, NULL, s, s->worker_context, 
true);
 
-s->compare_loop = g_main_loop_new(worker_context, FALSE);
+s->compare_loop = g_main_loop_new(s->worker_context, FALSE);
 
 /* To kick any packets that the secondary doesn't match */
 timeout_source = g_timeout_source_new(REGULAR_PACKET_CHECK_MS);
 g_source_set_callback(timeout_source,
   (GSourceFunc)check_old_packet_regular, s, NULL);
-g_source_attach(timeout_source, worker_context);
+g_source_attach(timeout_source, s->worker_context);
 
 g_main_loop_run(s->compare_loop);
 
 g_source_unref(timeout_source);
 g_main_loop_unref(s->compare_loop);
-g_main_context_unref(worker_context);
+g_main_context_unref(s->worker_context);
 return NULL;
 }
 
@@ -717,8 +717,10 @@ static void colo_compare_finalize(Object *obj)
 {
 CompareState *s = COLO_COMPARE(obj);
 
-qemu_chr_fe_deinit(&s->chr_pri_in);
-qemu_chr_fe_deinit(&s->chr_sec_in);
+qemu_chr_fe_set_handlers(&s->chr_pri_in, NULL, NULL, NULL, NULL,
+ s->worker_context, true);
+qemu_chr_fe_set_handlers(&s->chr_sec_in, NULL, NULL, NULL, NULL,
+ s->worker_context, true);
 qemu_chr_fe_deinit(&s->chr_out);
 
 g_main_loop_quit(s->compare_loop);
-- 
2.7.4




[Qemu-devel] [PULL RESEND 07/19] colo-compare: use g_timeout_source_new() to process the stale packets

2017-03-05 Thread Jason Wang
From: zhanghailiang 

Instead of using qemu timer to process the stale packets,
We re-use the colo compare thread to process these packets
by creating a new timeout coroutine.

Besides, since we process all the same vNIC's net connection/packets
in one thread, it is safe to remove the timer_check_lock.

Signed-off-by: zhanghailiang 
Signed-off-by: Jason Wang 
---
 net/colo-compare.c | 62 +++---
 1 file changed, 22 insertions(+), 40 deletions(-)

diff --git a/net/colo-compare.c b/net/colo-compare.c
index 162fd6a..fdde788 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -83,9 +83,6 @@ typedef struct CompareState {
 GHashTable *connection_track_table;
 /* compare thread, a thread for each NIC */
 QemuThread thread;
-/* Timer used on the primary to find packets that are never matched */
-QEMUTimer *timer;
-QemuMutex timer_check_lock;
 } CompareState;
 
 typedef struct CompareClass {
@@ -374,9 +371,7 @@ static void colo_compare_connection(void *opaque, void 
*user_data)
 
 while (!g_queue_is_empty(&conn->primary_list) &&
!g_queue_is_empty(&conn->secondary_list)) {
-qemu_mutex_lock(&s->timer_check_lock);
 pkt = g_queue_pop_tail(&conn->primary_list);
-qemu_mutex_unlock(&s->timer_check_lock);
 switch (conn->ip_proto) {
 case IPPROTO_TCP:
 result = g_queue_find_custom(&conn->secondary_list,
@@ -411,9 +406,7 @@ static void colo_compare_connection(void *opaque, void 
*user_data)
  * until next comparison.
  */
 trace_colo_compare_main("packet different");
-qemu_mutex_lock(&s->timer_check_lock);
 g_queue_push_tail(&conn->primary_list, pkt);
-qemu_mutex_unlock(&s->timer_check_lock);
 /* TODO: colo_notify_checkpoint();*/
 break;
 }
@@ -486,11 +479,26 @@ static void compare_sec_chr_in(void *opaque, const 
uint8_t *buf, int size)
 }
 }
 
+/*
+ * Check old packet regularly so it can watch for any packets
+ * that the secondary hasn't produced equivalents of.
+ */
+static gboolean check_old_packet_regular(void *opaque)
+{
+CompareState *s = opaque;
+
+/* if have old packet we will notify checkpoint */
+colo_old_packet_check(s);
+
+return TRUE;
+}
+
 static void *colo_compare_thread(void *opaque)
 {
 GMainContext *worker_context;
 GMainLoop *compare_loop;
 CompareState *s = opaque;
+GSource *timeout_source;
 
 worker_context = g_main_context_new();
 
@@ -501,8 +509,15 @@ static void *colo_compare_thread(void *opaque)
 
 compare_loop = g_main_loop_new(worker_context, FALSE);
 
+/* To kick any packets that the secondary doesn't match */
+timeout_source = g_timeout_source_new(REGULAR_PACKET_CHECK_MS);
+g_source_set_callback(timeout_source,
+  (GSourceFunc)check_old_packet_regular, s, NULL);
+g_source_attach(timeout_source, worker_context);
+
 g_main_loop_run(compare_loop);
 
+g_source_unref(timeout_source);
 g_main_loop_unref(compare_loop);
 g_main_context_unref(worker_context);
 return NULL;
@@ -604,26 +619,6 @@ static int find_and_check_chardev(Chardev **chr,
 }
 
 /*
- * Check old packet regularly so it can watch for any packets
- * that the secondary hasn't produced equivalents of.
- */
-static void check_old_packet_regular(void *opaque)
-{
-CompareState *s = opaque;
-
-timer_mod(s->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
-  REGULAR_PACKET_CHECK_MS);
-/* if have old packet we will notify checkpoint */
-/*
- * TODO: Make timer handler run in compare thread
- * like qemu_chr_add_handlers_full.
- */
-qemu_mutex_lock(&s->timer_check_lock);
-colo_old_packet_check(s);
-qemu_mutex_unlock(&s->timer_check_lock);
-}
-
-/*
  * Called from the main thread on the primary
  * to setup colo-compare.
  */
@@ -665,7 +660,6 @@ static void colo_compare_complete(UserCreatable *uc, Error 
**errp)
 net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize);
 
 g_queue_init(&s->conn_list);
-qemu_mutex_init(&s->timer_check_lock);
 
 s->connection_track_table = g_hash_table_new_full(connection_key_hash,
   connection_key_equal,
@@ -678,12 +672,6 @@ static void colo_compare_complete(UserCreatable *uc, Error 
**errp)
QEMU_THREAD_JOINABLE);
 compare_id++;
 
-/* A regular timer to kick any packets that the secondary doesn't match */
-s->timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, /* Only when guest runs */
-check_old_packet_regular, s);
-timer_mod(s->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
-REGULAR_PACKET_CHECK_MS);
-
 return;
 }
 
@@ -723,12 +711,6 @@ static void colo_compare_finalize(Object *obj)
 qemu_thread_join(&s->thread);
 }
 
-if (s->timer) {
-timer

[Qemu-devel] [PULL RESEND 05/19] NetRxPkt: Account buffer with ETH header in IOV length

2017-03-05 Thread Jason Wang
From: Dmitry Fleytman 

In case of VLAN stripping ETH header is stored in a
separate chunk and length of IOV should take this into
account.

This patch fixes checksum validation for RX packets
with VLAN header.

Devices affected by this problem: e1000e and vmxnet3.

Cc: qemu-sta...@nongnu.org
Signed-off-by: Dmitry Fleytman 
Signed-off-by: Jason Wang 
---
 hw/net/net_rx_pkt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
index 0003a0e..2649d40 100644
--- a/hw/net/net_rx_pkt.c
+++ b/hw/net/net_rx_pkt.c
@@ -97,7 +97,7 @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt,
 pkt->tot_len = iov_size(iov, iovcnt) - ploff + pkt->ehdr_buf_len;
 pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1,
 iov, iovcnt, ploff,
-pkt->tot_len - pkt->ehdr_buf_len);
+pkt->tot_len - pkt->ehdr_buf_len) + 1;
 } else {
 net_rx_pkt_iovec_realloc(pkt, iovcnt);
 
-- 
2.7.4




[Qemu-devel] [PULL RESEND 06/19] NetRxPkt: Remove code duplication in net_rx_pkt_pull_data()

2017-03-05 Thread Jason Wang
From: Dmitry Fleytman 

This is a refactoring commit that does not change behavior.

Signed-off-by: Dmitry Fleytman 
Signed-off-by: Jason Wang 
---
 hw/net/net_rx_pkt.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
index 2649d40..cef1c2e 100644
--- a/hw/net/net_rx_pkt.c
+++ b/hw/net/net_rx_pkt.c
@@ -88,20 +88,21 @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt,
 const struct iovec *iov, int iovcnt,
 size_t ploff)
 {
+uint32_t pllen = iov_size(iov, iovcnt) - ploff;
+
 if (pkt->ehdr_buf_len) {
 net_rx_pkt_iovec_realloc(pkt, iovcnt + 1);
 
 pkt->vec[0].iov_base = pkt->ehdr_buf;
 pkt->vec[0].iov_len = pkt->ehdr_buf_len;
 
-pkt->tot_len = iov_size(iov, iovcnt) - ploff + pkt->ehdr_buf_len;
+pkt->tot_len = pllen + pkt->ehdr_buf_len;
 pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1,
-iov, iovcnt, ploff,
-pkt->tot_len - pkt->ehdr_buf_len) + 1;
+iov, iovcnt, ploff, pllen) + 1;
 } else {
 net_rx_pkt_iovec_realloc(pkt, iovcnt);
 
-pkt->tot_len = iov_size(iov, iovcnt) - ploff;
+pkt->tot_len = pllen;
 pkt->vec_len = iov_copy(pkt->vec, pkt->vec_len_total,
 iov, iovcnt, ploff, pkt->tot_len);
 }
-- 
2.7.4




[Qemu-devel] [PULL RESEND 13/19] vmxnet3: VMStatify rx/tx q_descr and int_state

2017-03-05 Thread Jason Wang
From: "Dr. David Alan Gilbert" 

Fairly simple mechanical conversion of all fields.

TODO
The problem is vmxnet3-ring size/cell_size/next are declared as size_t
but written as 32bit.

Signed-off-by: Dr. David Alan Gilbert 
Acked-by: Dmitry Fleytman 
Signed-off-by: Jason Wang 
---
 hw/net/vmxnet3.c | 272 ++-
 1 file changed, 90 insertions(+), 182 deletions(-)

diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 224c109..8b1fab2 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -2403,155 +2403,87 @@ static const VMStateDescription 
vmxstate_vmxnet3_mcast_list = {
 }
 };
 
-static void vmxnet3_get_ring_from_file(QEMUFile *f, Vmxnet3Ring *r)
-{
-r->pa = qemu_get_be64(f);
-r->size = qemu_get_be32(f);
-r->cell_size = qemu_get_be32(f);
-r->next = qemu_get_be32(f);
-r->gen = qemu_get_byte(f);
-}
-
-static void vmxnet3_put_ring_to_file(QEMUFile *f, Vmxnet3Ring *r)
-{
-qemu_put_be64(f, r->pa);
-qemu_put_be32(f, r->size);
-qemu_put_be32(f, r->cell_size);
-qemu_put_be32(f, r->next);
-qemu_put_byte(f, r->gen);
-}
-
-static void vmxnet3_get_tx_stats_from_file(QEMUFile *f,
-struct UPT1_TxStats *tx_stat)
-{
-tx_stat->TSOPktsTxOK = qemu_get_be64(f);
-tx_stat->TSOBytesTxOK = qemu_get_be64(f);
-tx_stat->ucastPktsTxOK = qemu_get_be64(f);
-tx_stat->ucastBytesTxOK = qemu_get_be64(f);
-tx_stat->mcastPktsTxOK = qemu_get_be64(f);
-tx_stat->mcastBytesTxOK = qemu_get_be64(f);
-tx_stat->bcastPktsTxOK = qemu_get_be64(f);
-tx_stat->bcastBytesTxOK = qemu_get_be64(f);
-tx_stat->pktsTxError = qemu_get_be64(f);
-tx_stat->pktsTxDiscard = qemu_get_be64(f);
-}
-
-static void vmxnet3_put_tx_stats_to_file(QEMUFile *f,
-struct UPT1_TxStats *tx_stat)
-{
-qemu_put_be64(f, tx_stat->TSOPktsTxOK);
-qemu_put_be64(f, tx_stat->TSOBytesTxOK);
-qemu_put_be64(f, tx_stat->ucastPktsTxOK);
-qemu_put_be64(f, tx_stat->ucastBytesTxOK);
-qemu_put_be64(f, tx_stat->mcastPktsTxOK);
-qemu_put_be64(f, tx_stat->mcastBytesTxOK);
-qemu_put_be64(f, tx_stat->bcastPktsTxOK);
-qemu_put_be64(f, tx_stat->bcastBytesTxOK);
-qemu_put_be64(f, tx_stat->pktsTxError);
-qemu_put_be64(f, tx_stat->pktsTxDiscard);
-}
-
-static int vmxnet3_get_txq_descr(QEMUFile *f, void *pv, size_t size,
-VMStateField *field)
-{
-Vmxnet3TxqDescr *r = pv;
-
-vmxnet3_get_ring_from_file(f, &r->tx_ring);
-vmxnet3_get_ring_from_file(f, &r->comp_ring);
-r->intr_idx = qemu_get_byte(f);
-r->tx_stats_pa = qemu_get_be64(f);
-
-vmxnet3_get_tx_stats_from_file(f, &r->txq_stats);
-
-return 0;
-}
-
-static int vmxnet3_put_txq_descr(QEMUFile *f, void *pv, size_t size,
- VMStateField *field, QJSON *vmdesc)
-{
-Vmxnet3TxqDescr *r = pv;
-
-vmxnet3_put_ring_to_file(f, &r->tx_ring);
-vmxnet3_put_ring_to_file(f, &r->comp_ring);
-qemu_put_byte(f, r->intr_idx);
-qemu_put_be64(f, r->tx_stats_pa);
-vmxnet3_put_tx_stats_to_file(f, &r->txq_stats);
-
-return 0;
-}
-
-static const VMStateInfo txq_descr_info = {
-.name = "txq_descr",
-.get = vmxnet3_get_txq_descr,
-.put = vmxnet3_put_txq_descr
+static const VMStateDescription vmstate_vmxnet3_ring = {
+.name = "vmxnet3-ring",
+.version_id = 0,
+.fields = (VMStateField[]) {
+VMSTATE_UINT64(pa, Vmxnet3Ring),
+VMSTATE_UINT32(size, Vmxnet3Ring),
+VMSTATE_UINT32(cell_size, Vmxnet3Ring),
+VMSTATE_UINT32(next, Vmxnet3Ring),
+VMSTATE_UINT8(gen, Vmxnet3Ring),
+VMSTATE_END_OF_LIST()
+}
 };
 
-static void vmxnet3_get_rx_stats_from_file(QEMUFile *f,
-struct UPT1_RxStats *rx_stat)
-{
-rx_stat->LROPktsRxOK = qemu_get_be64(f);
-rx_stat->LROBytesRxOK = qemu_get_be64(f);
-rx_stat->ucastPktsRxOK = qemu_get_be64(f);
-rx_stat->ucastBytesRxOK = qemu_get_be64(f);
-rx_stat->mcastPktsRxOK = qemu_get_be64(f);
-rx_stat->mcastBytesRxOK = qemu_get_be64(f);
-rx_stat->bcastPktsRxOK = qemu_get_be64(f);
-rx_stat->bcastBytesRxOK = qemu_get_be64(f);
-rx_stat->pktsRxOutOfBuf = qemu_get_be64(f);
-rx_stat->pktsRxError = qemu_get_be64(f);
-}
-
-static void vmxnet3_put_rx_stats_to_file(QEMUFile *f,
-struct UPT1_RxStats *rx_stat)
-{
-qemu_put_be64(f, rx_stat->LROPktsRxOK);
-qemu_put_be64(f, rx_stat->LROBytesRxOK);
-qemu_put_be64(f, rx_stat->ucastPktsRxOK);
-qemu_put_be64(f, rx_stat->ucastBytesRxOK);
-qemu_put_be64(f, rx_stat->mcastPktsRxOK);
-qemu_put_be64(f, rx_stat->mcastBytesRxOK);
-qemu_put_be64(f, rx_stat->bcastPktsRxOK);
-qemu_put_be64(f, rx_stat->bcastBytesRxOK);
-qemu_put_be64(f, rx_stat->pktsRxOutOfBuf);
-qemu_put_be64(f, rx_stat->pktsRxError);
-}
-
-static int vmxnet3_get_rxq_descr(QEMUFile *f, void *pv, size_t size,
-VMStateField *field)
-{
-Vmxnet3RxqDescr *r = pv;
-int i;
-
-for (i = 0; i < VMXNET3_RX_RINGS_PER_QUEUE; i++) {
-vmxnet3_get_ring_f

[Qemu-devel] [PULL RESEND 03/19] NetRxPkt: Fix memory corruption on VLAN header stripping

2017-03-05 Thread Jason Wang
From: Dmitry Fleytman 

This patch fixed a problem that was introduced in commit eb700029.

When net_rx_pkt_attach_iovec() calls eth_strip_vlan()
this can result in pkt->ehdr_buf being overflowed, because
ehdr_buf is only sizeof(struct eth_header) bytes large
but eth_strip_vlan() can write
sizeof(struct eth_header) + sizeof(struct vlan_header)
bytes into it.

Devices affected by this problem: vmxnet3.

Cc: qemu-sta...@nongnu.org
Reported-by: Peter Maydell 
Signed-off-by: Dmitry Fleytman 
Signed-off-by: Jason Wang 
---
 hw/net/net_rx_pkt.c | 34 +-
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
index 7f928d7..3361d7e 100644
--- a/hw/net/net_rx_pkt.c
+++ b/hw/net/net_rx_pkt.c
@@ -23,13 +23,13 @@
 
 struct NetRxPkt {
 struct virtio_net_hdr virt_hdr;
-uint8_t ehdr_buf[sizeof(struct eth_header)];
+uint8_t ehdr_buf[sizeof(struct eth_header) + sizeof(struct vlan_header)];
 struct iovec *vec;
 uint16_t vec_len_total;
 uint16_t vec_len;
 uint32_t tot_len;
 uint16_t tci;
-bool vlan_stripped;
+size_t ehdr_buf_len;
 bool has_virt_hdr;
 eth_pkt_types_e packet_type;
 
@@ -88,15 +88,13 @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt,
 const struct iovec *iov, int iovcnt,
 size_t ploff)
 {
-if (pkt->vlan_stripped) {
+if (pkt->ehdr_buf_len) {
 net_rx_pkt_iovec_realloc(pkt, iovcnt + 1);
 
 pkt->vec[0].iov_base = pkt->ehdr_buf;
-pkt->vec[0].iov_len = sizeof(pkt->ehdr_buf);
-
-pkt->tot_len =
-iov_size(iov, iovcnt) - ploff + sizeof(struct eth_header);
+pkt->vec[0].iov_len = pkt->ehdr_buf_len;
 
+pkt->tot_len = iov_size(iov, iovcnt) - ploff + pkt->ehdr_buf_len;
 pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1,
 iov, iovcnt, ploff, pkt->tot_len);
 } else {
@@ -123,11 +121,12 @@ void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt,
 uint16_t tci = 0;
 uint16_t ploff = iovoff;
 assert(pkt);
-pkt->vlan_stripped = false;
 
 if (strip_vlan) {
-pkt->vlan_stripped = eth_strip_vlan(iov, iovcnt, iovoff, pkt->ehdr_buf,
-&ploff, &tci);
+pkt->ehdr_buf_len = eth_strip_vlan(iov, iovcnt, iovoff, pkt->ehdr_buf,
+   &ploff, &tci);
+} else {
+pkt->ehdr_buf_len = 0;
 }
 
 pkt->tci = tci;
@@ -143,12 +142,13 @@ void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt,
 uint16_t tci = 0;
 uint16_t ploff = iovoff;
 assert(pkt);
-pkt->vlan_stripped = false;
 
 if (strip_vlan) {
-pkt->vlan_stripped = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet,
-   pkt->ehdr_buf,
-   &ploff, &tci);
+pkt->ehdr_buf_len = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet,
+  pkt->ehdr_buf,
+  &ploff, &tci);
+} else {
+pkt->ehdr_buf_len = 0;
 }
 
 pkt->tci = tci;
@@ -161,8 +161,8 @@ void net_rx_pkt_dump(struct NetRxPkt *pkt)
 #ifdef NET_RX_PKT_DEBUG
 assert(pkt);
 
-printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n",
-  pkt->tot_len, pkt->vlan_stripped, pkt->tci);
+printf("RX PKT: tot_len: %d, ehdr_buf_len: %lu, vlan_tag: %d\n",
+  pkt->tot_len, pkt->ehdr_buf_len, pkt->tci);
 #endif
 }
 
@@ -425,7 +425,7 @@ bool net_rx_pkt_is_vlan_stripped(struct NetRxPkt *pkt)
 {
 assert(pkt);
 
-return pkt->vlan_stripped;
+return pkt->ehdr_buf_len ? true : false;
 }
 
 bool net_rx_pkt_has_virt_hdr(struct NetRxPkt *pkt)
-- 
2.7.4




[Qemu-devel] [PULL RESEND 02/19] eth: Extend vlan stripping functions

2017-03-05 Thread Jason Wang
From: Dmitry Fleytman 

Make VLAN stripping functions return number of bytes
copied to given Ethernet header buffer.

This information should be used to re-compose
packet IOV after VLAN stripping.

Cc: qemu-sta...@nongnu.org
Signed-off-by: Dmitry Fleytman 
Signed-off-by: Jason Wang 
---
 include/net/eth.h |  4 ++--
 net/eth.c | 25 ++---
 2 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/include/net/eth.h b/include/net/eth.h
index 2013175..afeb45b 100644
--- a/include/net/eth.h
+++ b/include/net/eth.h
@@ -331,12 +331,12 @@ eth_get_pkt_tci(const void *p)
 }
 }
 
-bool
+size_t
 eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
uint8_t *new_ehdr_buf,
uint16_t *payload_offset, uint16_t *tci);
 
-bool
+size_t
 eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
   uint16_t vet, uint8_t *new_ehdr_buf,
   uint16_t *payload_offset, uint16_t *tci);
diff --git a/net/eth.c b/net/eth.c
index df81efb..5b9ba26 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -232,7 +232,7 @@ void eth_get_protocols(const struct iovec *iov, int iovcnt,
 }
 }
 
-bool
+size_t
 eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
uint8_t *new_ehdr_buf,
uint16_t *payload_offset, uint16_t *tci)
@@ -244,7 +244,7 @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t 
iovoff,
new_ehdr, sizeof(*new_ehdr));
 
 if (copied < sizeof(*new_ehdr)) {
-return false;
+return 0;
 }
 
 switch (be16_to_cpu(new_ehdr->h_proto)) {
@@ -254,7 +254,7 @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t 
iovoff,
 &vlan_hdr, sizeof(vlan_hdr));
 
 if (copied < sizeof(vlan_hdr)) {
-return false;
+return 0;
 }
 
 new_ehdr->h_proto = vlan_hdr.h_proto;
@@ -268,18 +268,21 @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, 
size_t iovoff,
 PKT_GET_VLAN_HDR(new_ehdr), sizeof(vlan_hdr));
 
 if (copied < sizeof(vlan_hdr)) {
-return false;
+return 0;
 }
 
 *payload_offset += sizeof(vlan_hdr);
+
+return sizeof(struct eth_header) + sizeof(struct vlan_header);
+} else {
+return sizeof(struct eth_header);
 }
-return true;
 default:
-return false;
+return 0;
 }
 }
 
-bool
+size_t
 eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
   uint16_t vet, uint8_t *new_ehdr_buf,
   uint16_t *payload_offset, uint16_t *tci)
@@ -291,7 +294,7 @@ eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, 
size_t iovoff,
new_ehdr, sizeof(*new_ehdr));
 
 if (copied < sizeof(*new_ehdr)) {
-return false;
+return 0;
 }
 
 if (be16_to_cpu(new_ehdr->h_proto) == vet) {
@@ -299,17 +302,17 @@ eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, 
size_t iovoff,
 &vlan_hdr, sizeof(vlan_hdr));
 
 if (copied < sizeof(vlan_hdr)) {
-return false;
+return 0;
 }
 
 new_ehdr->h_proto = vlan_hdr.h_proto;
 
 *tci = be16_to_cpu(vlan_hdr.h_tci);
 *payload_offset = iovoff + sizeof(*new_ehdr) + sizeof(vlan_hdr);
-return true;
+return sizeof(struct eth_header);
 }
 
-return false;
+return 0;
 }
 
 void
-- 
2.7.4




[Qemu-devel] [PULL RESEND 04/19] NetRxPkt: Do not try to pull more data than present

2017-03-05 Thread Jason Wang
From: Dmitry Fleytman 

In case of VLAN stripping, ETH header put into a
separate buffer, therefore amont of data copied
from original IOV should be smaller.

Cc: qemu-sta...@nongnu.org
Signed-off-by: Dmitry Fleytman 
Signed-off-by: Jason Wang 
---
 hw/net/net_rx_pkt.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
index 3361d7e..0003a0e 100644
--- a/hw/net/net_rx_pkt.c
+++ b/hw/net/net_rx_pkt.c
@@ -96,7 +96,8 @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt,
 
 pkt->tot_len = iov_size(iov, iovcnt) - ploff + pkt->ehdr_buf_len;
 pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1,
-iov, iovcnt, ploff, pkt->tot_len);
+iov, iovcnt, ploff,
+pkt->tot_len - pkt->ehdr_buf_len);
 } else {
 net_rx_pkt_iovec_realloc(pkt, iovcnt);
 
-- 
2.7.4




[Qemu-devel] [PULL RESEND 00/19] Net patches

2017-03-05 Thread Jason Wang
The following changes since commit 17783ac828adc694d986698d2d7014aedfeb48c6:

  Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.9-20170303' into 
staging (2017-03-04 16:31:14 +)

are available in the git repository at:

  https://github.com/jasowang/qemu.git tags/net-pull-request

for you to fetch changes up to f0aabd5c4ae11fde704d138e8f06c69e5c902a16:

  net/filter-mirror: Follow CODING_STYLE (2017-03-06 11:46:02 +0800)


Preview pull does not reach list.

- fix vlan issues for e1000e
- convert to use vmstate for vmxnet3
- several fixes for colo

Dmitry Fleytman (5):
  eth: Extend vlan stripping functions
  NetRxPkt: Fix memory corruption on VLAN header stripping
  NetRxPkt: Do not try to pull more data than present
  NetRxPkt: Account buffer with ETH header in IOV length
  NetRxPkt: Remove code duplication in net_rx_pkt_pull_data()

Dr. David Alan Gilbert (2):
  vmxnet3: Convert ring values to uint32_t's
  vmxnet3: VMStatify rx/tx q_descr and int_state

Fam Zheng (1):
  net: Remove useless local var pkt

Zhang Chen (5):
  net/colo-compare: Fix memory free error
  COLO-compare: Rename compare function and remove duplicate codes
  COLO-compare: Optimize compare_common and compare_tcp
  COLO-compare: Fix icmp and udp compare different packet always dump bug
  net/filter-mirror: Follow CODING_STYLE

zhanghailiang (6):
  colo-compare: use g_timeout_source_new() to process the stale packets
  colo-compare: kick compare thread to exit after some cleanup in 
finalization
  char: remove the right fd been watched in qemu_chr_fe_set_handlers()
  colo-compare: Fix removing fds been watched incorrectly in finalization
  net/colo: fix memory double free error
  filter-rewriter: skip net_checksum_calculate() while offset = 0

 chardev/char-fd.c |   6 +-
 chardev/char-io.c |   8 +-
 chardev/char-io.h |   2 +-
 chardev/char-pty.c|   2 +-
 chardev/char-socket.c |   4 +-
 chardev/char-udp.c|   6 +-
 chardev/char.c|   2 +-
 hw/net/net_rx_pkt.c   |  41 
 hw/net/vmxnet3.c  | 284 +-
 include/net/eth.h |   4 +-
 net/colo-compare.c| 189 +++--
 net/colo.c|   4 +-
 net/eth.c |  25 +++--
 net/filter-mirror.c   |   7 +-
 net/filter-rewriter.c |  17 +--
 15 files changed, 273 insertions(+), 328 deletions(-)




[Qemu-devel] [PULL RESEND 09/19] char: remove the right fd been watched in qemu_chr_fe_set_handlers()

2017-03-05 Thread Jason Wang
From: zhanghailiang 

We can call qemu_chr_fe_set_handlers() to add/remove fd been watched
in 'context' which can be either default main context or other explicit
context. But the original logic is not correct, we didn't remove
the right fd because we call g_main_context_find_source_by_id(NULL, tag)
which always try to find the Gsource from default context.

Fix it by passing the right context to g_main_context_find_source_by_id().

Cc: Paolo Bonzini 
Cc: Marc-André Lureau 
Signed-off-by: zhanghailiang 
Reviewed-by: Marc-André Lureau 
Signed-off-by: Jason Wang 
---
 chardev/char-fd.c | 6 +++---
 chardev/char-io.c | 8 
 chardev/char-io.h | 2 +-
 chardev/char-pty.c| 2 +-
 chardev/char-socket.c | 4 ++--
 chardev/char-udp.c| 6 +++---
 chardev/char.c| 2 +-
 7 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/chardev/char-fd.c b/chardev/char-fd.c
index fb51ab4..548dd4c 100644
--- a/chardev/char-fd.c
+++ b/chardev/char-fd.c
@@ -58,7 +58,7 @@ static gboolean fd_chr_read(QIOChannel *chan, GIOCondition 
cond, void *opaque)
 ret = qio_channel_read(
 chan, (gchar *)buf, len, NULL);
 if (ret == 0) {
-remove_fd_in_watch(chr);
+remove_fd_in_watch(chr, NULL);
 qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 return FALSE;
 }
@@ -89,7 +89,7 @@ static void fd_chr_update_read_handler(Chardev *chr,
 {
 FDChardev *s = FD_CHARDEV(chr);
 
-remove_fd_in_watch(chr);
+remove_fd_in_watch(chr, NULL);
 if (s->ioc_in) {
 chr->fd_in_tag = io_add_watch_poll(chr, s->ioc_in,
fd_chr_read_poll,
@@ -103,7 +103,7 @@ static void char_fd_finalize(Object *obj)
 Chardev *chr = CHARDEV(obj);
 FDChardev *s = FD_CHARDEV(obj);
 
-remove_fd_in_watch(chr);
+remove_fd_in_watch(chr, NULL);
 if (s->ioc_in) {
 object_unref(OBJECT(s->ioc_in));
 }
diff --git a/chardev/char-io.c b/chardev/char-io.c
index 7dfc3f2..b4bb094 100644
--- a/chardev/char-io.c
+++ b/chardev/char-io.c
@@ -127,14 +127,14 @@ guint io_add_watch_poll(Chardev *chr,
 return tag;
 }
 
-static void io_remove_watch_poll(guint tag)
+static void io_remove_watch_poll(guint tag, GMainContext *context)
 {
 GSource *source;
 IOWatchPoll *iwp;
 
 g_return_if_fail(tag > 0);
 
-source = g_main_context_find_source_by_id(NULL, tag);
+source = g_main_context_find_source_by_id(context, tag);
 g_return_if_fail(source != NULL);
 
 iwp = io_watch_poll_from_source(source);
@@ -146,10 +146,10 @@ static void io_remove_watch_poll(guint tag)
 g_source_destroy(&iwp->parent);
 }
 
-void remove_fd_in_watch(Chardev *chr)
+void remove_fd_in_watch(Chardev *chr, GMainContext *context)
 {
 if (chr->fd_in_tag) {
-io_remove_watch_poll(chr->fd_in_tag);
+io_remove_watch_poll(chr->fd_in_tag, context);
 chr->fd_in_tag = 0;
 }
 }
diff --git a/chardev/char-io.h b/chardev/char-io.h
index d7ae5f1..842be56 100644
--- a/chardev/char-io.h
+++ b/chardev/char-io.h
@@ -36,7 +36,7 @@ guint io_add_watch_poll(Chardev *chr,
 gpointer user_data,
 GMainContext *context);
 
-void remove_fd_in_watch(Chardev *chr);
+void remove_fd_in_watch(Chardev *chr, GMainContext *context);
 
 int io_channel_send(QIOChannel *ioc, const void *buf, size_t len);
 
diff --git a/chardev/char-pty.c b/chardev/char-pty.c
index ecf2c7a..a6337be 100644
--- a/chardev/char-pty.c
+++ b/chardev/char-pty.c
@@ -199,7 +199,7 @@ static void pty_chr_state(Chardev *chr, int connected)
 g_source_remove(s->open_tag);
 s->open_tag = 0;
 }
-remove_fd_in_watch(chr);
+remove_fd_in_watch(chr, NULL);
 s->connected = 0;
 /* (re-)connect poll interval for idle guests: once per second.
  * We check more frequently in case the guests sends data to
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 865c527..d7e92e1 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -328,7 +328,7 @@ static void tcp_chr_free_connection(Chardev *chr)
 }
 
 tcp_set_msgfds(chr, NULL, 0);
-remove_fd_in_watch(chr);
+remove_fd_in_watch(chr, NULL);
 object_unref(OBJECT(s->sioc));
 s->sioc = NULL;
 object_unref(OBJECT(s->ioc));
@@ -498,7 +498,7 @@ static void tcp_chr_update_read_handler(Chardev *chr,
 return;
 }
 
-remove_fd_in_watch(chr);
+remove_fd_in_watch(chr, NULL);
 if (s->ioc) {
 chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
tcp_chr_read_poll,
diff --git a/chardev/char-udp.c b/chardev/char-udp.c
index 2c6c7dd..804bd22 100644
--- a/chardev/char-udp.c
+++ b/chardev/char-udp.c
@@ -81,7 +81,7 @@ static gboolean udp_chr_read(QIOChannel *chan, GIOCondition 
cond, void *opaque)
 ret = qio_channel_read(
 s->ioc, (char *)s->buf, sizeof(s->buf), NULL);
 if (ret <= 0) {
-remove_fd_in_watch(chr

[Qemu-devel] [PULL RESEND 01/19] net: Remove useless local var pkt

2017-03-05 Thread Jason Wang
From: Fam Zheng 

This has been pointless since commit 605d52e62, which was a
search-and-replace, overlooked the redundancy.

Signed-off-by: Fam Zheng 
Reviewed-by: Dmitry Fleytman 
Signed-off-by: Jason Wang 
---
 hw/net/net_rx_pkt.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
index 1019b50..7f928d7 100644
--- a/hw/net/net_rx_pkt.c
+++ b/hw/net/net_rx_pkt.c
@@ -159,7 +159,6 @@ void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt,
 void net_rx_pkt_dump(struct NetRxPkt *pkt)
 {
 #ifdef NET_RX_PKT_DEBUG
-NetRxPkt *pkt = (NetRxPkt *)pkt;
 assert(pkt);
 
 printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n",
-- 
2.7.4




Re: [Qemu-devel] [PATCH] net/filter-mirror: Follow CODING_STYLE

2017-03-05 Thread Jason Wang



On 2017年03月02日 11:59, Zhang Chen wrote:

Signed-off-by: Zhang Chen 
---
  net/filter-mirror.c | 7 ---
  1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index aa0aa98..72fa7c2 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -49,7 +49,7 @@ static int filter_mirror_send(CharBackend *chr_out,
  {
  int ret = 0;
  ssize_t size = 0;
-uint32_t len =  0;
+uint32_t len = 0;
  char *buf;
  
  size = iov_size(iov, iovcnt);

@@ -77,8 +77,9 @@ err:
  return ret < 0 ? ret : -EIO;
  }
  
-static void

-redirector_to_filter(NetFilterState *nf, const uint8_t *buf, int len)
+static void redirector_to_filter(NetFilterState *nf,
+ const uint8_t *buf,
+ int len)
  {
  struct iovec iov = {
  .iov_base = (void *)buf,


Applied, thanks.



Re: [Qemu-devel] [PATCH V3 0/3] COLO-compare: Optimize the code and fix some bug

2017-03-05 Thread Jason Wang



On 2017年03月02日 17:54, Zhang Chen wrote:

This series we will Optimize the code and fix some bug.
Patch1: Rename colo_packet_compare() and remove duplicate check in compare icmp.
Patch2: Optimize compare_common and increase compare performance.
Patch3: Fix debug info always print bug.

Zhang Chen (3):
   COLO-compare: Rename compare function and remove duplicate codes
   COLO-compare: Optimize compare_common and compare_tcp
   COLO-compare: Fix icmp and udp compare different packet always dump
 bug

  net/colo-compare.c | 74 --
  1 file changed, 49 insertions(+), 25 deletions(-)



Applied, thanks.



Re: [Qemu-devel] [PATCH v2] spapr_pci: allow control of BAR alignment through SLOF

2017-03-05 Thread David Gibson
On Fri, Mar 03, 2017 at 05:32:57PM -0600, Michael Roth wrote:
> In certain cases, such as PCI-passthrough with VFIO, we cannot offload
> MMIO accesses to KVM unless the BAR alignment matches the host. This
> patch, in conjunction with a separately submitted patch for SLOF
> which allows for control of this via the device-tree, allows us to
> set this alignment via QEMU.
> 
> Cc: qemu-...@nongnu.org
> Cc: Nikunj A Dadhania 
> Cc: David Gibson 
> Cc: Alexey Kardashevskiy 
> Signed-off-by: Michael Roth 
> ---
> v2:
>   * Keep natural alignment as the default in SLOF, only set DT prop if
> different alignment is specified by QEMU (David)

Unfortunately, this has missed the cutoff for qemu-2.9.  

I'm afraid I'm still not entirely clear on the rationale here.

Why do we need a variable parameter based on the host page size?
Couldn't we just have SLOF always align to something "big enough"
(64kiB, IIUC)?

> ---
>  hw/ppc/spapr.c  |  7 ++-
>  hw/ppc/spapr_pci.c  | 10 ++
>  include/hw/pci-host/spapr.h |  1 +
>  3 files changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 14192ac..ef8df35 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -3166,7 +3166,12 @@ DEFINE_SPAPR_MACHINE(2_9, "2.9", true);
>   * pseries-2.8
>   */
>  #define SPAPR_COMPAT_2_8\
> -HW_COMPAT_2_8
> +HW_COMPAT_2_8   \
> +{   \
> +.driver   = TYPE_SPAPR_PCI_HOST_BRIDGE, \
> +.property = "mem_bar_min_align",\
> +.value= "0",\
> +},  \
>  
>  static void spapr_machine_2_8_instance_options(MachineState *machine)
>  {
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index 919d3c2..485d32d 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -1664,6 +1664,10 @@ static void spapr_phb_realize(DeviceState *dev, Error 
> **errp)
>  return;
>  }
>  
> +if (sphb->mem_bar_min_align == (uint64_t)-1) {
> +sphb->mem_bar_min_align = qemu_real_host_page_size;
> +}
> +
>  sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid);
>  
>  namebuf = alloca(strlen(sphb->dtbusname) + 32);
> @@ -1858,6 +1862,8 @@ static Property spapr_phb_properties[] = {
>  DEFINE_PROP_UINT32("numa_node", sPAPRPHBState, numa_node, -1),
>  DEFINE_PROP_BOOL("pre-2.8-migration", sPAPRPHBState,
>   pre_2_8_migration, false),
> +DEFINE_PROP_UINT64("mem_bar_min_align", sPAPRPHBState, mem_bar_min_align,
> +   -1),
>  DEFINE_PROP_END_OF_LIST(),
>  };
>  
> @@ -2228,6 +2234,10 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
>  if (ret) {
>  return ret;
>  }
> +if (phb->mem_bar_min_align) {
> +_FDT(fdt_setprop_cell(fdt, bus_off, "qemu,mem-bar-min-align",
> +  phb->mem_bar_min_align));
> +}
>  
>  return 0;
>  }
> diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
> index dfa7614..fa33346 100644
> --- a/include/hw/pci-host/spapr.h
> +++ b/include/hw/pci-host/spapr.h
> @@ -79,6 +79,7 @@ struct sPAPRPHBState {
>  uint64_t dma64_win_addr;
>  
>  uint32_t numa_node;
> +uint64_t mem_bar_min_align;
>  
>  /* Fields for migration compatibility hacks */
>  bool pre_2_8_migration;

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


signature.asc
Description: PGP signature


[Qemu-devel] [PULL 4/5] target/ppc: fmadd: add macro for updating flags

2017-03-05 Thread David Gibson
From: Nikunj A Dadhania 

Adds FPU_MADDSUB_UPDATE macro, this will be used for other routines
having float32/16

Signed-off-by: Nikunj A Dadhania 
Signed-off-by: David Gibson 
---
 target/ppc/fpu_helper.c | 61 -
 1 file changed, 30 insertions(+), 31 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index a547f58..13bd6ce 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -743,38 +743,37 @@ uint64_t helper_frim(CPUPPCState *env, uint64_t arg)
 return do_fri(env, arg, float_round_down);
 }
 
-static void float64_maddsub_update_excp(CPUPPCState *env, float64 arg1,
-float64 arg2, float64 arg3,
-unsigned int madd_flags)
-{
-if (unlikely(float64_is_signaling_nan(arg1, &env->fp_status) ||
- float64_is_signaling_nan(arg2, &env->fp_status) ||
- float64_is_signaling_nan(arg3, &env->fp_status))) {
-/* sNaN operation */
-float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
-}
-
-if (unlikely((float64_is_infinity(arg1) && float64_is_zero(arg2)) ||
- (float64_is_zero(arg1) && float64_is_infinity(arg2 {
-/* Multiplication of zero by infinity */
-float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
-}
-
-if ((float64_is_infinity(arg1) || float64_is_infinity(arg2)) &&
-float64_is_infinity(arg3)) {
-uint8_t aSign, bSign, cSign;
-
-aSign = float64_is_neg(arg1);
-bSign = float64_is_neg(arg2);
-cSign = float64_is_neg(arg3);
-if (madd_flags & float_muladd_negate_c) {
-cSign ^= 1;
-}
-if (aSign ^ bSign ^ cSign) {
-float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
-}
-}
+#define FPU_MADDSUB_UPDATE(NAME, TP)\
+static void NAME(CPUPPCState *env, TP arg1, TP arg2, TP arg3,   \
+ unsigned int madd_flags)   \
+{   \
+if (TP##_is_signaling_nan(arg1, &env->fp_status) || \
+TP##_is_signaling_nan(arg2, &env->fp_status) || \
+TP##_is_signaling_nan(arg3, &env->fp_status)) { \
+/* sNaN operation */\
+float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);  \
+}   \
+if ((TP##_is_infinity(arg1) && TP##_is_zero(arg2)) ||   \
+(TP##_is_zero(arg1) && TP##_is_infinity(arg2))) {   \
+/* Multiplication of zero by infinity */\
+float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);   \
+}   \
+if ((TP##_is_infinity(arg1) || TP##_is_infinity(arg2)) &&   \
+TP##_is_infinity(arg3)) {   \
+uint8_t aSign, bSign, cSign;\
+\
+aSign = TP##_is_neg(arg1);  \
+bSign = TP##_is_neg(arg2);  \
+cSign = TP##_is_neg(arg3);  \
+if (madd_flags & float_muladd_negate_c) {   \
+cSign ^= 1; \
+}   \
+if (aSign ^ bSign ^ cSign) {\
+float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);   \
+}   \
+}   \
 }
+FPU_MADDSUB_UPDATE(float64_maddsub_update_excp, float64)
 
 #define FPU_FMADD(op, madd_flags)   \
 uint64_t helper_##op(CPUPPCState *env, uint64_t arg1,   \
-- 
2.9.3




[Qemu-devel] [PULL 5/5] target/ppc: use helper for excp handling

2017-03-05 Thread David Gibson
From: Nikunj A Dadhania 

Use the helper routine float[32,64]_maddsub_update_excp() in VSX_MADD
macro.

Signed-off-by: Nikunj A Dadhania 
Signed-off-by: David Gibson 
---
 target/ppc/fpu_helper.c | 20 ++--
 1 file changed, 2 insertions(+), 18 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 13bd6ce..c4dab15 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -773,6 +773,7 @@ static void NAME(CPUPPCState *env, TP arg1, TP arg2, TP 
arg3,   \
 }   \
 }   \
 }
+FPU_MADDSUB_UPDATE(float32_maddsub_update_excp, float32)
 FPU_MADDSUB_UPDATE(float64_maddsub_update_excp, float64)
 
 #define FPU_FMADD(op, madd_flags)   \
@@ -2239,24 +2240,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)  
 \
 env->fp_status.float_exception_flags |= tstat.float_exception_flags;  \
   \
 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
-if (tp##_is_signaling_nan(xa.fld, &tstat) ||  \
-tp##_is_signaling_nan(b->fld, &tstat) ||  \
-tp##_is_signaling_nan(c->fld, &tstat)) {  \
-float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);\
-tstat.float_exception_flags &= ~float_flag_invalid;   \
-} \
-if ((tp##_is_infinity(xa.fld) && tp##_is_zero(b->fld)) || \
-(tp##_is_zero(xa.fld) && tp##_is_infinity(b->fld))) { \
-xt_out.fld = float64_to_##tp(float_invalid_op_excp(env,   \
-POWERPC_EXCP_FP_VXIMZ, sfprf), &env->fp_status);  \
-tstat.float_exception_flags &= ~float_flag_invalid;   \
-} \
-if ((tstat.float_exception_flags & float_flag_invalid) && \
-((tp##_is_infinity(xa.fld) || \
-  tp##_is_infinity(b->fld)) &&\
-  tp##_is_infinity(c->fld))) {\
-float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf); \
-} \
+tp##_maddsub_update_excp(env, xa.fld, b->fld, c->fld, maddflgs);  \
 } \
   \
 if (r2sp) {   \
-- 
2.9.3




[Qemu-devel] [PULL 3/5] target/ppc: fmadd check for excp independently

2017-03-05 Thread David Gibson
From: Nikunj A Dadhania 

Current order of checking does not confirm with the spec
(ISA 3.0: MultiplyAddDP page-469). Change the order and make them
independent of each other.

For example: a = infinity, b = zero, c = SNaN, this should set both
VXIMZ and VXNAN

Signed-off-by: Nikunj A Dadhania 
Signed-off-by: David Gibson 
---
 target/ppc/fpu_helper.c | 20 
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 0535ad0..a547f58 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -747,17 +747,21 @@ static void float64_maddsub_update_excp(CPUPPCState *env, 
float64 arg1,
 float64 arg2, float64 arg3,
 unsigned int madd_flags)
 {
+if (unlikely(float64_is_signaling_nan(arg1, &env->fp_status) ||
+ float64_is_signaling_nan(arg2, &env->fp_status) ||
+ float64_is_signaling_nan(arg3, &env->fp_status))) {
+/* sNaN operation */
+float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+}
+
 if (unlikely((float64_is_infinity(arg1) && float64_is_zero(arg2)) ||
  (float64_is_zero(arg1) && float64_is_infinity(arg2 {
 /* Multiplication of zero by infinity */
-arg1 = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
-} else if (unlikely(float64_is_signaling_nan(arg1, &env->fp_status) ||
-float64_is_signaling_nan(arg2, &env->fp_status) ||
-float64_is_signaling_nan(arg3, &env->fp_status))) {
-/* sNaN operation */
-float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
-} else if ((float64_is_infinity(arg1) || float64_is_infinity(arg2)) &&
-   float64_is_infinity(arg3)) {
+float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
+}
+
+if ((float64_is_infinity(arg1) || float64_is_infinity(arg2)) &&
+float64_is_infinity(arg3)) {
 uint8_t aSign, bSign, cSign;
 
 aSign = float64_is_neg(arg1);
-- 
2.9.3




[Qemu-devel] [PULL 2/5] spapr: ensure that all threads within core are on the same NUMA node

2017-03-05 Thread David Gibson
From: Igor Mammedov 

Threads within a core shouldn't be on different
NUMA nodes, so if user has misconfgured command
line, fail QEMU at start up to force user fix it.

For now use the first thread on the core as source
of core's node-id. Later when cpu-numa refactoring
lands  it will be switched to core's node-id from
possible_cpus[].

This prevents the same problems as commit 20bb648d
"spapr: Fix default NUMA node allocation for threads",
but for the case of manually configured NUMA node
mappings, instead of just the default case.

Signed-off-by: Igor Mammedov 
Signed-off-by: David Gibson 
---
 hw/ppc/spapr_cpu_core.c | 23 +++
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index d37832d..6883f09 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -63,8 +63,6 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, 
PowerPCCPU *cpu,
Error **errp)
 {
 CPUPPCState *env = &cpu->env;
-CPUState *cs = CPU(cpu);
-int i;
 
 /* Set time-base frequency to 512 MHz */
 cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
@@ -82,12 +80,6 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, 
PowerPCCPU *cpu,
 }
 }
 
-/* Set NUMA node for the added CPUs  */
-i = numa_get_node_for_cpu(cs->cpu_index);
-if (i < nb_numa_nodes) {
-cs->numa_node = i;
-}
-
 xics_cpu_setup(XICS_FABRIC(spapr), cpu);
 
 qemu_register_reset(spapr_cpu_reset, cpu);
@@ -171,11 +163,13 @@ static void spapr_cpu_core_realize(DeviceState *dev, 
Error **errp)
 const char *typename = object_class_get_name(scc->cpu_class);
 size_t size = object_type_get_instance_size(typename);
 Error *local_err = NULL;
+int core_node_id = numa_get_node_for_cpu(cc->core_id);;
 void *obj;
 int i, j;
 
 sc->threads = g_malloc0(size * cc->nr_threads);
 for (i = 0; i < cc->nr_threads; i++) {
+int node_id;
 char id[32];
 CPUState *cs;
 
@@ -184,6 +178,19 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error 
**errp)
 object_initialize(obj, size, typename);
 cs = CPU(obj);
 cs->cpu_index = cc->core_id + i;
+
+/* Set NUMA node for the added CPUs  */
+node_id = numa_get_node_for_cpu(cs->cpu_index);
+if (node_id != core_node_id) {
+error_setg(&local_err, "Invalid node-id=%d of thread[cpu-index: 
%d]"
+" on CPU[core-id: %d, node-id: %d], node-id must be the same",
+ node_id, cs->cpu_index, cc->core_id, core_node_id);
+goto err;
+}
+if (node_id < nb_numa_nodes) {
+cs->numa_node = node_id;
+}
+
 snprintf(id, sizeof(id), "thread[%d]", i);
 object_property_add_child(OBJECT(sc), id, obj, &local_err);
 if (local_err) {
-- 
2.9.3




[Qemu-devel] [PULL 0/5] ppc-for-2.9 queue 20170306

2017-03-05 Thread David Gibson
The following changes since commit 17783ac828adc694d986698d2d7014aedfeb48c6:

  Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.9-20170303' into 
staging (2017-03-04 16:31:14 +)

are available in the git repository at:

  git://github.com/dgibson/qemu.git tags/ppc-for-2.9-20170306

for you to fetch changes up to 182fe2cf19e829e34f63443ee1ccd9f799715c2c:

  target/ppc: use helper for excp handling (2017-03-06 13:17:28 +1100)


ppc patch queue for 2017-03-06

Looks like my previous batch wasn't quite the last before hard freeze.
This has a handful of bugfixes to go in.  They're all genuine
bugfixes, though not regressions in some cases.


Cédric Le Goater (1):
  ppc/xics: register reset handlers for the ICP and ICS objects

Igor Mammedov (1):
  spapr: ensure that all threads within core are on the same NUMA node

Nikunj A Dadhania (3):
  target/ppc: fmadd check for excp independently
  target/ppc: fmadd: add macro for updating flags
  target/ppc: use helper for excp handling

 hw/intc/xics.c  | 10 ---
 hw/intc/xics_kvm.c  | 15 ++
 hw/ppc/spapr.c  |  2 --
 hw/ppc/spapr_cpu_core.c | 23 ++-
 target/ppc/fpu_helper.c | 77 -
 5 files changed, 63 insertions(+), 64 deletions(-)



[Qemu-devel] [PULL 1/5] ppc/xics: register reset handlers for the ICP and ICS objects

2017-03-05 Thread David Gibson
From: Cédric Le Goater 

The recent changes on the XICS layer removed the XICSState object to
let the sPAPR machine handle the ICP and ICS directly. The reset of
these objects was previously handled by XICSState, which was a SysBus
device, and to keep the same behavior, the ICP and ICS were assigned
to SysbBus.

But that broke the 'info qtree' command in the monitor. 'qtree'
performs a loop on the children of a bus to print their properties and
SysBus devices are expected to be found under SysBus, which is not the
case anymore.

The fix for this problem is to register reset handlers for the ICP and
ICS objects and stop using SysBus for such devices.

Signed-off-by: Cédric Le Goater 
Reviewed-by: Thomas Huth 
Tested-by: Thomas Huth 
Signed-off-by: David Gibson 
---
 hw/intc/xics.c | 10 ++
 hw/intc/xics_kvm.c | 15 ++-
 hw/ppc/spapr.c |  2 --
 3 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index ffc0747..e740989 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -333,7 +333,7 @@ static const VMStateDescription vmstate_icp_server = {
 },
 };
 
-static void icp_reset(DeviceState *dev)
+static void icp_reset(void *dev)
 {
 ICPState *icp = ICP(dev);
 
@@ -359,6 +359,8 @@ static void icp_realize(DeviceState *dev, Error **errp)
 }
 
 icp->xics = XICS_FABRIC(obj);
+
+qemu_register_reset(icp_reset, dev);
 }
 
 
@@ -366,7 +368,6 @@ static void icp_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 
-dc->reset = icp_reset;
 dc->vmsd = &vmstate_icp_server;
 dc->realize = icp_realize;
 }
@@ -522,7 +523,7 @@ static void ics_simple_eoi(ICSState *ics, uint32_t nr)
 }
 }
 
-static void ics_simple_reset(DeviceState *dev)
+static void ics_simple_reset(void *dev)
 {
 ICSState *ics = ICS_SIMPLE(dev);
 int i;
@@ -611,6 +612,8 @@ static void ics_simple_realize(DeviceState *dev, Error 
**errp)
 }
 ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
 ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);
+
+qemu_register_reset(ics_simple_reset, dev);
 }
 
 static Property ics_simple_properties[] = {
@@ -626,7 +629,6 @@ static void ics_simple_class_init(ObjectClass *klass, void 
*data)
 isc->realize = ics_simple_realize;
 dc->props = ics_simple_properties;
 dc->vmsd = &vmstate_ics_simple;
-dc->reset = ics_simple_reset;
 isc->reject = ics_simple_reject;
 isc->resend = ics_simple_resend;
 isc->eoi = ics_simple_eoi;
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index 0a3daca..42e0e0e 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -102,7 +102,7 @@ static int icp_set_kvm_state(ICPState *icp, int version_id)
 return 0;
 }
 
-static void icp_kvm_reset(DeviceState *dev)
+static void icp_kvm_reset(void *dev)
 {
 ICPState *icp = ICP(dev);
 
@@ -146,12 +146,17 @@ static void icp_kvm_cpu_setup(ICPState *icp, PowerPCCPU 
*cpu)
 icp->cap_irq_xics_enabled = true;
 }
 
+static void icp_kvm_realize(DeviceState *dev, Error **errp)
+{
+qemu_register_reset(icp_kvm_reset, dev);
+}
+
 static void icp_kvm_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 ICPStateClass *icpc = ICP_CLASS(klass);
 
-dc->reset = icp_kvm_reset;
+dc->realize = icp_kvm_realize;
 icpc->pre_save = icp_get_kvm_state;
 icpc->post_load = icp_set_kvm_state;
 icpc->cpu_setup = icp_kvm_cpu_setup;
@@ -293,7 +298,7 @@ static void ics_kvm_set_irq(void *opaque, int srcno, int 
val)
 }
 }
 
-static void ics_kvm_reset(DeviceState *dev)
+static void ics_kvm_reset(void *dev)
 {
 ICSState *ics = ICS_SIMPLE(dev);
 int i;
@@ -324,15 +329,15 @@ static void ics_kvm_realize(DeviceState *dev, Error 
**errp)
 }
 ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
 ics->qirqs = qemu_allocate_irqs(ics_kvm_set_irq, ics, ics->nr_irqs);
+
+qemu_register_reset(ics_kvm_reset, dev);
 }
 
 static void ics_kvm_class_init(ObjectClass *klass, void *data)
 {
-DeviceClass *dc = DEVICE_CLASS(klass);
 ICSStateClass *icsc = ICS_BASE_CLASS(klass);
 
 icsc->realize = ics_kvm_realize;
-dc->reset = ics_kvm_reset;
 icsc->pre_save = ics_get_kvm_state;
 icsc->post_load = ics_set_kvm_state;
 }
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 14192ac..c3bb991 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -106,7 +106,6 @@ static int try_create_xics(sPAPRMachineState *spapr, const 
char *type_ics,
 int i;
 
 ics = ICS_SIMPLE(object_new(type_ics));
-qdev_set_parent_bus(DEVICE(ics), sysbus_get_default());
 object_property_add_child(OBJECT(spapr), "ics", OBJECT(ics), NULL);
 object_property_set_int(OBJECT(ics), nr_irqs, "nr-irqs", &err);
 object_property_add_const_link(OBJECT(ics), "xics", OBJECT(xi), NULL);
@@ -123,7 +122,6 @@ static int try_create_xics(sPAPRMachineState *spapr, const 
char *type_ics,
 ICPStat

Re: [Qemu-devel] [Qemu-arm] [PATCH 3/3] hw/misc/exynos4210_pmu: Reorder local variables for readability

2017-03-05 Thread Philippe Mathieu-Daudé

Hi Krzysztof,

On 03/05/2017 06:48 PM, Krzysztof Kozlowski wrote:

Short declaration of 'i' was in the middle of declarations with
assignments.  Make it a little bit more readable.  No functional change.

Signed-off-by: Krzysztof Kozlowski 
---
 hw/misc/exynos4210_pmu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/misc/exynos4210_pmu.c b/hw/misc/exynos4210_pmu.c
index cbdfa0614600..60d1545c0baa 100644
--- a/hw/misc/exynos4210_pmu.c
+++ b/hw/misc/exynos4210_pmu.c
@@ -401,8 +401,8 @@ static uint64_t exynos4210_pmu_read(void *opaque, hwaddr 
offset,
 unsigned size)
 {
 const Exynos4210PmuState *s = (Exynos4210PmuState *)opaque;
-unsigned i;
 const Exynos4210PmuReg *reg_p = exynos4210_pmu_regs;
+unsigned i;


your change seems OK but while you are here, 'unsigned' is considered 
harmful since more than a decade. why not use 'size_t i' since 
PMU_NUM_OF_REGISTERS is indeed an ARRAY_SIZE()?




 for (i = 0; i < PMU_NUM_OF_REGISTERS; i++) {
 if (reg_p->offset == offset) {
@@ -420,8 +420,8 @@ static void exynos4210_pmu_write(void *opaque, hwaddr 
offset,
  uint64_t val, unsigned size)
 {
 Exynos4210PmuState *s = (Exynos4210PmuState *)opaque;
-unsigned i;
 const Exynos4210PmuReg *reg_p = exynos4210_pmu_regs;
+unsigned i;

 for (i = 0; i < PMU_NUM_OF_REGISTERS; i++) {
 if (reg_p->offset == offset) {





Re: [Qemu-devel] [PATCH V2] migration: expose qemu_announce_self() via qmp

2017-03-05 Thread Jason Wang



On 2017年03月03日 18:39, Dr. David Alan Gilbert wrote:

* Germano Veit Michel (germ...@redhat.com) wrote:

qemu_announce_self() is triggered by qemu at the end of migrations
to update the network regarding the path to the guest l2addr.

however it is also useful when there is a network change such as
an active bond slave swap. Essentially, it's the same as a migration
from a network perspective - the guest moves to a different point
in the network topology.

this exposes the function via qmp.

Markus: Since you're asking for tests for qmp commands; how would you
test this?

Jason: Does this look OK from the networking side of things?



Good as a start I think. We probably want to add callbacks for each 
kinds of nic. This will be useful for virtio, since some guest can 
announce themselves with complex configurations (e.g vlans).


Thanks



Re: [Qemu-devel] [Qemu-arm] [PATCH 2/3] hw/arm/exynos4210: Constify data pointed by few arguments and variables

2017-03-05 Thread Philippe Mathieu-Daudé

On 03/05/2017 06:48 PM, Krzysztof Kozlowski wrote:

In few places the function arguments and local variables are not
modifying data passed through pointers so this can be made const for
code safeness.  Also the static array exynos4210_uart_regs is not being
modified.

Signed-off-by: Krzysztof Kozlowski 


Reviewed-by: Philippe Mathieu-Daudé 


---
 hw/char/exynos4210_uart.c | 10 +-
 hw/intc/exynos4210_combiner.c |  2 +-
 hw/intc/exynos4210_gic.c  |  8 
 hw/misc/exynos4210_pmu.c  |  2 +-
 4 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
index b75f28d473bf..83e1be253255 100644
--- a/hw/char/exynos4210_uart.c
+++ b/hw/char/exynos4210_uart.c
@@ -102,7 +102,7 @@ typedef struct Exynos4210UartReg {
 uint32_treset_value;
 } Exynos4210UartReg;

-static Exynos4210UartReg exynos4210_uart_regs[] = {
+static const Exynos4210UartReg exynos4210_uart_regs[] = {
 {"ULCON",ULCON,0x},
 {"UCON", UCON, 0x3000},
 {"UFCON",UFCON,0x},
@@ -220,7 +220,7 @@ static uint8_t fifo_retrieve(Exynos4210UartFIFO *q)
 return  ret;
 }

-static int fifo_elements_number(Exynos4210UartFIFO *q)
+static int fifo_elements_number(const Exynos4210UartFIFO *q)
 {
 if (q->sp < q->rp) {
 return q->size - q->rp + q->sp;
@@ -229,7 +229,7 @@ static int fifo_elements_number(Exynos4210UartFIFO *q)
 return q->sp - q->rp;
 }

-static int fifo_empty_elements_number(Exynos4210UartFIFO *q)
+static int fifo_empty_elements_number(const Exynos4210UartFIFO *q)
 {
 return q->size - fifo_elements_number(q);
 }
@@ -245,7 +245,7 @@ static void fifo_reset(Exynos4210UartFIFO *q)
 q->rp = 0;
 }

-static uint32_t exynos4210_uart_Tx_FIFO_trigger_level(Exynos4210UartState *s)
+static uint32_t exynos4210_uart_Tx_FIFO_trigger_level(const 
Exynos4210UartState *s)
 {
 uint32_t level = 0;
 uint32_t reg;
@@ -488,7 +488,7 @@ static const MemoryRegionOps exynos4210_uart_ops = {

 static int exynos4210_uart_can_receive(void *opaque)
 {
-Exynos4210UartState *s = (Exynos4210UartState *)opaque;
+const Exynos4210UartState *s = (Exynos4210UartState *)opaque;

 return fifo_empty_elements_number(&s->rx);
 }
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
index f19a7062be3a..b057921e0504 100644
--- a/hw/intc/exynos4210_combiner.c
+++ b/hw/intc/exynos4210_combiner.c
@@ -180,7 +180,7 @@ void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, 
DeviceState *dev,
 static uint64_t
 exynos4210_combiner_read(void *opaque, hwaddr offset, unsigned size)
 {
-struct Exynos4210CombinerState *s =
+const struct Exynos4210CombinerState *s =
 (struct Exynos4210CombinerState *)opaque;
 uint32_t req_quad_base_n;/* Base of registers quad. Multiply it by 4 
and
get a start of corresponding group quad */
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
index 2a55817b7660..432b8425d09d 100644
--- a/hw/intc/exynos4210_gic.c
+++ b/hw/intc/exynos4210_gic.c
@@ -190,7 +190,7 @@ 
combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {

 static void exynos4210_irq_handler(void *opaque, int irq, int level)
 {
-Exynos4210Irq *s = (Exynos4210Irq *)opaque;
+const Exynos4210Irq *s = (Exynos4210Irq *)opaque;

 /* Bypass */
 qemu_set_irq(s->board_irqs[irq], level);
@@ -277,7 +277,7 @@ typedef struct {

 static void exynos4210_gic_set_irq(void *opaque, int irq, int level)
 {
-Exynos4210GicState *s = (Exynos4210GicState *)opaque;
+const Exynos4210GicState *s = (Exynos4210GicState *)opaque;
 qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
 }

@@ -401,7 +401,7 @@ static const VMStateDescription vmstate_exynos4210_irq_gate 
= {
 /* Process a change in IRQ input. */
 static void exynos4210_irq_gate_handler(void *opaque, int irq, int level)
 {
-Exynos4210IRQGateState *s = (Exynos4210IRQGateState *)opaque;
+const Exynos4210IRQGateState *s = (Exynos4210IRQGateState *)opaque;
 uint32_t i;

 assert(irq < s->n_in);
@@ -420,7 +420,7 @@ static void exynos4210_irq_gate_handler(void *opaque, int 
irq, int level)

 static void exynos4210_irq_gate_reset(DeviceState *d)
 {
-Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(d);
+const Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(d);

 memset(s->level, 0, s->n_in * sizeof(*s->level));
 }
diff --git a/hw/misc/exynos4210_pmu.c b/hw/misc/exynos4210_pmu.c
index e30dbc7d3d83..cbdfa0614600 100644
--- a/hw/misc/exynos4210_pmu.c
+++ b/hw/misc/exynos4210_pmu.c
@@ -400,7 +400,7 @@ typedef struct Exynos4210PmuState {
 static uint64_t exynos4210_pmu_read(void *opaque, hwaddr offset,
 unsigned size)
 {
-Exynos4210PmuState *s = (Exynos4210PmuState *)opaque;
+const Exynos4210PmuState *s = (Exynos4210PmuState *)opaque;
 unsigned i;
 const Exynos4210PmuReg *reg_p = exynos

[Qemu-devel] [PATCH] virtio-serial-bus: Delete timer from list before free it

2017-03-05 Thread zhanghailiang
Signed-off-by: zhanghailiang 
---
 hw/char/virtio-serial-bus.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index d544cd9..d797a67 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -724,6 +724,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
 }
 }
 g_free(s->post_load->connected);
+timer_del(s->post_load->timer);
 timer_free(s->post_load->timer);
 g_free(s->post_load);
 s->post_load = NULL;
-- 
1.8.3.1





Re: [Qemu-devel] [Bug?] BQL about live migration

2017-03-05 Thread yanghongyang


On 2017/3/3 18:42, Fam Zheng wrote:
> On Fri, 03/03 09:29, Gonglei (Arei) wrote:
>> Hello Juan & Dave,
>>
>> We hit a bug in our test:
>> Network error occurs when migrating a guest, libvirt then rollback the
>> migration, causes qemu coredump
>> qemu log:
>> 2017-03-01T12:54:33.904949+08:00|info|qemu[17672]|[33614]|monitor_qapi_event_emit[479]|:
>>  {"timestamp": {"seconds": 1488344073, "microseconds": 904914}, "event": 
>> "STOP"}
>> 2017-03-01T12:54:37.522500+08:00|info|qemu[17672]|[17672]|handle_qmp_command[3930]|:
>>  qmp_cmd_name: migrate_cancel
>> 2017-03-01T12:54:37.522607+08:00|info|qemu[17672]|[17672]|monitor_qapi_event_emit[479]|:
>>  {"timestamp": {"seconds": 1488344077, "microseconds": 522556}, "event": 
>> "MIGRATION", "data": {"status": "cancelling"}}
>> 2017-03-01T12:54:37.524671+08:00|info|qemu[17672]|[17672]|handle_qmp_command[3930]|:
>>  qmp_cmd_name: cont
>> 2017-03-01T12:54:37.524733+08:00|info|qemu[17672]|[17672]|virtio_set_status[725]|:
>>  virtio-balloon device status is 7 that means DRIVER OK
>> 2017-03-01T12:54:37.525434+08:00|info|qemu[17672]|[17672]|virtio_set_status[725]|:
>>  virtio-net device status is 7 that means DRIVER OK
>> 2017-03-01T12:54:37.525484+08:00|info|qemu[17672]|[17672]|virtio_set_status[725]|:
>>  virtio-blk device status is 7 that means DRIVER OK
>> 2017-03-01T12:54:37.525562+08:00|info|qemu[17672]|[17672]|virtio_set_status[725]|:
>>  virtio-serial device status is 7 that means DRIVER OK
>> 2017-03-01T12:54:37.527653+08:00|info|qemu[17672]|[17672]|vm_start[981]|: 
>> vm_state-notify:3ms
>> 2017-03-01T12:54:37.528523+08:00|info|qemu[17672]|[17672]|monitor_qapi_event_emit[479]|:
>>  {"timestamp": {"seconds": 1488344077, "microseconds": 527699}, "event": 
>> "RESUME"}
>> 2017-03-01T12:54:37.530680+08:00|info|qemu[17672]|[33614]|migration_bitmap_sync[720]|:
>>  this iteration cycle takes 3s, new dirtied data:0MB
>> 2017-03-01T12:54:37.530909+08:00|info|qemu[17672]|[33614]|monitor_qapi_event_emit[479]|:
>>  {"timestamp": {"seconds": 1488344077, "microseconds": 530733}, "event": 
>> "MIGRATION_PASS", "data": {"pass": 3}}
>> 2017-03-01T04:54:37.530997Z qemu-kvm: socket_writev_buffer: Got err=32 for 
>> (131583/18446744073709551615)
>> qemu-kvm: 
>> /home/abuild/rpmbuild/BUILD/qemu-kvm-2.6.0/hw/net/virtio_net.c:1519: 
>> virtio_net_save: Assertion `!n->vhost_started' failed.
>> 2017-03-01 12:54:43.028: shutting down
>>
>> From qemu log, qemu received and processed migrate_cancel/cont qmp commands
>> after guest been stopped and entered the last round of migration. Then
>> migration thread try to save device state when guest is running(started by
>> cont command), causes assert and coredump.
>> This is because in last iter, we call cpu_synchronize_all_states() to
>> synchronize vcpu states, this call will release qemu_global_mutex and wait
>> for do_kvm_cpu_synchronize_state() to be executed on target vcpu:
>> (gdb) bt
>> #0  0x7f763d1046d5 in pthread_cond_wait@@GLIBC_2.3.2 () from 
>> /lib64/libpthread.so.0
>> #1  0x7f7643e51d7f in qemu_cond_wait (cond=0x7f764445eca0 
>> , mutex=0x7f764445eba0 ) at 
>> util/qemu-thread-posix.c:132
>> #2  0x7f7643a2e154 in run_on_cpu (cpu=0x7f7644e06d80, 
>> func=0x7f7643a46413 , data=0x7f7644e06d80) at 
>> /mnt/public/yanghy/qemu-kvm/cpus.c:995
>> #3  0x7f7643a46487 in kvm_cpu_synchronize_state (cpu=0x7f7644e06d80) at 
>> /mnt/public/yanghy/qemu-kvm/kvm-all.c:1805
>> #4  0x7f7643a2c700 in cpu_synchronize_state (cpu=0x7f7644e06d80) at 
>> /mnt/public/yanghy/qemu-kvm/include/sysemu/kvm.h:457
>> #5  0x7f7643a2db0c in cpu_synchronize_all_states () at 
>> /mnt/public/yanghy/qemu-kvm/cpus.c:766
>> #6  0x7f7643a67b5b in qemu_savevm_state_complete_precopy 
>> (f=0x7f76462f2d30, iterable_only=false) at 
>> /mnt/public/yanghy/qemu-kvm/migration/savevm.c:1051
>> #7  0x7f7643d121e9 in migration_completion (s=0x7f76443e78c0 
>> , current_active_state=4, 
>> old_vm_running=0x7f74343fda00, start_time=0x7f74343fda08) at 
>> migration/migration.c:1753
>> #8  0x7f7643d126c5 in migration_thread (opaque=0x7f76443e78c0 
>> ) at migration/migration.c:1922
>> #9  0x7f763d100dc5 in start_thread () from /lib64/libpthread.so.0
>> #10 0x7f763ce2e71d in clone () from /lib64/libc.so.6
>> (gdb) p iothread_locked
>> $1 = true
>>
>> and then, qemu main thread been executed, it won't block because migration
>> thread released the qemu_global_mutex:
>> (gdb) thr 1
>> [Switching to thread 1 (Thread 0x7fe298e08bc0 (LWP 30767))]
>> #0  os_host_main_loop_wait (timeout=931565) at main-loop.c:270
>> 270 QEMU_LOG(LOG_INFO,"* after qemu_pool_ns: timeout 
>> %d\n", timeout);
>> (gdb) p iothread_locked
>> $2 = true
>> (gdb) l 268
>> 263
>> 264 ret = qemu_poll_ns((GPollFD *)gpollfds->data, gpollfds->len, 
>> timeout);
>> 265
>> 266
>> 267 if (timeout) {
>> 268 qemu_mutex_lock_iothread();
>> 269 if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
>> 270 QEMU_LOG(

Re: [Qemu-devel] [PATCH] ppc/xics: register reset handlers for the ICP and ICS objects

2017-03-05 Thread David Gibson
On Fri, Mar 03, 2017 at 01:51:03PM +0100, Cédric Le Goater wrote:
1;4601;0c> The recent changes on the XICS layer removed the XICSState object to
> let the sPAPR machine handle the ICP and ICS directly. The reset of
> these objects was previously handled by XICSState, which was a SysBus
> device, and to keep the same behavior, the ICP and ICS were assigned
> to SysbBus.
> 
> But that broke the 'info qtree' command in the monitor. 'qtree'
> performs a loop on the children of a bus to print their properties and
> SysBus devices are expected to be found under SysBus, which is not the
> case anymore.
> 
> The fix for this problem is to register reset handlers for the ICP and
> ICS objects and stop using SysBus for such devices.
> 
> Signed-off-by: Cédric Le Goater 

Applied to ppc-for-2.9, thanks.

> ---
>  hw/intc/xics.c | 10 ++
>  hw/intc/xics_kvm.c | 15 ++-
>  hw/ppc/spapr.c |  2 --
>  3 files changed, 16 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index ffc0747c7fa2..e740989a1162 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -333,7 +333,7 @@ static const VMStateDescription vmstate_icp_server = {
>  },
>  };
>  
> -static void icp_reset(DeviceState *dev)
> +static void icp_reset(void *dev)
>  {
>  ICPState *icp = ICP(dev);
>  
> @@ -359,6 +359,8 @@ static void icp_realize(DeviceState *dev, Error **errp)
>  }
>  
>  icp->xics = XICS_FABRIC(obj);
> +
> +qemu_register_reset(icp_reset, dev);
>  }
>  
>  
> @@ -366,7 +368,6 @@ static void icp_class_init(ObjectClass *klass, void *data)
>  {
>  DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -dc->reset = icp_reset;
>  dc->vmsd = &vmstate_icp_server;
>  dc->realize = icp_realize;
>  }
> @@ -522,7 +523,7 @@ static void ics_simple_eoi(ICSState *ics, uint32_t nr)
>  }
>  }
>  
> -static void ics_simple_reset(DeviceState *dev)
> +static void ics_simple_reset(void *dev)
>  {
>  ICSState *ics = ICS_SIMPLE(dev);
>  int i;
> @@ -611,6 +612,8 @@ static void ics_simple_realize(DeviceState *dev, Error 
> **errp)
>  }
>  ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
>  ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);
> +
> +qemu_register_reset(ics_simple_reset, dev);
>  }
>  
>  static Property ics_simple_properties[] = {
> @@ -626,7 +629,6 @@ static void ics_simple_class_init(ObjectClass *klass, 
> void *data)
>  isc->realize = ics_simple_realize;
>  dc->props = ics_simple_properties;
>  dc->vmsd = &vmstate_ics_simple;
> -dc->reset = ics_simple_reset;
>  isc->reject = ics_simple_reject;
>  isc->resend = ics_simple_resend;
>  isc->eoi = ics_simple_eoi;
> diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
> index 0a3daca3bb5a..42e0e0ef8484 100644
> --- a/hw/intc/xics_kvm.c
> +++ b/hw/intc/xics_kvm.c
> @@ -102,7 +102,7 @@ static int icp_set_kvm_state(ICPState *icp, int 
> version_id)
>  return 0;
>  }
>  
> -static void icp_kvm_reset(DeviceState *dev)
> +static void icp_kvm_reset(void *dev)
>  {
>  ICPState *icp = ICP(dev);
>  
> @@ -146,12 +146,17 @@ static void icp_kvm_cpu_setup(ICPState *icp, PowerPCCPU 
> *cpu)
>  icp->cap_irq_xics_enabled = true;
>  }
>  
> +static void icp_kvm_realize(DeviceState *dev, Error **errp)
> +{
> +qemu_register_reset(icp_kvm_reset, dev);
> +}
> +
>  static void icp_kvm_class_init(ObjectClass *klass, void *data)
>  {
>  DeviceClass *dc = DEVICE_CLASS(klass);
>  ICPStateClass *icpc = ICP_CLASS(klass);
>  
> -dc->reset = icp_kvm_reset;
> +dc->realize = icp_kvm_realize;
>  icpc->pre_save = icp_get_kvm_state;
>  icpc->post_load = icp_set_kvm_state;
>  icpc->cpu_setup = icp_kvm_cpu_setup;
> @@ -293,7 +298,7 @@ static void ics_kvm_set_irq(void *opaque, int srcno, int 
> val)
>  }
>  }
>  
> -static void ics_kvm_reset(DeviceState *dev)
> +static void ics_kvm_reset(void *dev)
>  {
>  ICSState *ics = ICS_SIMPLE(dev);
>  int i;
> @@ -324,15 +329,15 @@ static void ics_kvm_realize(DeviceState *dev, Error 
> **errp)
>  }
>  ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
>  ics->qirqs = qemu_allocate_irqs(ics_kvm_set_irq, ics, ics->nr_irqs);
> +
> +qemu_register_reset(ics_kvm_reset, dev);
>  }
>  
>  static void ics_kvm_class_init(ObjectClass *klass, void *data)
>  {
> -DeviceClass *dc = DEVICE_CLASS(klass);
>  ICSStateClass *icsc = ICS_BASE_CLASS(klass);
>  
>  icsc->realize = ics_kvm_realize;
> -dc->reset = ics_kvm_reset;
>  icsc->pre_save = ics_get_kvm_state;
>  icsc->post_load = ics_set_kvm_state;
>  }
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 14192accf486..c3bb99160545 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -106,7 +106,6 @@ static int try_create_xics(sPAPRMachineState *spapr, 
> const char *type_ics,
>  int i;
>  
>  ics = ICS_SIMPLE(object_new(type_ics));
> -qdev_set_parent_bus(DEVICE(ics), sysbus_get_de

Re: [Qemu-devel] [PATCH] tests/docker: support proxy / corporate firewall

2017-03-05 Thread Fam Zheng
On Sat, 03/04 16:12, Philippe Mathieu-Daudé wrote:
> if FTP_PROXY/HTTP_PROXY/HTTPS_PROXY standard environment variables available,
> pass them to the docker daemon to build images.
> this is required when building behind corporate proxy/firewall, but also help
> when using local cache server (ie: apt/yum).
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  tests/docker/docker.py | 10 ++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/tests/docker/docker.py b/tests/docker/docker.py
> index 9fd32ab5fa..02bf9363e1 100755
> --- a/tests/docker/docker.py
> +++ b/tests/docker/docker.py
> @@ -22,12 +22,16 @@ import argparse
>  import tempfile
>  import re
>  import signal
> +import string
>  from tarfile import TarFile, TarInfo
>  from StringIO import StringIO
>  from shutil import copy, rmtree
>  from pwd import getpwuid
>  
>  
> +FILTERED_ENV_NAMES = ['FTP_PROXY', 'HTTP_PROXY', 'HTTPS_PROXY']
> +
> +
>  DEVNULL = open(os.devnull, 'wb')
>  
>  
> @@ -272,6 +276,12 @@ class BuildCommand(SubCommand):
>  _copy_binary_with_libs(args.include_executable,
> docker_dir)
>  
> +filtered_keys = map(string.upper, FILTERED_ENV_NAMES)
> +filtered_keys += map(string.lower, FILTERED_ENV_NAMES)
> +for filtered_key in filtered_keys:
> +if filtered_key in os.environ.keys():
> +argv += ["--build-arg=" + filtered_key +
> +"=" + os.environ[filtered_key]]

Makes sense.

Could you simplify the above hunk as

args += ["--build-arg=" + k + "=" + v for k, v in \
os.environ.iteritems() if k.upper() in FILTERED_ENV_NAMES]

then 'import string' is not necessary.

Fam

>  dkr.build_image(tag, docker_dir, dockerfile,
>  quiet=args.quiet, user=args.user, argv=argv)
>  
> -- 
> 2.11.0
> 
> 



Re: [Qemu-devel] [PATCH] spapr: ensure that all threads within core are on the same NUMA node

2017-03-05 Thread David Gibson
On Fri, Mar 03, 2017 at 06:41:04PM +0100, Igor Mammedov wrote:
> On Fri, 24 Feb 2017 10:26:56 +0100
> Igor Mammedov  wrote:
> 
> > Threads within a core shouldn't be on different
> > NUMA nodes, so if user has misconfgured command
> > line, fail QEMU at start up to force user fix it.
> > 
> > For now use the first thread on the core as source
> > of core's node-id. Later when cpu-numa refactoring
> > lands  it will be switched to core's node-id from
> > possible_cpus[].
> > 
> > Signed-off-by: Igor Mammedov 
> ping,
> 
> David could you review/merge maybe adding to commit
> message:
> 
> "
> patch prevents the same issues as commit 20bb648d
> fixes, only instead of default mapping it adds
> check for manually configured NUMA node mapping
> "

Ok, merged.  I'll try to send that up today, just in time for the hard freeze.

> 
> > ---
> > Enforcement is necessary to ensure that it would be
> > possible to map legacy CPU index based CLI mapping
> > to core based one and replace numa_info[XXX].node_cpu
> > with possible_cpus[] as storage for mapping info.
> > 
> > CC: qemu-...@nongnu.org
> > CC: lviv...@redhat.com
> > CC: David Gibson 
> > CC: th...@redhat.com
> > CC: mdr...@linux.vnet.ibm.com
> > CC: ag...@suse.de
> > ---
> >  hw/ppc/spapr_cpu_core.c | 23 +++
> >  1 file changed, 15 insertions(+), 8 deletions(-)
> > 
> > diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
> > index 55cd045..1499a8b 100644
> > --- a/hw/ppc/spapr_cpu_core.c
> > +++ b/hw/ppc/spapr_cpu_core.c
> > @@ -50,8 +50,6 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, 
> > PowerPCCPU *cpu,
> > Error **errp)
> >  {
> >  CPUPPCState *env = &cpu->env;
> > -CPUState *cs = CPU(cpu);
> > -int i;
> >  
> >  /* Set time-base frequency to 512 MHz */
> >  cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
> > @@ -70,12 +68,6 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, 
> > PowerPCCPU *cpu,
> >  }
> >  }
> >  
> > -/* Set NUMA node for the added CPUs  */
> > -i = numa_get_node_for_cpu(cs->cpu_index);
> > -if (i < nb_numa_nodes) {
> > -cs->numa_node = i;
> > -}
> > -
> >  xics_cpu_setup(spapr->xics, cpu);
> >  
> >  qemu_register_reset(spapr_cpu_reset, cpu);
> > @@ -159,11 +151,13 @@ static void spapr_cpu_core_realize(DeviceState *dev, 
> > Error **errp)
> >  const char *typename = object_class_get_name(scc->cpu_class);
> >  size_t size = object_type_get_instance_size(typename);
> >  Error *local_err = NULL;
> > +int core_node_id = numa_get_node_for_cpu(cc->core_id);;
> >  void *obj;
> >  int i, j;
> >  
> >  sc->threads = g_malloc0(size * cc->nr_threads);
> >  for (i = 0; i < cc->nr_threads; i++) {
> > +int node_id;
> >  char id[32];
> >  CPUState *cs;
> >  
> > @@ -172,6 +166,19 @@ static void spapr_cpu_core_realize(DeviceState *dev, 
> > Error **errp)
> >  object_initialize(obj, size, typename);
> >  cs = CPU(obj);
> >  cs->cpu_index = cc->core_id + i;
> > +
> > +/* Set NUMA node for the added CPUs  */
> > +node_id = numa_get_node_for_cpu(cs->cpu_index);
> > +if (node_id != core_node_id) {
> > +error_setg(&local_err, "Invalid node-id=%d of 
> > thread[cpu-index: %d]"
> > +" on CPU[core-id: %d, node-id: %d], node-id must be the 
> > same",
> > + node_id, cs->cpu_index, cc->core_id, core_node_id);
> > +goto err;
> > +}
> > +if (node_id < nb_numa_nodes) {
> > +cs->numa_node = node_id;
> > +}
> > +
> >  snprintf(id, sizeof(id), "thread[%d]", i);
> >  object_property_add_child(OBJECT(sc), id, obj, &local_err);
> >  if (local_err) {
> 

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


signature.asc
Description: PGP signature


Re: [Qemu-devel] [PATCH] ppc/spapr: QOM'ify sPAPRRTCState

2017-03-05 Thread David Gibson
On Fri, Mar 03, 2017 at 06:23:15PM +0100, Cédric Le Goater wrote:
> On 03/03/2017 05:54 PM, Thomas Huth wrote:
> > On 03.03.2017 15:49, Cédric Le Goater wrote:
> >> On 03/03/2017 03:13 PM, Thomas Huth wrote:
> >>> On 03.03.2017 14:37, Cédric Le Goater wrote:
>  Also use an 'Object *' under the sPAPR machine to hold the RTC
>  object.
> >>>
> >>> The change from TYPE_SYS_BUS_DEVICE to TYPE_DEVICE is certainly a good
> >>> idea! But what's the advantage of using Object* instead of DeviceState*
> >>> in sPAPRMachineState ?
> >>
> >> it makes spapr_rtc_create() a little simpler.  
> >>
> >> We could go even further and use a sPAPRRTCState under sPAPRMachineState 
> >> that we  would initialize with object_initialize(). 
> > 
> > I think a sPAPRRTCState* would make more sense here - if you just see an
> > Object* and are not familiar with the code, you wonder what this pointer
> > is all about (and you then have to cast it to something different if you
> > want to do anything with it) ... so IMHO either a DeviceState* or
> > sPAPRRTCState* is the better choice here.
> 
> I think having a non-pointer is a better for the object lifecycle 
> but I don't have a strong opinion on that. We will see what Dave 
> prefers.

You seem to be talking at cross purposes.  AFAICT Thomas is not
talking about the difference between a pointer and a non-pointer, he's
talking about the difference between a generic Object (pointer or
otherwise) and a concrete type.

I agree with Thomas that a specific type is preferable.  I'm not
particularly bothered by the difference between pointer and
non-pointer.

In any case, this has missed the cutoff for qemu-2.9, I'm afraid.

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


signature.asc
Description: PGP signature


Re: [Qemu-devel] Qemu deadlocks in tb_lock when using SVM+SoftMMU

2017-03-05 Thread Richard Henderson

On 03/06/2017 08:32 AM, Alex Bennée wrote:

#5  0x0046ea2e in tlb_flush (cpu=0x164a360) at qemu.git/cputlb.c:121
#6  0x00538987 in cpu_x86_update_cr4 (env=0x16525f0, new_cr4=1784)
at qemu.git/target/i386/helper.c:660
#7  0x0055e318 in cpu_vmexit (env=0x16525f0, exit_code=78,
exit_info_1=4, retaddr=0)
at qemu.git/target/i386/svm_helper.c:689
#8  0x0055d9b7 in cpu_svm_check_intercept_param (env=0x16525f0,
type=78, param=4, retaddr=0)
at qemu.git/target/i386/svm_helper.c:511
#9  0x00541acf in raise_interrupt2 (env=0x16525f0, intno=14,
is_int=0, error_code=4, next_eip_addend=0, retaddr=0)
at qemu.git/target/i386/excp_helper.c:96
#10 0x00541c0d in raise_exception_err_ra (env=0x16525f0,
exception_index=14, error_code=4, retaddr=0)
at qemu.git/target/i386/excp_helper.c:127
#11 0x005621a9 in tlb_fill (cs=0x164a360, addr=1245184,
access_type=MMU_INST_FETCH, mmu_idx=1, retaddr=0)
at qemu.git/target/i386/mem_helper.c:212

Richard,

So this looks like another path through the SoftMMU code during
code-generation (which is why tb_lock() is held in the first place). I'm
not sure if the correct thing to do is bug out earlier or to defer the
exception raising part to async work and exit the loop.


My guess is that everything from cpu_svm_check_intercept_param on should be 
done from do_interrupt instead of during raise_interrupt.



r~




Re: [Qemu-devel] [PATCH for-2.9 0/6] disas: Fix various coverity nits

2017-03-05 Thread Fam Zheng
On Sat, 03/04 12:44, Peter Maydell wrote:
> On 4 March 2017 at 00:00,   wrote:
> > Hi,
> >
> > This series failed build test on s390x host. Please find the details below.
> 
> > === TEST BEGIN ===
> > Using CC: /home/fam/bin/cc
> > rm: cannot remove '/var/tmp/patchew-qemu-build/aarch64-softmmu': Directory 
> > not empty
> > === OUTPUT END ===
> 
> Fam, can we drop the s390x test from patchew until it gets fixed,
> please? Right now it's just spamming the list and means that
> actually interesting patchew emails are likely to get ignored...

OK, I've changed this test to off-list reply and I'll continue investigating.
Though I think that apart from this apparent tester hiccup and another one false
positive out of my manual intervention, other s390x reports are actual QEMU
issue.

Fam



Re: [Qemu-devel] [PATCH v8 1/2] block/vxhs.c: Add support for a new block device type called "vxhs"

2017-03-05 Thread ashish mittal
On Wed, Mar 1, 2017 at 1:18 AM, Daniel P. Berrange  wrote:
> On Tue, Feb 28, 2017 at 02:51:39PM -0800, ashish mittal wrote:
>> On Mon, Feb 27, 2017 at 1:22 AM, Daniel P. Berrange  
>> wrote:
>
>> >> +ret = -EINVAL;
>> >> +goto out;
>> >> +}
>> >> +
>> >> +secretid = qemu_opt_get(opts, VXHS_OPT_SECRETID);
>> >> +if (!secretid) {
>> >> +error_setg(&local_err, "please specify the ID of the secret to 
>> >> be "
>> >> +   "used for authenticating to target");
>> >> +qdict_del(backing_options, str);
>> >> +ret = -EINVAL;
>> >> +goto out;
>> >> +}
>> >> +
>> >> +/* check if we got password via the --object argument */
>> >> +password = qcrypto_secret_lookup_as_utf8(secretid, &local_err);
>> >> +if (local_err != NULL) {
>> >> +trace_vxhs_get_creds(user, secretid, password);
>> >> +qdict_del(backing_options, str);
>> >> +ret = -EINVAL;
>> >> +goto out;
>> >> +}
>> >> +trace_vxhs_get_creds(user, secretid, password);
>> >> +
>> >>  s->vdisk_hostinfo.host = g_strdup(server_host_opt);
>> >>
>> >>  s->vdisk_hostinfo.port = g_ascii_strtoll(qemu_opt_get(tcp_opts,
>>
>> The next thing we need consensus on, is to decide exactly what
>> additional information to pass.
>>
>> (1) Current security implementation in VxHS uses the SSL key and
>> certificate files. Do you think we can achieve all the intended
>> security goals if we pass these two files paths (and names?) from the
>> command line?
>
> Yes, that's how other parts of QEMU deal with SSL
>
> NB, QEMU needs to pass 3 paths to libqnoio - the client cert, the
> client key, and the certificate authority certlist
>

I see that the QEMU TLS code internally does expect to find cacert,
and errors out if this is missing. I did have to create one and place
it in the dir path where we are keeping the client key,cert files. The
code diff below requires all the three files.

Here are the files I had to create -
$ ll /etc/pki/qemu/vxhs
total 12
-r--r--r--. 1 root root 2094 Mar  4 18:02 ca-cert.pem
-r--r--r--. 1 root root 1899 Mar  4 18:00 client-cert.pem
-r--r--r--. 1 root root 1679 Mar  4 17:59 client-key.pem

>> (2) If we are OK to continue with the present security scheme (using
>> key and cert), then the only additional change needed might be to
>> accept these files on the command line.
>
> Yep, I think that's the minimum required change to make this mergable.
>
>> (3) If we decide to rely on file permissions and SELinux policy to
>> protect these key/cert files, then we don't need to pass the file
>> names as a secret, instead, passing them as regular qemu_opt_get()
>> options might be enough.
>
> That's correct - you can assume file permissions protect the cert
> files. I would expect the syntax to work as follows
>
>   $QEMU  -object 
> tls-creds-x509,id=tls0,dir=/etc/pki/qemu/vxhs,endpoint=client \
>  -drive  driver=vxhs,...other..opts...,tls-creds=tls0
>
> When you see the 'tls-creds' flag, you can lookup the corresponding
> QCryptoTLSCredsX509 object and extract the 'dir' property from it.
>

The code diff below works as above. Please verify.

> The include/crypto/tlscredsx509.h file has constants defined for the
> standard filenames - eg you would concatenate the directory with
> the constants QCRYPTO_TLS_CREDS_X509_CLIENT_KEY.
>
> This gives the filenames you can then pass to libqnio
>

I am using function qcrypto_tls_creds_get_path() to achieve the same.
Hope this is OK.

> Regards,
> Daniel
> --
> |: http://berrange.com  -o-http://www.flickr.com/photos/dberrange/ :|
> |: http://libvirt.org  -o- http://virt-manager.org :|
> |: http://entangle-photo.org   -o-http://search.cpan.org/~danberr/ :|


Example CLI accepting the new TLS credentials:

[amittal2@camshaft qemu] 2017-03-05 15:54:55$ ./qemu-io --trace
enable=vxhs* --object
tls-creds-x509,id=tls0,dir=/etc/pki/qemu/vxhs,endpoint=client -c 'read
66000 128k' 'json:{"server.host": "127.0.0.1", "server.port": "",
"vdisk-id": "/test.raw", "driver": "vxhs", "tls-creds":"tls0"}'
15116@1488758101.084355:vxhs_open_vdiskid Opening vdisk-id /test.raw
15116@1488758101.084396:vxhs_get_creds cacert
/etc/pki/qemu/vxhs/ca-cert.pem, client_key
/etc/pki/qemu/vxhs/client-key.pem, client_cert
/etc/pki/qemu/vxhs/client-cert.pem   <=  NOTE 
15116@1488758101.084402:vxhs_open_hostinfo Adding host 127.0.0.1:
to BDRVVXHSState
15116@1488758101.092060:vxhs_get_vdisk_stat vDisk /test.raw stat ioctl
returned size 1048576
read 131072/131072 bytes at offset 66000
128 KiB, 1 ops; 0.0006 sec (188.537 MiB/sec and 1508.2956 ops/sec)
15116@1488758101.094643:vxhs_close Closing vdisk /test.raw
[amittal2@camshaft qemu] 2017-03-05 15:55:01$

NB - I am passing client-key and client-cert to iio_open() here.
libqnio changes to work with these new args via iio_open() will
follow.

diff --git a/block/trace-events b/block/trace-events
index f193079..7758ec3 

Re: [Qemu-devel] [PATCH 2/2] vl: Print CPU help after we've registered the CPU accelerators

2017-03-05 Thread David Gibson
On Fri, Mar 03, 2017 at 11:58:07AM -0300, Eduardo Habkost wrote:
> On Tue, Jan 31, 2017 at 02:11:59PM +0100, Thomas Huth wrote:
> > When running with KVM on POWER, we register some CPU types during
> > the initialization function of the ppc64 KVM code (which unfortunately
> > also can not be done via a type_init() like it is done on x86).
> 
> Can you elaborate why it can't be done via type_init()? If the
> QOM type hierarchy depends on any runtime data unavailable at
> type_init(), we should fix that.

Hmm.. how?  This is specifically for the special 'host' cpu in the
case of KVM.  We can't use a static configuration here, because there
are things on the host that could limit what features of the CPU are
available for guest use.  So, we need KVM to be initialized in order
to query that information.

> > So to
> > be able to see these updates in the CPU help text, the code that calls
> > list_cpus() has to be run after configure_accelerator(). This move should
> > be fine since the "cpu_model" variable is also never used before the call
> > to configure_accelerator(), and thus there should not be any unwanted
> > side effects in the code before configure_accelerator() if the user
> > started QEMU with "-cpu ?" or "-cpu help".
> > 
> > Signed-off-by: Thomas Huth 
> 
> I am not convinced that the output of "-cpu help" and
> "-cpu help -machine accel=kvm" should look different. Do you have
> an example of what exactly is wrong with the output currently?
> 
> I actually believe list_cpus() needs to be called _earlier_, not
> later. Otherwise we won't be able to fix this bug:
> 
>   $ qemu-system-arm -cpu help
>   qemu-system-arm:/usr/local/etc/qemu/qemu.conf:1: No machine specified, and 
> there is no default
>   Use -machine help to list supported machines
>   $ 
> 
> > ---
> >  vl.c | 10 +-
> >  1 file changed, 5 insertions(+), 5 deletions(-)
> > 
> > diff --git a/vl.c b/vl.c
> > index 0b72b12..315c5c3 100644
> > --- a/vl.c
> > +++ b/vl.c
> > @@ -4055,11 +4055,6 @@ int main(int argc, char **argv, char **envp)
> >  qemu_set_hw_version(machine_class->hw_version);
> >  }
> >  
> > -if (cpu_model && is_help_option(cpu_model)) {
> > -list_cpus(stdout, &fprintf, cpu_model);
> > -exit(0);
> > -}
> > -
> >  if (!trace_init_backends()) {
> >  exit(1);
> >  }
> > @@ -4298,6 +4293,11 @@ int main(int argc, char **argv, char **envp)
> >  
> >  configure_accelerator(current_machine);
> >  
> > +if (cpu_model && is_help_option(cpu_model)) {
> > +list_cpus(stdout, &fprintf, cpu_model);
> > +exit(0);
> > +}
> > +
> >  if (qtest_chrdev) {
> >  qtest_init(qtest_chrdev, qtest_log, &error_fatal);
> >  }
> 

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


signature.asc
Description: PGP signature


Re: [Qemu-devel] [PATCH] block: Constify data passed by pointer to blk_name

2017-03-05 Thread Philippe Mathieu-Daudé

On 03/05/2017 06:44 PM, Krzysztof Kozlowski wrote:

blk_name() is not modifying data passed to it through pointer and it
returns also a pointer to const so the argument can be made const for
code safeness.

Signed-off-by: Krzysztof Kozlowski 


Reviewed-by: Philippe Mathieu-Daudé 


---
 block/block-backend.c  | 2 +-
 include/sysemu/block-backend.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index daa7908d0151..2d2169a5dfb0 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -409,7 +409,7 @@ void monitor_remove_blk(BlockBackend *blk)
  * Return @blk's name, a non-null string.
  * Returns an empty string iff @blk is not referenced by the monitor.
  */
-const char *blk_name(BlockBackend *blk)
+const char *blk_name(const BlockBackend *blk)
 {
 return blk->name ?: "";
 }
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 096c17fce064..d16c85d67b5c 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -91,7 +91,7 @@ int blk_get_refcnt(BlockBackend *blk);
 void blk_ref(BlockBackend *blk);
 void blk_unref(BlockBackend *blk);
 void blk_remove_all_bs(void);
-const char *blk_name(BlockBackend *blk);
+const char *blk_name(const BlockBackend *blk);
 BlockBackend *blk_by_name(const char *name);
 BlockBackend *blk_next(BlockBackend *blk);
 bool monitor_add_blk(BlockBackend *blk, const char *name, Error **errp);





Re: [Qemu-devel] [Qemu-arm] [PATCH 1/3] hw/arm/exynos: Convert fprintf to error_report()

2017-03-05 Thread Philippe Mathieu-Daudé

Hi Krzysztof,

On 03/05/2017 06:48 PM, Krzysztof Kozlowski wrote:

error_report() is preferred over fprintf() for logging errors.  Also
remove square brackets [] and additional new line characters in printed
messages.

Signed-off-by: Krzysztof Kozlowski 
---
 hw/arm/exynos4_boards.c   |  6 +++---
 hw/timer/exynos4210_mct.c |  5 +++--
 hw/timer/exynos4210_pwm.c | 11 +--
 hw/timer/exynos4210_rtc.c | 16 +++-
 4 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
index 0efa19405409..5cd94d402b52 100644
--- a/hw/arm/exynos4_boards.c
+++ b/hw/arm/exynos4_boards.c
@@ -22,6 +22,7 @@
  */

 #include "qemu/osdep.h"
+#include "qemu/error-report.h"
 #include "qemu-common.h"
 #include "cpu.h"
 #include "sysemu/sysemu.h"
@@ -101,9 +102,8 @@ static Exynos4210State 
*exynos4_boards_init_common(MachineState *machine,
 MachineClass *mc = MACHINE_GET_CLASS(machine);

 if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) {
-fprintf(stderr, "%s board supports only %d CPU cores. Ignoring 
smp_cpus"
-" value.\n",
-mc->name, EXYNOS4210_NCPUS);
+error_report("%s board supports only %d CPU cores. Ignoring smp_cpus 
value.",
+ mc->name, EXYNOS4210_NCPUS);


ok, to inform the user


 }

 exynos4_board_binfo.ram_size = exynos4_board_ram_size[board_type];
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index 6069116942a4..48041ab036a6 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -53,6 +53,7 @@
  */

 #include "qemu/osdep.h"
+#include "qemu/error-report.h"
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu/main-loop.h"
@@ -1364,8 +1365,8 @@ static void exynos4210_mct_write(void *opaque, hwaddr 
offset,
 case L0_TCNTO: case L1_TCNTO:
 case L0_ICNTO: case L1_ICNTO:
 case L0_FRCNTO: case L1_FRCNTO:
-fprintf(stderr, "\n[exynos4210.mct: write to RO register "
-TARGET_FMT_plx "]\n\n", offset);
+error_report("exynos4210.mct: write to RO register " TARGET_FMT_plx,
+ offset);


no need to annoy the user here, it seems better to use 
qemu_log_mask(LOG_UNIMP, ...


same for following diffs


 break;

 case L0_INT_CSTAT: case L1_INT_CSTAT:
diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c
index f5765075c720..f8826e24e63d 100644
--- a/hw/timer/exynos4210_pwm.c
+++ b/hw/timer/exynos4210_pwm.c
@@ -21,6 +21,7 @@
  */

 #include "qemu/osdep.h"
+#include "qemu/error-report.h"
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
@@ -252,9 +253,8 @@ static uint64_t exynos4210_pwm_read(void *opaque, hwaddr 
offset,
 break;

 default:
-fprintf(stderr,
-"[exynos4210.pwm: bad read offset " TARGET_FMT_plx "]\n",
-offset);
+error_report("exynos4210.pwm: bad read offset " TARGET_FMT_plx,
+ offset);
 break;
 }
 return value;
@@ -343,9 +343,8 @@ static void exynos4210_pwm_write(void *opaque, hwaddr 
offset,
 break;

 default:
-fprintf(stderr,
-"[exynos4210.pwm: bad write offset " TARGET_FMT_plx "]\n",
-offset);
+error_report("exynos4210.pwm: bad write offset " TARGET_FMT_plx,
+ offset);
 break;

 }
diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c
index 1a648c5d9e67..f4548cd555f4 100644
--- a/hw/timer/exynos4210_rtc.c
+++ b/hw/timer/exynos4210_rtc.c
@@ -26,6 +26,7 @@
  */

 #include "qemu/osdep.h"
+#include "qemu/error-report.h"
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
@@ -370,9 +371,8 @@ static uint64_t exynos4210_rtc_read(void *opaque, hwaddr 
offset,
 break;

 default:
-fprintf(stderr,
-"[exynos4210.rtc: bad read offset " TARGET_FMT_plx "]\n",
-offset);
+error_report("exynos4210.rtc: bad read offset " TARGET_FMT_plx,
+ offset);
 break;
 }
 return value;
@@ -433,9 +433,8 @@ static void exynos4210_rtc_write(void *opaque, hwaddr 
offset,
 if (value > TICNT_THRESHOLD) {
 s->reg_ticcnt = value;
 } else {
-fprintf(stderr,
-"[exynos4210.rtc: bad TICNT value %u ]\n",
-(uint32_t)value);
+error_report("exynos4210.rtc: bad TICNT value %u",
+ (uint32_t)value);
 }
 break;

@@ -500,9 +499,8 @@ static void exynos4210_rtc_write(void *opaque, hwaddr 
offset,
 break;

 default:
-fprintf(stderr,
-"[exynos4210.rtc: bad write offset " TARGET_FMT_plx "]\n",
-offset);
+error_report("exynos4210.rtc: bad write offset " TARGET_FMT_plx,
+ offset);
 break;

 }





[Qemu-devel] [PATCH 3/3] hw/misc/exynos4210_pmu: Reorder local variables for readability

2017-03-05 Thread Krzysztof Kozlowski
Short declaration of 'i' was in the middle of declarations with
assignments.  Make it a little bit more readable.  No functional change.

Signed-off-by: Krzysztof Kozlowski 
---
 hw/misc/exynos4210_pmu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/misc/exynos4210_pmu.c b/hw/misc/exynos4210_pmu.c
index cbdfa0614600..60d1545c0baa 100644
--- a/hw/misc/exynos4210_pmu.c
+++ b/hw/misc/exynos4210_pmu.c
@@ -401,8 +401,8 @@ static uint64_t exynos4210_pmu_read(void *opaque, hwaddr 
offset,
 unsigned size)
 {
 const Exynos4210PmuState *s = (Exynos4210PmuState *)opaque;
-unsigned i;
 const Exynos4210PmuReg *reg_p = exynos4210_pmu_regs;
+unsigned i;
 
 for (i = 0; i < PMU_NUM_OF_REGISTERS; i++) {
 if (reg_p->offset == offset) {
@@ -420,8 +420,8 @@ static void exynos4210_pmu_write(void *opaque, hwaddr 
offset,
  uint64_t val, unsigned size)
 {
 Exynos4210PmuState *s = (Exynos4210PmuState *)opaque;
-unsigned i;
 const Exynos4210PmuReg *reg_p = exynos4210_pmu_regs;
+unsigned i;
 
 for (i = 0; i < PMU_NUM_OF_REGISTERS; i++) {
 if (reg_p->offset == offset) {
-- 
2.9.3




[Qemu-devel] [PATCH 2/3] hw/arm/exynos4210: Constify data pointed by few arguments and variables

2017-03-05 Thread Krzysztof Kozlowski
In few places the function arguments and local variables are not
modifying data passed through pointers so this can be made const for
code safeness.  Also the static array exynos4210_uart_regs is not being
modified.

Signed-off-by: Krzysztof Kozlowski 
---
 hw/char/exynos4210_uart.c | 10 +-
 hw/intc/exynos4210_combiner.c |  2 +-
 hw/intc/exynos4210_gic.c  |  8 
 hw/misc/exynos4210_pmu.c  |  2 +-
 4 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
index b75f28d473bf..83e1be253255 100644
--- a/hw/char/exynos4210_uart.c
+++ b/hw/char/exynos4210_uart.c
@@ -102,7 +102,7 @@ typedef struct Exynos4210UartReg {
 uint32_treset_value;
 } Exynos4210UartReg;
 
-static Exynos4210UartReg exynos4210_uart_regs[] = {
+static const Exynos4210UartReg exynos4210_uart_regs[] = {
 {"ULCON",ULCON,0x},
 {"UCON", UCON, 0x3000},
 {"UFCON",UFCON,0x},
@@ -220,7 +220,7 @@ static uint8_t fifo_retrieve(Exynos4210UartFIFO *q)
 return  ret;
 }
 
-static int fifo_elements_number(Exynos4210UartFIFO *q)
+static int fifo_elements_number(const Exynos4210UartFIFO *q)
 {
 if (q->sp < q->rp) {
 return q->size - q->rp + q->sp;
@@ -229,7 +229,7 @@ static int fifo_elements_number(Exynos4210UartFIFO *q)
 return q->sp - q->rp;
 }
 
-static int fifo_empty_elements_number(Exynos4210UartFIFO *q)
+static int fifo_empty_elements_number(const Exynos4210UartFIFO *q)
 {
 return q->size - fifo_elements_number(q);
 }
@@ -245,7 +245,7 @@ static void fifo_reset(Exynos4210UartFIFO *q)
 q->rp = 0;
 }
 
-static uint32_t exynos4210_uart_Tx_FIFO_trigger_level(Exynos4210UartState *s)
+static uint32_t exynos4210_uart_Tx_FIFO_trigger_level(const 
Exynos4210UartState *s)
 {
 uint32_t level = 0;
 uint32_t reg;
@@ -488,7 +488,7 @@ static const MemoryRegionOps exynos4210_uart_ops = {
 
 static int exynos4210_uart_can_receive(void *opaque)
 {
-Exynos4210UartState *s = (Exynos4210UartState *)opaque;
+const Exynos4210UartState *s = (Exynos4210UartState *)opaque;
 
 return fifo_empty_elements_number(&s->rx);
 }
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
index f19a7062be3a..b057921e0504 100644
--- a/hw/intc/exynos4210_combiner.c
+++ b/hw/intc/exynos4210_combiner.c
@@ -180,7 +180,7 @@ void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, 
DeviceState *dev,
 static uint64_t
 exynos4210_combiner_read(void *opaque, hwaddr offset, unsigned size)
 {
-struct Exynos4210CombinerState *s =
+const struct Exynos4210CombinerState *s =
 (struct Exynos4210CombinerState *)opaque;
 uint32_t req_quad_base_n;/* Base of registers quad. Multiply it by 4 
and
get a start of corresponding group quad */
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
index 2a55817b7660..432b8425d09d 100644
--- a/hw/intc/exynos4210_gic.c
+++ b/hw/intc/exynos4210_gic.c
@@ -190,7 +190,7 @@ 
combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
 
 static void exynos4210_irq_handler(void *opaque, int irq, int level)
 {
-Exynos4210Irq *s = (Exynos4210Irq *)opaque;
+const Exynos4210Irq *s = (Exynos4210Irq *)opaque;
 
 /* Bypass */
 qemu_set_irq(s->board_irqs[irq], level);
@@ -277,7 +277,7 @@ typedef struct {
 
 static void exynos4210_gic_set_irq(void *opaque, int irq, int level)
 {
-Exynos4210GicState *s = (Exynos4210GicState *)opaque;
+const Exynos4210GicState *s = (Exynos4210GicState *)opaque;
 qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
 }
 
@@ -401,7 +401,7 @@ static const VMStateDescription vmstate_exynos4210_irq_gate 
= {
 /* Process a change in IRQ input. */
 static void exynos4210_irq_gate_handler(void *opaque, int irq, int level)
 {
-Exynos4210IRQGateState *s = (Exynos4210IRQGateState *)opaque;
+const Exynos4210IRQGateState *s = (Exynos4210IRQGateState *)opaque;
 uint32_t i;
 
 assert(irq < s->n_in);
@@ -420,7 +420,7 @@ static void exynos4210_irq_gate_handler(void *opaque, int 
irq, int level)
 
 static void exynos4210_irq_gate_reset(DeviceState *d)
 {
-Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(d);
+const Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(d);
 
 memset(s->level, 0, s->n_in * sizeof(*s->level));
 }
diff --git a/hw/misc/exynos4210_pmu.c b/hw/misc/exynos4210_pmu.c
index e30dbc7d3d83..cbdfa0614600 100644
--- a/hw/misc/exynos4210_pmu.c
+++ b/hw/misc/exynos4210_pmu.c
@@ -400,7 +400,7 @@ typedef struct Exynos4210PmuState {
 static uint64_t exynos4210_pmu_read(void *opaque, hwaddr offset,
 unsigned size)
 {
-Exynos4210PmuState *s = (Exynos4210PmuState *)opaque;
+const Exynos4210PmuState *s = (Exynos4210PmuState *)opaque;
 unsigned i;
 const Exynos4210PmuReg *reg_p = exynos4210_pmu_regs;
 
-- 
2.9.3




[Qemu-devel] [PATCH 1/3] hw/arm/exynos: Convert fprintf to error_report()

2017-03-05 Thread Krzysztof Kozlowski
error_report() is preferred over fprintf() for logging errors.  Also
remove square brackets [] and additional new line characters in printed
messages.

Signed-off-by: Krzysztof Kozlowski 
---
 hw/arm/exynos4_boards.c   |  6 +++---
 hw/timer/exynos4210_mct.c |  5 +++--
 hw/timer/exynos4210_pwm.c | 11 +--
 hw/timer/exynos4210_rtc.c | 16 +++-
 4 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
index 0efa19405409..5cd94d402b52 100644
--- a/hw/arm/exynos4_boards.c
+++ b/hw/arm/exynos4_boards.c
@@ -22,6 +22,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/error-report.h"
 #include "qemu-common.h"
 #include "cpu.h"
 #include "sysemu/sysemu.h"
@@ -101,9 +102,8 @@ static Exynos4210State 
*exynos4_boards_init_common(MachineState *machine,
 MachineClass *mc = MACHINE_GET_CLASS(machine);
 
 if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) {
-fprintf(stderr, "%s board supports only %d CPU cores. Ignoring 
smp_cpus"
-" value.\n",
-mc->name, EXYNOS4210_NCPUS);
+error_report("%s board supports only %d CPU cores. Ignoring smp_cpus 
value.",
+ mc->name, EXYNOS4210_NCPUS);
 }
 
 exynos4_board_binfo.ram_size = exynos4_board_ram_size[board_type];
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index 6069116942a4..48041ab036a6 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -53,6 +53,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/error-report.h"
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu/main-loop.h"
@@ -1364,8 +1365,8 @@ static void exynos4210_mct_write(void *opaque, hwaddr 
offset,
 case L0_TCNTO: case L1_TCNTO:
 case L0_ICNTO: case L1_ICNTO:
 case L0_FRCNTO: case L1_FRCNTO:
-fprintf(stderr, "\n[exynos4210.mct: write to RO register "
-TARGET_FMT_plx "]\n\n", offset);
+error_report("exynos4210.mct: write to RO register " TARGET_FMT_plx,
+ offset);
 break;
 
 case L0_INT_CSTAT: case L1_INT_CSTAT:
diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c
index f5765075c720..f8826e24e63d 100644
--- a/hw/timer/exynos4210_pwm.c
+++ b/hw/timer/exynos4210_pwm.c
@@ -21,6 +21,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/error-report.h"
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
@@ -252,9 +253,8 @@ static uint64_t exynos4210_pwm_read(void *opaque, hwaddr 
offset,
 break;
 
 default:
-fprintf(stderr,
-"[exynos4210.pwm: bad read offset " TARGET_FMT_plx "]\n",
-offset);
+error_report("exynos4210.pwm: bad read offset " TARGET_FMT_plx,
+ offset);
 break;
 }
 return value;
@@ -343,9 +343,8 @@ static void exynos4210_pwm_write(void *opaque, hwaddr 
offset,
 break;
 
 default:
-fprintf(stderr,
-"[exynos4210.pwm: bad write offset " TARGET_FMT_plx "]\n",
-offset);
+error_report("exynos4210.pwm: bad write offset " TARGET_FMT_plx,
+ offset);
 break;
 
 }
diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c
index 1a648c5d9e67..f4548cd555f4 100644
--- a/hw/timer/exynos4210_rtc.c
+++ b/hw/timer/exynos4210_rtc.c
@@ -26,6 +26,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/error-report.h"
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
@@ -370,9 +371,8 @@ static uint64_t exynos4210_rtc_read(void *opaque, hwaddr 
offset,
 break;
 
 default:
-fprintf(stderr,
-"[exynos4210.rtc: bad read offset " TARGET_FMT_plx "]\n",
-offset);
+error_report("exynos4210.rtc: bad read offset " TARGET_FMT_plx,
+ offset);
 break;
 }
 return value;
@@ -433,9 +433,8 @@ static void exynos4210_rtc_write(void *opaque, hwaddr 
offset,
 if (value > TICNT_THRESHOLD) {
 s->reg_ticcnt = value;
 } else {
-fprintf(stderr,
-"[exynos4210.rtc: bad TICNT value %u ]\n",
-(uint32_t)value);
+error_report("exynos4210.rtc: bad TICNT value %u",
+ (uint32_t)value);
 }
 break;
 
@@ -500,9 +499,8 @@ static void exynos4210_rtc_write(void *opaque, hwaddr 
offset,
 break;
 
 default:
-fprintf(stderr,
-"[exynos4210.rtc: bad write offset " TARGET_FMT_plx "]\n",
-offset);
+error_report("exynos4210.rtc: bad write offset " TARGET_FMT_plx,
+ offset);
 break;
 
 }
-- 
2.9.3




[Qemu-devel] [PATCH] qdev: Constify data pointed by few arguments and local variables

2017-03-05 Thread Krzysztof Kozlowski
In few places the function arguments and local variables are not
modifying data passed through pointers so this can be made const for
code safeness.

Signed-off-by: Krzysztof Kozlowski 
---
 hw/core/qdev-properties-system.c |  6 +++---
 hw/core/qdev-properties.c|  7 ---
 include/hw/qdev-properties.h | 11 +++
 3 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index c34be1c1bace..abbf3ef754d8 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -405,7 +405,7 @@ void qdev_prop_set_drive(DeviceState *dev, const char *name,
 if (value) {
 ref = blk_name(value);
 if (!*ref) {
-BlockDriverState *bs = blk_bs(value);
+const BlockDriverState *bs = blk_bs(value);
 if (bs) {
 ref = bdrv_get_node_name(bs);
 }
@@ -416,7 +416,7 @@ void qdev_prop_set_drive(DeviceState *dev, const char *name,
 }
 
 void qdev_prop_set_chr(DeviceState *dev, const char *name,
-   Chardev *value)
+   const Chardev *value)
 {
 assert(!value || value->label);
 object_property_set_str(OBJECT(dev),
@@ -424,7 +424,7 @@ void qdev_prop_set_chr(DeviceState *dev, const char *name,
 }
 
 void qdev_prop_set_netdev(DeviceState *dev, const char *name,
-  NetClientState *value)
+  const NetClientState *value)
 {
 assert(!value || value->name);
 object_property_set_str(OBJECT(dev),
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 6ab4265eb478..34ec10f0caac 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -1010,7 +1010,8 @@ void qdev_prop_set_string(DeviceState *dev, const char 
*name, const char *value)
 object_property_set_str(OBJECT(dev), value, name, &error_abort);
 }
 
-void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
+void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
+   const uint8_t *value)
 {
 char str[2 * 6 + 5 + 1];
 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
@@ -1028,10 +1029,10 @@ void qdev_prop_set_enum(DeviceState *dev, const char 
*name, int value)
 name, &error_abort);
 }
 
-void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
+void qdev_prop_set_ptr(DeviceState *dev, const char *name, const void *value)
 {
 Property *prop;
-void **ptr;
+const void **ptr;
 
 prop = qdev_prop_find(dev, name);
 assert(prop && prop->info == &qdev_prop_ptr);
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 7ac315331aa0..659561daad0d 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -184,14 +184,17 @@ void qdev_prop_set_uint32(DeviceState *dev, const char 
*name, uint32_t value);
 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
 void qdev_prop_set_string(DeviceState *dev, const char *name, const char 
*value);
-void qdev_prop_set_chr(DeviceState *dev, const char *name, Chardev *value);
-void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState 
*value);
+void qdev_prop_set_chr(DeviceState *dev, const char *name,
+   const Chardev *value);
+void qdev_prop_set_netdev(DeviceState *dev, const char *name,
+  const NetClientState *value);
 void qdev_prop_set_drive(DeviceState *dev, const char *name,
  BlockBackend *value, Error **errp);
-void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
+void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
+   const uint8_t *value);
 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
 /* FIXME: Remove opaque pointer properties.  */
-void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
+void qdev_prop_set_ptr(DeviceState *dev, const char *name, const void *value);
 
 void qdev_prop_register_global(GlobalProperty *prop);
 void qdev_prop_register_global_list(GlobalProperty *props);
-- 
2.9.3




[Qemu-devel] [PATCH 2/2] char: Remove confusing mix of assignment with local variables

2017-03-05 Thread Krzysztof Kozlowski
The assignment under pointed offset was put next to declaration of local
variables.  This might be quite confusing as the assignment looks like
duplicated declaration of offset variable.

Signed-off-by: Krzysztof Kozlowski 
---
 chardev/char.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/chardev/char.c b/chardev/char.c
index a2571409bf65..b9343e03b9ec 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -104,6 +104,7 @@ static int qemu_chr_fe_write_buffer(Chardev *s,
 {
 const ChardevClass *cc = CHARDEV_GET_CLASS(s);
 int res = 0;
+
 *offset = 0;
 
 qemu_mutex_lock(&s->chr_write_lock);
-- 
2.9.3




[Qemu-devel] [PATCH 1/2] char: Constify data pointed by few arguments and local variables

2017-03-05 Thread Krzysztof Kozlowski
In few places the function arguments and local variables are not
modifying data passed through pointers so this can be made const for
code safeness.

Signed-off-by: Krzysztof Kozlowski 
---
 chardev/char.c| 18 +-
 include/sysemu/char.h |  2 +-
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/chardev/char.c b/chardev/char.c
index 54cd5f408150..a2571409bf65 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -102,7 +102,7 @@ static void qemu_chr_fe_write_log(Chardev *s,
 static int qemu_chr_fe_write_buffer(Chardev *s,
 const uint8_t *buf, int len, int *offset)
 {
-ChardevClass *cc = CHARDEV_GET_CLASS(s);
+const ChardevClass *cc = CHARDEV_GET_CLASS(s);
 int res = 0;
 *offset = 0;
 
@@ -129,7 +129,7 @@ static int qemu_chr_fe_write_buffer(Chardev *s,
 return res;
 }
 
-static bool qemu_chr_replay(Chardev *chr)
+static bool qemu_chr_replay(const Chardev *chr)
 {
 return qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_REPLAY);
 }
@@ -137,7 +137,7 @@ static bool qemu_chr_replay(Chardev *chr)
 int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len)
 {
 Chardev *s = be->chr;
-ChardevClass *cc;
+const ChardevClass *cc;
 int ret;
 
 if (!s) {
@@ -369,7 +369,7 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, 
...)
 static void qemu_char_open(Chardev *chr, ChardevBackend *backend,
bool *be_opened, Error **errp)
 {
-ChardevClass *cc = CHARDEV_GET_CLASS(chr);
+const ChardevClass *cc = CHARDEV_GET_CLASS(chr);
 /* Any ChardevCommon member would work */
 ChardevCommon *common = backend ? backend->u.null.data : NULL;
 
@@ -513,10 +513,10 @@ unavailable:
 return false;
 }
 
-static bool qemu_chr_is_busy(Chardev *s)
+static bool qemu_chr_is_busy(const Chardev *s)
 {
 if (CHARDEV_IS_MUX(s)) {
-MuxChardev *d = MUX_CHARDEV(s);
+const MuxChardev *d = MUX_CHARDEV(s);
 return d->mux_cnt >= 0;
 } else {
 return s->be != NULL;
@@ -549,7 +549,7 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
   bool set_open)
 {
 Chardev *s;
-ChardevClass *cc;
+const ChardevClass *cc;
 int fe_open;
 
 s = b->chr;
@@ -603,7 +603,7 @@ void qemu_chr_fe_take_focus(CharBackend *b)
 
 int qemu_chr_wait_connected(Chardev *chr, Error **errp)
 {
-ChardevClass *cc = CHARDEV_GET_CLASS(chr);
+const ChardevClass *cc = CHARDEV_GET_CLASS(chr);
 
 if (cc->chr_wait_connected) {
 return cc->chr_wait_connected(chr, errp);
@@ -1223,7 +1223,7 @@ QemuOptsList qemu_chardev_opts = {
 },
 };
 
-bool qemu_chr_has_feature(Chardev *chr,
+bool qemu_chr_has_feature(const Chardev *chr,
   ChardevFeature feature)
 {
 return test_bit(feature, chr->features);
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 450881d42cb5..2b11bbc40692 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -432,7 +432,7 @@ void qemu_chr_fe_accept_input(CharBackend *be);
 int qemu_chr_add_client(Chardev *s, int fd);
 Chardev *qemu_chr_find(const char *name);
 
-bool qemu_chr_has_feature(Chardev *chr,
+bool qemu_chr_has_feature(const Chardev *chr,
   ChardevFeature feature);
 void qemu_chr_set_feature(Chardev *chr,
   ChardevFeature feature);
-- 
2.9.3




[Qemu-devel] [PATCH] block: Constify data passed by pointer to blk_name

2017-03-05 Thread Krzysztof Kozlowski
blk_name() is not modifying data passed to it through pointer and it
returns also a pointer to const so the argument can be made const for
code safeness.

Signed-off-by: Krzysztof Kozlowski 
---
 block/block-backend.c  | 2 +-
 include/sysemu/block-backend.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index daa7908d0151..2d2169a5dfb0 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -409,7 +409,7 @@ void monitor_remove_blk(BlockBackend *blk)
  * Return @blk's name, a non-null string.
  * Returns an empty string iff @blk is not referenced by the monitor.
  */
-const char *blk_name(BlockBackend *blk)
+const char *blk_name(const BlockBackend *blk)
 {
 return blk->name ?: "";
 }
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 096c17fce064..d16c85d67b5c 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -91,7 +91,7 @@ int blk_get_refcnt(BlockBackend *blk);
 void blk_ref(BlockBackend *blk);
 void blk_unref(BlockBackend *blk);
 void blk_remove_all_bs(void);
-const char *blk_name(BlockBackend *blk);
+const char *blk_name(const BlockBackend *blk);
 BlockBackend *blk_by_name(const char *name);
 BlockBackend *blk_next(BlockBackend *blk);
 bool monitor_add_blk(BlockBackend *blk, const char *name, Error **errp);
-- 
2.9.3




Re: [Qemu-devel] Qemu deadlocks in tb_lock when using SVM+SoftMMU

2017-03-05 Thread Alex Bennée

Alexander Boettcher  writes:

> Hello,
>
> beginning with commit 3bd1d74576bacb120949e13cdeded7a0c792c685
>
> "cputlb: introduce tlb_flush_* async work"
>
> using Qemu with SoftMMU+SVM virtualization deadlocks because tb_lock is
> taken second time in cputlb.c tlb_flush_nocheck() function. The first
> time tb_lock is taken, according to my debugging, in cpu-exex.c
> tb_find() line 361.


> (gdb) info threads
>   Id   Target Id Frame
> * 1Thread 0x7ffbc19d3c00 (LWP 8396) "qemu-system-x86"
> 0x7ffbbfd2ac21 in __GI_ppoll (fds=0x273a330, nfds=6,
> timeout=, sigmask=0x0) at
> ../sysdeps/unix/sysv/linux/ppoll.c:50
>   2Thread 0x7ffbbb970700 (LWP 8397) "qemu-system-x86" syscall () at
> ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
>   3Thread 0x7ffbb8206700 (LWP 8399) "qemu-system-x86" __lll_lock_wait ()
> at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
> (gdb) thread 3
> [Switching to thread 3 (Thread 0x7ffbb8206700 (LWP 8399))]
> #0  __lll_lock_wait () at
> ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
> 135   ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: No such file or
> directory.
> (gdb) bt
> #0  __lll_lock_wait () at
> ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
> #1  0x7ffbc0002dbd in __GI___pthread_mutex_lock (mutex=0xf6ea18
> ) at ../nptl/pthread_mutex_lock.c:80
> #2  0x0089852c in qemu_mutex_lock (mutex=0xf6ea18 )
> at util/qemu-thread-posix.c:60
> #3  0x00416103 in tb_lock () at qemu.git/translate-all.c:166
> #4  0x0046e8d7 in tlb_flush_nocheck (cpu=0x164a360) at
> qemu.git/cputlb.c:93
> #5  0x0046ea2e in tlb_flush (cpu=0x164a360) at qemu.git/cputlb.c:121
> #6  0x00538987 in cpu_x86_update_cr4 (env=0x16525f0, new_cr4=1784)
> at qemu.git/target/i386/helper.c:660
> #7  0x0055e318 in cpu_vmexit (env=0x16525f0, exit_code=78,
> exit_info_1=4, retaddr=0)
> at qemu.git/target/i386/svm_helper.c:689
> #8  0x0055d9b7 in cpu_svm_check_intercept_param (env=0x16525f0,
> type=78, param=4, retaddr=0)
> at qemu.git/target/i386/svm_helper.c:511
> #9  0x00541acf in raise_interrupt2 (env=0x16525f0, intno=14,
> is_int=0, error_code=4, next_eip_addend=0, retaddr=0)
> at qemu.git/target/i386/excp_helper.c:96
> #10 0x00541c0d in raise_exception_err_ra (env=0x16525f0,
> exception_index=14, error_code=4, retaddr=0)
> at qemu.git/target/i386/excp_helper.c:127
> #11 0x005621a9 in tlb_fill (cs=0x164a360, addr=1245184,
> access_type=MMU_INST_FETCH, mmu_idx=1, retaddr=0)
> at qemu.git/target/i386/mem_helper.c:212

Richard,

So this looks like another path through the SoftMMU code during
code-generation (which is why tb_lock() is held in the first place). I'm
not sure if the correct thing to do is bug out earlier or to defer the
exception raising part to async work and exit the loop.


> #12 0x00476c15 in helper_ret_ldb_cmmu (env=0x16525f0,
> addr=1245184, oi=1, retaddr=0)
> at qemu.git/softmmu_template.h:127
> #13 0x0051c86e in cpu_ldub_code_ra (env=0x16525f0, ptr=1245184,
> retaddr=0)
> at qemu.git/include/exec/cpu_ldst_template.h:102
> #14 0x0051c8e4 in cpu_ldub_code (env=0x16525f0, ptr=1245184)
> at qemu.git/include/exec/cpu_ldst_template.h:114
> #15 0x00522182 in insn_get (env=0x16525f0, s=0x7ffbb82057e0,
> ot=MO_8)
> at qemu.git/target/i386/translate.c:2107
> #16 0x0052ff3c in disas_insn (env=0x16525f0, s=0x7ffbb82057e0,
> pc_start=1245183)
> at qemu.git/target/i386/translate.c:6520
> #17 0x00536458 in gen_intermediate_code (env=0x16525f0,
> tb=0x7ffbb9ce3a38)
> at qemu.git/target/i386/translate.c:8449
> ---Type  to continue, or q  to quit---
> #18 0x00417616 in tb_gen_code (cpu=0x164a360, pc=1245179,
> cs_base=0, flags=7342771, cflags=0)
> at qemu.git/translate-all.c:1281
> #19 0x0041993c in tb_find (cpu=0x164a360, last_tb=0x0,
> tb_exit=0) at qemu.git/cpu-exec.c:370
> #20 0x0041a25b in cpu_exec (cpu=0x164a360) at
> qemu.git/cpu-exec.c:685
> #21 0x0044b078 in tcg_cpu_exec (cpu=0x164a360) at
> qemu.git/cpus.c:1251
> #22 0x0044b2e7 in qemu_tcg_rr_cpu_thread_fn (arg=0x164a360) at
> qemu.git/cpus.c:1347
> #23 0x7ffbc6ba in start_thread (arg=0x7ffbb8206700) at
> pthread_create.c:333
> #24 0x7ffbbfd3682d in clone () at
> ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
>

>
> I'm using Qemu with:
>
> qemu-system-x86_64 -s -no-kvm -display sdl -m 512 -cpu phenom -nographic
> -cdrom genode.iso
>
> When building with
> ./configure --target-list=x86_64-softmmu --enable-debug --disable-pie
> --enable-debug-tcg
>
> I get also a
>
> translate-all.c:165: tb_lock: Assertion `!have_tb_lock' failed.
>
> beginning with commit 3bd1d74576bacb120949e13cdeded7a0c792c685. Before
> the commit all is fine.
>
> Since I'm not very familiar with Qemu internals, it is not clear to me
> whether this commit breaks things or whether something must be
> handled/added 

Re: [Qemu-devel] [PATCH 1/3] usb-ccid: make ccid_write_data_block() cope with null buffers

2017-03-05 Thread Marc-André Lureau
On Sat, Mar 4, 2017 at 10:57 PM Philippe Mathieu-Daudé 
wrote:

> static code analyzer complain:
>
> hw/usb/dev-smartcard-reader.c:816:5: warning: Null pointer passed as an
> argument to a 'nonnull' parameter
> memcpy(p->abData, data, len);
> ^~~~
>
> Reported-by: Clang Static Analyzer
> Signed-off-by: Philippe Mathieu-Daudé 
>


Reviewed-by: Marc-André Lureau 



> ---
>  hw/usb/dev-smartcard-reader.c | 8 +++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
> index 757b8b3f5a..c38a4e5886 100644
> --- a/hw/usb/dev-smartcard-reader.c
> +++ b/hw/usb/dev-smartcard-reader.c
> @@ -799,8 +799,14 @@ static void ccid_write_parameters(USBCCIDState *s,
> CCID_Header *recv)
>  static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t
> seq,
>const uint8_t *data, uint32_t len)
>  {
> -CCID_DataBlock *p = ccid_reserve_recv_buf(s, sizeof(*p) + len);
> +CCID_DataBlock *p;
>
> +if (len == 0) {
> +return;
> +}
> +g_assert(data != NULL);
> +
> +p = ccid_reserve_recv_buf(s, sizeof(*p) + len);
>  if (p == NULL) {
>  return;
>  }
> --
> 2.11.0
>
>
> --
Marc-André Lureau


Re: [Qemu-devel] [PATCH 3/3] qga: fix compiler warnings (clang 5)

2017-03-05 Thread Marc-André Lureau
On Sat, Mar 4, 2017 at 10:58 PM Philippe Mathieu-Daudé 
wrote:

> static code analyzer complain:
>
> qga/commands-posix.c:2127:9: warning: Null pointer passed as an argument
> to a 'nonnull' parameter
> closedir(dp);
> ^~~~
>
> Reported-by: Clang Static Analyzer
> Signed-off-by: Philippe Mathieu-Daudé 
>


Reviewed-by: Marc-André Lureau 



> ---
>  qga/commands-posix.c | 8 +---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/qga/commands-posix.c b/qga/commands-posix.c
> index ea37c097cf..9c4ef2d640 100644
> --- a/qga/commands-posix.c
> +++ b/qga/commands-posix.c
> @@ -2119,9 +2119,11 @@ static void transfer_memory_block(GuestMemoryBlock
> *mem_blk, bool sys2memblk,
>   * we think this VM does not support online/offline memory block,
>   * any other solution?
>   */
> -if (!dp && errno == ENOENT) {
> -result->response =
> -GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED;
> +if (!dp) {
> +if (errno == ENOENT) {
> +result->response =
> +
> GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED;
> +}
>  goto out1;
>  }
>  closedir(dp);
> --
> 2.11.0
>
>
> --
Marc-André Lureau


[Qemu-devel] [Bug 1670175] [NEW] qemu-system-sparc64 with tribblix-sparc-0m16.iso ends with "panic - kernel: no nucleus hblk8 to allocate"

2017-03-05 Thread Michal Nowak
Public bug reported:

> qemu-system-sparc64 -m 1024 -cdrom Downloads/tribblix-sparc-0m16.iso -boot d 
> -nographic
OpenBIOS for Sparc64
Configuration device id QEMU version 1 machine id 0
kernel cmdline 
CPUs: 1 x SUNW,UltraSPARC-IIi
UUID: ----
Welcome to OpenBIOS v1.1 built on Nov 24 2016 21:23
  Type 'help' for detailed information
Trying cdrom:f...
Not a bootable ELF image
Not a bootable a.out image

Loading FCode image...
Loaded 7120 bytes
entry point is 0x4000
Evaluating FCode...
Evaluating FCode...
Ignoring failed claim for va 10a96a0 memsz 19!
Ignoring failed claim for va 100 memsz d1fb6!
Ignoring failed claim for va 1402000 memsz 32518!
Ignoring failed claim for va 180 memsz 52ac8!
SunOS Release 5.11 Version tribblix-m16 64-bit
Copyright (c) 1983, 2010, Oracle and/or its affiliates. All rights reserved.
could not find debugger-vocabulary-hook>threads:interpret: exception -13 caught
interpret \ ident   "%Z%%M% %I% %E% SMI"
\ Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
\ Use is subject to license terms.
\
\ CDDL HEADER START
\
\ The contents of this file are subject to the terms of the
\ Common Development and Distribution License, Version 1.0 only
\ (the "License").  You may not use this file except in compliance
\ with the License.
\
\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
\ or http://www.opensolaris.org/os/licensing.
\ See the License for 
WARNING: add_spec: No major number for sf
panic - kernel: no nucleus hblk8 to allocate
EXIT

QEMU keeps running (CPU is on 100 % all the time), I can interact with
the prompt:

0 > boot
Not a Linux kernel image
Not a bootable ELF image
Not a bootable a.out image

Loading FCode image...
Unhandled Exception 0x0018
PC = 0xffd25310 NPC = 0xffd25314
Stopping execution

> qemu-system-sparc64 -version
QEMU emulator version 2.8.0(Virtualization:Staging / SLE_12_SP2)

from https://build.opensuse.org/package/show/Virtualization:Staging/qemu
on openSUSE Leap 42.2.

ISO: http://pkgs.tribblix.org/iso/tribblix-sparc-0m16.iso.

** Affects: qemu
 Importance: Undecided
 Status: New


** Tags: sparc

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

Title:
  qemu-system-sparc64 with tribblix-sparc-0m16.iso ends with "panic -
  kernel: no nucleus hblk8 to allocate"

Status in QEMU:
  New

Bug description:
  > qemu-system-sparc64 -m 1024 -cdrom Downloads/tribblix-sparc-0m16.iso -boot 
d -nographic
  OpenBIOS for Sparc64
  Configuration device id QEMU version 1 machine id 0
  kernel cmdline 
  CPUs: 1 x SUNW,UltraSPARC-IIi
  UUID: ----
  Welcome to OpenBIOS v1.1 built on Nov 24 2016 21:23
Type 'help' for detailed information
  Trying cdrom:f...
  Not a bootable ELF image
  Not a bootable a.out image

  Loading FCode image...
  Loaded 7120 bytes
  entry point is 0x4000
  Evaluating FCode...
  Evaluating FCode...
  Ignoring failed claim for va 10a96a0 memsz 19!
  Ignoring failed claim for va 100 memsz d1fb6!
  Ignoring failed claim for va 1402000 memsz 32518!
  Ignoring failed claim for va 180 memsz 52ac8!
  SunOS Release 5.11 Version tribblix-m16 64-bit
  Copyright (c) 1983, 2010, Oracle and/or its affiliates. All rights reserved.
  could not find debugger-vocabulary-hook>threads:interpret: exception -13 
caught
  interpret \ ident "%Z%%M% %I% %E% SMI"
  \ Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  \ Use is subject to license terms.
  \
  \ CDDL HEADER START
  \
  \ The contents of this file are subject to the terms of the
  \ Common Development and Distribution License, Version 1.0 only
  \ (the "License").  You may not use this file except in compliance
  \ with the License.
  \
  \ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  \ or http://www.opensolaris.org/os/licensing.
  \ See the License for 
  WARNING: add_spec: No major number for sf
  panic - kernel: no nucleus hblk8 to allocate
  EXIT

  QEMU keeps running (CPU is on 100 % all the time), I can interact with
  the prompt:

  0 > boot
  Not a Linux kernel image
  Not a bootable ELF image
  Not a bootable a.out image

  Loading FCode image...
  Unhandled Exception 0x0018
  PC = 0xffd25310 NPC = 0xffd25314
  Stopping execution

  > qemu-system-sparc64 -version
  QEMU emulator version 2.8.0(Virtualization:Staging / SLE_12_SP2)

  from
  https://build.opensuse.org/package/show/Virtualization:Staging/qemu on
  openSUSE Leap 42.2.

  ISO: http://pkgs.tribblix.org/iso/tribblix-sparc-0m16.iso.

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



[Qemu-devel] [Bug 1670170] [NEW] `qemu-system-sparc64 -M Niagara` Aborted (core dumped)

2017-03-05 Thread Michal Nowak
Public bug reported:

> qemu-system-sparc64 -M Niagara
qemu: fatal: Trap 0x0064 while trap level (6) >= MAXTL (6), Error state
pc: 4c80  npc: 4c84
%g0-3:    
%g4-7:    
%o0-3:     
%o4-7:     
%l0-3: 07f0 01ff 01fff008  
%l4-7:     
%i0-3:     
%i4-7:     
%f00:     
%f08:     
%f16:     
%f24:     
%f32:     
%f40:     
%f48:     
%f56:     
pstate: 0414 ccr: 44 (icc: -Z-- xcc: -Z--) asi: 00 tl: 6 pil: 0
cansave: 6 canrestore: 0 otherwin: 0 wstate: 0 cleanwin: 6 cwp: 7
fsr:  y:  fprs: 

Aborted (core dumped)

> qemu-system-sparc64 -M help
Supported machines are:
Niagara  Sun4v platform, Niagara
none empty machine
sun4uSun4u platform (default)
sun4vSun4v platform

> qemu-system-sparc64 -version
QEMU emulator version 2.8.0(Virtualization:Staging / SLE_12_SP2)

from https://build.opensuse.org/package/show/Virtualization:Staging/qemu
on openSUSE Leap 42.2.

** Affects: qemu
 Importance: Undecided
 Status: New


** Tags: sparc

** Attachment added: "coredumpctl core dump"
   
https://bugs.launchpad.net/bugs/1670170/+attachment/4831907/+files/core.qemu-system-spa.1000.79fef1d6233b4b989c19ea5c5c809627.451.148873742600.xz

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

Title:
  `qemu-system-sparc64 -M Niagara` Aborted (core dumped)

Status in QEMU:
  New

Bug description:
  > qemu-system-sparc64 -M Niagara
  qemu: fatal: Trap 0x0064 while trap level (6) >= MAXTL (6), Error state
  pc: 4c80  npc: 4c84
  %g0-3:    
  %g4-7:    
  %o0-3:     
  %o4-7:     
  %l0-3: 07f0 01ff 01fff008  
  %l4-7:     
  %i0-3:     
  %i4-7:     
  %f00:     
  %f08:     
  %f16:     
  %f24:     
  %f32:     
  %f40:     
  %f48:     
  %f56:     
  pstate: 0414 ccr: 44 (icc: -Z-- xcc: -Z--) asi: 00 tl: 6 pil: 0
  cansave: 6 canrestore: 0 otherwin: 0 wstate: 0 cleanwin: 6 cwp: 7
  fsr:  y:  fprs: 

  Aborted (core dumped)

  > qemu-system-sparc64 -M help
  Supported machines are:
  Niagara  Sun4v platform, Niagara
  none empty machine
  sun4uSun4u platform (default)
  sun4vSun4v platform

  > qemu-system-sparc64 -version
  QEMU emulator version 2.8.0(Virtualization:Staging / SLE_12_SP2)

  from
  https://build.opensuse.org/package/show/Virtualization:Staging/qemu on
  openSUSE Leap 42.2.

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



Re: [Qemu-devel] [RFC 0/5] hw: arm: exynos: Bring up secondary CPU + CPUIDLE issue

2017-03-05 Thread Krzysztof Kozlowski
On Thu, Mar 02, 2017 at 04:56:22PM +, Peter Maydell wrote:
> On 1 March 2017 at 18:26, Krzysztof Kozlowski  wrote:
> > Overview of the problem
> > ===
> > On Exynos4210, by default Linux kernel uses cpuidle driver which tries
> > to enter low power mode, called AFTR (Arm Off, Top Running).  On real
> > hardware this brings some power savings.  This AFTR mode requires second
> > CPU to be off, so the driver (coupled cpuidle driver) when system is idle:
> > 1. Turns off second CPU,
> > 2. Enters AFTR on CPU0.
> >
> > However the QEMU system is then totally unresponsive (e.g. on serial 
> > console)
> > and RCU stalls appear from time to time.  I spent some time on it and did 
> > not
> > find the real cause behind the lag.  Maybe it is because the second CPU
> > does not really power down itself and system just burns the cycles under 
> > spin
> > locks?
> 
> Possibly so. You might check whether it still has this behaviour with
> current head of git now that the multi-threaded TCG support has landed.

No changes.

> > I am quite new to QEMU.  I do not know the internals (yet), nor the design
> > how hardware should be emulated in such subtle details.
> >
> > The questions I have are:
> > 1. What is the preferred way to solve it? Maybe some a QEMU
> >workaround to disable the cpuidle is okay?
> > 2. Is it worth implementing a proper secondary CPU power down and
> >at the end proper AFTR cpuidle? It might be quite difficult...
> > 3. How such issues with deep sleep modes were solved for other
> >ARM targets?
> 
> The general answer to 3 is "we don't bother implementing deep sleep
> and mostly this hasn't caused problems, but more by luck than
> judgement". Most of our boards aren't SMP; until now SMP TCG guests
> have been slower than single core so even on a nominally SMP guest
> board most users probably use (the default) -smp 1.
> 
>  The SMP board that gets most use is the "virt" board whose
> power-down functionality works through our PSCI implementation.
> The other board we have which has power-down is the imx6 one:
> hw/misc/imx6_src.c is the system reset controller model which
> does this. Basically the model of the whatever-it-is that
> causes the CPU to be powered down does it via the APIs in
> target/arm/arm-powerctl.h, which lets you turn CPUs off and on.
> When a CPU is off then we don't try to let it execute instructions,
> so it shouldn't chew host CPU at the expense of other guest CPUs.
> 
> Minor caution with that API: arm_set_cpu_on() is asynchronous,
> so if you need to tell the guest "CPU now actually booted" then
> you'll need to use an async_run_on_cpu() callback the way the
> imx6_src.c code does.
> 
> If the "CPU on" behaviour you need is "CPU powers on as if
> starting up in standard reset" rather than "CPU powers up
> and appears to start execution at given address", then it's
> probably best to improve the arm_powerctl APIs rather than
> fudge it by trying to work out the arguments to pass to
> arm_set_cpu_on() to make its "and now go to this address"
> code not do anything. (The APIs are targeted at the current
> users which both want "do things which are done in the guest
> firmware or real hardware".)

Thanks for the hints! Especially the existing implementations might be
quite useful.

The cpuidle driver expects the CPU to come up to the same resume
address. I'll see what others are doing and learn from that. 

As I mentioned before, on current master thish patchset makes everything
more laggish and unresponsive (because of cpuidle) so actually I think
the first commit could be postponed for now. At least till I figure out
solution for the cpuidle problem.


Best regards,
Krzysztof




[Qemu-devel] [PATCH± SVM I/O permission bitmap for user-level (ring-3) code ignored

2017-03-05 Thread Alexander Boettcher
Hello,

the SVM I/O permission bitmap for user-level (ring-3) VM code running in
SVM seems to be ignored and causes a GP-fault. (Actual the IO permission
was granted by the kernel via the TSS I/O port permission bitmap).

After some debugging the GP code originates from target/i386/translate.c
gen_check_io() within the if(s->pe && (s->cpl > s->iopl || s->vm86))
condition. However, the actual SVM IO permission bitmap is checked after
that condition, which succeeds and would permit the access.

When I exchange the order, first executing the if(s->flags &
HF_SVMI_MASK) block and later on executing the if (s->pe && (s->cpl >
s->iopl || s->vm86)) block my use-case succeeds.

Please check and consider the patch for addition. The patch is based on
17783ac828adc694d986698d2d7014aedfeb48c6 qemu master.

Thanks,

-- 
Alexander Boettcher
Genode Labs

http://www.genode-labs.com - http://www.genode.org

Genode Labs GmbH - Amtsgericht Dresden - HRB 28424 - Sitz Dresden
Geschäftsführer: Dr.-Ing. Norman Feske, Christian Helmuth


qemu-system-x86_64 -s -no-kvm -display sdl -m 512 -cpu phenom -nographic
-cdrom ...

...
[init -> log_terminal] NOVA Microhypervisor v7-2436fe2 (x86_32): Feb 25
2017 17:58:48 [gcc 4.9.2]
[init -> log_terminal] [ 0] CORE:0:0:0 10:2:3:0 [0] AMD Phenom(tm) 9550
Quad-Core Processor
[init -> log_terminal] [ 0] Killed EC:0xc002c160 SC:0xc002d100 V:0xd
CS:0x1b EIP:0x14455e CR2:0xe0004004 ERR:0x0 (PT not found) Pd::root




>From 4a66a5f21085625c770e53cef4968607b897e432 Mon Sep 17 00:00:00 2001
From: Alexander Boettcher 
Date: Sun, 5 Mar 2017 18:55:32 +0100
Subject: [PATCH] svm: check io permission bitmap in VMCB first

Signed-off-by: Alexander Boettcher 
---
 target/i386/translate.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 72c1b03..b59ca3b 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -606,6 +606,16 @@ static void gen_check_io(DisasContext *s, TCGMemOp
ot, target_ulong cur_eip,
 {
 target_ulong next_eip;

+if(s->flags & HF_SVMI_MASK) {
+gen_update_cc_op(s);
+gen_jmp_im(cur_eip);
+svm_flags |= (1 << (4 + ot));
+next_eip = s->pc - s->cs_base;
+tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
+gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32,
+tcg_const_i32(svm_flags),
+tcg_const_i32(next_eip - cur_eip));
+}
 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
 switch (ot) {
@@ -622,16 +632,6 @@ static void gen_check_io(DisasContext *s, TCGMemOp
ot, target_ulong cur_eip,
 tcg_abort();
 }
 }
-if(s->flags & HF_SVMI_MASK) {
-gen_update_cc_op(s);
-gen_jmp_im(cur_eip);
-svm_flags |= (1 << (4 + ot));
-next_eip = s->pc - s->cs_base;
-tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
-gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32,
-tcg_const_i32(svm_flags),
-tcg_const_i32(next_eip - cur_eip));
-}
 }

 static inline void gen_movs(DisasContext *s, TCGMemOp ot)
-- 
2.7.4



[Qemu-devel] Qemu deadlocks in tb_lock when using SVM+SoftMMU

2017-03-05 Thread Alexander Boettcher
Hello,

beginning with commit 3bd1d74576bacb120949e13cdeded7a0c792c685

"cputlb: introduce tlb_flush_* async work"

using Qemu with SoftMMU+SVM virtualization deadlocks because tb_lock is
taken second time in cputlb.c tlb_flush_nocheck() function. The first
time tb_lock is taken, according to my debugging, in cpu-exex.c
tb_find() line 361.

I'm using Qemu with:

qemu-system-x86_64 -s -no-kvm -display sdl -m 512 -cpu phenom -nographic
-cdrom genode.iso

When building with
./configure --target-list=x86_64-softmmu --enable-debug --disable-pie
--enable-debug-tcg

I get also a

translate-all.c:165: tb_lock: Assertion `!have_tb_lock' failed.

beginning with commit 3bd1d74576bacb120949e13cdeded7a0c792c685. Before
the commit all is fine.

Since I'm not very familiar with Qemu internals, it is not clear to me
whether this commit breaks things or whether something must be
handled/added special somewhere else. I attached below the backtrace of
Qemu when it hangs in tb_lock.

In [0] my branch based on 3bd1d74576bacb120949e13cdeded7a0c792c685 is
used and [1] contains the iso image, if somebody wants try to reproduce it.

[0] https://github.com/alex-ab/qemu/commits/genode_svm_issue
[1]
https://github.com/alex-ab/qemu/commit/1130fee3b04dd2bee576241de9a5771d6855b327

Thanks in advance,

Alex.

-- 
Alexander Boettcher
Genode Labs

http://www.genode-labs.com - http://www.genode.org

Genode Labs GmbH - Amtsgericht Dresden - HRB 28424 - Sitz Dresden
Geschäftsführer: Dr.-Ing. Norman Feske, Christian Helmuth




[init -> log_terminal]
[init -> log_terminal] [ 0] CORE:0:0:0 10:2:3:0 [0] AMD Phenom(tm) 9550
Quad-Core Processor
qemu-system-x86_64: qemu.git/translate-all.c:165: tb_lock: Assertion
`!have_tb_lock' failed.




(gdb) info threads
  Id   Target Id Frame
* 1Thread 0x7ffbc19d3c00 (LWP 8396) "qemu-system-x86"
0x7ffbbfd2ac21 in __GI_ppoll (fds=0x273a330, nfds=6,
timeout=, sigmask=0x0) at
../sysdeps/unix/sysv/linux/ppoll.c:50
  2Thread 0x7ffbbb970700 (LWP 8397) "qemu-system-x86" syscall () at
../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
  3Thread 0x7ffbb8206700 (LWP 8399) "qemu-system-x86" __lll_lock_wait ()
at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
(gdb) thread 3
[Switching to thread 3 (Thread 0x7ffbb8206700 (LWP 8399))]
#0  __lll_lock_wait () at
../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
135 ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: No such file or
directory.
(gdb) bt
#0  __lll_lock_wait () at
../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
#1  0x7ffbc0002dbd in __GI___pthread_mutex_lock (mutex=0xf6ea18
) at ../nptl/pthread_mutex_lock.c:80
#2  0x0089852c in qemu_mutex_lock (mutex=0xf6ea18 )
at util/qemu-thread-posix.c:60
#3  0x00416103 in tb_lock () at qemu.git/translate-all.c:166
#4  0x0046e8d7 in tlb_flush_nocheck (cpu=0x164a360) at
qemu.git/cputlb.c:93
#5  0x0046ea2e in tlb_flush (cpu=0x164a360) at qemu.git/cputlb.c:121
#6  0x00538987 in cpu_x86_update_cr4 (env=0x16525f0, new_cr4=1784)
at qemu.git/target/i386/helper.c:660
#7  0x0055e318 in cpu_vmexit (env=0x16525f0, exit_code=78,
exit_info_1=4, retaddr=0)
at qemu.git/target/i386/svm_helper.c:689
#8  0x0055d9b7 in cpu_svm_check_intercept_param (env=0x16525f0,
type=78, param=4, retaddr=0)
at qemu.git/target/i386/svm_helper.c:511
#9  0x00541acf in raise_interrupt2 (env=0x16525f0, intno=14,
is_int=0, error_code=4, next_eip_addend=0, retaddr=0)
at qemu.git/target/i386/excp_helper.c:96
#10 0x00541c0d in raise_exception_err_ra (env=0x16525f0,
exception_index=14, error_code=4, retaddr=0)
at qemu.git/target/i386/excp_helper.c:127
#11 0x005621a9 in tlb_fill (cs=0x164a360, addr=1245184,
access_type=MMU_INST_FETCH, mmu_idx=1, retaddr=0)
at qemu.git/target/i386/mem_helper.c:212
#12 0x00476c15 in helper_ret_ldb_cmmu (env=0x16525f0,
addr=1245184, oi=1, retaddr=0)
at qemu.git/softmmu_template.h:127
#13 0x0051c86e in cpu_ldub_code_ra (env=0x16525f0, ptr=1245184,
retaddr=0)
at qemu.git/include/exec/cpu_ldst_template.h:102
#14 0x0051c8e4 in cpu_ldub_code (env=0x16525f0, ptr=1245184)
at qemu.git/include/exec/cpu_ldst_template.h:114
#15 0x00522182 in insn_get (env=0x16525f0, s=0x7ffbb82057e0,
ot=MO_8)
at qemu.git/target/i386/translate.c:2107
#16 0x0052ff3c in disas_insn (env=0x16525f0, s=0x7ffbb82057e0,
pc_start=1245183)
at qemu.git/target/i386/translate.c:6520
#17 0x00536458 in gen_intermediate_code (env=0x16525f0,
tb=0x7ffbb9ce3a38)
at qemu.git/target/i386/translate.c:8449
---Type  to continue, or q  to quit---
#18 0x00417616 in tb_gen_code (cpu=0x164a360, pc=1245179,
cs_base=0, flags=7342771, cflags=0)
at qemu.git/translate-all.c:1281
#19 0x0041993c in tb_find (cpu=0x164a360, last_tb=0x0,
tb_exit=0) at qemu.git/cpu-exec.c:370
#20 0x0041a25b in cpu_exec (cpu=0x164a360) at
qemu.git/cpu-exec.c:685
#21 0x0

Re: [Qemu-devel] [PATCH v2 03/24] keyval: New keyval_parse()

2017-03-05 Thread Markus Armbruster
Markus Armbruster  writes:

> Eric Blake  writes:
>
>> On 02/28/2017 03:26 PM, Markus Armbruster wrote:
>>> keyval_parse() parses KEY=VALUE,... into a QDict.  Works like
>>> qemu_opts_parse(), except:
>>> 
>>> * Returns a QDict instead of a QemuOpts (d'oh).
>>> 
>>> * Supports nesting, unlike QemuOpts: a KEY is split into key
>>>   fragments at '.' (dotted key convention; the block layer does
>>>   something similar on top of QemuOpts).  The key fragments are QDict
>>>   keys, and the last one's value is updated to VALUE.
>>> 
>>> * Each key fragment may be up to 127 bytes long.  qemu_opts_parse()
>>>   limits the entire key to 127 bytes.
>>> 
>>> * Overlong key fragments are rejected.  qemu_opts_parse() silently
>>>   truncates them.
>>> 
>>> * Empty key fragments are rejected.  qemu_opts_parse() happily
>>>   accepts empty keys.
>>> 
>>> * It does not store the returned value.  qemu_opts_parse() stores it
>>>   in the QemuOptsList.
>>> 
>>> * It does not treat parameter "id" specially.  qemu_opts_parse()
>>>   ignores all but the first "id", and fails when its value isn't
>>>   id_wellformed(), or duplicate (a QemuOpts with the same ID is
>>>   already stored).  It also screws up when a value contains ",id=".
>>> 
>>> * Implied value is not supported.  qemu_opts_parse() desugars "foo" to
>>>   "foo=on", and "nofoo" to "foo=off".
>>> 
>>> * An implied key's value can't be empty, and can't contain ','.
>>
>> or '=' (but the presence of '=' means no implied key, while the presence
>> of ',' marks end of the implied key's value).  Not sure it's worth
>> tweaking this commit message any further.
>
> Both fail the assertion they're meant to fail (I tested).  I'll fix the
> commit message.

Actually, there is nothing to fix, because there's no difference to
qemu_opts_parse().

Note that the comment in the code documents both ',' and '=', because
it's about keyval_parse(), not its difference to qemu_opts_parse().

>>> I intend to grow this into a saner replacement for QemuOpts.  It'll
>>> take time, though.
>>> 
>>> Note: keyval_parse() provides no way to do lists, and its key syntax
>>> is incompatible with the __RFQDN_ prefix convention for downstream
>>> extensions, because it blindly splits at '.', even in __RFQDN_.  Both
>>> issues will be addressed later in the series.
>>> 
>>> Signed-off-by: Markus Armbruster 
>>> ---
>>
>> Looks like you addressed all the comments.
>> Reviewed-by: Eric Blake 
>
> Thanks!



Re: [Qemu-devel] [PULL v2 00/27] QAPI patches for 2017-02-28

2017-03-05 Thread no-reply
Hi,

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

Message-id: 1488702958-24336-1-git-send-email-arm...@redhat.com
Subject: [Qemu-devel] [PULL v2 00/27] QAPI patches for 2017-02-28
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

# Useful git options
git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag] 
patchew/1488702958-24336-1-git-send-email-arm...@redhat.com -> 
patchew/1488702958-24336-1-git-send-email-arm...@redhat.com
Switched to a new branch 'test'
237fd42 qapi: Improve qobject visitor documentation
eb597a1 qapi: Fix object input visit beyond end of list
9cedcef tests: Cover input visit beyond end of list
084bed2 qapi: Make input visitors detect unvisited list tails
265cff9 test-qobject-input-visitor: Cover missing nested struct member
1895e8c tests: Cover partial input visit of list
9c386d6 test-string-input-visitor: Improve list coverage
3246dfe test-string-input-visitor: Tear down existing test automatically
35b1cf2 tests-qobject-input-strict: Merge into test-qobject-input-visitor
4a0f189 qapi: Drop unused non-strict qobject input visitor
399f667 test-qobject-input-visitor: Use strict visitor
5a27c27 qom: Make object_property_set_qobject()'s input visitor strict
f12998d qapi: Make string input and opts visitor require non-null input
d475401 qapi: Drop string input visitor method optional()
2ff6b3a qapi: Improve qobject input visitor error reporting
aced9bc qapi: Make QObject input visitor set *list reliably
f30e3ee qapi: Clean up after commit 3d344c2
a3d2837 qapi: Improve a QObject input visitor error message
13f967d qmp: Eliminate silly QERR_QMP_* macros
f896f27 qmp: Drop duplicated QMP command object checks
56a487e qmp: Clean up how we enforce capability negotiation
20ccec8 qapi-introspect: Mangle --prefix argument properly for C
f036df9 qapi: Support multiple command registries per program
2eabb0e qmp: Dumb down how we run QMP command registration
c7de68c qmp-test: New, covering basic QMP protocol
a6e3300 libqtest: Work around a "QMP wants a newline" bug
d71ca4f qga: Fix crash on non-dictionary QMP argument

=== OUTPUT BEGIN ===
Checking PATCH 1/27: qga: Fix crash on non-dictionary QMP argument...
Checking PATCH 2/27: libqtest: Work around a "QMP wants a newline" bug...
Checking PATCH 3/27: qmp-test: New, covering basic QMP protocol...
Checking PATCH 4/27: qmp: Dumb down how we run QMP command registration...
Checking PATCH 5/27: qapi: Support multiple command registries per program...
ERROR: trailing whitespace
#401: FILE: scripts/qapi-commands.py:201:
+qmp_register_command(cmds, "%(name)s", $

total: 1 errors, 0 warnings, 415 lines checked

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

Checking PATCH 6/27: qapi-introspect: Mangle --prefix argument properly for C...
Checking PATCH 7/27: qmp: Clean up how we enforce capability negotiation...
Checking PATCH 8/27: qmp: Drop duplicated QMP command object checks...
Checking PATCH 9/27: qmp: Eliminate silly QERR_QMP_* macros...
Checking PATCH 10/27: qapi: Improve a QObject input visitor error message...
Checking PATCH 11/27: qapi: Clean up after commit 3d344c2...
Checking PATCH 12/27: qapi: Make QObject input visitor set *list reliably...
Checking PATCH 13/27: qapi: Improve qobject input visitor error reporting...
Checking PATCH 14/27: qapi: Drop string input visitor method optional()...
Checking PATCH 15/27: qapi: Make string input and opts visitor require non-null 
input...
Checking PATCH 16/27: qom: Make object_property_set_qobject()'s input visitor 
strict...
Checking PATCH 17/27: test-qobject-input-visitor: Use strict visitor...
Checking PATCH 18/27: qapi: Drop unused non-strict qobject input visitor...
Checking PATCH 19/27: tests-qobject-input-strict: Merge into 
test-qobject-input-visitor...
ERROR: line over 90 characters
#487: FILE: tests/test-qobject-input-visitor.c:847:
+v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 
'string': 'foo', 'extra': 42 }");

ERROR: line over 90 characters
#501: FILE: tests/test-qobject-input-visitor.c:861:
+v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 
'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 
'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");

ERROR: line over 90 characters
#515: FILE: tests/test-qobject-input-visitor.c:875:

[Qemu-devel] [PULL v2 18/27] qapi: Drop unused non-strict qobject input visitor

2017-03-05 Thread Markus Armbruster
The split between tests/test-qobject-input-visitor.c and
tests/test-qobject-input-strict.c now makes less sense than ever.  The
next commit will take care of that.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-20-git-send-email-arm...@redhat.com>
---
 block/nbd.c  |  2 +-
 block/nfs.c  |  2 +-
 block/ssh.c  |  2 +-
 docs/qapi-code-gen.txt   |  2 +-
 include/qapi/qobject-input-visitor.h |  5 +
 qapi/qobject-input-visitor.c | 28 ++--
 qmp.c|  2 +-
 qom/qom-qobject.c|  2 +-
 scripts/qapi-commands.py |  2 +-
 target/s390x/cpu_models.c|  2 +-
 tests/check-qnull.c  |  2 +-
 tests/qmp-test.c |  2 +-
 tests/test-qmp-commands.c|  2 +-
 tests/test-qobject-input-strict.c|  2 +-
 tests/test-qobject-input-visitor.c   |  2 +-
 tests/test-visitor-serialization.c   |  2 +-
 16 files changed, 25 insertions(+), 36 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index a7f9108..f478f80 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -278,7 +278,7 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict 
*options, Error **errp)
 goto done;
 }
 
-iv = qobject_input_visitor_new(crumpled_addr, true);
+iv = qobject_input_visitor_new(crumpled_addr);
 visit_type_SocketAddress(iv, NULL, &saddr, &local_err);
 if (local_err) {
 error_propagate(errp, local_err);
diff --git a/block/nfs.c b/block/nfs.c
index 890d5d4..3f43f6e 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -474,7 +474,7 @@ static NFSServer *nfs_config(QDict *options, Error **errp)
 goto out;
 }
 
-iv = qobject_input_visitor_new(crumpled_addr, true);
+iv = qobject_input_visitor_new(crumpled_addr);
 visit_type_NFSServer(iv, NULL, &server, &local_error);
 if (local_error) {
 error_propagate(errp, local_error);
diff --git a/block/ssh.c b/block/ssh.c
index 835932e..278e66f 100644
--- a/block/ssh.c
+++ b/block/ssh.c
@@ -601,7 +601,7 @@ static InetSocketAddress *ssh_config(QDict *options, Error 
**errp)
 goto out;
 }
 
-iv = qobject_input_visitor_new(crumpled_addr, true);
+iv = qobject_input_visitor_new(crumpled_addr);
 visit_type_InetSocketAddress(iv, NULL, &inet, &local_error);
 if (local_error) {
 error_propagate(errp, local_error);
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 7eb7be1..6746c10 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -1138,7 +1138,7 @@ Example:
 Visitor *v;
 UserDefOneList *arg1 = NULL;
 
-v = qobject_input_visitor_new(QOBJECT(args), true);
+v = qobject_input_visitor_new(QOBJECT(args));
 visit_start_struct(v, NULL, NULL, 0, &err);
 if (err) {
 goto out;
diff --git a/include/qapi/qobject-input-visitor.h 
b/include/qapi/qobject-input-visitor.h
index cde328d..21db9c4 100644
--- a/include/qapi/qobject-input-visitor.h
+++ b/include/qapi/qobject-input-visitor.h
@@ -21,10 +21,7 @@ typedef struct QObjectInputVisitor QObjectInputVisitor;
 
 /*
  * Return a new input visitor that converts a QObject to a QAPI object.
- *
- * Set @strict to reject a parse that doesn't consume all keys of a
- * dictionary; otherwise excess input is ignored.
  */
-Visitor *qobject_input_visitor_new(QObject *obj, bool strict);
+Visitor *qobject_input_visitor_new(QObject *obj);
 
 #endif
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index 8015a98..eafcdf4 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -43,9 +43,6 @@ struct QObjectInputVisitor {
  * QDict or QList). */
 QSLIST_HEAD(, StackObject) stack;
 
-/* True to reject parse in visit_end_struct() if unvisited keys remain. */
-bool strict;
-
 GString *errname;   /* Accumulator for full_name() */
 };
 
@@ -157,11 +154,12 @@ static const QListEntry 
*qobject_input_push(QObjectInputVisitor *qiv,
 tos->obj = obj;
 tos->qapi = qapi;
 
-if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
+if (qobject_type(obj) == QTYPE_QDICT) {
 h = g_hash_table_new(g_str_hash, g_str_equal);
 qdict_iter(qobject_to_qdict(obj), qdict_add_key, h);
 tos->h = h;
-} else if (qobject_type(obj) == QTYPE_QLIST) {
+} else {
+assert(qobject_type(obj) == QTYPE_QLIST);
 tos->entry = qlist_first(qobject_to_qlist(obj));
 tos->index = -1;
 }
@@ -175,20 +173,15 @@ static void qobject_input_check_struct(Visitor *v, Error 
**errp)
 {
 QObjectInputVisitor *qiv = to_qiv(v);
 StackObject *tos = QSLIST_FIRST(&qiv->stack);
+GHashTableIter iter;
+const char *key;
 
 assert(tos && !tos->entry);
-if (qiv->strict) {
-GHashTable *const top_ht = tos->h;
-if (top_ht) {
-GHash

[Qemu-devel] [PULL v2 13/27] qapi: Improve qobject input visitor error reporting

2017-03-05 Thread Markus Armbruster
Error messages refer to nodes of the QObject being visited by name.
Trouble is the names are sometimes less than helpful:

* The name of the root QObject is whatever @name argument got passed
  to the visitor, except NULL gets mapped to "null".  We commonly pass
  NULL.  Not good.

  Avoiding errors "at the root" mitigates.  For instance,
  visit_start_struct() can only fail when the visited object is not a
  dictionary, and we commonly ensure it is beforehand.

* The name of a QDict's member is the member key.  Good enough only
  when this happens to be unique.

* The name of a QList's member is "null".  Not good.

Improve error messages by referring to nodes by path instead, as
follows:

* The path of the root QObject is whatever @name argument got passed
  to the visitor, except NULL gets mapped to "".

* The path of a root QDict's member is the member key.

* The path of a root QList's member is "[%u]", where %u is the list
  index, starting at zero.

* The path of a non-root QDict's member is the path of the QDict
  concatenated with "." and the member key.

* The path of a non-root QList's member is the path of the QList
  concatenated with "[%u]", where %u is the list index.

For example, the incorrect QMP command

{ "execute": "blockdev-add", "arguments": { "node-name": "foo", "driver": 
"raw", "file": {"driver": "file" } } }

now fails with

{"error": {"class": "GenericError", "desc": "Parameter 'file.filename' is 
missing"}}

instead of

{"error": {"class": "GenericError", "desc": "Parameter 'filename' is 
missing"}}

and

{ "execute": "input-send-event", "arguments": { "device": "bar", "events": 
[ [] ] } }

now fails with

{"error": {"class": "GenericError", "desc": "Invalid parameter type for 
'events[0]', expected: object"}}

instead of

{"error": {"class": "GenericError", "desc": "Invalid parameter type for 
'null', expected: QDict"}}

Aside: calling the thing "parameter" is suboptimal for QMP, because
the root object is "arguments" there.

The qobject output visitor doesn't have this problem because it should
not fail.  Same for dealloc and clone visitors.

The string visitors don't have this problem because they visit just
one value, whose name needs to be passed to the visitor as @name.  The
string output visitor shouldn't fail anyway.

The options visitor uses QemuOpts names.  Their name space is flat, so
the use of QDict member keys as names is fine.  NULL names used with
roots and lists could conceivably result in bad error messages.  Left
for another day.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-15-git-send-email-arm...@redhat.com>
---
 include/qapi/visitor.h   |   6 ---
 qapi/qobject-input-visitor.c | 121 +++
 2 files changed, 87 insertions(+), 40 deletions(-)

diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 9bb6cba..7c91a50 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -66,12 +66,6 @@
  * object, @name is the key associated with the value; and when
  * visiting a member of a list, @name is NULL.
  *
- * FIXME: Clients must pass NULL for @name when visiting a member of a
- * list, but this leads to poor error messages; it might be nicer to
- * require a non-NULL name such as "key.0" for '{ "key": [ "value" ]
- * }' if an error is encountered on "value" (or to have the visitor
- * core auto-generate the nicer name).
- *
  * The visit_type_FOO() functions expect a non-null @obj argument;
  * they allocate *@obj during input visits, leave it unchanged on
  * output visits, and recursively free any resources during a dealloc
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index d58696c..8015a98 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -21,19 +21,19 @@
 #include "qapi/qmp/types.h"
 #include "qapi/qmp/qerror.h"
 
-typedef struct StackObject
-{
-QObject *obj; /* Object being visited */
+typedef struct StackObject {
+const char *name;/* Name of @obj in its parent, if any */
+QObject *obj;/* QDict or QList being visited */
 void *qapi; /* sanity check that caller uses same pointer */
 
-GHashTable *h;   /* If obj is dict: unvisited keys */
-const QListEntry *entry; /* If obj is list: unvisited tail */
+GHashTable *h;  /* If @obj is QDict: unvisited keys */
+const QListEntry *entry;/* If @obj is QList: unvisited tail */
+unsigned index; /* If @obj is QList: list index of @entry */
 
-QSLIST_ENTRY(StackObject) node;
+QSLIST_ENTRY(StackObject) node; /* parent */
 } StackObject;
 
-struct QObjectInputVisitor
-{
+struct QObjectInputVisitor {
 Visitor visitor;
 
 /* Root of visit at visitor creation. */
@@ -45,6 +45,8 @@ struct QObjectInputVisitor
 
 /* True to reject parse in visit_end_struct() if unvisited keys remain. */
 bool strict;
+
+GString *errna

[Qemu-devel] [PULL v2 05/27] qapi: Support multiple command registries per program

2017-03-05 Thread Markus Armbruster
The command registry encapsulates a single command list.  Give the
functions using it a parameter instead.  Define suitable command lists
in monitor, guest agent and test-qmp-commands.

Signed-off-by: Markus Armbruster 
Message-Id: <1488544368-30622-6-git-send-email-arm...@redhat.com>
[Debugging turds buried]
Reviewed-by: Eric Blake 
---
 include/qapi/qmp/dispatch.h | 22 ++
 monitor.c   | 31 +--
 qapi/qmp-dispatch.c |  9 +
 qapi/qmp-registry.c | 37 ++---
 qga/commands.c  |  2 +-
 qga/guest-agent-core.h  |  2 ++
 qga/main.c  | 19 ++-
 scripts/qapi-commands.py| 16 ++--
 tests/test-qmp-commands.c   | 12 +++-
 9 files changed, 84 insertions(+), 66 deletions(-)

diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
index 57651ea..20578dc 100644
--- a/include/qapi/qmp/dispatch.h
+++ b/include/qapi/qmp/dispatch.h
@@ -34,18 +34,24 @@ typedef struct QmpCommand
 bool enabled;
 } QmpCommand;
 
-void qmp_register_command(const char *name, QmpCommandFunc *fn,
-  QmpCommandOptions options);
-void qmp_unregister_command(const char *name);
-QmpCommand *qmp_find_command(const char *name);
-QObject *qmp_dispatch(QObject *request);
-void qmp_disable_command(const char *name);
-void qmp_enable_command(const char *name);
+typedef QTAILQ_HEAD(QmpCommandList, QmpCommand) QmpCommandList;
+
+void qmp_register_command(QmpCommandList *cmds, const char *name,
+  QmpCommandFunc *fn, QmpCommandOptions options);
+void qmp_unregister_command(QmpCommandList *cmds, const char *name);
+QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name);
+QObject *qmp_dispatch(QmpCommandList *cmds, QObject *request);
+void qmp_disable_command(QmpCommandList *cmds, const char *name);
+void qmp_enable_command(QmpCommandList *cmds, const char *name);
+
 bool qmp_command_is_enabled(const QmpCommand *cmd);
 const char *qmp_command_name(const QmpCommand *cmd);
 bool qmp_has_success_response(const QmpCommand *cmd);
 QObject *qmp_build_error_object(Error *err);
+
 typedef void (*qmp_cmd_callback_fn)(QmpCommand *cmd, void *opaque);
-void qmp_for_each_command(qmp_cmd_callback_fn fn, void *opaque);
+
+void qmp_for_each_command(QmpCommandList *cmds, qmp_cmd_callback_fn fn,
+  void *opaque);
 
 #endif
diff --git a/monitor.c b/monitor.c
index 53f5f5a..c7f7602 100644
--- a/monitor.c
+++ b/monitor.c
@@ -221,6 +221,8 @@ static int mon_refcount;
 static mon_cmd_t mon_cmds[];
 static mon_cmd_t info_cmds[];
 
+QmpCommandList qmp_commands;
+
 Monitor *cur_mon;
 
 static QEMUClockType event_clock_type = QEMU_CLOCK_REALTIME;
@@ -919,7 +921,7 @@ CommandInfoList *qmp_query_commands(Error **errp)
 {
 CommandInfoList *list = NULL;
 
-qmp_for_each_command(query_commands_cb, &list);
+qmp_for_each_command(&qmp_commands, query_commands_cb, &list);
 
 return list;
 }
@@ -973,39 +975,40 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject 
**ret_data,
 static void qmp_unregister_commands_hack(void)
 {
 #ifndef CONFIG_SPICE
-qmp_unregister_command("query-spice");
+qmp_unregister_command(&qmp_commands, "query-spice");
 #endif
 #ifndef TARGET_I386
-qmp_unregister_command("rtc-reset-reinjection");
+qmp_unregister_command(&qmp_commands, "rtc-reset-reinjection");
 #endif
 #ifndef TARGET_S390X
-qmp_unregister_command("dump-skeys");
+qmp_unregister_command(&qmp_commands, "dump-skeys");
 #endif
 #ifndef TARGET_ARM
-qmp_unregister_command("query-gic-capabilities");
+qmp_unregister_command(&qmp_commands, "query-gic-capabilities");
 #endif
 #if !defined(TARGET_S390X) && !defined(TARGET_I386)
-qmp_unregister_command("query-cpu-model-expansion");
+qmp_unregister_command(&qmp_commands, "query-cpu-model-expansion");
 #endif
 #if !defined(TARGET_S390X)
-qmp_unregister_command("query-cpu-model-baseline");
-qmp_unregister_command("query-cpu-model-comparison");
+qmp_unregister_command(&qmp_commands, "query-cpu-model-baseline");
+qmp_unregister_command(&qmp_commands, "query-cpu-model-comparison");
 #endif
 #if !defined(TARGET_PPC) && !defined(TARGET_ARM) && !defined(TARGET_I386) \
 && !defined(TARGET_S390X)
-qmp_unregister_command("query-cpu-definitions");
+qmp_unregister_command(&qmp_commands, "query-cpu-definitions");
 #endif
 }
 
 void monitor_init_qmp_commands(void)
 {
-qmp_init_marshal();
+qmp_init_marshal(&qmp_commands);
 
-qmp_register_command("query-qmp-schema", qmp_query_qmp_schema,
+qmp_register_command(&qmp_commands, "query-qmp-schema",
+ qmp_query_qmp_schema,
  QCO_NO_OPTIONS);
-qmp_register_command("device_add", qmp_device_add,
+qmp_register_command(&qmp_commands, "device_add", qmp_device_add,
  QCO_NO_OPTIONS);
-qm

[Qemu-devel] [PULL v2 20/27] test-string-input-visitor: Tear down existing test automatically

2017-03-05 Thread Markus Armbruster
Call visitor_input_teardown() from visitor_input_test_init(), so you
don't have to call it from the actual tests.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-22-git-send-email-arm...@redhat.com>
---
 tests/test-string-input-visitor.c | 19 ++-
 1 file changed, 2 insertions(+), 17 deletions(-)

diff --git a/tests/test-string-input-visitor.c 
b/tests/test-string-input-visitor.c
index 7f10e25..a32828c 100644
--- a/tests/test-string-input-visitor.c
+++ b/tests/test-string-input-visitor.c
@@ -39,6 +39,8 @@ static
 Visitor *visitor_input_test_init(TestInputVisitorData *data,
  const char *string)
 {
+visitor_input_teardown(data, NULL);
+
 data->v = string_input_visitor_new(string);
 g_assert(data->v);
 return data->v;
@@ -57,8 +59,6 @@ static void test_visitor_in_int(TestInputVisitorData *data,
 g_assert(!err);
 g_assert_cmpint(res, ==, value);
 
-visitor_input_teardown(data, unused);
-
 v = visitor_input_test_init(data, "not an int");
 
 visit_type_int(v, NULL, &res, &err);
@@ -87,8 +87,6 @@ static void test_visitor_in_intList(TestInputVisitorData 
*data,
 
 qapi_free_int16List(res);
 
-visitor_input_teardown(data, unused);
-
 v = visitor_input_test_init(data, "not an int list");
 
 visit_type_int16List(v, NULL, &res, &err);
@@ -108,35 +106,30 @@ static void test_visitor_in_bool(TestInputVisitorData 
*data,
 visit_type_bool(v, NULL, &res, &err);
 g_assert(!err);
 g_assert_cmpint(res, ==, true);
-visitor_input_teardown(data, unused);
 
 v = visitor_input_test_init(data, "yes");
 
 visit_type_bool(v, NULL, &res, &err);
 g_assert(!err);
 g_assert_cmpint(res, ==, true);
-visitor_input_teardown(data, unused);
 
 v = visitor_input_test_init(data, "on");
 
 visit_type_bool(v, NULL, &res, &err);
 g_assert(!err);
 g_assert_cmpint(res, ==, true);
-visitor_input_teardown(data, unused);
 
 v = visitor_input_test_init(data, "false");
 
 visit_type_bool(v, NULL, &res, &err);
 g_assert(!err);
 g_assert_cmpint(res, ==, false);
-visitor_input_teardown(data, unused);
 
 v = visitor_input_test_init(data, "no");
 
 visit_type_bool(v, NULL, &res, &err);
 g_assert(!err);
 g_assert_cmpint(res, ==, false);
-visitor_input_teardown(data, unused);
 
 v = visitor_input_test_init(data, "off");
 
@@ -190,8 +183,6 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
 visit_type_EnumOne(v, NULL, &res, &err);
 g_assert(!err);
 g_assert_cmpint(i, ==, res);
-
-visitor_input_teardown(data, NULL);
 }
 }
 
@@ -224,30 +215,24 @@ static void test_visitor_in_fuzz(TestInputVisitorData 
*data,
 
 v = visitor_input_test_init(data, buf);
 visit_type_int(v, NULL, &ires, NULL);
-visitor_input_teardown(data, NULL);
 
 v = visitor_input_test_init(data, buf);
 visit_type_intList(v, NULL, &ilres, NULL);
 qapi_free_intList(ilres);
-visitor_input_teardown(data, NULL);
 
 v = visitor_input_test_init(data, buf);
 visit_type_bool(v, NULL, &bres, NULL);
-visitor_input_teardown(data, NULL);
 
 v = visitor_input_test_init(data, buf);
 visit_type_number(v, NULL, &nres, NULL);
-visitor_input_teardown(data, NULL);
 
 v = visitor_input_test_init(data, buf);
 sres = NULL;
 visit_type_str(v, NULL, &sres, NULL);
 g_free(sres);
-visitor_input_teardown(data, NULL);
 
 v = visitor_input_test_init(data, buf);
 visit_type_EnumOne(v, NULL, &eres, NULL);
-visitor_input_teardown(data, NULL);
 }
 }
 
-- 
2.7.4




[Qemu-devel] [PULL v2 27/27] qapi: Improve qobject visitor documentation

2017-03-05 Thread Markus Armbruster
Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-29-git-send-email-arm...@redhat.com>
---
 include/qapi/qobject-input-visitor.h  | 37 ++-
 include/qapi/qobject-output-visitor.h | 35 +
 2 files changed, 67 insertions(+), 5 deletions(-)

diff --git a/include/qapi/qobject-input-visitor.h 
b/include/qapi/qobject-input-visitor.h
index 21db9c4..0b7633a 100644
--- a/include/qapi/qobject-input-visitor.h
+++ b/include/qapi/qobject-input-visitor.h
@@ -1,6 +1,7 @@
 /*
  * Input Visitor
  *
+ * Copyright (C) 2017 Red Hat, Inc.
  * Copyright IBM, Corp. 2011
  *
  * Authors:
@@ -20,7 +21,41 @@
 typedef struct QObjectInputVisitor QObjectInputVisitor;
 
 /*
- * Return a new input visitor that converts a QObject to a QAPI object.
+ * Create a QObject input visitor for @obj
+ *
+ * A QObject input visitor visit builds a QAPI object from a QObject.
+ * This simultaneously walks the QAPI object being built and the
+ * QObject.  The latter walk starts at @obj.
+ *
+ * visit_type_FOO() creates an instance of QAPI type FOO.  The visited
+ * QObject must match FOO.  QDict matches struct/union types, QList
+ * matches list types, QString matches type 'str' and enumeration
+ * types, QInt matches integer types, QFloat matches type 'number',
+ * QBool matches type 'bool'.  Type 'any' is matched by QObject.  A
+ * QAPI alternate type is matched when one of its member types is.
+ *
+ * visit_start_struct() ... visit_end_struct() visits a QDict and
+ * creates a QAPI struct/union.  Visits in between visit the
+ * dictionary members.  visit_optional() is true when the QDict has
+ * this member.  visit_check_struct() fails if unvisited members
+ * remain.
+ *
+ * visit_start_list() ... visit_end_list() visits a QList and creates
+ * a QAPI list.  Visits in between visit list members, one after the
+ * other.  visit_next_list() returns NULL when all QList members have
+ * been visited.  visit_check_list() fails if unvisited members
+ * remain.
+ *
+ * visit_start_alternate() ... visit_end_alternate() visits a QObject
+ * and creates a QAPI alternate.  The visit in between visits the same
+ * QObject and initializes the alternate member that is in use.
+ *
+ * Error messages refer to parts of @obj in JavaScript/Python syntax.
+ * For example, 'a.b[2]' refers to the second member of the QList
+ * member 'b' of the QDict member 'a' of QDict @obj.
+ *
+ * The caller is responsible for freeing the visitor with
+ * visit_free().
  */
 Visitor *qobject_input_visitor_new(QObject *obj);
 
diff --git a/include/qapi/qobject-output-visitor.h 
b/include/qapi/qobject-output-visitor.h
index 8241877..9b990c3 100644
--- a/include/qapi/qobject-output-visitor.h
+++ b/include/qapi/qobject-output-visitor.h
@@ -19,11 +19,38 @@
 
 typedef struct QObjectOutputVisitor QObjectOutputVisitor;
 
-/*
- * Create a new QObject output visitor.
+/**
+ * Create a QObject output visitor for @obj
  *
- * If everything else succeeds, pass @result to visit_complete() to
- * collect the result of the visit.
+ * A QObject output visitor visit builds a QObject from QAPI Object.
+ * This simultaneously walks the QAPI object and the QObject being
+ * built.  The latter walk starts at @obj.
+ *
+ * visit_type_FOO() creates a QObject for QAPI type FOO.  It creates a
+ * QDict for struct/union types, a QList for list types, QString for
+ * type 'str' and enumeration types, QInt for integer types, QFloat
+ * for type 'number', QBool for type 'bool'.  For type 'any', it
+ * increments the QObject's reference count.  For QAPI alternate
+ * types, it creates the QObject for the member that is in use.
+ *
+ * visit_start_struct() ... visit_end_struct() visits a QAPI
+ * struct/union and creates a QDict.  Visits in between visit the
+ * members.  visit_optional() is true when the struct/union has this
+ * member.  visit_check_struct() does nothing.
+ *
+ * visit_start_list() ... visit_end_list() visits a QAPI list and
+ * creates a QList.  Visits in between visit list members, one after
+ * the other.  visit_next_list() returns NULL when all QAPI list
+ * members have been visited.  visit_check_list() does nothing.
+ *
+ * visit_start_alternate() ... visit_end_alternate() visits a QAPI
+ * alternate.  The visit in between creates the QObject for the
+ * alternate member that is in use.
+ *
+ * Errors are not expected to happen.
+ *
+ * The caller is responsible for freeing the visitor with
+ * visit_free().
  */
 Visitor *qobject_output_visitor_new(QObject **result);
 
-- 
2.7.4




[Qemu-devel] [PULL v2 22/27] tests: Cover partial input visit of list

2017-03-05 Thread Markus Armbruster
Demonstrates a design flaw: there is no way to for input visitors to
report that a list visit didn't visit the complete input list.  The
generated list visits always do, but manual visits needn't.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-24-git-send-email-arm...@redhat.com>
---
 tests/test-opts-visitor.c  | 41 +++
 tests/test-qobject-input-visitor.c | 44 ++
 tests/test-string-input-visitor.c  | 22 +++
 3 files changed, 107 insertions(+)

diff --git a/tests/test-opts-visitor.c b/tests/test-opts-visitor.c
index 0a9e75f..d0f7646 100644
--- a/tests/test-opts-visitor.c
+++ b/tests/test-opts-visitor.c
@@ -172,6 +172,44 @@ expect_u64_max(OptsVisitorFixture *f, gconstpointer 
test_data)
 
 /* test cases */
 
+static void
+test_opts_range_unvisited(void)
+{
+intList *list = NULL;
+intList *tail;
+QemuOpts *opts;
+Visitor *v;
+
+opts = qemu_opts_parse(qemu_find_opts("userdef"), "ilist=0-2", false,
+   &error_abort);
+
+v = opts_visitor_new(opts);
+
+visit_start_struct(v, NULL, NULL, 0, &error_abort);
+
+/* Would be simpler if the visitor genuinely supported virtual walks */
+visit_start_list(v, "ilist", (GenericList **)&list, sizeof(*list),
+ &error_abort);
+tail = list;
+visit_type_int(v, NULL, &tail->value, &error_abort);
+g_assert_cmpint(tail->value, ==, 0);
+tail = (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*list));
+g_assert(tail);
+visit_type_int(v, NULL, &tail->value, &error_abort);
+g_assert_cmpint(tail->value, ==, 1);
+tail = (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*list));
+g_assert(tail);
+visit_end_list(v, (void **)&list);
+/* BUG: unvisited tail not reported; actually not reportable by design */
+
+visit_check_struct(v, &error_abort);
+visit_end_struct(v, NULL);
+
+qapi_free_intList(list);
+visit_free(v);
+qemu_opts_del(opts);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -263,6 +301,9 @@ main(int argc, char **argv)
 add_test("/visitor/opts/i64/range/2big/full", &expect_fail,
  "i64=-0x8000-0x7fff");
 
+g_test_add_func("/visitor/opts/range/unvisited",
+test_opts_range_unvisited);
+
 g_test_run();
 return 0;
 }
diff --git a/tests/test-qobject-input-visitor.c 
b/tests/test-qobject-input-visitor.c
index 32c6b3d..10c15c4 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -923,6 +923,46 @@ static void 
test_visitor_in_fail_struct_missing(TestInputVisitorData *data,
 visit_end_struct(v, NULL);
 }
 
+static void test_visitor_in_fail_list(TestInputVisitorData *data,
+  const void *unused)
+{
+int64_t i64 = -1;
+Visitor *v;
+
+/* Unvisited list tail */
+
+v = visitor_input_test_init(data, "[ 1, 2, 3 ]");
+
+visit_start_list(v, NULL, NULL, 0, &error_abort);
+visit_type_int(v, NULL, &i64, &error_abort);
+g_assert_cmpint(i64, ==, 1);
+visit_type_int(v, NULL, &i64, &error_abort);
+g_assert_cmpint(i64, ==, 2);
+visit_end_list(v, NULL);
+/* BUG: unvisited tail not reported; actually not reportable by design */
+}
+
+static void test_visitor_in_fail_list_nested(TestInputVisitorData *data,
+ const void *unused)
+{
+int64_t i64 = -1;
+Visitor *v;
+
+/* Unvisited nested list tail */
+
+v = visitor_input_test_init(data, "[ 0, [ 1, 2, 3 ] ]");
+
+visit_start_list(v, NULL, NULL, 0, &error_abort);
+visit_type_int(v, NULL, &i64, &error_abort);
+g_assert_cmpint(i64, ==, 0);
+visit_start_list(v, NULL, NULL, 0, &error_abort);
+visit_type_int(v, NULL, &i64, &error_abort);
+g_assert_cmpint(i64, ==, 1);
+visit_end_list(v, NULL);
+/* BUG: unvisited tail not reported; actually not reportable by design */
+visit_end_list(v, NULL);
+}
+
 static void test_visitor_in_fail_union_native_list(TestInputVisitorData *data,
const void *unused)
 {
@@ -1070,6 +1110,10 @@ int main(int argc, char **argv)
NULL, test_visitor_in_fail_struct_in_list);
 input_visitor_test_add("/visitor/input/fail/struct-missing",
NULL, test_visitor_in_fail_struct_missing);
+input_visitor_test_add("/visitor/input/fail/list",
+   NULL, test_visitor_in_fail_list);
+input_visitor_test_add("/visitor/input/fail/list-nested",
+   NULL, test_visitor_in_fail_list_nested);
 input_visitor_test_add("/visitor/input/fail/union-flat",
NULL, test_visitor_in_fail_union_flat);
 input_visitor_test_add("/visitor/input/fail/union-flat-no-discriminator",
diff --git a/tests/test-string-input-vis

[Qemu-devel] [PULL v2 19/27] tests-qobject-input-strict: Merge into test-qobject-input-visitor

2017-03-05 Thread Markus Armbruster
Much of test-qobject-input-strict.c duplicates
test-qobject-input-strict.c, but with less assertions on expected
output:

* test_validate_struct() duplicates test_visitor_in_struct()

* test_validate_struct_nested() duplicates
  test_visitor_in_struct_nested()

* test_validate_list() duplicates the first half of
  test_visitor_in_list()

* test_validate_union_native_list() duplicates
  test_visitor_in_native_list_int()

* test_validate_union_flat() duplicates test_visitor_in_union_flat()

* test_validate_alternate() duplicates the first part of
  test_visitor_in_alternate()

Merge the remaining test cases into test-qobject-input-visitor.c, and
drop the now redundant test-qobject-input-strict.c.

Test case "/visitor/input-strict/fail/list" isn't really about lists,
it's about a bad struct nested in a list.  Rename accordingly.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-21-git-send-email-arm...@redhat.com>
---
 tests/Makefile.include |   4 +-
 tests/test-qobject-input-strict.c  | 381 -
 tests/test-qobject-input-visitor.c | 187 ++
 3 files changed, 188 insertions(+), 384 deletions(-)
 delete mode 100644 tests/test-qobject-input-strict.c

diff --git a/tests/Makefile.include b/tests/Makefile.include
index bb0f430..ace4e80 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -28,7 +28,6 @@ check-unit-y += tests/test-clone-visitor$(EXESUF)
 gcov-files-test-clone-visitor-y = qapi/qapi-clone-visitor.c
 check-unit-y += tests/test-qobject-input-visitor$(EXESUF)
 gcov-files-test-qobject-input-visitor-y = qapi/qobject-input-visitor.c
-check-unit-y += tests/test-qobject-input-strict$(EXESUF)
 check-unit-y += tests/test-qmp-commands$(EXESUF)
 gcov-files-test-qmp-commands-y = qapi/qmp-dispatch.c
 check-unit-y += tests/test-string-input-visitor$(EXESUF)
@@ -489,7 +488,7 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o 
tests/check-qdict.o \
tests/test-coroutine.o tests/test-string-output-visitor.o \
tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
tests/test-clone-visitor.o \
-   tests/test-qobject-input-visitor.o tests/test-qobject-input-strict.o \
+   tests/test-qobject-input-visitor.o \
tests/test-qmp-commands.o tests/test-visitor-serialization.o \
tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
tests/test-opts-visitor.o tests/test-qmp-event.o \
@@ -598,7 +597,6 @@ tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o 
$(test-qapi-obj-y)
 tests/test-qobject-output-visitor$(EXESUF): 
tests/test-qobject-output-visitor.o $(test-qapi-obj-y)
 tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o 
$(test-qapi-obj-y)
 tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visitor.o 
$(test-qapi-obj-y)
-tests/test-qobject-input-strict$(EXESUF): tests/test-qobject-input-strict.o 
$(test-qapi-obj-y)
 tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o 
tests/test-qmp-marshal.o $(test-qapi-obj-y)
 tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o 
$(test-qapi-obj-y)
 tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y)
diff --git a/tests/test-qobject-input-strict.c 
b/tests/test-qobject-input-strict.c
deleted file mode 100644
index 7d26113..000
--- a/tests/test-qobject-input-strict.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * QObject Input Visitor unit-tests (strict mode).
- *
- * Copyright (C) 2011-2012, 2015 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino 
- *  Paolo Bonzini 
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-
-#include "qemu-common.h"
-#include "qapi/error.h"
-#include "qapi/qobject-input-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qapi/qmp/types.h"
-#include "qapi/qmp/qjson.h"
-#include "test-qmp-introspect.h"
-#include "qmp-introspect.h"
-#include "qapi-visit.h"
-
-typedef struct TestInputVisitorData {
-QObject *obj;
-Visitor *qiv;
-} TestInputVisitorData;
-
-static void validate_teardown(TestInputVisitorData *data,
-   const void *unused)
-{
-qobject_decref(data->obj);
-data->obj = NULL;
-
-if (data->qiv) {
-visit_free(data->qiv);
-data->qiv = NULL;
-}
-}
-
-/* The various test_init functions are provided instead of a test setup
-   function so that the JSON string used by the tests are kept in the test
-   functions (and not in main()). */
-static Visitor *validate_test_init_internal(TestInputVisitorData *data,
-const char *json_string,
-va_list *ap)
-{
-validate_teardown(data, NULL);
-
-data->obj = qobject_from_jsonv(json_string, ap);
-g_assert(data->obj);
-
-data->qiv = qobj

[Qemu-devel] [PULL v2 21/27] test-string-input-visitor: Improve list coverage

2017-03-05 Thread Markus Armbruster
Lists with elements above INT64_MAX don't work (known bug).  Empty
lists don't work (weird).

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-23-git-send-email-arm...@redhat.com>
---
 tests/test-string-input-visitor.c | 85 +--
 1 file changed, 72 insertions(+), 13 deletions(-)

diff --git a/tests/test-string-input-visitor.c 
b/tests/test-string-input-visitor.c
index a32828c..72f8732 100644
--- a/tests/test-string-input-visitor.c
+++ b/tests/test-string-input-visitor.c
@@ -65,31 +65,90 @@ static void test_visitor_in_int(TestInputVisitorData *data,
 error_free_or_abort(&err);
 }
 
+static void check_ilist(Visitor *v, int64_t *expected, size_t n)
+{
+int64List *res = NULL;
+int64List *tail;
+int i;
+
+visit_type_int64List(v, NULL, &res, &error_abort);
+tail = res;
+for (i = 0; i < n; i++) {
+g_assert(tail);
+g_assert_cmpint(tail->value, ==, expected[i]);
+tail = tail->next;
+}
+g_assert(!tail);
+
+qapi_free_int64List(res);
+}
+
+static void check_ulist(Visitor *v, uint64_t *expected, size_t n)
+{
+uint64List *res = NULL;
+uint64List *tail;
+int i;
+
+/* BUG: unsigned numbers above INT64_MAX don't work */
+for (i = 0; i < n; i++) {
+if (expected[i] > INT64_MAX) {
+Error *err = NULL;
+visit_type_uint64List(v, NULL, &res, &err);
+error_free_or_abort(&err);
+return;
+}
+}
+
+visit_type_uint64List(v, NULL, &res, &error_abort);
+tail = res;
+for (i = 0; i < n; i++) {
+g_assert(tail);
+g_assert_cmpuint(tail->value, ==, expected[i]);
+tail = tail->next;
+}
+g_assert(!tail);
+
+qapi_free_uint64List(res);
+}
+
 static void test_visitor_in_intList(TestInputVisitorData *data,
 const void *unused)
 {
-int64_t value[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20};
-int16List *res = NULL, *tmp;
+/* Note: the visitor *sorts* ranges *unsigned* */
+int64_t expect1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20 };
+int64_t expect2[] = { 32767, -32768, -32767 };
+int64_t expect3[] = { INT64_MAX, INT64_MIN };
+uint64_t expect4[] = { UINT64_MAX };
 Error *err = NULL;
+int64List *res = NULL;
 Visitor *v;
-int i = 0;
+
+/* Valid lists */
 
 v = visitor_input_test_init(data, "1,2,0,2-4,20,5-9,1-8");
+check_ilist(v, expect1, ARRAY_SIZE(expect1));
 
-visit_type_int16List(v, NULL, &res, &error_abort);
-tmp = res;
-while (i < sizeof(value) / sizeof(value[0])) {
-g_assert(tmp);
-g_assert_cmpint(tmp->value, ==, value[i++]);
-tmp = tmp->next;
-}
-g_assert(!tmp);
+v = visitor_input_test_init(data, "32767,-32768--32767");
+check_ilist(v, expect2, ARRAY_SIZE(expect2));
 
-qapi_free_int16List(res);
+v = visitor_input_test_init(data,
+"-9223372036854775808,9223372036854775807");
+check_ilist(v, expect3, ARRAY_SIZE(expect3));
+
+v = visitor_input_test_init(data, "18446744073709551615");
+check_ulist(v, expect4, ARRAY_SIZE(expect4));
+
+/* Empty list is invalid (weird) */
+
+v = visitor_input_test_init(data, "");
+visit_type_int64List(v, NULL, &res, &err);
+error_free_or_abort(&err);
+
+/* Not a list */
 
 v = visitor_input_test_init(data, "not an int list");
 
-visit_type_int16List(v, NULL, &res, &err);
+visit_type_int64List(v, NULL, &res, &err);
 error_free_or_abort(&err);
 g_assert(!res);
 }
-- 
2.7.4




[Qemu-devel] [PULL v2 15/27] qapi: Make string input and opts visitor require non-null input

2017-03-05 Thread Markus Armbruster
The string input visitor tries to cope with null input.  Null input
isn't used anywhere, and isn't covered by tests.  Unsurprisingly, it
doesn't fully work: start_list() crashes because it passes the input
via parse_str() to strtoll() unchecked.

Make string_input_visitor_new() assert its argument isn't null, and
drop the code trying to deal with null input.

The opts visitor crashes when you try to actually visit something with
null input.  Make opts_visitor_new() assert its argument isn't null,
mostly for clarity.

qobject_input_visitor_new() already asserts its argument isn't null.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-17-git-send-email-arm...@redhat.com>
---
 qapi/opts-visitor.c |  1 +
 qapi/string-input-visitor.c | 54 ++---
 2 files changed, 18 insertions(+), 37 deletions(-)

diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
index a0a7c0e..c50dc4b 100644
--- a/qapi/opts-visitor.c
+++ b/qapi/opts-visitor.c
@@ -528,6 +528,7 @@ opts_visitor_new(const QemuOpts *opts)
 {
 OptsVisitor *ov;
 
+assert(opts);
 ov = g_malloc0(sizeof *ov);
 
 ov->visitor.type = VISITOR_INPUT;
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
index 1a855c5..f126cd9 100644
--- a/qapi/string-input-visitor.c
+++ b/qapi/string-input-visitor.c
@@ -182,12 +182,6 @@ static void parse_type_int64(Visitor *v, const char *name, 
int64_t *obj,
 {
 StringInputVisitor *siv = to_siv(v);
 
-if (!siv->string) {
-error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
-   "integer");
-return;
-}
-
 if (parse_str(siv, name, errp) < 0) {
 return;
 }
@@ -242,13 +236,7 @@ static void parse_type_size(Visitor *v, const char *name, 
uint64_t *obj,
 Error *err = NULL;
 uint64_t val;
 
-if (siv->string) {
-parse_option_size(name, siv->string, &val, &err);
-} else {
-error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
-   "size");
-return;
-}
+parse_option_size(name, siv->string, &val, &err);
 if (err) {
 error_propagate(errp, err);
 return;
@@ -262,19 +250,17 @@ static void parse_type_bool(Visitor *v, const char *name, 
bool *obj,
 {
 StringInputVisitor *siv = to_siv(v);
 
-if (siv->string) {
-if (!strcasecmp(siv->string, "on") ||
-!strcasecmp(siv->string, "yes") ||
-!strcasecmp(siv->string, "true")) {
-*obj = true;
-return;
-}
-if (!strcasecmp(siv->string, "off") ||
-!strcasecmp(siv->string, "no") ||
-!strcasecmp(siv->string, "false")) {
-*obj = false;
-return;
-}
+if (!strcasecmp(siv->string, "on") ||
+!strcasecmp(siv->string, "yes") ||
+!strcasecmp(siv->string, "true")) {
+*obj = true;
+return;
+}
+if (!strcasecmp(siv->string, "off") ||
+!strcasecmp(siv->string, "no") ||
+!strcasecmp(siv->string, "false")) {
+*obj = false;
+return;
 }
 
 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -285,13 +271,8 @@ static void parse_type_str(Visitor *v, const char *name, 
char **obj,
Error **errp)
 {
 StringInputVisitor *siv = to_siv(v);
-if (siv->string) {
-*obj = g_strdup(siv->string);
-} else {
-*obj = NULL;
-error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
-   "string");
-}
+
+*obj = g_strdup(siv->string);
 }
 
 static void parse_type_number(Visitor *v, const char *name, double *obj,
@@ -302,10 +283,8 @@ static void parse_type_number(Visitor *v, const char 
*name, double *obj,
 double val;
 
 errno = 0;
-if (siv->string) {
-val = strtod(siv->string, &endp);
-}
-if (!siv->string || errno || endp == siv->string || *endp) {
+val = strtod(siv->string, &endp);
+if (errno || endp == siv->string || *endp) {
 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"number");
 return;
@@ -327,6 +306,7 @@ Visitor *string_input_visitor_new(const char *str)
 {
 StringInputVisitor *v;
 
+assert(str);
 v = g_malloc0(sizeof(*v));
 
 v->visitor.type = VISITOR_INPUT;
-- 
2.7.4




[Qemu-devel] [PULL v2 16/27] qom: Make object_property_set_qobject()'s input visitor strict

2017-03-05 Thread Markus Armbruster
Commit 240f64b made all qobject input visitors created outside tests
strict, except for the one in object_property_set_qobject().  That one
was left behind only because Eric couldn't spare the time to figure
out whether making it strict would break anything, with a TODO
comment.  Time to resolve it.

Strict makes a difference only for otherwise successful visits of QAPI
structs or unions.  Let's examine what the callers of
object_property_set_qobject() visit:

* object_property_set_str(), object_property_set_bool(),
  object_property_set_int() visit a QString, QBool, QInt,
  respectively.  Strictness can't matter.

* qmp_qom_set visits its @value argument.  Comes straight from QMP and
  can be anything ('any' in the QAPI schema).  Strictness matters when
  the property's set() method visits a struct or union QAPI type.

  No such methods exist, thus switching to strict can't break
  anything.

  If we acquire such methods in the future, we'll *want* the visitor
  to be strict, so that unexpected members get rejected as they should
  be.

Switch to strict.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-18-git-send-email-arm...@redhat.com>
---
 qom/qom-qobject.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/qom/qom-qobject.c b/qom/qom-qobject.c
index 447e4a0..bbdedda 100644
--- a/qom/qom-qobject.c
+++ b/qom/qom-qobject.c
@@ -22,8 +22,8 @@ void object_property_set_qobject(Object *obj, QObject *value,
  const char *name, Error **errp)
 {
 Visitor *v;
-/* TODO: Should we reject, rather than ignore, excess input? */
-v = qobject_input_visitor_new(value, false);
+
+v = qobject_input_visitor_new(value, true);
 object_property_set(obj, v, name, errp);
 visit_free(v);
 }
-- 
2.7.4




[Qemu-devel] [PULL v2 24/27] qapi: Make input visitors detect unvisited list tails

2017-03-05 Thread Markus Armbruster
Fix the design flaw demonstrated in the previous commit: new method
check_list() lets input visitors report that unvisited input remains
for a list, exactly like check_struct() lets them report that
unvisited input remains for a struct or union.

Implement the method for the qobject input visitor (straightforward),
and the string input visitor (less so, due to the magic list syntax
there).  The opts visitor's list magic is even more impenetrable, and
all I can do there today is a stub with a FIXME comment.  No worse
than before.

Signed-off-by: Markus Armbruster 
Message-Id: <1488544368-30622-26-git-send-email-arm...@redhat.com>
Reviewed-by: Eric Blake 
---
 hw/ppc/spapr_drc.c |  5 +
 include/qapi/visitor-impl.h|  3 +++
 include/qapi/visitor.h | 13 +
 qapi/opts-visitor.c| 11 +++
 qapi/qapi-visit-core.c |  8 
 qapi/qobject-input-visitor.c   | 37 +++--
 qapi/string-input-visitor.c| 30 ++
 qapi/trace-events  |  1 +
 scripts/qapi-visit.py  |  3 +++
 tests/test-opts-visitor.c  |  2 +-
 tests/test-qobject-input-visitor.c |  9 +++--
 tests/test-string-input-visitor.c  |  4 +++-
 12 files changed, 116 insertions(+), 10 deletions(-)

diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 2de6377..150f6bf 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -326,7 +326,12 @@ static void prop_get_fdt(Object *obj, Visitor *v, const 
char *name,
 return;
 }
 }
+visit_check_list(v, &err);
 visit_end_list(v, NULL);
+if (err) {
+error_propagate(errp, err);
+return;
+}
 break;
 }
 default:
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 962ba1d..e87709d 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -61,6 +61,9 @@ struct Visitor
 /* Must be set */
 GenericList *(*next_list)(Visitor *v, GenericList *tail, size_t size);
 
+/* Optional; intended for input visitors */
+void (*check_list)(Visitor *v, Error **errp);
+
 /* Must be set */
 void (*end_list)(Visitor *v, void **list);
 
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 7c91a50..1a1b620 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -370,6 +370,19 @@ void visit_start_list(Visitor *v, const char *name, 
GenericList **list,
 GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size);
 
 /*
+ * Prepare for completing a list visit.
+ *
+ * @errp obeys typical error usage, and reports failures such as
+ * unvisited list tail remaining in the input stream.
+ *
+ * Should be called prior to visit_end_list() if all other
+ * intermediate visit steps were successful, to allow the visitor one
+ * last chance to report errors.  May be skipped on a cleanup path,
+ * where there is no need to check for further errors.
+ */
+void visit_check_list(Visitor *v, Error **errp);
+
+/*
  * Complete a list visit started earlier.
  *
  * @list must match what was passed to the paired visit_start_list().
diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
index c50dc4b..026d25b 100644
--- a/qapi/opts-visitor.c
+++ b/qapi/opts-visitor.c
@@ -273,6 +273,16 @@ opts_next_list(Visitor *v, GenericList *tail, size_t size)
 
 
 static void
+opts_check_list(Visitor *v, Error **errp)
+{
+/*
+ * FIXME should set error when unvisited elements remain.  Mostly
+ * harmless, as the generated visits always visit all elements.
+ */
+}
+
+
+static void
 opts_end_list(Visitor *v, void **obj)
 {
 OptsVisitor *ov = to_ov(v);
@@ -539,6 +549,7 @@ opts_visitor_new(const QemuOpts *opts)
 
 ov->visitor.start_list = &opts_start_list;
 ov->visitor.next_list  = &opts_next_list;
+ov->visitor.check_list = &opts_check_list;
 ov->visitor.end_list   = &opts_end_list;
 
 ov->visitor.type_int64  = &opts_type_int64;
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index e6e93f0..43a09d1 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -90,6 +90,14 @@ GenericList *visit_next_list(Visitor *v, GenericList *tail, 
size_t size)
 return v->next_list(v, tail, size);
 }
 
+void visit_check_list(Visitor *v, Error **errp)
+{
+trace_visit_check_list(v);
+if (v->check_list) {
+v->check_list(v, errp);
+}
+}
+
 void visit_end_list(Visitor *v, void **obj)
 {
 trace_visit_end_list(v, obj);
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index eafcdf4..34065ba 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -51,7 +51,8 @@ static QObjectInputVisitor *to_qiv(Visitor *v)
 return container_of(v, QObjectInputVisitor, visitor);
 }
 
-static const char *full_name(QObjectInputVisitor *qiv, co

[Qemu-devel] [PULL v2 09/27] qmp: Eliminate silly QERR_QMP_* macros

2017-03-05 Thread Markus Armbruster
The QERR_ macros are leftovers from the days of "rich" error objects.

QERR_QMP_BAD_INPUT_OBJECT, QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
QERR_QMP_EXTRA_MEMBER are used in just one place now, except for one
use that has crept into qobject-input-visitor.c.

Drop these macros, to make the (bad) error messages more visible.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-10-git-send-email-arm...@redhat.com>
---
 include/qapi/qmp/qerror.h|  9 -
 qapi/qmp-dispatch.c  | 13 +++--
 qapi/qobject-input-visitor.c |  3 ++-
 3 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h
index 6586c9f..c82360f 100644
--- a/include/qapi/qmp/qerror.h
+++ b/include/qapi/qmp/qerror.h
@@ -82,15 +82,6 @@
 #define QERR_QGA_COMMAND_FAILED \
 "Guest agent command failed, error was '%s'"
 
-#define QERR_QMP_BAD_INPUT_OBJECT \
-"Expected '%s' in QMP input"
-
-#define QERR_QMP_BAD_INPUT_OBJECT_MEMBER \
-"QMP input object member '%s' expects '%s'"
-
-#define QERR_QMP_EXTRA_MEMBER \
-"QMP input object member '%s' is unexpected"
-
 #define QERR_SET_PASSWD_FAILED \
 "Could not set password"
 
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 7fb8aef..dc50212 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -30,7 +30,7 @@ static QDict *qmp_dispatch_check_obj(const QObject *request, 
Error **errp)
 
 dict = qobject_to_qdict(request);
 if (!dict) {
-error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "object");
+error_setg(errp, "Expected '%s' in QMP input", "object");
 return NULL;
 }
 
@@ -41,25 +41,26 @@ static QDict *qmp_dispatch_check_obj(const QObject 
*request, Error **errp)
 
 if (!strcmp(arg_name, "execute")) {
 if (qobject_type(arg_obj) != QTYPE_QSTRING) {
-error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute",
-   "string");
+error_setg(errp, "QMP input object member '%s' expects '%s'",
+   "execute", "string");
 return NULL;
 }
 has_exec_key = true;
 } else if (!strcmp(arg_name, "arguments")) {
 if (qobject_type(arg_obj) != QTYPE_QDICT) {
-error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
+error_setg(errp, "QMP input object member '%s' expects '%s'",
"arguments", "object");
 return NULL;
 }
 } else {
-error_setg(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
+error_setg(errp, "QMP input object member '%s' is unexpected",
+   arg_name);
 return NULL;
 }
 }
 
 if (!has_exec_key) {
-error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute");
+error_setg(errp, "Expected '%s' in QMP input", "execute");
 return NULL;
 }
 
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index 0063327..ed6c24c 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -140,7 +140,8 @@ static void qobject_input_check_struct(Visitor *v, Error 
**errp)
 
 g_hash_table_iter_init(&iter, top_ht);
 if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) {
-error_setg(errp, QERR_QMP_EXTRA_MEMBER, key);
+error_setg(errp, "QMP input object member '%s' is unexpected",
+   key);
 }
 }
 }
-- 
2.7.4




[Qemu-devel] [PULL v2 23/27] test-qobject-input-visitor: Cover missing nested struct member

2017-03-05 Thread Markus Armbruster
Signed-off-by: Markus Armbruster 
Message-Id: <1488544368-30622-25-git-send-email-arm...@redhat.com>
Reviewed-by: Eric Blake 
---
 tests/test-qobject-input-visitor.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/tests/test-qobject-input-visitor.c 
b/tests/test-qobject-input-visitor.c
index 10c15c4..9f3a826 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -894,7 +894,7 @@ static void 
test_visitor_in_fail_struct_missing(TestInputVisitorData *data,
 char *str;
 double dbl;
 
-v = visitor_input_test_init(data, "{}");
+v = visitor_input_test_init(data, "{ 'sub': [ {} ] }");
 visit_start_struct(v, NULL, NULL, 0, &error_abort);
 visit_start_struct(v, "struct", NULL, 0, &err);
 error_free_or_abort(&err);
@@ -920,6 +920,12 @@ static void 
test_visitor_in_fail_struct_missing(TestInputVisitorData *data,
 error_free_or_abort(&err);
 visit_type_null(v, "null", &err);
 error_free_or_abort(&err);
+visit_start_list(v, "sub", NULL, 0, &error_abort);
+visit_start_struct(v, NULL, NULL, 0, &error_abort);
+visit_type_int(v, "i64", &i64, &err);
+error_free_or_abort(&err);
+visit_end_struct(v, NULL);
+visit_end_list(v, NULL);
 visit_end_struct(v, NULL);
 }
 
-- 
2.7.4




[Qemu-devel] [PULL v2 14/27] qapi: Drop string input visitor method optional()

2017-03-05 Thread Markus Armbruster
visit_optional() is to be called only between visit_start_struct() and
visit_end_struct().  Visitors that don't support struct visits,
i.e. don't implement start_struct(), end_struct(), have no use for it.
Clarify documentation.

The string input visitor doesn't support struct visits.  Its
parse_optional() is therefore useless.  Drop it.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-16-git-send-email-arm...@redhat.com>
---
 include/qapi/visitor-impl.h |  4 ++--
 qapi/string-input-visitor.c | 13 -
 2 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 8bd47ee..962ba1d 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -102,8 +102,8 @@ struct Visitor
 /* Must be set to visit explicit null values.  */
 void (*type_null)(Visitor *v, const char *name, Error **errp);
 
-/* Must be set for input visitors, optional otherwise.  The core
- * takes care of the return type in the public interface. */
+/* Must be set for input visitors to visit structs, optional otherwise.
+   The core takes care of the return type in the public interface. */
 void (*optional)(Visitor *v, const char *name, bool *present);
 
 /* Must be set */
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
index 8dfa561..1a855c5 100644
--- a/qapi/string-input-visitor.c
+++ b/qapi/string-input-visitor.c
@@ -314,18 +314,6 @@ static void parse_type_number(Visitor *v, const char 
*name, double *obj,
 *obj = val;
 }
 
-static void parse_optional(Visitor *v, const char *name, bool *present)
-{
-StringInputVisitor *siv = to_siv(v);
-
-if (!siv->string) {
-*present = false;
-return;
-}
-
-*present = true;
-}
-
 static void string_input_free(Visitor *v)
 {
 StringInputVisitor *siv = to_siv(v);
@@ -351,7 +339,6 @@ Visitor *string_input_visitor_new(const char *str)
 v->visitor.start_list = start_list;
 v->visitor.next_list = next_list;
 v->visitor.end_list = end_list;
-v->visitor.optional = parse_optional;
 v->visitor.free = string_input_free;
 
 v->string = str;
-- 
2.7.4




[Qemu-devel] [PULL v2 26/27] qapi: Fix object input visit beyond end of list

2017-03-05 Thread Markus Armbruster
Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-28-git-send-email-arm...@redhat.com>
---
 qapi/qobject-input-visitor.c   | 11 ---
 tests/test-qobject-input-visitor.c |  2 --
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index 34065ba..d192727 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -122,10 +122,15 @@ static QObject 
*qobject_input_try_get_object(QObjectInputVisitor *qiv,
 } else {
 assert(qobject_type(qobj) == QTYPE_QLIST);
 assert(!name);
-ret = qlist_entry_obj(tos->entry);
-assert(ret);
+if (tos->entry) {
+ret = qlist_entry_obj(tos->entry);
+if (consume) {
+tos->entry = qlist_next(tos->entry);
+}
+} else {
+ret = NULL;
+}
 if (consume) {
-tos->entry = qlist_next(tos->entry);
 tos->index++;
 }
 }
diff --git a/tests/test-qobject-input-visitor.c 
b/tests/test-qobject-input-visitor.c
index 8011baa..94305f5 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -953,10 +953,8 @@ static void test_visitor_in_fail_list(TestInputVisitorData 
*data,
 v = visitor_input_test_init(data, "[]");
 
 visit_start_list(v, NULL, NULL, 0, &error_abort);
-#if 0 /* FIXME crash */
 visit_type_int(v, NULL, &i64, &err);
 error_free_or_abort(&err);
-#endif
 visit_end_list(v, NULL);
 }
 
-- 
2.7.4




[Qemu-devel] [PULL v2 04/27] qmp: Dumb down how we run QMP command registration

2017-03-05 Thread Markus Armbruster
The way we get QMP commands registered is high tech:

* qapi-commands.py generates qmp_init_marshal() that does the actual work

* it also generates the magic to register it as a MODULE_INIT_QAPI
  function, so it runs when someone calls
  module_call_init(MODULE_INIT_QAPI)

* main() calls module_call_init()

QEMU needs to register a few non-qapified commands.  Same high tech
works: monitor.c has its own qmp_init_marshal() along with the magic
to make it run in module_call_init(MODULE_INIT_QAPI).

QEMU also needs to unregister commands that are not wanted in this
build's configuration (commit 5032a16).  Simple enough:
qmp_unregister_commands_hack().  The difficulty is to make it run
after the generated qmp_init_marshal().  We can't simply run it in
monitor.c's qmp_init_marshal(), because the order in which the
registered functions run is indeterminate.  So qmp_init_marshal()
registers qmp_unregister_commands_hack() separately.  Since
registering *appends* to the list of registered functions, this will
make it run after all the functions that have been registered already.

I suspect it takes a long and expensive computer science education to
not find this silly.

Dumb it down as follows:

* Drop MODULE_INIT_QAPI entirely

* Give the generated qmp_init_marshal() external linkage.

* Call it instead of module_call_init(MODULE_INIT_QAPI)

* Except in QEMU proper, call new monitor_init_qmp_commands() that in
  turn calls the generated qmp_init_marshal(), registers the
  additional commands and unregisters the unwanted ones.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-5-git-send-email-arm...@redhat.com>
---
 include/monitor/monitor.h | 1 +
 include/qemu/module.h | 2 --
 monitor.c | 9 -
 qga/main.c| 2 +-
 scripts/qapi-commands.py  | 5 ++---
 tests/test-qmp-commands.c | 2 +-
 vl.c  | 2 +-
 7 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index e64b944..d2b3aaf 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -16,6 +16,7 @@ extern Monitor *cur_mon;
 
 bool monitor_cur_is_qmp(void);
 
+void monitor_init_qmp_commands(void);
 void monitor_init(Chardev *chr, int flags);
 void monitor_cleanup(void);
 
diff --git a/include/qemu/module.h b/include/qemu/module.h
index 877cca7..56dd218 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -42,7 +42,6 @@ static void __attribute__((constructor)) do_qemu_init_ ## 
function(void)\
 typedef enum {
 MODULE_INIT_BLOCK,
 MODULE_INIT_OPTS,
-MODULE_INIT_QAPI,
 MODULE_INIT_QOM,
 MODULE_INIT_TRACE,
 MODULE_INIT_MAX
@@ -50,7 +49,6 @@ typedef enum {
 
 #define block_init(function) module_init(function, MODULE_INIT_BLOCK)
 #define opts_init(function) module_init(function, MODULE_INIT_OPTS)
-#define qapi_init(function) module_init(function, MODULE_INIT_QAPI)
 #define type_init(function) module_init(function, MODULE_INIT_QOM)
 #define trace_init(function) module_init(function, MODULE_INIT_TRACE)
 
diff --git a/monitor.c b/monitor.c
index b68944d..53f5f5a 100644
--- a/monitor.c
+++ b/monitor.c
@@ -997,8 +997,10 @@ static void qmp_unregister_commands_hack(void)
 #endif
 }
 
-static void qmp_init_marshal(void)
+void monitor_init_qmp_commands(void)
 {
+qmp_init_marshal();
+
 qmp_register_command("query-qmp-schema", qmp_query_qmp_schema,
  QCO_NO_OPTIONS);
 qmp_register_command("device_add", qmp_device_add,
@@ -1006,12 +1008,9 @@ static void qmp_init_marshal(void)
 qmp_register_command("netdev_add", qmp_netdev_add,
  QCO_NO_OPTIONS);
 
-/* call it after the rest of qapi_init() */
-register_module_init(qmp_unregister_commands_hack, MODULE_INIT_QAPI);
+qmp_unregister_commands_hack();
 }
 
-qapi_init(qmp_init_marshal);
-
 /* set the current CPU defined by the user */
 int monitor_set_cpu(int cpu_index)
 {
diff --git a/qga/main.c b/qga/main.c
index 538e4ee..6f8c614 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -1321,7 +1321,7 @@ int main(int argc, char **argv)
 
 config->log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL;
 
-module_call_init(MODULE_INIT_QAPI);
+qmp_init_marshal();
 
 init_dfl_pathnames();
 config_load(config);
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 09e8467..a75946f 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -208,14 +208,12 @@ def gen_register_command(name, success_response):
 def gen_registry(registry):
 ret = mcgen('''
 
-static void qmp_init_marshal(void)
+void qmp_init_marshal(void)
 {
 ''')
 ret += registry
 ret += mcgen('''
 }
-
-qapi_init(qmp_init_marshal);
 ''')
 return ret
 
@@ -308,6 +306,7 @@ fdecl.write(mcgen('''
 #include "qapi/qmp/qdict.h"
 #include "qapi/error.h"
 
+void qmp_init_marshal(void);
 ''',
   prefix=prefix))
 
diff --git a/tests/tes

[Qemu-devel] [PULL v2 17/27] test-qobject-input-visitor: Use strict visitor

2017-03-05 Thread Markus Armbruster
The qobject input visitor comes in a strict and a non-strict variant.
This test is the non-strict variant's last user.  Turns out it relies
on non-strict only in test_visitor_in_null(), and just out of
laziness.  We don't actually test the non-strict behavior.

Clean up test_visitor_in_null(), and switch to the strict variant.
The next commit will drop the non-strict variant.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-19-git-send-email-arm...@redhat.com>
---
 tests/test-qobject-input-visitor.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tests/test-qobject-input-visitor.c 
b/tests/test-qobject-input-visitor.c
index 945404a..125e34c 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -49,7 +49,7 @@ static Visitor 
*visitor_input_test_init_internal(TestInputVisitorData *data,
 data->obj = qobject_from_jsonv(json_string, ap);
 g_assert(data->obj);
 
-data->qiv = qobject_input_visitor_new(data->obj, false);
+data->qiv = qobject_input_visitor_new(data->obj, true);
 g_assert(data->qiv);
 return data->qiv;
 }
@@ -290,14 +290,14 @@ static void test_visitor_in_null(TestInputVisitorData 
*data,
  * when input is not null.
  */
 
-v = visitor_input_test_init(data, "{ 'a': null, 'b': '' }");
+v = visitor_input_test_init(data, "{ 'a': null, 'b': '', 'c': null }");
 visit_start_struct(v, NULL, NULL, 0, &error_abort);
 visit_type_null(v, "a", &error_abort);
-visit_type_str(v, "a", &tmp, &err);
-g_assert(!tmp);
-error_free_or_abort(&err);
 visit_type_null(v, "b", &err);
 error_free_or_abort(&err);
+visit_type_str(v, "c", &tmp, &err);
+g_assert(!tmp);
+error_free_or_abort(&err);
 visit_check_struct(v, &error_abort);
 visit_end_struct(v, NULL);
 }
-- 
2.7.4




[Qemu-devel] [PULL v2 10/27] qapi: Improve a QObject input visitor error message

2017-03-05 Thread Markus Armbruster
The QObject input visitor has three error message formats:

* Parameter '%s' is missing
* "Invalid parameter type for '%s', expected: %s"
* "QMP input object member '%s' is unexpected"

The '%s' are member names (or "null", but I'll fix that later).

The last error message calls the thing "QMP input object member"
instead of "parameter".  Misleading when the visitor is used on
QObjects that don't come from QMP.  Change it to "Parameter '%s' is
unexpected".

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-12-git-send-email-arm...@redhat.com>
---
 qapi/qobject-input-visitor.c | 3 +--
 tests/test-qga.c | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index ed6c24c..f3b6713 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -140,8 +140,7 @@ static void qobject_input_check_struct(Visitor *v, Error 
**errp)
 
 g_hash_table_iter_init(&iter, top_ht);
 if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) {
-error_setg(errp, "QMP input object member '%s' is unexpected",
-   key);
+error_setg(errp, "Parameter '%s' is unexpected", key);
 }
 }
 }
diff --git a/tests/test-qga.c b/tests/test-qga.c
index 868b02a..ae97b57 100644
--- a/tests/test-qga.c
+++ b/tests/test-qga.c
@@ -213,7 +213,7 @@ static void test_qga_invalid_args(gconstpointer fix)
 desc = qdict_get_try_str(error, "desc");
 
 g_assert_cmpstr(class, ==, "GenericError");
-g_assert_cmpstr(desc, ==, "QMP input object member 'foo' is unexpected");
+g_assert_cmpstr(desc, ==, "Parameter 'foo' is unexpected");
 
 QDECREF(ret);
 }
-- 
2.7.4




[Qemu-devel] [PULL v2 25/27] tests: Cover input visit beyond end of list

2017-03-05 Thread Markus Armbruster
When you try to visit beyond the end of a list, the qobject input
visitor crashes, and the string visitor screws returns garbage.  The
generated list visits never go beyond the list end, but manual visits
could.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-27-git-send-email-arm...@redhat.com>
---
 tests/test-opts-visitor.c  | 39 ++
 tests/test-qobject-input-visitor.c | 10 ++
 tests/test-string-input-visitor.c  | 16 
 3 files changed, 65 insertions(+)

diff --git a/tests/test-opts-visitor.c b/tests/test-opts-visitor.c
index b93fd33..2238f8e 100644
--- a/tests/test-opts-visitor.c
+++ b/tests/test-opts-visitor.c
@@ -210,6 +210,43 @@ test_opts_range_unvisited(void)
 qemu_opts_del(opts);
 }
 
+static void
+test_opts_range_beyond(void)
+{
+Error *err = NULL;
+intList *list = NULL;
+intList *tail;
+QemuOpts *opts;
+Visitor *v;
+int64_t val;
+
+opts = qemu_opts_parse(qemu_find_opts("userdef"), "ilist=0", false,
+   &error_abort);
+
+v = opts_visitor_new(opts);
+
+visit_start_struct(v, NULL, NULL, 0, &error_abort);
+
+/* Would be simpler if the visitor genuinely supported virtual walks */
+visit_start_list(v, "ilist", (GenericList **)&list, sizeof(*list),
+ &error_abort);
+tail = list;
+visit_type_int(v, NULL, &tail->value, &error_abort);
+g_assert_cmpint(tail->value, ==, 0);
+tail = (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*tail));
+g_assert(!tail);
+visit_type_int(v, NULL, &val, &err);
+error_free_or_abort(&err);
+visit_end_list(v, (void **)&list);
+
+visit_check_struct(v, &error_abort);
+visit_end_struct(v, NULL);
+
+qapi_free_intList(list);
+visit_free(v);
+qemu_opts_del(opts);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -303,6 +340,8 @@ main(int argc, char **argv)
 
 g_test_add_func("/visitor/opts/range/unvisited",
 test_opts_range_unvisited);
+g_test_add_func("/visitor/opts/range/beyond",
+test_opts_range_beyond);
 
 g_test_run();
 return 0;
diff --git a/tests/test-qobject-input-visitor.c 
b/tests/test-qobject-input-visitor.c
index 87d4a77..8011baa 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -948,6 +948,16 @@ static void test_visitor_in_fail_list(TestInputVisitorData 
*data,
 visit_check_list(v, &err);
 error_free_or_abort(&err);
 visit_end_list(v, NULL);
+
+/* Visit beyond end of list */
+v = visitor_input_test_init(data, "[]");
+
+visit_start_list(v, NULL, NULL, 0, &error_abort);
+#if 0 /* FIXME crash */
+visit_type_int(v, NULL, &i64, &err);
+error_free_or_abort(&err);
+#endif
+visit_end_list(v, NULL);
 }
 
 static void test_visitor_in_fail_list_nested(TestInputVisitorData *data,
diff --git a/tests/test-string-input-visitor.c 
b/tests/test-string-input-visitor.c
index fbe380a..6db850b 100644
--- a/tests/test-string-input-visitor.c
+++ b/tests/test-string-input-visitor.c
@@ -123,6 +123,7 @@ static void test_visitor_in_intList(TestInputVisitorData 
*data,
 int64List *res = NULL;
 int64List *tail;
 Visitor *v;
+int64_t val;
 
 /* Valid lists */
 
@@ -175,6 +176,21 @@ static void test_visitor_in_intList(TestInputVisitorData 
*data,
 visit_end_list(v, (void **)&res);
 
 qapi_free_int64List(res);
+
+/* Visit beyond end of list */
+v = visitor_input_test_init(data, "0");
+
+visit_start_list(v, NULL, (GenericList **)&res, sizeof(*res),
+ &error_abort);
+tail = res;
+visit_type_int64(v, NULL, &tail->value, &err);
+g_assert_cmpint(tail->value, ==, 0);
+visit_type_int64(v, NULL, &val, &err);
+g_assert_cmpint(val, ==, 1); /* BUG */
+visit_check_list(v, &error_abort);
+visit_end_list(v, (void **)&res);
+
+qapi_free_int64List(res);
 }
 
 static void test_visitor_in_bool(TestInputVisitorData *data,
-- 
2.7.4




[Qemu-devel] [PULL v2 00/27] QAPI patches for 2017-02-28

2017-03-05 Thread Markus Armbruster
The following changes since commit 17783ac828adc694d986698d2d7014aedfeb48c6:

  Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.9-20170303' into 
staging (2017-03-04 16:31:14 +)

are available in the git repository at:

  git://repo.or.cz/qemu/armbru.git tags/pull-qapi-2017-02-28

for you to fetch changes up to aa3a982e674b09ae32502940f93ba98b3a8ad50e:

  qapi: Improve qobject visitor documentation (2017-03-05 09:14:20 +0100)


QAPI patches for 2017-02-28


Markus Armbruster (27):
  qga: Fix crash on non-dictionary QMP argument
  libqtest: Work around a "QMP wants a newline" bug
  qmp-test: New, covering basic QMP protocol
  qmp: Dumb down how we run QMP command registration
  qapi: Support multiple command registries per program
  qapi-introspect: Mangle --prefix argument properly for C
  qmp: Clean up how we enforce capability negotiation
  qmp: Drop duplicated QMP command object checks
  qmp: Eliminate silly QERR_QMP_* macros
  qapi: Improve a QObject input visitor error message
  qapi: Clean up after commit 3d344c2
  qapi: Make QObject input visitor set *list reliably
  qapi: Improve qobject input visitor error reporting
  qapi: Drop string input visitor method optional()
  qapi: Make string input and opts visitor require non-null input
  qom: Make object_property_set_qobject()'s input visitor strict
  test-qobject-input-visitor: Use strict visitor
  qapi: Drop unused non-strict qobject input visitor
  tests-qobject-input-strict: Merge into test-qobject-input-visitor
  test-string-input-visitor: Tear down existing test automatically
  test-string-input-visitor: Improve list coverage
  tests: Cover partial input visit of list
  test-qobject-input-visitor: Cover missing nested struct member
  qapi: Make input visitors detect unvisited list tails
  tests: Cover input visit beyond end of list
  qapi: Fix object input visit beyond end of list
  qapi: Improve qobject visitor documentation

 MAINTAINERS   |   1 +
 block/nbd.c   |   2 +-
 block/nfs.c   |   2 +-
 block/ssh.c   |   2 +-
 docs/qapi-code-gen.txt|   2 +-
 hw/ppc/spapr_drc.c|   5 +
 include/monitor/monitor.h |   1 +
 include/qapi/qmp/dispatch.h   |  22 +-
 include/qapi/qmp/qerror.h |   9 -
 include/qapi/qobject-input-visitor.h  |  40 +++-
 include/qapi/qobject-output-visitor.h |  35 +++-
 include/qapi/visitor-impl.h   |   7 +-
 include/qapi/visitor.h|  19 +-
 include/qemu/module.h |   2 -
 monitor.c | 178 ++--
 qapi/opts-visitor.c   |  12 ++
 qapi/qapi-visit-core.c|   8 +
 qapi/qmp-dispatch.c   |  29 ++-
 qapi/qmp-registry.c   |  37 ++--
 qapi/qobject-input-visitor.c  | 219 ---
 qapi/string-input-visitor.c   |  97 +
 qapi/trace-events |   1 +
 qga/commands.c|   2 +-
 qga/guest-agent-core.h|   2 +
 qga/main.c|  19 +-
 qmp.c |   2 +-
 qom/qom-qobject.c |   4 +-
 scripts/qapi-commands.py  |  19 +-
 scripts/qapi-introspect.py|   2 +-
 scripts/qapi-visit.py |   3 +
 target/s390x/cpu_models.c |   2 +-
 tests/Makefile.include|   9 +-
 tests/check-qnull.c   |   2 +-
 tests/libqtest.c  |  29 ++-
 tests/libqtest.h  |   8 +
 tests/qmp-test.c  | 139 +
 tests/test-opts-visitor.c |  80 +++
 tests/test-qga.c  |   2 +-
 tests/test-qmp-commands.c |  14 +-
 tests/test-qobject-input-strict.c | 381 --
 tests/test-qobject-input-visitor.c| 260 ++-
 tests/test-string-input-visitor.c | 142 ++---
 tests/test-visitor-serialization.c|   2 +-
 trace-events  |   1 -
 vl.c  |   2 +-
 45 files changed, 1083 insertions(+), 773 deletions(-)
 create mode 100644 tests/qmp-test.c
 delete mode 100644 tests/test-qobject-input-strict.c

-- 
2.7.4




[Qemu-devel] [PULL v2 08/27] qmp: Drop duplicated QMP command object checks

2017-03-05 Thread Markus Armbruster
qmp_check_input_obj() duplicates qmp_dispatch_check_obj(), except the
latter screws up an error message.  handle_qmp_command() runs first
the former, then the latter via qmp_dispatch(), masking the screwup.

qemu-ga also masks the screwup, because it also duplicates checks,
just differently.

qmp_check_input_obj() exists because handle_qmp_command() needs to
examine the command before dispatching it.  The previous commit got
rid of this need, except for a tracepoint, and a bit of "id" code that
relies on qdict not being null.

Fix up the error message in qmp_dispatch_check_obj(), drop
qmp_check_input_obj() and the tracepoint.  Protect the "id" code with
a conditional.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-9-git-send-email-arm...@redhat.com>
---
 monitor.c   | 74 +
 qapi/qmp-dispatch.c |  3 +--
 trace-events|  1 -
 3 files changed, 7 insertions(+), 71 deletions(-)

diff --git a/monitor.c b/monitor.c
index 0c06dc7..ec7623e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3700,67 +3700,10 @@ static int monitor_can_read(void *opaque)
 return (mon->suspend_cnt == 0) ? 1 : 0;
 }
 
-/*
- * Input object checking rules
- *
- * 1. Input object must be a dict
- * 2. The "execute" key must exist
- * 3. The "execute" key must be a string
- * 4. If the "arguments" key exists, it must be a dict
- * 5. If the "id" key exists, it can be anything (ie. json-value)
- * 6. Any argument not listed above is considered invalid
- */
-static QDict *qmp_check_input_obj(QObject *input_obj, Error **errp)
-{
-const QDictEntry *ent;
-int has_exec_key = 0;
-QDict *input_dict;
-
-input_dict = qobject_to_qdict(input_obj);
-if (!input_dict) {
-error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "object");
-return NULL;
-}
-
-
-for (ent = qdict_first(input_dict); ent; ent = qdict_next(input_dict, 
ent)){
-const char *arg_name = qdict_entry_key(ent);
-const QObject *arg_obj = qdict_entry_value(ent);
-
-if (!strcmp(arg_name, "execute")) {
-if (qobject_type(arg_obj) != QTYPE_QSTRING) {
-error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
-   "execute", "string");
-return NULL;
-}
-has_exec_key = 1;
-} else if (!strcmp(arg_name, "arguments")) {
-if (qobject_type(arg_obj) != QTYPE_QDICT) {
-error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
-   "arguments", "object");
-return NULL;
-}
-} else if (!strcmp(arg_name, "id")) {
-/* Any string is acceptable as "id", so nothing to check */
-} else {
-error_setg(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
-return NULL;
-}
-}
-
-if (!has_exec_key) {
-error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute");
-return NULL;
-}
-
-return input_dict;
-}
-
 static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
 {
 QObject *req, *rsp = NULL, *id = NULL;
 QDict *qdict = NULL;
-const char *cmd_name;
 Monitor *mon = cur_mon;
 Error *err = NULL;
 
@@ -3773,17 +3716,12 @@ static void handle_qmp_command(JSONMessageParser 
*parser, GQueue *tokens)
 goto err_out;
 }
 
-qdict = qmp_check_input_obj(req, &err);
-if (!qdict) {
-goto err_out;
-}
-
-id = qdict_get(qdict, "id");
-qobject_incref(id);
-qdict_del(qdict, "id");
-
-cmd_name = qdict_get_str(qdict, "execute");
-trace_handle_qmp_command(mon, cmd_name);
+qdict = qobject_to_qdict(req);
+if (qdict) {
+id = qdict_get(qdict, "id");
+qobject_incref(id);
+qdict_del(qdict, "id");
+} /* else will fail qmp_dispatch() */
 
 rsp = qmp_dispatch(cur_mon->qmp.commands, req);
 
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 72827a3..7fb8aef 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -30,8 +30,7 @@ static QDict *qmp_dispatch_check_obj(const QObject *request, 
Error **errp)
 
 dict = qobject_to_qdict(request);
 if (!dict) {
-error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT,
-   "request is not a dictionary");
+error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "object");
 return NULL;
 }
 
diff --git a/trace-events b/trace-events
index 7288557..b07a09b 100644
--- a/trace-events
+++ b/trace-events
@@ -65,7 +65,6 @@ xen_remap_bucket(uint64_t index) "index %#"PRIx64
 xen_map_cache_return(void* ptr) "%p"
 
 # monitor.c
-handle_qmp_command(void *mon, const char *cmd_name) "mon %p cmd_name \"%s\""
 monitor_protocol_event_handler(uint32_t event, void *qdict) "event=%d data=%p"
 monitor_protocol_event_emit(uint32_t event, void *data) "event=%d data=%p"
 monitor_protocol_event_queue(uint32_t event, void *qdict, uint64_t rate) 
"event=%d data=%p rate=%" PRId64

[Qemu-devel] [PULL v2 01/27] qga: Fix crash on non-dictionary QMP argument

2017-03-05 Thread Markus Armbruster
The value of key 'arguments' must be a JSON object.  qemu-ga neglects
to check, and crashes.  To reproduce, send

{ 'execute': 'guest-sync', 'arguments': [] }

to qemu-ga.

do_qmp_dispatch() uses qdict_get_qdict() to get the arguments.  When
not a JSON object, this gets a null pointer, which flows through the
generated marshalling function to qobject_input_visitor_new(), where
it fails the assertion.  qmp_dispatch_check_obj() needs to catch this
error.

QEMU isn't affected, because it runs qmp_check_input_obj() first,
which basically duplicates qmp_dispatch_check_obj()'s checks, plus the
missing one.

Fix by copying the missing one from qmp_check_input_obj() to
qmp_dispatch_check_obj().

Signed-off-by: Markus Armbruster 
Cc: Michael Roth 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-2-git-send-email-arm...@redhat.com>
---
 qapi/qmp-dispatch.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 48bec20..621922f 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -47,7 +47,13 @@ static QDict *qmp_dispatch_check_obj(const QObject *request, 
Error **errp)
 return NULL;
 }
 has_exec_key = true;
-} else if (strcmp(arg_name, "arguments")) {
+} else if (!strcmp(arg_name, "arguments")) {
+if (qobject_type(arg_obj) != QTYPE_QDICT) {
+error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
+   "arguments", "object");
+return NULL;
+}
+} else {
 error_setg(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
 return NULL;
 }
-- 
2.7.4




[Qemu-devel] [PULL v2 12/27] qapi: Make QObject input visitor set *list reliably

2017-03-05 Thread Markus Armbruster
qobject_input_start_struct() sets *list, except when it fails because
qobject_input_get_object() fails, i.e. the input object doesn't exist.

All the other input visitor start_struct(), start_list(),
start_alternate() always set *obj / *list.

Change qobject_input_start_struct() to match.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-14-git-send-email-arm...@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé 
---
 qapi/qobject-input-visitor.c | 14 +-
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index 2c2f883..d58696c 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -196,25 +196,21 @@ static void qobject_input_start_list(Visitor *v, const 
char *name,
 QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
 const QListEntry *entry;
 
+if (list) {
+*list = NULL;
+}
 if (!qobj) {
 return;
 }
 if (qobject_type(qobj) != QTYPE_QLIST) {
-if (list) {
-*list = NULL;
-}
 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"list");
 return;
 }
 
 entry = qobject_input_push(qiv, qobj, list);
-if (list) {
-if (entry) {
-*list = g_malloc0(size);
-} else {
-*list = NULL;
-}
+if (entry && list) {
+*list = g_malloc0(size);
 }
 }
 
-- 
2.7.4




[Qemu-devel] [PULL v2 03/27] qmp-test: New, covering basic QMP protocol

2017-03-05 Thread Markus Armbruster
Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-4-git-send-email-arm...@redhat.com>
---
 MAINTAINERS|   1 +
 tests/Makefile.include |   5 +-
 tests/libqtest.c   |  17 --
 tests/libqtest.h   |   8 +++
 tests/qmp-test.c   | 139 +
 5 files changed, 164 insertions(+), 6 deletions(-)
 create mode 100644 tests/qmp-test.c

diff --git a/MAINTAINERS b/MAINTAINERS
index b9a2171..e3edd04 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1404,6 +1404,7 @@ F: qmp.c
 F: monitor.c
 F: docs/*qmp-*
 F: scripts/qmp/
+F: tests/qmp-test.c
 T: git git://repo.or.cz/qemu/armbru.git qapi-next
 
 Register API
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 364ef1b..bb0f430 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -133,7 +133,9 @@ check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 # All QTests for now are POSIX-only, but the dependencies are
 # really in libqtest, not in the testcases themselves.
 
-check-qtest-generic-y = tests/device-introspect-test$(EXESUF)
+check-qtest-generic-y = tests/qmp-test$(EXESUF)
+gcov-files-generic-y = monitor.c qapi/qmp-dispatch.c
+check-qtest-generic-y += tests/device-introspect-test$(EXESUF)
 gcov-files-generic-y = qdev-monitor.c qmp.c
 
 gcov-files-ipack-y += hw/ipack/ipack.c
@@ -653,6 +655,7 @@ libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o
 libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/usb.o
 libqos-virtio-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) 
tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o 
tests/libqos/malloc-generic.o
 
+tests/qmp-test$(EXESUF): tests/qmp-test.o
 tests/device-introspect-test$(EXESUF): tests/device-introspect-test.o
 tests/rtc-test$(EXESUF): tests/rtc-test.o
 tests/m48t59-test$(EXESUF): tests/m48t59-test.o
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 951a3b4..ca6b641 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -149,7 +149,7 @@ void qtest_add_abrt_handler(GHookFunc fn, const void *data)
 g_hook_prepend(&abrt_hooks, hook);
 }
 
-QTestState *qtest_init(const char *extra_args)
+QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
 {
 QTestState *s;
 int sock, qmpsock, i;
@@ -204,10 +204,6 @@ QTestState *qtest_init(const char *extra_args)
 s->irq_level[i] = false;
 }
 
-/* Read the QMP greeting and then do the handshake */
-qtest_qmp_discard_response(s, "");
-qtest_qmp_discard_response(s, "{ 'execute': 'qmp_capabilities' }");
-
 if (getenv("QTEST_STOP")) {
 kill(s->qemu_pid, SIGSTOP);
 }
@@ -219,6 +215,17 @@ QTestState *qtest_init(const char *extra_args)
 return s;
 }
 
+QTestState *qtest_init(const char *extra_args)
+{
+QTestState *s = qtest_init_without_qmp_handshake(extra_args);
+
+/* Read the QMP greeting and then do the handshake */
+qtest_qmp_discard_response(s, "");
+qtest_qmp_discard_response(s, "{ 'execute': 'qmp_capabilities' }");
+
+return s;
+}
+
 void qtest_quit(QTestState *s)
 {
 qtest_instances = g_list_remove(qtest_instances, s);
diff --git a/tests/libqtest.h b/tests/libqtest.h
index 90f182e..2c9962d 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -32,6 +32,14 @@ extern QTestState *global_qtest;
 QTestState *qtest_init(const char *extra_args);
 
 /**
+ * qtest_init_without_qmp_handshake:
+ * @extra_args: other arguments to pass to QEMU.
+ *
+ * Returns: #QTestState instance.
+ */
+QTestState *qtest_init_without_qmp_handshake(const char *extra_args);
+
+/**
  * qtest_quit:
  * @s: #QTestState instance to operate on.
  *
diff --git a/tests/qmp-test.c b/tests/qmp-test.c
new file mode 100644
index 000..405e49e
--- /dev/null
+++ b/tests/qmp-test.c
@@ -0,0 +1,139 @@
+/*
+ * QMP protocol test cases
+ *
+ * Copyright (c) 2017 Red Hat Inc.
+ *
+ * Authors:
+ *  Markus Armbruster ,
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "qapi-visit.h"
+#include "qapi/error.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/visitor.h"
+
+const char common_args[] = "-nodefaults -machine none";
+
+static const char *get_error_class(QDict *resp)
+{
+QDict *error = qdict_get_qdict(resp, "error");
+const char *desc = qdict_get_try_str(error, "desc");
+
+g_assert(desc);
+return error ? qdict_get_try_str(error, "class") : NULL;
+}
+
+static void test_version(QObject *version)
+{
+Visitor *v;
+VersionInfo *vinfo;
+
+g_assert(version);
+v = qobject_input_visitor_new(version, true);
+visit_type_VersionInfo(v, "version", &vinfo, &error_abort);
+qapi_free_VersionInfo(vinfo);
+visit_free(v);
+}
+
+static void test_malformed(void)
+{
+QDict *resp;
+
+/* Not even a dictionary */
+resp = qmp("null");
+g_assert_cmpst

[Qemu-devel] [PULL v2 02/27] libqtest: Work around a "QMP wants a newline" bug

2017-03-05 Thread Markus Armbruster
The next commit is going to add a test that calls qmp("null").
Curiously, this hangs.  Here's why.

qmp_fd_sendv() doesn't send newlines.  Not even when @fmt contains
some.  At first glance, the QMP parser seems to be fine with that.
However, it turns out that it fails to react to input until it sees
either a newline, an object or an array.  To reproduce, feed to a QMP
monitor like this:

$ echo -n 'null' | socat UNIX:/work/armbru/images/test-qmp STDIO
{"QMP": {"version": {"qemu": {"micro": 50, "minor": 8, "major": 2}, 
"package": " (v2.8.0-1195-gf84141e-dirty)"}, "capabilities": []}}

No output after the greeting.

Add a newline:

$ echo 'null' | socat UNIX:/work/armbru/images/test-qmp STDIO
{"QMP": {"version": {"qemu": {"micro": 50, "minor": 8, "major": 2}, 
"package": " (v2.8.0-1195-gf84141e-dirty)"}, "capabilities": []}}
{"error": {"class": "GenericError", "desc": "Expected 'object' in QMP 
input"}}

Correct output for input 'null'.

Add an object instead:

$ echo -n 'null { "execute": "qmp_capabilities" }' | socat UNIX:qmp-socket 
STDIO
{"QMP": {"version": {"qemu": {"micro": 50, "minor": 8, "major": 2}, 
"package": " (v2.8.0-1195-gf84141e-dirty)"}, "capabilities": []}}
{"error": {"class": "GenericError", "desc": "Expected 'object' in QMP 
input"}}
{"return": {}}

Also correct output.

Work around this QMP bug by having qmp_fd_sendv() append a newline.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-3-git-send-email-arm...@redhat.com>
---
 tests/libqtest.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/tests/libqtest.c b/tests/libqtest.c
index 3a0e0d6..951a3b4 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -442,14 +442,20 @@ void qmp_fd_sendv(int fd, const char *fmt, va_list ap)
 if (qobj) {
 int log = getenv("QTEST_LOG") != NULL;
 QString *qstr = qobject_to_json(qobj);
-const char *str = qstring_get_str(qstr);
-size_t size = qstring_get_length(qstr);
+const char *str;
+
+/*
+ * BUG: QMP doesn't react to input until it sees a newline, an
+ * object, or an array.  Work-around: give it a newline.
+ */
+qstring_append_chr(qstr, '\n');
+str = qstring_get_str(qstr);
 
 if (log) {
 fprintf(stderr, "%s", str);
 }
 /* Send QMP request */
-socket_send(fd, str, size);
+socket_send(fd, str, qstring_get_length(qstr));
 
 QDECREF(qstr);
 qobject_decref(qobj);
-- 
2.7.4




[Qemu-devel] [PULL v2 07/27] qmp: Clean up how we enforce capability negotiation

2017-03-05 Thread Markus Armbruster
To enforce capability negotiation before normal operation,
handle_qmp_command() inspects every command before it's handed off to
qmp_dispatch().  This is a bit of a layering violation, and results in
duplicated code.

Before capability negotiation (!cur_mon->in_command_mode), we fail
commands other than "qmp_capabilities".  This is what enforces
capability negotiation.

Afterwards, we fail command "qmp_capabilities".

Clean this up as follows.

The obvious place to fail a command is the command itself, so move the
"afterwards" check to qmp_qmp_capabilities().

We do the "before" check in every other command, but that would be
bothersome.  Instead, start with an alternate list of commands that
contains only "qmp_capabilities".  Switch to the full list in
qmp_qmp_capabilities().

Additionally, replace the generic human-readable error message for
CommandNotFound by one that reminds the user to run qmp_capabilities.
Without that, we'd regress commit 2d5a834.

Signed-off-by: Markus Armbruster 
Message-Id: <1488544368-30622-8-git-send-email-arm...@redhat.com>
[Mirco-optimization squashed in, commit message typo fixed]
Reviewed-by: Eric Blake 
---
 monitor.c | 76 +++
 1 file changed, 42 insertions(+), 34 deletions(-)

diff --git a/monitor.c b/monitor.c
index c7f7602..0c06dc7 100644
--- a/monitor.c
+++ b/monitor.c
@@ -165,7 +165,7 @@ typedef struct {
  * When command qmp_capabilities succeeds, we go into command
  * mode.
  */
-bool in_command_mode;   /* are we in command mode? */
+QmpCommandList *commands;
 } MonitorQMP;
 
 /*
@@ -221,7 +221,7 @@ static int mon_refcount;
 static mon_cmd_t mon_cmds[];
 static mon_cmd_t info_cmds[];
 
-QmpCommandList qmp_commands;
+QmpCommandList qmp_commands, qmp_cap_negotiation_commands;
 
 Monitor *cur_mon;
 
@@ -416,7 +416,8 @@ static void monitor_qapi_event_emit(QAPIEvent event, QDict 
*qdict)
 
 trace_monitor_protocol_event_emit(event, qdict);
 QLIST_FOREACH(mon, &mon_list, entry) {
-if (monitor_is_qmp(mon) && mon->qmp.in_command_mode) {
+if (monitor_is_qmp(mon)
+&& mon->qmp.commands != &qmp_cap_negotiation_commands) {
 monitor_json_emitter(mon, QOBJECT(qdict));
 }
 }
@@ -565,11 +566,6 @@ static void monitor_qapi_event_init(void)
 qmp_event_set_func_emit(monitor_qapi_event_queue);
 }
 
-void qmp_qmp_capabilities(Error **errp)
-{
-cur_mon->qmp.in_command_mode = true;
-}
-
 static void handle_hmp_command(Monitor *mon, const char *cmdline);
 
 static void monitor_data_init(Monitor *mon)
@@ -921,7 +917,7 @@ CommandInfoList *qmp_query_commands(Error **errp)
 {
 CommandInfoList *list = NULL;
 
-qmp_for_each_command(&qmp_commands, query_commands_cb, &list);
+qmp_for_each_command(cur_mon->qmp.commands, query_commands_cb, &list);
 
 return list;
 }
@@ -1001,6 +997,13 @@ static void qmp_unregister_commands_hack(void)
 
 void monitor_init_qmp_commands(void)
 {
+/*
+ * Two command lists:
+ * - qmp_commands contains all QMP commands
+ * - qmp_cap_negotiation_commands contains just
+ *   "qmp_capabilities", to enforce capability negotiation
+ */
+
 qmp_init_marshal(&qmp_commands);
 
 qmp_register_command(&qmp_commands, "query-qmp-schema",
@@ -1012,6 +1015,22 @@ void monitor_init_qmp_commands(void)
  QCO_NO_OPTIONS);
 
 qmp_unregister_commands_hack();
+
+QTAILQ_INIT(&qmp_cap_negotiation_commands);
+qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
+ qmp_marshal_qmp_capabilities, QCO_NO_OPTIONS);
+}
+
+void qmp_qmp_capabilities(Error **errp)
+{
+if (cur_mon->qmp.commands == &qmp_commands) {
+error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
+  "Capabilities negotiation is already complete, command "
+  "ignored");
+return;
+}
+
+cur_mon->qmp.commands = &qmp_commands;
 }
 
 /* set the current CPU defined by the user */
@@ -3681,26 +3700,6 @@ static int monitor_can_read(void *opaque)
 return (mon->suspend_cnt == 0) ? 1 : 0;
 }
 
-static bool invalid_qmp_mode(const Monitor *mon, const char *cmd,
- Error **errp)
-{
-bool is_cap = g_str_equal(cmd, "qmp_capabilities");
-
-if (is_cap && mon->qmp.in_command_mode) {
-error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
-  "Capabilities negotiation is already complete, command "
-  "'%s' ignored", cmd);
-return true;
-}
-if (!is_cap && !mon->qmp.in_command_mode) {
-error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
-  "Expecting capabilities negotiation with "
-  "'qmp_capabilities' before command '%s'", cmd);
-return true;
-}
-return false;
-}
-
 /*
  * Input object checking rules
  *
@@ -3786,11 +3785,20 @@ static void handle_qmp_command(JSONMessageParser 
*parser, GQueue *toke

[Qemu-devel] [PULL v2 11/27] qapi: Clean up after commit 3d344c2

2017-03-05 Thread Markus Armbruster
Drop unused QIV_STACK_SIZE and unused qobject_input_start_struct()
parameter errp.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <1488544368-30622-13-git-send-email-arm...@redhat.com>
---
 qapi/qobject-input-visitor.c | 14 +++---
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index f3b6713..2c2f883 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -21,8 +21,6 @@
 #include "qapi/qmp/types.h"
 #include "qapi/qmp/qerror.h"
 
-#define QIV_STACK_SIZE 1024
-
 typedef struct StackObject
 {
 QObject *obj; /* Object being visited */
@@ -103,8 +101,7 @@ static void qdict_add_key(const char *key, QObject *obj, 
void *opaque)
 }
 
 static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv,
-QObject *obj, void *qapi,
-Error **errp)
+QObject *obj, void *qapi)
 {
 GHashTable *h;
 StackObject *tos = g_new0(StackObject, 1);
@@ -170,7 +167,6 @@ static void qobject_input_start_struct(Visitor *v, const 
char *name, void **obj,
 {
 QObjectInputVisitor *qiv = to_qiv(v);
 QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
-Error *err = NULL;
 
 if (obj) {
 *obj = NULL;
@@ -184,11 +180,7 @@ static void qobject_input_start_struct(Visitor *v, const 
char *name, void **obj,
 return;
 }
 
-qobject_input_push(qiv, qobj, obj, &err);
-if (err) {
-error_propagate(errp, err);
-return;
-}
+qobject_input_push(qiv, qobj, obj);
 
 if (obj) {
 *obj = g_malloc0(size);
@@ -216,7 +208,7 @@ static void qobject_input_start_list(Visitor *v, const char 
*name,
 return;
 }
 
-entry = qobject_input_push(qiv, qobj, list, errp);
+entry = qobject_input_push(qiv, qobj, list);
 if (list) {
 if (entry) {
 *list = g_malloc0(size);
-- 
2.7.4




[Qemu-devel] [PULL v2 06/27] qapi-introspect: Mangle --prefix argument properly for C

2017-03-05 Thread Markus Armbruster
qapi-introspect.py --prefix hasn't been used so far, but fix it anyway.

Signed-off-by: Markus Armbruster 
Message-Id: <1488544368-30622-7-git-send-email-arm...@redhat.com>
[Commit message improved]
Reviewed-by: Eric Blake 
---
 scripts/qapi-introspect.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 541644e..fb72c61 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -64,7 +64,7 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
 # generate C
 # TODO can generate awfully long lines
 jsons.extend(self._jsons)
-name = prefix + 'qmp_schema_json'
+name = c_name(prefix, protect=False) + 'qmp_schema_json'
 self.decl = mcgen('''
 extern const char %(c_name)s[];
 ''',
-- 
2.7.4




Re: [Qemu-devel] [PATCH v4 25/28] qapi: Make input visitors detect unvisited list tails

2017-03-05 Thread Markus Armbruster
Eric Blake  writes:

> On 03/03/2017 01:50 PM, Markus Armbruster wrote:
>> Eric Blake  writes:
>> 
>>> On 03/03/2017 06:32 AM, Markus Armbruster wrote:
 Fix the design flaw demonstrated in the previous commit: new method
 check_list() lets input visitors report that unvisited input remains
 for a list, exactly like check_struct() lets them report that
 unvisited input remains for a struct or union.

 Implement the method for the qobject input visitor (straightforward),
 and the string input visitor (less so, due to the magic list syntax
 there).  The opts visitor's list magic is even more impenetrable, and
 all I can do there today is a stub with a FIXME comment.  No worse
 than before.

 Signed-off-by: Markus Armbruster 
 ---
>>>
>>> Didn't I already review this one?
>>>
>>> Ah, there's my R-b:
>>> https://lists.gnu.org/archive/html/qemu-devel/2017-02/msg07614.html
>> 
>
 
 --- a/qapi/qobject-input-visitor.c
 +++ b/qapi/qobject-input-visitor.c
 @@ -51,7 +51,8 @@ static QObjectInputVisitor *to_qiv(Visitor *v)
  return container_of(v, QObjectInputVisitor, visitor);
  }
  
 -static const char *full_name(QObjectInputVisitor *qiv, const char *name)
 +static const char *full_name_nth(QObjectInputVisitor *qiv, const char 
 *name,
 + int n)
  {
>
> No function comment, so the _nth and int n are guesses on their meaning...
>
>
>>> If I'm reading this right, your use of n-- in the loop followed by the
>>> post-condition is to assert that QSLIST_FOREACH() iterated n times, but
>>> lets see what callers pass for n:
>> 
>> At least @n times.
>
> Ah, as in 'use first available result' or 'iterate at least once', based
> on our callers, but could also mean 'iterate at least twice' for a
> caller that passes 2.
>
>
>>> the other passes 1.  No other calls.  Did we really need an integer,
>>> where we use n--, or would a bool have done as well?
>> 
>> Since I actually use only 0 and 1, a bool would do, but would it make
>> the code simpler?
>
> I don't know that a bool would be any simpler,
>
>> 
>>> At any rate, since I've already reviewed it once, you can add R-b, but
>>> we may want a followup to make it less confusing.
>> 
>> Would renaming the function to full_name_but_n() help?
>
> Or even keep the name unchanged, but add function comments describing
> what 'n' means.

Makes sense.  I'll do it on top to avoid delaying merge of this series
and the other stuff that depends on it.



  1   2   >