Re: [Qemu-devel] [PATCH] exec: Stop using memory after free

2015-12-02 Thread Don Slutz


On 12/01/15 04:52, Paolo Bonzini wrote:
> 
> 
> On 30/11/2015 23:11, Don Slutz wrote:
>> memory_region_unref(mr) can free memory.
>>
>> For example I got:
>>
>> Program received signal SIGSEGV, Segmentation fault.
>> [Switching to Thread 0x7f43280d4700 (LWP 4462)]
>> 0x7f43323283c0 in phys_section_destroy (mr=0x7f43259468b0)
>> at /home/don/xen/tools/qemu-xen-dir/exec.c:1023
>> 1023if (mr->subpage) {
>> (gdb) bt
>> at /home/don/xen/tools/qemu-xen-dir/exec.c:1023
>> at /home/don/xen/tools/qemu-xen-dir/exec.c:1034
>> at /home/don/xen/tools/qemu-xen-dir/exec.c:2205
>> (gdb) p mr
>> $1 = (MemoryRegion *) 0x7f43259468b0
>>
>> And this change prevents this.
> 
> Great, thanks!  I think this fixes also the problem that Gonglei was
> seeing a few months ago.  I'll queue it for 2.5.
> 

Thanks.

> BTW, since I have your attention, have you noticed my refresh/rewrite of
> your SAS1068 patches?  A review would be welcome.
> 

It has been on the list of things to do.  Since I no longer work for
Verizon, it is now a non-work time event.  I also not longer have access
to the testing machines that I had used.

   -Don Slutz

> Paolo
> 
>> Signed-off-by: Don Slutz <don.sl...@gmail.com>
>> ---
>>  exec.c | 4 +++-
>>  1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/exec.c b/exec.c
>> index de1cf19..0bf0a6e 100644
>> --- a/exec.c
>> +++ b/exec.c
>> @@ -1064,9 +1064,11 @@ static uint16_t phys_section_add(PhysPageMap *map,
>>  
>>  static void phys_section_destroy(MemoryRegion *mr)
>>  {
>> +bool have_sub_page = mr->subpage;
>> +
>>  memory_region_unref(mr);
>>  
>> -if (mr->subpage) {
>> +if (have_sub_page) {
>>  subpage_t *subpage = container_of(mr, subpage_t, iomem);
>>  object_unref(OBJECT(>iomem));
>>  g_free(subpage);
>>



Re: [Qemu-devel] [PATCH] exec: Stop using memory after free

2015-12-02 Thread Don Slutz
On 12/02/15 04:47, Paolo Bonzini wrote:
> 
> 
> On 02/12/2015 08:59, Gonglei (Arei) wrote:
>>>>>  static void phys_section_destroy(MemoryRegion *mr)  {
>>>>> +bool have_sub_page = mr->subpage;
>>>>> +
>>>>>  memory_region_unref(mr);
>>>>>
>>>>> -if (mr->subpage) {
>>>>> +if (have_sub_page) {
>>>>>  subpage_t *subpage = container_of(mr, subpage_t, iomem);
>>
>> Can we use the *mr* here again?
> 
> Yes, in the subpage case the memory is allocated by exec.c.  Accessing
> mr->subpage is only problematic if memory_region_unref destroys a device.
> 

My memory of debugging this in June, was that when ever subpage is true
the reference count on the mr was greater then (>2?) so that after the
call on memory_region_unref(mr), the reference count on the mr was still
non-zero and so g_free() was not called.

>> IMO we should invoke memory_region_unref(mr) after the if check.
> 
> That's also possible.

My attempts to do so all failed, maybe coding bugs.  At that time I came
up with the patch:

commit 475d53a44933171222516689ae00e7fad5a8bf69
Author: Don Slutz <dsl...@verizon.com>
Date:   Sat Jun 6 10:13:08 2015 -0400

exec: Do not use MemoryRegion after free

Here is gdb output that shows this happening:

  Breakpoint 3, object_finalize (data=0x7fdf32a14010) at
qom/object.c:417
  417 obj->free(obj);
  (gdb) bt
  #0  object_finalize (data=0x7fdf32a14010) at qom/object.c:417
  #1  0x007329d4 in object_unref (obj=0x7fdf32a14010) at
qom/object.c:720
  #2  0x00468a65 in memory_region_unref (mr=0x7fdf32a168b0)
at /home/don/xen/tools/qemu-xen-dir/memory.c:1359
  #3  0x0040eb52 in phys_section_destroy (mr=0x7fdf32a168b0)
at /home/don/xen/tools/qemu-xen-dir/exec.c:960
  #4  0x0040ec0a in phys_sections_free (map=0x3e51fc8) at
/home/don/xen/tools/qemu-xen-dir/exec.c:973
  #5  0x00411cc9 in address_space_dispatch_free
(d=0x3e51fb0) at /home/don/xen/tools/qemu-xen-dir/exec.c:2133
  #6  0x00840ae2 in call_rcu_thread (opaque=0x0) at
util/rcu.c:256
  #7  0x0032fdc07d14 in start_thread (arg=0x7fdf34866700) at
pthread_create.c:309
  #8  0x0032fd4f168d in clone () at
../sysdeps/unix/sysv/linux/x86_64/clone.S:115
  (gdb) p obj
  $5 = (Object *) 0x7fdf32a14010
  (gdb) p *obj
  $6 = {class = 0x302f380, free = 0x40a1e0 <g_free@plt>, properties
= {tqh_first = 0x0, tqh_last = 0x7fdf32a14020},
  ref = 0, parent = 0x0}
  (gdb) up
  #1  0x007329d4 in object_unref (obj=0x7fdf32a14010) at
qom/object.c:720
  720 object_finalize(obj);
  (gdb) up
  #2  0x00468a65 in memory_region_unref (mr=0x7fdf32a168b0)
at /home/don/xen/tools/qemu-xen-dir/memory.c:1359
  1359object_unref(obj->parent);
  (gdb) up
  #3  0x0040eb52 in phys_section_destroy (mr=0x7fdf32a168b0)
at /home/don/xen/tools/qemu-xen-dir/exec.c:960
  960 memory_region_unref(mr);
  (gdb) l
  955 return map->sections_nb++;
  956 }
  957
  958 static void phys_section_destroy(MemoryRegion *mr)
  959 {
  960 memory_region_unref(mr);
  961
  962 if (mr->subpage) {
  963 subpage_t *subpage = container_of(mr, subpage_t,
iomem);
  964 object_unref(OBJECT(>iomem));
  (gdb) p mr
  $7 = (MemoryRegion *) 0x7fdf32a168b0
  (gdb) p mr->subpage
  $9 = false
  (gdb) n
  419 }
  (gdb) n
  object_unref (obj=0x7fdf32a14010) at qom/object.c:722
  722 }
  (gdb) n
  memory_region_unref (mr=0x7fdf32a168b0) at
/home/don/xen/tools/qemu-xen-dir/memory.c:1363
  1363}
  (gdb) n
  phys_section_destroy (mr=0x7fdf32a168b0) at
/home/don/xen/tools/qemu-xen-dir/exec.c:962
  962 if (mr->subpage) {
  (gdb) p mr
  $10 = (MemoryRegion *) 0x7fdf32a168b0
  (gdb) p *mr
  Cannot access memory at address 0x7fdf32a168b0

Signed-off-by: Don Slutz <dsl...@verizon.com>

diff --git a/exec.c b/exec.c
index f7883d2..b4be5d9 100644
--- a/exec.c
+++ b/exec.c
@@ -958,10 +958,14 @@ static uint16_t phys_section_add(PhysPageMap *map,

 static void phys_section_destroy(MemoryRegion *mr)
 {
-memory_region_unref(mr);
+subpage_t *subpage = NULL;

 if (mr->subpage) {
-subpage_t *subpage = container_of(mr, subpage_t, iomem);
+subpage = container_of(mr, subpage_t, iomem);
+}
+memory_region_unref(mr);
+
+if (subpage) {
 object_unref(OBJECT(>iomem));
 g_free(subpage);
 }

which never got posted do to external events.  When I hit this again, I
was able to remember enough to generate this patch from scratch.  I only
found this patch when reading this email thread.

   -Don Slutz
P.S. I no longer work for verizon, and so the email address above no
longer works.


> 
> Paolo
> 



[Qemu-devel] [PATCH] exec: Stop using memory after free

2015-11-30 Thread Don Slutz
memory_region_unref(mr) can free memory.

For example I got:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7f43280d4700 (LWP 4462)]
0x7f43323283c0 in phys_section_destroy (mr=0x7f43259468b0)
at /home/don/xen/tools/qemu-xen-dir/exec.c:1023
1023if (mr->subpage) {
(gdb) bt
at /home/don/xen/tools/qemu-xen-dir/exec.c:1023
at /home/don/xen/tools/qemu-xen-dir/exec.c:1034
at /home/don/xen/tools/qemu-xen-dir/exec.c:2205
(gdb) p mr
$1 = (MemoryRegion *) 0x7f43259468b0

And this change prevents this.

Signed-off-by: Don Slutz <don.sl...@gmail.com>
---
 exec.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/exec.c b/exec.c
index de1cf19..0bf0a6e 100644
--- a/exec.c
+++ b/exec.c
@@ -1064,9 +1064,11 @@ static uint16_t phys_section_add(PhysPageMap *map,
 
 static void phys_section_destroy(MemoryRegion *mr)
 {
+bool have_sub_page = mr->subpage;
+
 memory_region_unref(mr);
 
-if (mr->subpage) {
+if (have_sub_page) {
 subpage_t *subpage = container_of(mr, subpage_t, iomem);
 object_unref(OBJECT(>iomem));
 g_free(subpage);
-- 
1.8.3.1




Re: [Qemu-devel] [PATCH v8 8/8] vmport: Add VMware all ring hack

2015-07-29 Thread Don Slutz

On 7/5/2015 2:40 AM, Michael S. Tsirkin wrote:

On Fri, Jul 03, 2015 at 03:50:19PM +0200, Paolo Bonzini wrote:


On 03/07/2015 15:08, Don Slutz wrote:

Creating it at the pc level and propagating makes code
messy but I'd go along with it if it made sense from
user's point of view, but it does not seem to make sense:
to me this looks more like a CPU feature than a machine property.
Or the property of the vmport rpc device that you created.

Well this is not a clear area.  It does look more like a CPU feature.  I
went with a machine feature because that is where vmport currently is.

I think it should be a vmport property.

It would be cleaner to implement it using the MemTxAttrs mechanism, but
for KVM I'm afraid it would be too slow (and the slowness would affect
all I/O accesses, not just vmport ones, unless really ugly hacks are done).

Paolo

Can it ever be implemented for kvm? I couldn't think of a clean way to do it.



I do not know of a clean way.  For Xen I need to enable #GP fault 
reporting and add code to check in/out to the magic VMware port.  I 
would assume that some thing similar would be needed in kvm.  Hope this 
helps.


   -Don Slutz




Re: [Qemu-devel] [PATCH v8 8/8] vmport: Add VMware all ring hack

2015-07-03 Thread Don Slutz

On 07/01/15 02:50, Michael S. Tsirkin wrote:

On Tue, Jun 23, 2015 at 07:39:33PM -0400, Don Slutz wrote:

From: Don Slutz dsl...@verizon.com

This is done by adding a new machine property vmware-port-ring3 that
needs to be enabled to have any effect.  It only effects accel=tcg
mode.  It is needed if you want to use VMware tools in accel=tcg
mode.

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com

IMO this patch isn't ready yet.


---
  hw/i386/pc.c | 26 +-
  hw/i386/pc_piix.c|  2 +-
  hw/i386/pc_q35.c |  2 +-
  include/hw/i386/pc.h |  6 +-
  target-i386/cpu-qom.h|  3 +++
  target-i386/seg_helper.c |  9 +
  6 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 7072930..3ae4476 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1042,7 +1042,9 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
  object_unref(OBJECT(cpu));
  }
  
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)

+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+  bool vmware_port_ring3)
  {
  int i;
  X86CPU *cpu = NULL;
@@ -1073,6 +1075,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState 
*icc_bridge)
  error_report_err(error);
  exit(1);
  }
+cpu-allow_vmport_ring3 = vmware_port_ring3;
  object_unref(OBJECT(cpu));
  }
  
@@ -1835,6 +1838,21 @@ static bool pc_machine_get_aligned_dimm(Object *obj, Error **errp)

  return pcms-enforce_aligned_dimm;
  }
  
+static bool pc_machine_get_vmware_port_ring3(Object *obj, Error **errp)

+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+return pcms-vmware_port_ring3;
+}
+
+static void pc_machine_set_vmware_port_ring3(Object *obj, bool value,
+ Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+pcms-vmware_port_ring3 = value;
+}
+
  static void pc_machine_initfn(Object *obj)
  {
  PCMachineState *pcms = PC_MACHINE(obj);
@@ -1865,6 +1883,12 @@ static void pc_machine_initfn(Object *obj)
  object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM,
   pc_machine_get_aligned_dimm,
   NULL, NULL);
+
+pcms-vmware_port_ring3 = false;
+object_property_add_bool(obj, PC_MACHINE_VMWARE_PORT_RING3,
+ pc_machine_get_vmware_port_ring3,
+ pc_machine_set_vmware_port_ring3,
+ NULL);

New properties should have a description.


Ok.





  }
  
  static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index)

diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index e142f75..890c45e 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -146,7 +146,7 @@ static void pc_init1(MachineState *machine)
  object_property_add_child(qdev_get_machine(), icc-bridge,
OBJECT(icc_bridge), NULL);
  
-pc_cpus_init(machine-cpu_model, icc_bridge);

+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
  
  if (kvm_enabled()  kvmclock_enabled) {

  kvmclock_create();
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 082cd93..8288a5f 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -137,7 +137,7 @@ static void pc_q35_init(MachineState *machine)
  object_property_add_child(qdev_get_machine(), icc-bridge,
OBJECT(icc_bridge), NULL);
  
-pc_cpus_init(machine-cpu_model, icc_bridge);

+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
  pc_acpi_init(q35-acpi-dsdt.aml);
  
  kvmclock_create();

diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 3270a97..f9e74c7 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -40,6 +40,7 @@ struct PCMachineState {
  
  uint64_t max_ram_below_4g;

  OnOffAuto vmport;
+bool vmware_port_ring3;
  bool enforce_aligned_dimm;
  };
  
@@ -48,6 +49,7 @@ struct PCMachineState {

  #define PC_MACHINE_MAX_RAM_BELOW_4G max-ram-below-4g
  #define PC_MACHINE_VMPORT   vmport
  #define PC_MACHINE_ENFORCE_ALIGNED_DIMM enforce-aligned-dimm
+#define PC_MACHINE_VMWARE_PORT_RING3 vmware-port-ring3
  
  /**

   * PCMachineClass:

Creating it at the pc level and propagating makes code
messy but I'd go along with it if it made sense from
user's point of view, but it does not seem to make sense:
to me this looks more like a CPU feature than a machine property.
Or the property of the vmport rpc device that you created.


Well this is not a clear area.  It does look more like a CPU feature.  I 
went with a machine feature because that is where vmport currently is.





If it's required for the rpc device to be used -
why not set this unconditionally if the rpc device

Re: [Qemu-devel] [PATCH v8 6/8] vmport_rpc: Add QMP access to vmport_rpc object.

2015-07-03 Thread Don Slutz

On 07/02/15 10:11, Markus Armbruster wrote:

Don Slutz don.sl...@gmail.com writes:


From: Don Slutz dsl...@verizon.com

This adds one new inject command:

inject-vmport-action

And three guest info commands:

vmport-guestinfo-set
vmport-guestinfo-get
query-vmport-guestinfo

More details in qmp-commands.hx

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com

Reviewing only the QAPI/QMP interface, plus a bit of drive-by shooting.


diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index f157425..917898b 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -178,6 +178,19 @@ typedef struct VMPortRpcState {
  #endif
  } VMPortRpcState;
  
+typedef int FindVMPortRpcDeviceFunc(VMPortRpcState *s, const void *arg);

+
+/*
+ * The input and output argument that find_VMPortRpc_device() uses
+ * to do its work.
+ */
+typedef struct VMPortRpcFind {
+const void *arg;
+FindVMPortRpcDeviceFunc *func;
+int found;
+int rc;
+} VMPortRpcFind;
+
  /* Basic request types */
  typedef enum {
  MESSAGE_TYPE_OPEN,
@@ -202,6 +215,56 @@ typedef struct {
  uint32_t edi;
  } vregs;
  
+/*

+ * Run func() for every VMPortRpc device, traverse the tree for
+ * everything else.
+ */
+static int find_VMPortRpc_device(Object *obj, void *opaque)
+{
+VMPortRpcFind *find = opaque;
+Object *dev;
+VMPortRpcState *s;
+
+assert(find);
+if (find-found) {
+return 0;
+}
+dev = object_dynamic_cast(obj, TYPE_VMPORT_RPC);
+s = (VMPortRpcState *)dev;
+
+if (!s) {
+/* Container, traverse it for children */
+return object_child_foreach(obj, find_VMPortRpc_device, opaque);
+}
+
+find-found++;
+find-rc = find-func(s, find-arg);
+
+return 0;
+}
+
+/*
+ * Loop through all dynamically created VMPortRpc devices and call
+ * func() for each instance.
+ */
+static int foreach_dynamic_vmport_rpc_device(FindVMPortRpcDeviceFunc *func,
+ const void *arg)
+{
+VMPortRpcFind find = {
+.func = func,
+.arg = arg,
+};
+
+/* Loop through all VMPortRpc devices that were spawned outside
+ * the machine */
+find_VMPortRpc_device(qdev_get_machine(), find);
+if (find.found) {
+return find.rc;
+} else {
+return VMPORT_DEVICE_NOT_FOUND;
+}
+}
+
  #ifdef VMPORT_RPC_DEBUG
  /*
   * Add helper function for tracing.  This routine will convert
@@ -329,7 +392,7 @@ static int vmport_rpc_send(VMPortRpcState *s, channel_t *c,
  return rc;
  }
  
-static int vmport_rpc_ctrl_send(VMPortRpcState *s, char *msg)

+static int vmport_rpc_ctrl_send(VMPortRpcState *s, const char *msg)
  {
  int rc = SEND_NOT_OPEN;
  unsigned int i;
@@ -457,6 +520,29 @@ static int get_guestinfo(VMPortRpcState *s,
  return GUESTINFO_NOTFOUND;
  }
  
+static int get_qmp_guestinfo(VMPortRpcState *s,

+ unsigned int a_key_len, const char *a_info_key,
+ unsigned int *a_value_len, void **a_value_data)
+{
+guestinfo_t *gi = NULL;
+
+if (a_key_len = MAX_KEY_LEN) {
+gpointer key = g_strndup(a_info_key, a_key_len);
+
+gi = (guestinfo_t *)g_hash_table_lookup(s-guestinfo, key);
+g_free(key);
+} else {
+return GUESTINFO_KEYTOOLONG;
+}
+if (gi) {
+*a_value_len = gi-val_len;
+*a_value_data = gi-val_data;
+return 0;
+}
+
+return GUESTINFO_NOTFOUND;
+}
+
  static int set_guestinfo(VMPortRpcState *s, int a_key_len,
   unsigned int a_val_len, const char *a_info_key,
   char *val)
@@ -775,7 +861,7 @@ static void vmport_rpc(VMPortRpcState *s , vregs *ur)
  }
  if (delta  s-reset_time) {
  trace_vmport_rpc_ping(delta);
-vmport_rpc_ctrl_send(s, (char *)reset);
+vmport_rpc_ctrl_send(s, reset);
  }
  vmport_rpc_sweep(s, now_time);
  do {
@@ -848,6 +934,206 @@ static uint32_t vmport_rpc_ioport_read(void *opaque, 
uint32_t addr)
  return ur.data[0];
  }
  
+static int vmport_rpc_find_send(VMPortRpcState *s, const void *arg)

+{
+return vmport_rpc_ctrl_send(s, arg);
+}
+
+static void convert_local_rc(Error **errp, int rc)
+{
+switch (rc) {
+case 0:
+break;
+case VMPORT_DEVICE_NOT_FOUND:
+error_set(errp, QERR_DEVICE_NOT_FOUND, TYPE_VMPORT_RPC);
+break;

Conflicts with

commit 75158ebbe259f0bd8bf435e8f4827a43ec89c877
Author: Markus Armbruster arm...@redhat.com
Date:   Mon Mar 16 08:57:47 2015 +0100

 qerror: Eliminate QERR_DEVICE_NOT_FOUND
 
 Error classes other than ERROR_CLASS_GENERIC_ERROR should not be used

 in new code.  Hiding them in QERR_ macros makes new uses hard to spot.
 Fortunately, there's just one such macro left.  Eliminate it with this
 coccinelle semantic patch:
 
 @@

 expression EP, E;
 @@
 -error_set(EP, QERR_DEVICE_NOT_FOUND, E

Re: [Qemu-devel] [PATCH v8 6/8] vmport_rpc: Add QMP access to vmport_rpc object.

2015-07-03 Thread Don Slutz

On 07/03/15 13:56, Markus Armbruster wrote:

Don Slutz don.sl...@gmail.com writes:


On 07/02/15 10:11, Markus Armbruster wrote:

Don Slutz don.sl...@gmail.com writes:


From: Don Slutz dsl...@verizon.com

This adds one new inject command:

inject-vmport-action

And three guest info commands:

vmport-guestinfo-set
vmport-guestinfo-get
query-vmport-guestinfo

More details in qmp-commands.hx

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com

Reviewing only the QAPI/QMP interface, plus a bit of drive-by shooting.


diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index f157425..917898b 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -178,6 +178,19 @@ typedef struct VMPortRpcState {
   #endif
   } VMPortRpcState;
   +typedef int FindVMPortRpcDeviceFunc(VMPortRpcState *s, const
void *arg);
+
+/*
+ * The input and output argument that find_VMPortRpc_device() uses
+ * to do its work.
+ */
+typedef struct VMPortRpcFind {
+const void *arg;
+FindVMPortRpcDeviceFunc *func;
+int found;
+int rc;
+} VMPortRpcFind;
+
   /* Basic request types */
   typedef enum {
   MESSAGE_TYPE_OPEN,
@@ -202,6 +215,56 @@ typedef struct {
   uint32_t edi;
   } vregs;
   +/*
+ * Run func() for every VMPortRpc device, traverse the tree for
+ * everything else.
+ */
+static int find_VMPortRpc_device(Object *obj, void *opaque)
+{
+VMPortRpcFind *find = opaque;
+Object *dev;
+VMPortRpcState *s;
+
+assert(find);
+if (find-found) {
+return 0;
+}
+dev = object_dynamic_cast(obj, TYPE_VMPORT_RPC);
+s = (VMPortRpcState *)dev;
+
+if (!s) {
+/* Container, traverse it for children */
+return object_child_foreach(obj, find_VMPortRpc_device, opaque);
+}
+
+find-found++;
+find-rc = find-func(s, find-arg);
+
+return 0;
+}
+
+/*
+ * Loop through all dynamically created VMPortRpc devices and call
+ * func() for each instance.
+ */
+static int foreach_dynamic_vmport_rpc_device(FindVMPortRpcDeviceFunc *func,
+ const void *arg)
+{
+VMPortRpcFind find = {
+.func = func,
+.arg = arg,
+};
+
+/* Loop through all VMPortRpc devices that were spawned outside
+ * the machine */
+find_VMPortRpc_device(qdev_get_machine(), find);
+if (find.found) {
+return find.rc;
+} else {
+return VMPORT_DEVICE_NOT_FOUND;
+}
+}
+
   #ifdef VMPORT_RPC_DEBUG
   /*
* Add helper function for tracing.  This routine will convert
@@ -329,7 +392,7 @@ static int vmport_rpc_send(VMPortRpcState *s, channel_t *c,
   return rc;
   }
   -static int vmport_rpc_ctrl_send(VMPortRpcState *s, char *msg)
+static int vmport_rpc_ctrl_send(VMPortRpcState *s, const char *msg)
   {
   int rc = SEND_NOT_OPEN;
   unsigned int i;
@@ -457,6 +520,29 @@ static int get_guestinfo(VMPortRpcState *s,
   return GUESTINFO_NOTFOUND;
   }
   +static int get_qmp_guestinfo(VMPortRpcState *s,
+ unsigned int a_key_len, const char *a_info_key,
+ unsigned int *a_value_len, void **a_value_data)
+{
+guestinfo_t *gi = NULL;
+
+if (a_key_len = MAX_KEY_LEN) {
+gpointer key = g_strndup(a_info_key, a_key_len);
+
+gi = (guestinfo_t *)g_hash_table_lookup(s-guestinfo, key);
+g_free(key);
+} else {
+return GUESTINFO_KEYTOOLONG;
+}
+if (gi) {
+*a_value_len = gi-val_len;
+*a_value_data = gi-val_data;
+return 0;
+}
+
+return GUESTINFO_NOTFOUND;
+}
+
   static int set_guestinfo(VMPortRpcState *s, int a_key_len,
unsigned int a_val_len, const char *a_info_key,
char *val)
@@ -775,7 +861,7 @@ static void vmport_rpc(VMPortRpcState *s , vregs *ur)
   }
   if (delta  s-reset_time) {
   trace_vmport_rpc_ping(delta);
-vmport_rpc_ctrl_send(s, (char *)reset);
+vmport_rpc_ctrl_send(s, reset);
   }
   vmport_rpc_sweep(s, now_time);
   do {
@@ -848,6 +934,206 @@ static uint32_t vmport_rpc_ioport_read(void *opaque, 
uint32_t addr)
   return ur.data[0];
   }
   +static int vmport_rpc_find_send(VMPortRpcState *s, const void
*arg)
+{
+return vmport_rpc_ctrl_send(s, arg);
+}
+
+static void convert_local_rc(Error **errp, int rc)
+{
+switch (rc) {
+case 0:
+break;
+case VMPORT_DEVICE_NOT_FOUND:
+error_set(errp, QERR_DEVICE_NOT_FOUND, TYPE_VMPORT_RPC);
+break;

Conflicts with

commit 75158ebbe259f0bd8bf435e8f4827a43ec89c877
Author: Markus Armbruster arm...@redhat.com
Date:   Mon Mar 16 08:57:47 2015 +0100

  qerror: Eliminate QERR_DEVICE_NOT_FOUND
   Error classes other than ERROR_CLASS_GENERIC_ERROR should
not be used
  in new code.  Hiding them in QERR_ macros makes new uses hard to spot.
  Fortunately, there's just one such macro left.  Eliminate it with this
  coccinelle semantic

Re: [Qemu-devel] [ping][PATCH v8 0/8] Add limited support of VMware's hyper-call rpc

2015-06-30 Thread Don Slutz

Ping

On 06/23/15 19:39, Don Slutz wrote:

Changes v7 to v8:
   Rebase to master

   Drop patch #1 since commit 965eb2fcdfe919ecced6c34803535ad32dc1249c
   fixed this.

   Paolo Bonzini
 Ok to pull v7 1,2,3, and 9.
   Added Acked-by: Paolo Bonzini pbonz...@redhat.com
   Moved v7 #9 to v8 #3

   Eric Blake
 s/it's/its/
   Done
 No space after **.
   Done
 Don't know if any static checkers will complain about the break being
 dead code.
   Dropped break since this is the last case.
 Would it help if struct keyValue declared 'const char *key_data'?
   It does, so switch to this.
 This cast is spurious (foreach_dynamic_vmport_rpc_device)
   Dropped all casts using this routine.
 Do you want g_malloc0, or g_new0?
   Switched to g_new0.
 Adjust /* FIXME should check for...
   Added Or cause an error to be raised.

   Michael S. Tsirkin
 To me it looks like this will break cross-version migration
   Dropped code to always add the new device.
   Add code to check for vmport enabled.
 Quite possibly but personally I'm confused.
   No partial PULL request sent.


Changes v6 to v7:
   Rebase to master

   Fixed a bug caused by commit c3c1bb99d1c11978d9ce94d1bdcf0705378c1459 now 
patch #1

   Added patch #2 to switch to using trace in vm,port.c.

   Delay call on g_strndup till after key length check.

   Switched e-mail address in MAINTAINERS.

   Eric Blake
 Why not assert(find) instead of leaving it to the comment?
   Switch to assert.
 Is it worth marking arg const here and in the VMPortRpcFind struct
   Switch to const.
 I'd rather abort() if someone compiled with -NDEBUG
   Done.
 Still mismatches on  line length (several sites).
   Done


Changes v5 to v6:

   Rebase to master

   Eric Blake
 Returning a non-dictionary is not extensible.
   Added new type VmportGuestInfoValue.
   s/VmportGuestInfo/VmportGuestInfoKey/
   s/type/struct/
 Issues with examples
   Fixed.


Changes v4 to v5:

   Paolo Bonzini
 What is VMPORT_SHORT about?
   Dropped this.
 Why not use a bool in CPUX86State?
   Took his sugestion and moved to a bool in X86CPU.

Changes v3 to v4:

   Paolo Bonzini on vmort_rpc: Add QMP access to vmport_rpc
 Does this compile on non-x86 targets?
   Nope.  Fixed.

Changes v2 to v3:

   s/2.3/2.4

Changes v1 to v2:

Added live migration code.
Adjust data structures for migration.
Switch to GHashTable.

   Eric Blake
 s/spawened/spawned/
   Done
 s/traceing/tracing/
   Done
 Change error_set(errp, ERROR_CLASS_GENERIC_ERROR,  to
 error_setg(errp, 
   Done
 Why two commands (inject-vmport-reboot, inject-vmport-halt)?
   Switched to inject-vmport-action.
 format=base64 bug statements.
   Dropped.

Much more on format=base64:

If there is a bug it is in GLIB.  However the Glib reference manual
refers to RFC 1421 and RFC 2045 and MIME encoding.  Based on all
that (which seems to match:

http://en.wikipedia.org/wiki/Base64

) MIME states that all characters outside the (base64) alphabet are
to be ignored.  Testing shows that g_base64_decode() does this.

The confusion is that most non-MIME uses reject a base64 string that
contain characters outside the alphabet.  I was just following the
other uses of base64 in this file.

DataFormat refers to RFC 3548, which has the info:


Implementations MUST reject the encoding if it contains
characters outside the base alphabet when interpreting base
encoded data, unless the specification referring to this document
explicitly states otherwise.  Such specifications may, as MIME
does, instead state that characters outside the base encoding
alphabet should simply be ignored when interpreting data (be
liberal in what you accept).


So with GLIB going the MIME way, I do not think this is a QEMU bug
(you could consider this a GLIB bug, but the document I found says
that GLIB goes the MIME way and so does not reject anything).

---


The support included is enough to allow VMware tools to install in a
guest and provide guestinfo support.  guestinfo support is provided
by what is known as VMware RPC support.

One of the better on-line references is:

https://sites.google.com/site/chitchatvmback/backdoor

As a place to get more accurate information by studying:

http://open-vm-tools.sourceforge.net/

With vmware tools installed, you can do:

---
Last login: Fri Jan 30 16:03:08 2015
[root@C63-min-tools ~]# vmtoolsd --cmd info-get guestinfo.joejoel
No value found
[root@C63-min-tools ~]# vmtoolsd --cmd info-set guestinfo.joejoel bar

[root@C63-min-tools ~]# vmtoolsd --cmd info-get guestinfo.joejoel
bar
[root@C63-min-tools ~]#
---

to access guest info.  QMP access is also provided

[Qemu-devel] [PATCH v8 5/8] vmport_rpc: Add limited support of VMware's hyper-call rpc

2015-06-23 Thread Don Slutz
From: Don Slutz dsl...@verizon.com

To enable you must add -device vmport_rpc to command line.

The support included is enough to allow VMware tools to install in a
guest and provide guestinfo support.  guestinfo support is provided
by what is known as VMware RPC support.

If the guest is running VMware tools, then the build version of
the tools is also available via the property build-number-value of
the vmport_rpc object.  The build-number-time property is changed
every time the VMware tools running in the guest sends the
build version via the rpc.

The property reset-time controls how often to request them in
seconds minus 1.  The minus 1 is to handle to 0 case.  I.E. the
fastest that can be selected is every second.  The default is 4
times a minute.

The VMware RPC support includes the notion of channels that are
opened, active and closed.  All RPC messages sent via a channel
starts with normal ASCII text.  The message some times does include
binary data.

Currently there are 2 protocols defined for VMware RPC.  They
determine the direction for data flow, guest to tool stack or tool
stack to guest.

There is no provided interrupt for VMware RPC.

Getting VMPORT_RPC_DEBUG will provide a higher level trace calls
that are simpler to understand.

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 hw/misc/vmport_rpc.c | 797 ++-
 trace-events |  22 ++
 2 files changed, 818 insertions(+), 1 deletion(-)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index 3b1baea..f157425 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -40,6 +40,123 @@
 /* VMPORT RPC Command */
 #define VMPORT_RPC_COMMAND  30
 
+/* Limits on amount of non guest memory to use */
+#define MAX_KEY_LEN  128
+#define MIN_VAL_LEN  64
+#define MAX_VAL_LEN  8192
+#define MAX_NUM_KEY  256
+#define MAX_BKTS 4
+/* Max number of channels. */
+#define GUESTMSG_MAX_CHANNEL 8
+
+/*
+ * All of VMware's rpc is based on 32bit registers.  So this is the
+ * number of bytes in ebx.
+ */
+#define CHAR_PER_CALL   sizeof(uint32_t)
+/* Room for basic commands */
+#define EXTRA_SEND 22
+/* Status code and NULL */
+#define EXTRA_RECV 2
+#define MAX_SEND_BUF DIV_ROUND_UP(EXTRA_SEND + MAX_KEY_LEN + MAX_VAL_LEN, \
+  CHAR_PER_CALL)
+#define MAX_RECV_BUF DIV_ROUND_UP(EXTRA_RECV + MAX_VAL_LEN, CHAR_PER_CALL)
+#define MIN_SEND_BUF DIV_ROUND_UP(EXTRA_SEND + MAX_KEY_LEN + MIN_VAL_LEN, \
+  CHAR_PER_CALL)
+
+/* Reply statuses */
+/*  The basic request succeeded */
+#define MESSAGE_STATUS_SUCCESS  0x0001
+/*  vmware has a message available for its party */
+#define MESSAGE_STATUS_DORECV   0x0002
+/*  The channel has been closed */
+#define MESSAGE_STATUS_CLOSED   0x0004
+/*  vmware removed the message before the party fetched it */
+#define MESSAGE_STATUS_UNSENT   0x0008
+/*  A checkpoint occurred */
+#define MESSAGE_STATUS_CPT  0x0010
+/*  An underlying device is powering off */
+#define MESSAGE_STATUS_POWEROFF 0x0020
+/*  vmware has detected a timeout on the channel */
+#define MESSAGE_STATUS_TIMEOUT  0x0040
+/*  vmware supports high-bandwidth for sending and receiving the payload */
+#define MESSAGE_STATUS_HB   0x0080
+
+/* Max number of channels. */
+#define GUESTMSG_MAX_CHANNEL 8
+
+/* Flags to open a channel. */
+#define GUESTMSG_FLAG_COOKIE 0x8000
+
+/* Data to guest */
+#define VMWARE_PROTO_TO_GUEST   0x4f4c4354
+/* Data from guest */
+#define VMWARE_PROTO_FROM_GUEST 0x49435052
+
+/*
+ * Error return values used only in this file.  The routine
+ * convert_local_rc() is used to convert these to an Error
+ * object.
+ */
+#define VMPORT_DEVICE_NOT_FOUND -1
+#define SEND_NOT_OPEN   -2
+#define SEND_SKIPPED-3
+#define SEND_TRUCATED   -4
+#define SEND_NO_MEMORY  -5
+#define GUESTINFO_NOTFOUND  -6
+#define GUESTINFO_VALTOOLONG-7
+#define GUESTINFO_KEYTOOLONG-8
+#define GUESTINFO_TOOMANYKEYS   -9
+#define GUESTINFO_NO_MEMORY -10
+
+
+/* The VMware RPC guest info storage . */
+typedef struct {
+char *val_data;
+uint16_t val_len;
+uint16_t val_max;
+} guestinfo_t;
+
+/* The VMware RPC bucket control. */
+typedef struct {
+uint16_t recv_len;
+uint16_t recv_idx;
+uint16_t recv_buf_max;
+} bucket_control_t;
+
+/* The VMware RPC bucket info. */
+typedef struct {
+union {
+uint32_t *words;
+char *bytes;
+} recv;
+bucket_control_t ctl;
+} bucket_t;
+
+
+/* The VMware RPC channel control. */
+typedef struct {
+uint64_t active_time;
+uint32_t chan_id;
+uint32_t cookie;
+uint32_t proto_num;
+uint16_t send_len;
+uint16_t send_idx;
+uint16_t send_buf_max;
+uint8_t recv_read;
+uint8_t recv_write;
+} channel_control_t;
+
+/* The VMware RPC channel info. */
+typedef struct {
+union {
+uint32_t *words

[Qemu-devel] [PATCH v8 4/8] vmport_rpc: Add the object vmport_rpc

2015-06-23 Thread Don Slutz
From: Don Slutz dsl...@verizon.com

This is the 1st part of Add limited support of VMware's hyper-call
rpc.

This patch uses existing infrastructure used by vmmouse.c (provided
by vmport.c) to handle the VMware backdoor command 30.

One of the better on-line references is:

https://sites.google.com/site/chitchatvmback/backdoor

More in next patch.

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
v8:
  Dropped code to always add the new device.
  Add code to check for vmport enabled.


 hw/misc/Makefile.objs |   1 +
 hw/misc/vmport.c  |   8 ++--
 hw/misc/vmport_rpc.c  | 130 ++
 include/hw/i386/pc.h  |   2 +-
 4 files changed, 137 insertions(+), 4 deletions(-)
 create mode 100644 hw/misc/vmport_rpc.c

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 4aa76ff..e04c8ac 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -7,6 +7,7 @@ common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o
 common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o
 
 obj-$(CONFIG_VMPORT) += vmport.o
+obj-$(CONFIG_VMPORT) += vmport_rpc.o
 
 # ARM devices
 common-obj-$(CONFIG_PL310) += arm_l2x0.o
diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index 783827d..6794ecf 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -50,13 +50,15 @@ typedef struct VMPortState
 
 static VMPortState *port_state;
 
-void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque)
+bool vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque)
 {
-if (command = VMPORT_ENTRIES)
-return;
+if (command = VMPORT_ENTRIES || !port_state) {
+return false;
+}
 
 port_state-func[command] = func;
 port_state-opaque[command] = opaque;
+return true;
 }
 
 static uint64_t vmport_ioport_read(void *opaque, hwaddr addr,
diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
new file mode 100644
index 000..3b1baea
--- /dev/null
+++ b/hw/misc/vmport_rpc.c
@@ -0,0 +1,130 @@
+/*
+ * QEMU VMPORT RPC emulation
+ *
+ * Copyright (C) 2015 Verizon Corporation
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License Version 2 (GPLv2)
+ * as published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details. http://www.gnu.org/licenses/.
+ */
+
+/*
+ * One of the better on-line references is:
+ *
+ * https://sites.google.com/site/chitchatvmback/backdoor
+ *
+ * Which points you to:
+ *
+ * http://open-vm-tools.sourceforge.net/
+ *
+ * as a place to get more accurate information by studying.
+ */
+
+#include hw/hw.h
+#include hw/i386/pc.h
+#include hw/qdev.h
+#include trace.h
+#include qmp-commands.h
+#include qapi/qmp/qerror.h
+
+/* #define VMPORT_RPC_DEBUG */
+
+#define TYPE_VMPORT_RPC vmport_rpc
+#define VMPORT_RPC(obj) OBJECT_CHECK(VMPortRpcState, (obj), TYPE_VMPORT_RPC)
+
+/* VMPORT RPC Command */
+#define VMPORT_RPC_COMMAND  30
+
+/* The vmport_rpc object. */
+typedef struct VMPortRpcState {
+ISADevice parent_obj;
+
+/* Properties */
+uint64_t reset_time;
+uint64_t build_number_value;
+uint64_t build_number_time;
+
+/* Private data */
+} VMPortRpcState;
+
+typedef struct {
+uint32_t eax;
+uint32_t ebx;
+uint32_t ecx;
+uint32_t edx;
+uint32_t esi;
+uint32_t edi;
+} vregs;
+
+static uint32_t vmport_rpc_ioport_read(void *opaque, uint32_t addr)
+{
+VMPortRpcState *s = opaque;
+union {
+uint32_t data[6];
+vregs regs;
+} ur;
+
+vmmouse_get_data(ur.data);
+
+s-build_number_time++;
+
+vmmouse_set_data(ur.data);
+return ur.data[0];
+}
+
+static void vmport_rpc_reset(DeviceState *d)
+{
+VMPortRpcState *s = VMPORT_RPC(d);
+
+s-reset_time = 14;
+s-build_number_value = 0;
+s-build_number_time = 0;
+}
+
+static void vmport_rpc_realize(DeviceState *dev, Error **errp)
+{
+VMPortRpcState *s = VMPORT_RPC(dev);
+
+if (!vmport_register(VMPORT_RPC_COMMAND, vmport_rpc_ioport_read, s)) {
+error_set(errp, ERROR_CLASS_GENERIC_ERROR,
+  vmport_rpc needs vmport enabled);
+}
+}
+
+static Property vmport_rpc_properties[] = {
+DEFINE_PROP_UINT64(reset-time, VMPortRpcState, reset_time, 14),
+DEFINE_PROP_UINT64(build-number-value, VMPortRpcState,
+   build_number_value, 0),
+DEFINE_PROP_UINT64(build-number-time, VMPortRpcState,
+   build_number_time, 0),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vmport_rpc_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc-realize = vmport_rpc_realize;
+dc-reset = vmport_rpc_reset;
+dc-desc = Enable VMware's hyper-call rpc;
+dc

[Qemu-devel] [PATCH v8 1/8] vmport: Switch to trace

2015-06-23 Thread Don Slutz
From: Don Slutz dsl...@verizon.com

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
Acked-by: Paolo Bonzini pbonz...@redhat.com
---
v8:
  Added Acked-by: Paolo Bonzini

 hw/misc/vmport.c | 6 ++
 trace-events | 3 +++
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index 7fcc00d..3b81d04 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -27,7 +27,7 @@
 #include sysemu/kvm.h
 #include hw/qdev.h
 
-//#define VMPORT_DEBUG
+#include trace.h
 
 #define VMPORT_CMD_GETVERSION 0x0a
 #define VMPORT_CMD_GETRAMSIZE 0x14
@@ -80,9 +80,7 @@ static uint64_t vmport_ioport_read(void *opaque, hwaddr addr,
 return eax;
 if (!s-func[command])
 {
-#ifdef VMPORT_DEBUG
-fprintf(stderr, vmport: unknown command %x\n, command);
-#endif
+trace_vmport_ioport_unknown_command(command);
 return eax;
 }
 
diff --git a/trace-events b/trace-events
index 90099e6..80e8a76 100644
--- a/trace-events
+++ b/trace-events
@@ -889,6 +889,9 @@ pc87312_info_ide(uint32_t base) base 0x%x
 pc87312_info_parallel(uint32_t base, uint32_t irq) base 0x%x, irq %u
 pc87312_info_serial(int n, uint32_t base, uint32_t irq) id=%d, base 0x%x, irq 
%u
 
+# hw/misc/vmport.c
+vmport_ioport_unknown_command(unsigned char command) %x
+
 # hw/scsi/vmw_pvscsi.c
 pvscsi_ring_init_data(uint32_t txr_len_log2, uint32_t rxr_len_log2) TX/RX 
rings logarithms set to %d/%d
 pvscsi_ring_init_msg(uint32_t len_log2) MSG ring logarithm set to %d
-- 
1.8.3.1




[Qemu-devel] [PATCH v8 0/8] Add limited support of VMware's hyper-call rpc

2015-06-23 Thread Don Slutz
Changes v7 to v8:
  Rebase to master

  Drop patch #1 since commit 965eb2fcdfe919ecced6c34803535ad32dc1249c
  fixed this.

  Paolo Bonzini
Ok to pull v7 1,2,3, and 9.
  Added Acked-by: Paolo Bonzini pbonz...@redhat.com
  Moved v7 #9 to v8 #3

  Eric Blake
s/it's/its/
  Done
No space after **.
  Done
Don't know if any static checkers will complain about the break being
dead code.
  Dropped break since this is the last case.
Would it help if struct keyValue declared 'const char *key_data'?
  It does, so switch to this.
This cast is spurious (foreach_dynamic_vmport_rpc_device)
  Dropped all casts using this routine.
Do you want g_malloc0, or g_new0?
  Switched to g_new0.
Adjust /* FIXME should check for...
  Added Or cause an error to be raised.

  Michael S. Tsirkin
To me it looks like this will break cross-version migration
  Dropped code to always add the new device.
  Add code to check for vmport enabled.
Quite possibly but personally I'm confused.
  No partial PULL request sent.


Changes v6 to v7:
  Rebase to master

  Fixed a bug caused by commit c3c1bb99d1c11978d9ce94d1bdcf0705378c1459 now 
patch #1

  Added patch #2 to switch to using trace in vm,port.c.

  Delay call on g_strndup till after key length check.

  Switched e-mail address in MAINTAINERS.

  Eric Blake
Why not assert(find) instead of leaving it to the comment?
  Switch to assert.
Is it worth marking arg const here and in the VMPortRpcFind struct
  Switch to const.
I'd rather abort() if someone compiled with -NDEBUG
  Done.
Still mismatches on  line length (several sites).
  Done


Changes v5 to v6:

  Rebase to master

  Eric Blake
Returning a non-dictionary is not extensible.
  Added new type VmportGuestInfoValue.
  s/VmportGuestInfo/VmportGuestInfoKey/
  s/type/struct/
Issues with examples
  Fixed.


Changes v4 to v5:

  Paolo Bonzini
What is VMPORT_SHORT about?
  Dropped this.
Why not use a bool in CPUX86State?
  Took his sugestion and moved to a bool in X86CPU.

Changes v3 to v4:

  Paolo Bonzini on vmort_rpc: Add QMP access to vmport_rpc
Does this compile on non-x86 targets?
  Nope.  Fixed.

Changes v2 to v3:

  s/2.3/2.4

Changes v1 to v2:

   Added live migration code.
   Adjust data structures for migration.
   Switch to GHashTable.

  Eric Blake
s/spawened/spawned/
  Done
s/traceing/tracing/
  Done
Change error_set(errp, ERROR_CLASS_GENERIC_ERROR,  to
error_setg(errp, 
  Done
Why two commands (inject-vmport-reboot, inject-vmport-halt)?
  Switched to inject-vmport-action.
format=base64 bug statements.
  Dropped.

Much more on format=base64:

If there is a bug it is in GLIB.  However the Glib reference manual
refers to RFC 1421 and RFC 2045 and MIME encoding.  Based on all
that (which seems to match:

http://en.wikipedia.org/wiki/Base64

) MIME states that all characters outside the (base64) alphabet are
to be ignored.  Testing shows that g_base64_decode() does this.

The confusion is that most non-MIME uses reject a base64 string that
contain characters outside the alphabet.  I was just following the
other uses of base64 in this file.

DataFormat refers to RFC 3548, which has the info:


   Implementations MUST reject the encoding if it contains
   characters outside the base alphabet when interpreting base
   encoded data, unless the specification referring to this document
   explicitly states otherwise.  Such specifications may, as MIME
   does, instead state that characters outside the base encoding
   alphabet should simply be ignored when interpreting data (be
   liberal in what you accept).


So with GLIB going the MIME way, I do not think this is a QEMU bug
(you could consider this a GLIB bug, but the document I found says
that GLIB goes the MIME way and so does not reject anything).

---


The support included is enough to allow VMware tools to install in a
guest and provide guestinfo support.  guestinfo support is provided
by what is known as VMware RPC support.

One of the better on-line references is:

https://sites.google.com/site/chitchatvmback/backdoor

As a place to get more accurate information by studying:

http://open-vm-tools.sourceforge.net/

With vmware tools installed, you can do:

---
Last login: Fri Jan 30 16:03:08 2015
[root@C63-min-tools ~]# vmtoolsd --cmd info-get guestinfo.joejoel
No value found
[root@C63-min-tools ~]# vmtoolsd --cmd info-set guestinfo.joejoel bar

[root@C63-min-tools ~]# vmtoolsd --cmd info-get guestinfo.joejoel
bar
[root@C63-min-tools ~]# 
---

to access guest info.  QMP access is also provided.

The live migration code is still in progress.

Don Slutz (8):
  vmport: Switch to trace
  vmport: Fix vmport_cmd_ram_size

[Qemu-devel] [BUGFIX][PATCH v8 2/8] vmport: Fix vmport_cmd_ram_size

2015-06-23 Thread Don Slutz
From: Don Slutz dsl...@verizon.com

Based on

https://sites.google.com/site/chitchatvmback/backdoor

and testing on ESXi, this should be in MB not bytes.

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
Acked-by: Paolo Bonzini pbonz...@redhat.com
---
v8:
  Added Acked-by: Paolo Bonzini

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

diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index 3b81d04..783827d 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -108,7 +108,7 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t 
addr)
 X86CPU *cpu = X86_CPU(current_cpu);
 
 cpu-env.regs[R_EBX] = 0x1177;
-return ram_size;
+return ram_size  20; /* in MB */
 }
 
 static uint32_t vmport_cmd_xtest(void *opaque, uint32_t addr)
-- 
1.8.3.1




[Qemu-devel] [PATCH v8 3/8] MAINTAINERS: add VMware port

2015-06-23 Thread Don Slutz
From: Don Slutz don.sl...@gmail.com

Signed-off-by: Don Slutz don.sl...@gmail.com
CC: Don Slutz dsl...@verizon.com
Acked-by: Paolo Bonzini pbonz...@redhat.com
---
v8:
  Added Acked-by: Paolo Bonzini

v7:
  Switched e-mail address in MAINTAINERS.


 MAINTAINERS | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 3639173..1872a9c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -781,6 +781,13 @@ M: Jiri Pirko j...@resnulli.us
 S: Maintained
 F: hw/net/rocker/
 
+VMware port
+M: Don Slutz don.sl...@gmail.com
+S: Maintained
+F: hw/misc/vmport.c
+F: hw/input/vmmouse.c
+F: hw/misc/vmport_rpc.c
+
 Subsystems
 --
 Audio
-- 
1.8.3.1




[Qemu-devel] [PATCH v8 8/8] vmport: Add VMware all ring hack

2015-06-23 Thread Don Slutz
From: Don Slutz dsl...@verizon.com

This is done by adding a new machine property vmware-port-ring3 that
needs to be enabled to have any effect.  It only effects accel=tcg
mode.  It is needed if you want to use VMware tools in accel=tcg
mode.

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 hw/i386/pc.c | 26 +-
 hw/i386/pc_piix.c|  2 +-
 hw/i386/pc_q35.c |  2 +-
 include/hw/i386/pc.h |  6 +-
 target-i386/cpu-qom.h|  3 +++
 target-i386/seg_helper.c |  9 +
 6 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 7072930..3ae4476 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1042,7 +1042,9 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
 object_unref(OBJECT(cpu));
 }
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+  bool vmware_port_ring3)
 {
 int i;
 X86CPU *cpu = NULL;
@@ -1073,6 +1075,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState 
*icc_bridge)
 error_report_err(error);
 exit(1);
 }
+cpu-allow_vmport_ring3 = vmware_port_ring3;
 object_unref(OBJECT(cpu));
 }
 
@@ -1835,6 +1838,21 @@ static bool pc_machine_get_aligned_dimm(Object *obj, 
Error **errp)
 return pcms-enforce_aligned_dimm;
 }
 
+static bool pc_machine_get_vmware_port_ring3(Object *obj, Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+return pcms-vmware_port_ring3;
+}
+
+static void pc_machine_set_vmware_port_ring3(Object *obj, bool value,
+ Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+pcms-vmware_port_ring3 = value;
+}
+
 static void pc_machine_initfn(Object *obj)
 {
 PCMachineState *pcms = PC_MACHINE(obj);
@@ -1865,6 +1883,12 @@ static void pc_machine_initfn(Object *obj)
 object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM,
  pc_machine_get_aligned_dimm,
  NULL, NULL);
+
+pcms-vmware_port_ring3 = false;
+object_property_add_bool(obj, PC_MACHINE_VMWARE_PORT_RING3,
+ pc_machine_get_vmware_port_ring3,
+ pc_machine_set_vmware_port_ring3,
+ NULL);
 }
 
 static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index e142f75..890c45e 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -146,7 +146,7 @@ static void pc_init1(MachineState *machine)
 object_property_add_child(qdev_get_machine(), icc-bridge,
   OBJECT(icc_bridge), NULL);
 
-pc_cpus_init(machine-cpu_model, icc_bridge);
+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
 
 if (kvm_enabled()  kvmclock_enabled) {
 kvmclock_create();
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 082cd93..8288a5f 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -137,7 +137,7 @@ static void pc_q35_init(MachineState *machine)
 object_property_add_child(qdev_get_machine(), icc-bridge,
   OBJECT(icc_bridge), NULL);
 
-pc_cpus_init(machine-cpu_model, icc_bridge);
+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
 pc_acpi_init(q35-acpi-dsdt.aml);
 
 kvmclock_create();
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 3270a97..f9e74c7 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -40,6 +40,7 @@ struct PCMachineState {
 
 uint64_t max_ram_below_4g;
 OnOffAuto vmport;
+bool vmware_port_ring3;
 bool enforce_aligned_dimm;
 };
 
@@ -48,6 +49,7 @@ struct PCMachineState {
 #define PC_MACHINE_MAX_RAM_BELOW_4G max-ram-below-4g
 #define PC_MACHINE_VMPORT   vmport
 #define PC_MACHINE_ENFORCE_ALIGNED_DIMM enforce-aligned-dimm
+#define PC_MACHINE_VMWARE_PORT_RING3 vmware-port-ring3
 
 /**
  * PCMachineClass:
@@ -161,7 +163,9 @@ extern int fd_bootchk;
 void pc_register_ferr_irq(qemu_irq irq);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+  bool vmware_port_ring3);
 void pc_hot_add_cpu(const int64_t id, Error **errp);
 void pc_acpi_init(const char *default_dsdt);
 
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 7a4fddd..ccbc5bb 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -109,6 +109,9 @@ typedef struct X86CPU {
  */
 bool enable_pmu;
 
+/* allow_vmport_ring3 true says enable VMware port access in ring3

[Qemu-devel] [PATCH v8 7/8] vmport_rpc: Add migration

2015-06-23 Thread Don Slutz
From: Don Slutz dsl...@verizon.com

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 hw/misc/vmport_rpc.c | 250 +++
 trace-events |   2 +
 2 files changed, 252 insertions(+)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index 917898b..7198e30 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -171,6 +171,14 @@ typedef struct VMPortRpcState {
 uint32_t open_cookie;
 channel_t chans[GUESTMSG_MAX_CHANNEL];
 GHashTable *guestinfo;
+/* Temporary cache for migration purposes */
+int32_t mig_chan_num;
+int32_t mig_bucket_num;
+uint32_t mig_guestinfo_size;
+uint32_t mig_guestinfo_off;
+uint8_t *mig_guestinfo_buf;
+channel_control_t *mig_chans;
+bucket_control_t *mig_buckets;
 #ifdef VMPORT_RPC_DEBUG
 unsigned int end;
 unsigned int last;
@@ -1186,6 +1194,247 @@ static Property vmport_rpc_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static const VMStateDescription vmstate_vmport_rpc_chan = {
+.name = vmport_rpc/chan,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField [])
+{
+VMSTATE_UINT64(active_time, channel_control_t),
+VMSTATE_UINT32(chan_id, channel_control_t),
+VMSTATE_UINT32(cookie, channel_control_t),
+VMSTATE_UINT32(proto_num, channel_control_t),
+VMSTATE_UINT16(send_len, channel_control_t),
+VMSTATE_UINT16(send_idx, channel_control_t),
+VMSTATE_UINT16(send_buf_max, channel_control_t),
+VMSTATE_UINT8(recv_read, channel_control_t),
+VMSTATE_UINT8(recv_write, channel_control_t),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static const VMStateDescription vmstate_vmport_rpc_bucket = {
+.name = vmport_rpc/bucket,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField [])
+{
+VMSTATE_UINT16(recv_len, bucket_control_t),
+VMSTATE_UINT16(recv_idx, bucket_control_t),
+VMSTATE_UINT16(recv_buf_max, bucket_control_t),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void vmport_rpc_size_mig_guestinfo(gpointer key, gpointer value,
+  gpointer opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int key_len = strlen(key) + 1;
+guestinfo_t *gi = value;
+
+s-mig_guestinfo_size += 1 + key_len + 4 + gi-val_max;
+}
+
+static void vmport_rpc_fill_mig_guestinfo(gpointer key, gpointer value,
+  gpointer opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int key_len = strlen(key) + 1;
+guestinfo_t *gi = value;
+
+assert(gi-val_len = gi-val_max);
+trace_vmport_rpc_fill_mig_guestinfo(key_len, key_len, key, gi-val_len,
+gi-val_len, gi-val_data);
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = key_len;
+memcpy(s-mig_guestinfo_buf + s-mig_guestinfo_off, key, key_len);
+s-mig_guestinfo_off += key_len;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_len  8;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_len;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_max  8;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_max;
+memcpy(s-mig_guestinfo_buf + s-mig_guestinfo_off, gi-val_data,
+   gi-val_max);
+s-mig_guestinfo_off += gi-val_max;
+}
+
+static int vmport_rpc_pre_load(void *opaque)
+{
+VMPortRpcState *s = opaque;
+
+g_free(s-mig_guestinfo_buf);
+s-mig_guestinfo_buf = NULL;
+s-mig_guestinfo_size = 0;
+s-mig_guestinfo_off = 0;
+g_free(s-mig_chans);
+s-mig_chans = NULL;
+s-mig_chan_num = 0;
+g_free(s-mig_buckets);
+s-mig_buckets = NULL;
+s-mig_bucket_num = 0;
+
+return 0;
+}
+
+static void vmport_rpc_pre_save(void *opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int i;
+unsigned int mig_chan_idx = 0;
+unsigned int mig_bucket_idx = 0;
+
+(void)vmport_rpc_pre_load(opaque);
+for (i = 0; i  GUESTMSG_MAX_CHANNEL; ++i) {
+channel_t *c = s-chans[i];
+
+if (c-ctl.proto_num) {
+unsigned int j;
+
+s-mig_chan_num++;
+for (j = 0; j  MAX_BKTS; ++j) {
+bucket_t *b = c-recv_bkt[j];
+
+s-mig_bucket_num++;
+s-mig_guestinfo_size +=
+(b-ctl.recv_buf_max + 1) * CHAR_PER_CALL;
+}
+s-mig_guestinfo_size += (c-ctl.send_buf_max + 1) * CHAR_PER_CALL;
+}
+}
+g_hash_table_foreach(s-guestinfo, vmport_rpc_size_mig_guestinfo, s);
+s-mig_guestinfo_size++;
+s-mig_guestinfo_buf = g_malloc(s-mig_guestinfo_size);
+s-mig_chans = g_malloc(s-mig_chan_num * sizeof(channel_control_t));
+s-mig_buckets = g_malloc(s-mig_bucket_num * sizeof(bucket_control_t));
+
+for (i = 0; i  GUESTMSG_MAX_CHANNEL; ++i) {
+channel_t *c = s-chans[i];
+
+if (c-ctl.proto_num

Re: [Qemu-devel] [PATCH v7 0/9] Add limited support of VMware's hyper-call rpc

2015-06-18 Thread Don Slutz
On 06/17/15 14:58, Michael S. Tsirkin wrote:
 On Wed, Jun 17, 2015 at 01:34:33PM -0400, Don Slutz wrote:
 On 06/17/15 13:25, Paolo Bonzini wrote:


 On 17/06/2015 19:14, Paolo Bonzini wrote:


 On 17/06/2015 19:03, Don Slutz wrote:
 On 06/17/15 12:29, Michael S. Tsirkin wrote:
 On Wed, Jun 17, 2015 at 06:17:19PM +0200, Paolo Bonzini wrote:


 On 17/06/2015 16:29, Michael S. Tsirkin wrote:
 On Wed, Jun 17, 2015 at 04:27:13PM +0200, Paolo Bonzini wrote:


 On 17/06/2015 16:18, Michael S. Tsirkin wrote:
 Yes, that's what was done for parallel and pcspk as well.  There's 
 no
 infrastructure to avoid it.

 Paolo
 How do you mean? We have multiple ways to keep devices
 compatible with old versions.
 Set a new property to skip the extra stuff.

 Not if the device didn't have a vmstate at all, unfortunately.

 Skip creating the device completely for old machine types.

 Which device?  The vmstate is tied to the same device that has always
 been created.

 Just disable the new functionality. Make it behave in
 a compatible way.

  we enable this thing by default (why do we?)

 Sigh. There is a very simple way to add a device in qemu: let user
 request it with -device.  If one does this, one gets to maintain the
 resulting mess without bothering with pc maintainers in any way.

 But of course, everyone implementing a new feature feels it's such a
 great thing, and completel zero risk, it must be part of the default
 machine. Guess what, one then gets to bother with versioning from day 0.

 this seems like a big deal ...

 The PC speaker device is also enabled by default.

 This is historical, isn't it?

 Yes, but it has broken 2.3-2.2 migration.

 Let's just stop fighting windmills.

 Paolo

 I don't see what you are saying. Suddenly guest visible
 changes within a machine type are ok?

 So we have a bug, need to fix it, preferably before piling up
 more features. The best way imho is for 2.4 to avoid
 this device unless requested explicitly.


 My take on this is that Michael would like me to have a vmport_rpc=on
 option, just like vmport=on (which already exists).  With a default of 
 off.

 It wouldn't be enough, because dc-vmsd would be non-NULL anyway.

 (But yes, that option would be a good thing anyway).

 Even better would be to have a -global vmport.rpc=no option.  It would
 be simpler to disable it in existing machine types.


 Either way I can avoid the device creation... Unless I hear otherwise I
 will go the global way.  Since the default would be no, should I also
 make the default =yes for the 2.4 pc?

-Don Slutz

-Don Slutz
 
 Can you use -device vmport_rpc, and avoid adding code to the default pc?
 

I have made this change (drop default creation, require -device to use)
and so far testing looks good.

   -Don Slutz

 Paolo




Re: [Qemu-devel] [PATCH 0/2] exec: fixes for access clamping

2015-06-18 Thread Don Slutz
On 06/18/15 11:43, Paolo Bonzini wrote:
 The first patch fixes the remaining problems with Peter Crosthwaite's
 access clamping patch (which broke kvmvapic and hence Windows XP/2003).
 The second patch actually puts the clamping to good use: by fixing
 address_space_translate_internal, the MIPS rc4030 emulation does not need
 anymore the address_space_rw hack.
 
 Please test!
 

My testing on vmport says that this change also fixed:

Subject: [BUGFIX][PATCH v7 1/9] vmport: The io memory region needs to be
at least a size of 4
Date: Fri, 12 Jun 2015 10:05:48 -0400
Message-Id: 1434117956-4929-2-git-send-email-dsl...@verizon.com

So as long as this change goes in, the patch vmport: The io memory
region will be dropped.

   -Don Slutz

 Paolo
 
 Paolo Bonzini (2):
   exec: do not clamp accesses to MMIO regions
   exec: clamp accesses against the MemoryRegionSection
 
  exec.c | 8 ++--
  1 file changed, 6 insertions(+), 2 deletions(-)
 



Re: [Qemu-devel] [PATCH v7 0/9] Add limited support of VMware's hyper-call rpc

2015-06-17 Thread Don Slutz

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 06/17/15 09:44, Paolo Bonzini wrote:

 On 12/06/2015 16:05, Don Slutz wrote:
 Changes v6 to v7:
...
 Looks good, feel free to send out patches 1+2+3+9 in a pull request if
 you want.

If I am reading this correctly, I should add

Acked-by: Paolo Bonzini pbonz...@redhat.com

to these 4 patches.

Since I have never sent a pull request to QEMU before here is what I
think should be in it:


The following changes since commit f754c3c9cce3c4789733d9068394be4256dfe6a8:

  Merge remote-tracking branch
'remotes/agraf/tags/signed-s390-for-upstream' into staging (2015-06-17
12:43:26 +0100)

are available in the git repository at:


  g...@github.com:dslutz/qemu.git vmware_pull_v7

for you to fetch changes up to a9e61af94c4452270521638c6bac11262ff2f2b7:

  MAINTAINERS: add VMware port (2015-06-17 18:21:02 -0400)

- 
Don Slutz (4):
  vmport: The io memory region needs to be at least a size of 4
  vmport: Switch to trace
  vmport: Fix vmport_cmd_ram_size
  MAINTAINERS: add VMware port

 MAINTAINERS  |  7 +++
 hw/misc/vmport.c | 15 +--
 trace-events |  4 
 3 files changed, 20 insertions(+), 6 deletions(-)


Not clear at all about signing this pull.

   -Don Slutz

 Thanks,

 Paolo


-BEGIN PGP SIGNATURE-
Version: GnuPG v2.0.22 (GNU/Linux)

iQIcBAEBAgAGBQJVgfP9AAoJEMH0lYjxq9KcR2YP/RRWoCXrROAdiJfqEKOdrccn
ZrIOF+DT2nDD7VvzYvRvPNXaCZk7ugwzqHeMBTBzwFHXpxsoFMWSQkO1rwl5S7GC
T4JHMwOBNcKY3DUasbAHjE/BPF2nJF+fkBmb6lhH7gbOSaSc/CB7JNc9UkMlBMFG
BQj0vpcgGJnhGj3eL+aQ6juulNyWioHSsSoLAMLr8wB6ywpxm2W3lrzQhgvp7v5U
Qn7r5Fp5AfmzP3Pxl2iS0bW7wligfPX0UgNw5GM1OIVnNHtZaRE0zKpdy2zvBfFs
XS/DlWK1v6VcUyb0ywi1uFmnprmluiycKBafozK8wHgi75THw1MKY6G1V2GTWt6O
PlCQnF9VOmKVzrg7YIa+7alyyJSeh7ELfBZOAl4zejbg1Mp7CoW7wvOOVX4TuJJ8
S5nAIYJa0XfkRsaNYRD3LR6i7u35CA0f2dzRSXepDIkTmFihYA3i/tBZyjIc8+vP
9W1txyWyi9i8S6pzC5UCpERvq5+bOYAi/LaOKnh5N2TiILIZ91vK+o8zTkc1J5e2
DBmE5cHRYHLf3HEPf5+wahQLKdCLV3cKF7LwkJyZEpfYW31jBlt2ePA2w5ebJenN
KJ+rS9SKswUbvgC+EdR9TQHvmSQjJyVx20dsZ0CALL3lwxFFbXRsPleKpCFmx2Q4
D2vNnwaa6GFzM48CNjcO
=xLeM
-END PGP SIGNATURE-




Re: [Qemu-devel] [PATCH v7 0/9] Add limited support of VMware's hyper-call rpc

2015-06-17 Thread Don Slutz
On 06/17/15 13:25, Paolo Bonzini wrote:
 
 
 On 17/06/2015 19:14, Paolo Bonzini wrote:


 On 17/06/2015 19:03, Don Slutz wrote:
 On 06/17/15 12:29, Michael S. Tsirkin wrote:
 On Wed, Jun 17, 2015 at 06:17:19PM +0200, Paolo Bonzini wrote:


 On 17/06/2015 16:29, Michael S. Tsirkin wrote:
 On Wed, Jun 17, 2015 at 04:27:13PM +0200, Paolo Bonzini wrote:


 On 17/06/2015 16:18, Michael S. Tsirkin wrote:
 Yes, that's what was done for parallel and pcspk as well.  There's no
 infrastructure to avoid it.

 Paolo
 How do you mean? We have multiple ways to keep devices
 compatible with old versions.
 Set a new property to skip the extra stuff.

 Not if the device didn't have a vmstate at all, unfortunately.

 Skip creating the device completely for old machine types.

 Which device?  The vmstate is tied to the same device that has always
 been created.

 Just disable the new functionality. Make it behave in
 a compatible way.

  we enable this thing by default (why do we?)

 Sigh. There is a very simple way to add a device in qemu: let user
 request it with -device.  If one does this, one gets to maintain the
 resulting mess without bothering with pc maintainers in any way.

 But of course, everyone implementing a new feature feels it's such a
 great thing, and completel zero risk, it must be part of the default
 machine. Guess what, one then gets to bother with versioning from day 0.

 this seems like a big deal ...

 The PC speaker device is also enabled by default.

 This is historical, isn't it?

 Yes, but it has broken 2.3-2.2 migration.

 Let's just stop fighting windmills.

 Paolo

 I don't see what you are saying. Suddenly guest visible
 changes within a machine type are ok?

 So we have a bug, need to fix it, preferably before piling up
 more features. The best way imho is for 2.4 to avoid
 this device unless requested explicitly.


 My take on this is that Michael would like me to have a vmport_rpc=on
 option, just like vmport=on (which already exists).  With a default of off.

 It wouldn't be enough, because dc-vmsd would be non-NULL anyway.

 (But yes, that option would be a good thing anyway).
 
 Even better would be to have a -global vmport.rpc=no option.  It would
 be simpler to disable it in existing machine types.
 

Either way I can avoid the device creation... Unless I hear otherwise I
will go the global way.  Since the default would be no, should I also
make the default =yes for the 2.4 pc?

   -Don Slutz

   -Don Slutz

 Paolo
 



Re: [Qemu-devel] [PATCH v7 6/9] vmport_rpc: Add QMP access to vmport_rpc object.

2015-06-17 Thread Don Slutz
On 06/15/15 11:53, Eric Blake wrote:
 On 06/12/2015 08:05 AM, Don Slutz wrote:
 This adds one new inject command:

 inject-vmport-action

 And three guest info commands:

 vmport-guestinfo-set
 vmport-guestinfo-get
 query-vmport-guestinfo

 More details in qmp-commands.hx

 Signed-off-by: Don Slutz dsl...@verizon.com
 CC: Don Slutz don.sl...@gmail.com
 ---
 
 +typedef int FindVMPortRpcDeviceFunc(VMPortRpcState *s, const void *arg);
 +
 +/*
 + * The input and output argument that find_VMPortRpc_device() uses
 + * to do it's work.
 
 s/it's/its/ (the only time it's is correct is if it is would also be
 correct)
 

Will fix.

 
  
 +static int get_qmp_guestinfo(VMPortRpcState *s,
 + unsigned int a_key_len, const char *a_info_key,
 + unsigned int *a_value_len, void ** 
 a_value_data)
 
 No space after **.
 

Will fix.

 
 +void qmp_inject_vmport_action(enum VmportAction action, Error **errp)
 +{
 +int rc;
 +
 +switch (action) {
 +case VMPORT_ACTION_REBOOT:
 +rc = foreach_dynamic_vmport_rpc_device(vmport_rpc_find_send,
 +   OS_Reboot);
 +break;
 +case VMPORT_ACTION_HALT:
 +rc = foreach_dynamic_vmport_rpc_device(vmport_rpc_find_send,
 +   OS_Halt);
 +break;
 +case VMPORT_ACTION_MAX:
 +assert(action != VMPORT_ACTION_MAX);
 +abort(); /* Should be impossible to get here. */
 +break;
 
 Don't know if any static checkers will complain about the break being
 dead code.
 
 

I do not know.  However I can just delete it, and so will do so.

 +
 +void qmp_vmport_guestinfo_set(const char *key, const char *value,
 +  bool has_format, enum DataFormat format,
 +  Error **errp)
 +{
 +int rc;
 +keyValue key_value;
 +
 +if (strncmp(key, guestinfo., strlen(guestinfo.)) == 0) {
 +key_value.key_data = (void *)(key + strlen(guestinfo.));
 
 Cast here...
 
 +key_value.key_len = strlen(key) - strlen(guestinfo.);
 +} else {
 +key_value.key_data = (void *)key;
 
 ...and here...
 
 +key_value.key_len = strlen(key);
 +}
 +if (has_format  (format == DATA_FORMAT_BASE64)) {
 +gsize write_count;
 +
 +key_value.value_data = g_base64_decode(value, write_count);
 +key_value.value_len = write_count;
 +} else {
 +key_value.value_data = (void *)value;
 
 ...and here is only needed to get rid of const. Would it help if struct
 keyValue declared 'const char *key_data' instead of 'void *key_data'?

This is value_data not key_data. So this cast is needed with 'const char
*key_data', the other 2 do go away.


 
 +key_value.value_len = strlen(value);
 +}
 +
 +rc = foreach_dynamic_vmport_rpc_device(find_set, (void *)key_value);
 
 This cast is spurious (it does not get rid of const, and any non-const
 pointer in C can already be passed to void* without a cast).
 

Yup fixed.

 +VmportGuestInfoValue *qmp_vmport_guestinfo_get(const char *key,
 +   bool has_format,
 +   enum DataFormat format,
 +   Error **errp)
 +{
 +int rc;
 +keyValue key_value;
 +VmportGuestInfoValue *ret_value;
 +
 +if (strncmp(key, guestinfo., strlen(guestinfo.)) == 0) {
 +key_value.key_data = (void *)(key + strlen(guestinfo.));
 +key_value.key_len = strlen(key) - strlen(guestinfo.);
 +} else {
 +key_value.key_data = (void *)key;
 
 More casts that might be prevented with correct const in the callback
 struct.
 

these 2 do get fixed.

 +key_value.key_len = strlen(key);
 +}
 +
 +rc = foreach_dynamic_vmport_rpc_device(find_get, (void *)key_value);
 
 Another spurious cast.
 

Fixed.

 +if (rc) {
 +convert_local_rc(errp, rc);
 +return NULL;
 +}
 +
 +ret_value = g_malloc(sizeof(VmportGuestInfoKey));
 
 Do you want g_malloc0, or even the additional type-safety (and less
 typing) of g_new0(VmportGuestInfoKey, 1)?  Otherwise, if you later add
 fields, but forget to initialize them, you'll have random garbage.
 

Switched to g_new0.

 +if (has_format  (format == DATA_FORMAT_BASE64)) {
 +ret_value-value = g_base64_encode(key_value.value_data,
 +   key_value.value_len);
 +} else {
 +/*
 + * FIXME should check for complete, valid UTF-8 characters.
 + * Invalid sequences should be replaced by a suitable
 + * replacement character.
 
 Or cause an error to be raised.

Added that to the comment.


 
 Looking better, though.
 


   -Don Slutz



Re: [Qemu-devel] [PATCH v7 0/9] Add limited support of VMware's hyper-call rpc

2015-06-17 Thread Don Slutz
On 06/17/15 12:29, Michael S. Tsirkin wrote:
 On Wed, Jun 17, 2015 at 06:17:19PM +0200, Paolo Bonzini wrote:


 On 17/06/2015 16:29, Michael S. Tsirkin wrote:
 On Wed, Jun 17, 2015 at 04:27:13PM +0200, Paolo Bonzini wrote:


 On 17/06/2015 16:18, Michael S. Tsirkin wrote:
 Yes, that's what was done for parallel and pcspk as well.  There's no
 infrastructure to avoid it.

 Paolo
 How do you mean? We have multiple ways to keep devices
 compatible with old versions.
 Set a new property to skip the extra stuff.

 Not if the device didn't have a vmstate at all, unfortunately.

 Skip creating the device completely for old machine types.

 Which device?  The vmstate is tied to the same device that has always
 been created.
 
 Just disable the new functionality. Make it behave in
 a compatible way.
 
  we enable this thing by default (why do we?)
 
 Sigh. There is a very simple way to add a device in qemu: let user
 request it with -device.  If one does this, one gets to maintain the
 resulting mess without bothering with pc maintainers in any way.
 
 But of course, everyone implementing a new feature feels it's such a
 great thing, and completel zero risk, it must be part of the default
 machine. Guess what, one then gets to bother with versioning from day 0.
 
 this seems like a big deal ...

 The PC speaker device is also enabled by default.

 This is historical, isn't it?

 Yes, but it has broken 2.3-2.2 migration.

 Let's just stop fighting windmills.

 Paolo
 
 I don't see what you are saying. Suddenly guest visible
 changes within a machine type are ok?
 
 So we have a bug, need to fix it, preferably before piling up
 more features. The best way imho is for 2.4 to avoid
 this device unless requested explicitly.
 

My take on this is that Michael would like me to have a vmport_rpc=on
option, just like vmport=on (which already exists).  With a default of off.

I have no problem adding it.

   -Don Slutz



Re: [Qemu-devel] [BUGFIX][PATCH v7 1/9] vmport: The io memory region needs to be at least a size of 4

2015-06-15 Thread Don Slutz
On 06/12/15 18:38, Eric Blake wrote:
 On 06/12/2015 08:05 AM, Don Slutz wrote:
 Before:

 commit c3c1bb99d1c11978d9ce94d1bdcf0705378c1459
 Author: Peter Crosthwaite peter.crosthwa...@xilinx.com
 Date:   Mon Mar 16 22:35:54 2015 -0700

 exec: Respect as_tranlsate_internal length clamp

 it did not matter.  Only accept I/O that starts on 1st
 port.

 Signed-off-by: Don Slutz dsl...@verizon.com
 CC: Don Slutz don.sl...@gmail.com
 ---
  hw/misc/vmport.c | 6 +-
  1 file changed, 5 insertions(+), 1 deletion(-)

 diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
 index 7fcc00d..51b64bc 100644
 --- a/hw/misc/vmport.c
 +++ b/hw/misc/vmport.c
 @@ -69,6 +69,10 @@ static uint64_t vmport_ioport_read(void *opaque, hwaddr 
 addr,
  unsigned char command;
  uint32_t eax;
  
 +/* Only support 1 address */
 +if (addr) {
 +return ~0U;
 +}
 
 Different answer on 32-bit platforms (there, ~0U is 0x, which
 then 0-extends to uint64_t rather than your desired result of
 0xULL).
 

This is not true:

Using:

build1:~/tmpcat zr64.c
#include stdio.h

#include stdint.h

uint64_t vmport_ioport_read(void)
{
return ~0U;
}

int
main(void)
{
uint64_t res = vmport_ioport_read();

printf(res=0x%llx\n, res);
}

On 32-bits:

build1:~/tmpfile zr64
zr64: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
build1:~/tmp./zr64
res=0x

on 64-bits:


build2:~/tmpfile zr64
zr64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically
linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
build2:~/tmp./zr64
res=0x




 Why can't you just 'return -1;'?
 

I/O instructions on x86 are limited to 32bits max.  Also when EAX is
changed via inl, the high 32bits are 0.  So the correct result is ~0U
not -1.

   -Don Slutz



Re: [Qemu-devel] [BUGFIX][PATCH v7 1/9] vmport: The io memory region needs to be at least a size of 4

2015-06-15 Thread Don Slutz
On 06/15/15 11:09, Eric Blake wrote:
 On 06/15/2015 07:53 AM, Don Slutz wrote:
 On 06/12/15 18:38, Eric Blake wrote:
 
  
 +/* Only support 1 address */
 +if (addr) {
 +return ~0U;
 +}

 Different answer on 32-bit platforms (there, ~0U is 0x, which
 then 0-extends to uint64_t rather than your desired result of
 0xULL).


 This is not true:
 
 Oh, I was confusing ~0UL (where sign extension on 32- vs 64-bit matters)
 and ~0U (which you used).
 

 Why can't you just 'return -1;'?


 I/O instructions on x86 are limited to 32bits max.  Also when EAX is
 changed via inl, the high 32bits are 0.  So the correct result is ~0U
 not -1.
 
 Still, it might be better to write an explicit 0x or even have a
 named constant, rather than making people reason about whether ~0U
 promotes into a 64-bit value with only 32 bits set.
 

Ok, Will switch to 0x.

   -Don Slutz



[Qemu-devel] [PATCH v7 9/9] MAINTAINERS: add VMware port

2015-06-12 Thread Don Slutz
From: Don Slutz don.sl...@gmail.com

Signed-off-by: Don Slutz don.sl...@gmail.com
CC: Don Slutz dsl...@verizon.com
---
v7:
  Switched e-mail address in MAINTAINERS.


 MAINTAINERS | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index e728d3a..5155128 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -767,6 +767,13 @@ M: Jiri Pirko j...@resnulli.us
 S: Maintained
 F: hw/net/rocker/
 
+VMware port
+M: Don Slutz don.sl...@gmail.com
+S: Maintained
+F: hw/misc/vmport.c
+F: hw/input/vmmouse.c
+F: hw/misc/vmport_rpc.c
+
 Subsystems
 --
 Audio
-- 
1.8.4




[Qemu-devel] [BUGFIX][PATCH v7 3/9] vmport: Fix vmport_cmd_ram_size

2015-06-12 Thread Don Slutz
Based on

https://sites.google.com/site/chitchatvmback/backdoor

and testing on ESXi, this should be in MB not bytes.

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 hw/misc/vmport.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index 203e892..000af18 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -113,7 +113,7 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t 
addr)
 X86CPU *cpu = X86_CPU(current_cpu);
 
 cpu-env.regs[R_EBX] = 0x1177;
-return ram_size;
+return ram_size  20; /* in MB */
 }
 
 static uint32_t vmport_cmd_xtest(void *opaque, uint32_t addr)
-- 
1.8.4




[Qemu-devel] [PATCH v7 6/9] vmport_rpc: Add QMP access to vmport_rpc object.

2015-06-12 Thread Don Slutz
This adds one new inject command:

inject-vmport-action

And three guest info commands:

vmport-guestinfo-set
vmport-guestinfo-get
query-vmport-guestinfo

More details in qmp-commands.hx

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
v7:
  Delay call on g_strndup till after key length check.

Why not assert(find) instead of leaving it to the comment?
  Switch to assert.
Is it worth marking arg const here and in the VMPortRpcFind struct
  Switch to const.
I'd rather abort() if someone compiled with -NDEBUG
  Done.
Still mismatches on  line length (several sites).
  Done


 hw/misc/vmport_rpc.c | 291 ++-
 monitor.c|  24 +
 qapi-schema.json | 101 ++
 qmp-commands.hx  | 119 +
 4 files changed, 533 insertions(+), 2 deletions(-)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index e2d5c36..e122bad 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -178,6 +178,19 @@ typedef struct VMPortRpcState {
 #endif
 } VMPortRpcState;
 
+typedef int FindVMPortRpcDeviceFunc(VMPortRpcState *s, const void *arg);
+
+/*
+ * The input and output argument that find_VMPortRpc_device() uses
+ * to do it's work.
+ */
+typedef struct VMPortRpcFind {
+const void *arg;
+FindVMPortRpcDeviceFunc *func;
+int found;
+int rc;
+} VMPortRpcFind;
+
 /* Basic request types */
 typedef enum {
 MESSAGE_TYPE_OPEN,
@@ -202,6 +215,56 @@ typedef struct {
 uint32_t edi;
 } vregs;
 
+/*
+ * Run func() for every VMPortRpc device, traverse the tree for
+ * everything else.
+ */
+static int find_VMPortRpc_device(Object *obj, void *opaque)
+{
+VMPortRpcFind *find = opaque;
+Object *dev;
+VMPortRpcState *s;
+
+assert(find);
+if (find-found) {
+return 0;
+}
+dev = object_dynamic_cast(obj, TYPE_VMPORT_RPC);
+s = (VMPortRpcState *)dev;
+
+if (!s) {
+/* Container, traverse it for children */
+return object_child_foreach(obj, find_VMPortRpc_device, opaque);
+}
+
+find-found++;
+find-rc = find-func(s, find-arg);
+
+return 0;
+}
+
+/*
+ * Loop through all dynamically created VMPortRpc devices and call
+ * func() for each instance.
+ */
+static int foreach_dynamic_vmport_rpc_device(FindVMPortRpcDeviceFunc *func,
+ const void *arg)
+{
+VMPortRpcFind find = {
+.func = func,
+.arg = arg,
+};
+
+/* Loop through all VMPortRpc devices that were spawned outside
+ * the machine */
+find_VMPortRpc_device(qdev_get_machine(), find);
+if (find.found) {
+return find.rc;
+} else {
+return VMPORT_DEVICE_NOT_FOUND;
+}
+}
+
 #ifdef VMPORT_RPC_DEBUG
 /*
  * Add helper function for tracing.  This routine will convert
@@ -329,7 +392,7 @@ static int vmport_rpc_send(VMPortRpcState *s, channel_t *c,
 return rc;
 }
 
-static int vmport_rpc_ctrl_send(VMPortRpcState *s, char *msg)
+static int vmport_rpc_ctrl_send(VMPortRpcState *s, const char *msg)
 {
 int rc = SEND_NOT_OPEN;
 unsigned int i;
@@ -457,6 +520,29 @@ static int get_guestinfo(VMPortRpcState *s,
 return GUESTINFO_NOTFOUND;
 }
 
+static int get_qmp_guestinfo(VMPortRpcState *s,
+ unsigned int a_key_len, const char *a_info_key,
+ unsigned int *a_value_len, void ** a_value_data)
+{
+guestinfo_t *gi = NULL;
+
+if (a_key_len = MAX_KEY_LEN) {
+gpointer key = g_strndup(a_info_key, a_key_len);
+
+gi = (guestinfo_t *)g_hash_table_lookup(s-guestinfo, key);
+g_free(key);
+} else {
+return GUESTINFO_KEYTOOLONG;
+}
+if (gi) {
+*a_value_len = gi-val_len;
+*a_value_data = gi-val_data;
+return 0;
+}
+
+return GUESTINFO_NOTFOUND;
+}
+
 static int set_guestinfo(VMPortRpcState *s, int a_key_len,
  unsigned int a_val_len, const char *a_info_key,
  char *val)
@@ -775,7 +861,7 @@ static void vmport_rpc(VMPortRpcState *s , vregs *ur)
 }
 if (delta  s-reset_time) {
 trace_vmport_rpc_ping(delta);
-vmport_rpc_ctrl_send(s, (char *)reset);
+vmport_rpc_ctrl_send(s, reset);
 }
 vmport_rpc_sweep(s, now_time);
 do {
@@ -848,6 +934,207 @@ static uint32_t vmport_rpc_ioport_read(void *opaque, 
uint32_t addr)
 return ur.data[0];
 }
 
+static int vmport_rpc_find_send(VMPortRpcState *s, const void *arg)
+{
+return vmport_rpc_ctrl_send(s, arg);
+}
+
+static void convert_local_rc(Error **errp, int rc)
+{
+switch (rc) {
+case 0:
+break;
+case VMPORT_DEVICE_NOT_FOUND:
+error_set(errp, QERR_DEVICE_NOT_FOUND, TYPE_VMPORT_RPC);
+break;
+case SEND_NOT_OPEN:
+error_setg(errp, VMWare rpc not open);
+break;
+case SEND_SKIPPED:
+error_setg(errp, VMWare rpc

[Qemu-devel] [PATCH v7 7/9] vmport_rpc: Add migration

2015-06-12 Thread Don Slutz
Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 hw/misc/vmport_rpc.c | 250 +++
 trace-events |   2 +
 2 files changed, 252 insertions(+)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index e122bad..4984193 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -171,6 +171,14 @@ typedef struct VMPortRpcState {
 uint32_t open_cookie;
 channel_t chans[GUESTMSG_MAX_CHANNEL];
 GHashTable *guestinfo;
+/* Temporary cache for migration purposes */
+int32_t mig_chan_num;
+int32_t mig_bucket_num;
+uint32_t mig_guestinfo_size;
+uint32_t mig_guestinfo_off;
+uint8_t *mig_guestinfo_buf;
+channel_control_t *mig_chans;
+bucket_control_t *mig_buckets;
 #ifdef VMPORT_RPC_DEBUG
 unsigned int end;
 unsigned int last;
@@ -1183,6 +1191,247 @@ static Property vmport_rpc_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static const VMStateDescription vmstate_vmport_rpc_chan = {
+.name = vmport_rpc/chan,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField [])
+{
+VMSTATE_UINT64(active_time, channel_control_t),
+VMSTATE_UINT32(chan_id, channel_control_t),
+VMSTATE_UINT32(cookie, channel_control_t),
+VMSTATE_UINT32(proto_num, channel_control_t),
+VMSTATE_UINT16(send_len, channel_control_t),
+VMSTATE_UINT16(send_idx, channel_control_t),
+VMSTATE_UINT16(send_buf_max, channel_control_t),
+VMSTATE_UINT8(recv_read, channel_control_t),
+VMSTATE_UINT8(recv_write, channel_control_t),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static const VMStateDescription vmstate_vmport_rpc_bucket = {
+.name = vmport_rpc/bucket,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField [])
+{
+VMSTATE_UINT16(recv_len, bucket_control_t),
+VMSTATE_UINT16(recv_idx, bucket_control_t),
+VMSTATE_UINT16(recv_buf_max, bucket_control_t),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void vmport_rpc_size_mig_guestinfo(gpointer key, gpointer value,
+  gpointer opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int key_len = strlen(key) + 1;
+guestinfo_t *gi = value;
+
+s-mig_guestinfo_size += 1 + key_len + 4 + gi-val_max;
+}
+
+static void vmport_rpc_fill_mig_guestinfo(gpointer key, gpointer value,
+  gpointer opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int key_len = strlen(key) + 1;
+guestinfo_t *gi = value;
+
+assert(gi-val_len = gi-val_max);
+trace_vmport_rpc_fill_mig_guestinfo(key_len, key_len, key, gi-val_len,
+gi-val_len, gi-val_data);
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = key_len;
+memcpy(s-mig_guestinfo_buf + s-mig_guestinfo_off, key, key_len);
+s-mig_guestinfo_off += key_len;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_len  8;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_len;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_max  8;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_max;
+memcpy(s-mig_guestinfo_buf + s-mig_guestinfo_off, gi-val_data,
+   gi-val_max);
+s-mig_guestinfo_off += gi-val_max;
+}
+
+static int vmport_rpc_pre_load(void *opaque)
+{
+VMPortRpcState *s = opaque;
+
+g_free(s-mig_guestinfo_buf);
+s-mig_guestinfo_buf = NULL;
+s-mig_guestinfo_size = 0;
+s-mig_guestinfo_off = 0;
+g_free(s-mig_chans);
+s-mig_chans = NULL;
+s-mig_chan_num = 0;
+g_free(s-mig_buckets);
+s-mig_buckets = NULL;
+s-mig_bucket_num = 0;
+
+return 0;
+}
+
+static void vmport_rpc_pre_save(void *opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int i;
+unsigned int mig_chan_idx = 0;
+unsigned int mig_bucket_idx = 0;
+
+(void)vmport_rpc_pre_load(opaque);
+for (i = 0; i  GUESTMSG_MAX_CHANNEL; ++i) {
+channel_t *c = s-chans[i];
+
+if (c-ctl.proto_num) {
+unsigned int j;
+
+s-mig_chan_num++;
+for (j = 0; j  MAX_BKTS; ++j) {
+bucket_t *b = c-recv_bkt[j];
+
+s-mig_bucket_num++;
+s-mig_guestinfo_size +=
+(b-ctl.recv_buf_max + 1) * CHAR_PER_CALL;
+}
+s-mig_guestinfo_size += (c-ctl.send_buf_max + 1) * CHAR_PER_CALL;
+}
+}
+g_hash_table_foreach(s-guestinfo, vmport_rpc_size_mig_guestinfo, s);
+s-mig_guestinfo_size++;
+s-mig_guestinfo_buf = g_malloc(s-mig_guestinfo_size);
+s-mig_chans = g_malloc(s-mig_chan_num * sizeof(channel_control_t));
+s-mig_buckets = g_malloc(s-mig_bucket_num * sizeof(bucket_control_t));
+
+for (i = 0; i  GUESTMSG_MAX_CHANNEL; ++i) {
+channel_t *c = s-chans[i];
+
+if (c-ctl.proto_num) {
+unsigned int j

[Qemu-devel] [BUGFIX][PATCH v7 1/9] vmport: The io memory region needs to be at least a size of 4

2015-06-12 Thread Don Slutz
Before:

commit c3c1bb99d1c11978d9ce94d1bdcf0705378c1459
Author: Peter Crosthwaite peter.crosthwa...@xilinx.com
Date:   Mon Mar 16 22:35:54 2015 -0700

exec: Respect as_tranlsate_internal length clamp

it did not matter.  Only accept I/O that starts on 1st
port.

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 hw/misc/vmport.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index 7fcc00d..51b64bc 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -69,6 +69,10 @@ static uint64_t vmport_ioport_read(void *opaque, hwaddr addr,
 unsigned char command;
 uint32_t eax;
 
+/* Only support 1 address */
+if (addr) {
+return ~0U;
+}
 cpu_synchronize_state(cs);
 
 eax = env-regs[R_EAX];
@@ -159,7 +163,7 @@ static void vmport_realizefn(DeviceState *dev, Error **errp)
 ISADevice *isadev = ISA_DEVICE(dev);
 VMPortState *s = VMPORT(dev);
 
-memory_region_init_io(s-io, OBJECT(s), vmport_ops, s, vmport, 1);
+memory_region_init_io(s-io, OBJECT(s), vmport_ops, s, vmport, 4);
 isa_register_ioport(isadev, s-io, 0x5658);
 
 port_state = s;
-- 
1.8.4




[Qemu-devel] [PATCH v7 5/9] vmport_rpc: Add limited support of VMware's hyper-call rpc

2015-06-12 Thread Don Slutz
The support included is enough to allow VMware tools to install in a
guest and provide guestinfo support.  guestinfo support is provided
by what is known as VMware RPC support.

If the guest is running VMware tools, then the build version of
the tools is also available via the property build-number-value of
the vmport_rpc object.  The build-number-time property is changed
every time the VMware tools running in the guest sends the
build version via the rpc.

The property reset-time controls how often to request them in
seconds minus 1.  The minus 1 is to handle to 0 case.  I.E. the
fastest that can be selected is every second.  The default is 4
times a minute.

The VMware RPC support includes the notion of channels that are
opened, active and closed.  All RPC messages sent via a channel
starts with normal ASCII text.  The message some times does include
binary data.

Currently there are 2 protocols defined for VMware RPC.  They
determine the direction for data flow, guest to tool stack or tool
stack to guest.

There is no provided interrupt for VMware RPC.

Getting VMPORT_RPC_DEBUG will provide a higher level trace calls
that are simpler to understand.

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 hw/misc/vmport_rpc.c | 796 ++-
 trace-events |  22 ++
 2 files changed, 817 insertions(+), 1 deletion(-)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index b7cd355..e2d5c36 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -40,6 +40,123 @@
 /* VMPORT RPC Command */
 #define VMPORT_RPC_COMMAND  30
 
+/* Limits on amount of non guest memory to use */
+#define MAX_KEY_LEN  128
+#define MIN_VAL_LEN  64
+#define MAX_VAL_LEN  8192
+#define MAX_NUM_KEY  256
+#define MAX_BKTS 4
+/* Max number of channels. */
+#define GUESTMSG_MAX_CHANNEL 8
+
+/*
+ * All of VMware's rpc is based on 32bit registers.  So this is the
+ * number of bytes in ebx.
+ */
+#define CHAR_PER_CALL   sizeof(uint32_t)
+/* Room for basic commands */
+#define EXTRA_SEND 22
+/* Status code and NULL */
+#define EXTRA_RECV 2
+#define MAX_SEND_BUF DIV_ROUND_UP(EXTRA_SEND + MAX_KEY_LEN + MAX_VAL_LEN, \
+  CHAR_PER_CALL)
+#define MAX_RECV_BUF DIV_ROUND_UP(EXTRA_RECV + MAX_VAL_LEN, CHAR_PER_CALL)
+#define MIN_SEND_BUF DIV_ROUND_UP(EXTRA_SEND + MAX_KEY_LEN + MIN_VAL_LEN, \
+  CHAR_PER_CALL)
+
+/* Reply statuses */
+/*  The basic request succeeded */
+#define MESSAGE_STATUS_SUCCESS  0x0001
+/*  vmware has a message available for its party */
+#define MESSAGE_STATUS_DORECV   0x0002
+/*  The channel has been closed */
+#define MESSAGE_STATUS_CLOSED   0x0004
+/*  vmware removed the message before the party fetched it */
+#define MESSAGE_STATUS_UNSENT   0x0008
+/*  A checkpoint occurred */
+#define MESSAGE_STATUS_CPT  0x0010
+/*  An underlying device is powering off */
+#define MESSAGE_STATUS_POWEROFF 0x0020
+/*  vmware has detected a timeout on the channel */
+#define MESSAGE_STATUS_TIMEOUT  0x0040
+/*  vmware supports high-bandwidth for sending and receiving the payload */
+#define MESSAGE_STATUS_HB   0x0080
+
+/* Max number of channels. */
+#define GUESTMSG_MAX_CHANNEL 8
+
+/* Flags to open a channel. */
+#define GUESTMSG_FLAG_COOKIE 0x8000
+
+/* Data to guest */
+#define VMWARE_PROTO_TO_GUEST   0x4f4c4354
+/* Data from guest */
+#define VMWARE_PROTO_FROM_GUEST 0x49435052
+
+/*
+ * Error return values used only in this file.  The routine
+ * convert_local_rc() is used to convert these to an Error
+ * object.
+ */
+#define VMPORT_DEVICE_NOT_FOUND -1
+#define SEND_NOT_OPEN   -2
+#define SEND_SKIPPED-3
+#define SEND_TRUCATED   -4
+#define SEND_NO_MEMORY  -5
+#define GUESTINFO_NOTFOUND  -6
+#define GUESTINFO_VALTOOLONG-7
+#define GUESTINFO_KEYTOOLONG-8
+#define GUESTINFO_TOOMANYKEYS   -9
+#define GUESTINFO_NO_MEMORY -10
+
+
+/* The VMware RPC guest info storage . */
+typedef struct {
+char *val_data;
+uint16_t val_len;
+uint16_t val_max;
+} guestinfo_t;
+
+/* The VMware RPC bucket control. */
+typedef struct {
+uint16_t recv_len;
+uint16_t recv_idx;
+uint16_t recv_buf_max;
+} bucket_control_t;
+
+/* The VMware RPC bucket info. */
+typedef struct {
+union {
+uint32_t *words;
+char *bytes;
+} recv;
+bucket_control_t ctl;
+} bucket_t;
+
+
+/* The VMware RPC channel control. */
+typedef struct {
+uint64_t active_time;
+uint32_t chan_id;
+uint32_t cookie;
+uint32_t proto_num;
+uint16_t send_len;
+uint16_t send_idx;
+uint16_t send_buf_max;
+uint8_t recv_read;
+uint8_t recv_write;
+} channel_control_t;
+
+/* The VMware RPC channel info. */
+typedef struct {
+union {
+uint32_t *words;
+char *bytes;
+} send;
+channel_control_t ctl;
+bucket_t recv_bkt[MAX_BKTS

[Qemu-devel] [PATCH v7 0/9] Add limited support of VMware's hyper-call rpc

2015-06-12 Thread Don Slutz
Changes v6 to v7:
  Rebase to master

  Fixed a bug caused by commit c3c1bb99d1c11978d9ce94d1bdcf0705378c1459 now 
patch #1

  Added patch #2 to switch to using trace in vm,port.c.

  Delay call on g_strndup till after key length check.

  Switched e-mail address in MAINTAINERS.

  Eric Blake
Why not assert(find) instead of leaving it to the comment?
  Switch to assert.
Is it worth marking arg const here and in the VMPortRpcFind struct
  Switch to const.
I'd rather abort() if someone compiled with -NDEBUG
  Done.
Still mismatches on  line length (several sites).
  Done


Changes v5 to v6:

  Rebase to master

  Eric Blake
Returning a non-dictionary is not extensible.
  Added new type VmportGuestInfoValue.
  s/VmportGuestInfo/VmportGuestInfoKey/
  s/type/struct/
Issues with examples
  Fixed.


Changes v4 to v5:

  Paolo Bonzini
What is VMPORT_SHORT about?
  Dropped this.
Why not use a bool in CPUX86State?
  Took his sugestion and moved to a bool in X86CPU.

Changes v3 to v4:

  Paolo Bonzini on vmort_rpc: Add QMP access to vmport_rpc
Does this compile on non-x86 targets?
  Nope.  Fixed.

Changes v2 to v3:

  s/2.3/2.4

Changes v1 to v2:

   Added live migration code.
   Adjust data structures for migration.
   Switch to GHashTable.

  Eric Blake
s/spawened/spawned/
  Done
s/traceing/tracing/
  Done
Change error_set(errp, ERROR_CLASS_GENERIC_ERROR,  to
error_setg(errp, 
  Done
Why two commands (inject-vmport-reboot, inject-vmport-halt)?
  Switched to inject-vmport-action.
format=base64 bug statements.
  Dropped.

Much more on format=base64:

If there is a bug it is in GLIB.  However the Glib reference manual
refers to RFC 1421 and RFC 2045 and MIME encoding.  Based on all
that (which seems to match:

http://en.wikipedia.org/wiki/Base64

) MIME states that all characters outside the (base64) alphabet are
to be ignored.  Testing shows that g_base64_decode() does this.

The confusion is that most non-MIME uses reject a base64 string that
contain characters outside the alphabet.  I was just following the
other uses of base64 in this file.

DataFormat refers to RFC 3548, which has the info:


   Implementations MUST reject the encoding if it contains
   characters outside the base alphabet when interpreting base
   encoded data, unless the specification referring to this document
   explicitly states otherwise.  Such specifications may, as MIME
   does, instead state that characters outside the base encoding
   alphabet should simply be ignored when interpreting data (be
   liberal in what you accept).


So with GLIB going the MIME way, I do not think this is a QEMU bug
(you could consider this a GLIB bug, but the document I found says
that GLIB goes the MIME way and so does not reject anything).

---


The support included is enough to allow VMware tools to install in a
guest and provide guestinfo support.  guestinfo support is provided
by what is known as VMware RPC support.

One of the better on-line references is:

https://sites.google.com/site/chitchatvmback/backdoor

As a place to get more accurate information by studying:

http://open-vm-tools.sourceforge.net/

With vmware tools installed, you can do:

---
Last login: Fri Jan 30 16:03:08 2015
[root@C63-min-tools ~]# vmtoolsd --cmd info-get guestinfo.joejoel
No value found
[root@C63-min-tools ~]# vmtoolsd --cmd info-set guestinfo.joejoel bar

[root@C63-min-tools ~]# vmtoolsd --cmd info-get guestinfo.joejoel
bar
[root@C63-min-tools ~]# 
---

to access guest info.  QMP access is also provided.

The live migration code is still in progress.

Don Slutz (9):
  vmport: The io memory region needs to be at least a size of 4
  vmport: Switch to trace
  vmport: Fix vmport_cmd_ram_size
  vmport_rpc: Add the object vmport_rpc
  vmport_rpc: Add limited support of VMware's hyper-call rpc
  vmport_rpc: Add QMP access to vmport_rpc object.
  vmport_rpc: Add migration
  vmport:  Add VMware all ring hack
  MAINTAINERS: add VMware port

 MAINTAINERS  |7 +
 hw/i386/pc.c |   32 +-
 hw/i386/pc_piix.c|2 +-
 hw/i386/pc_q35.c |2 +-
 hw/misc/Makefile.objs|1 +
 hw/misc/vmport.c |   15 +-
 hw/misc/vmport_rpc.c | 1457 ++
 include/hw/i386/pc.h |6 +-
 monitor.c|   24 +
 qapi-schema.json |  101 
 qmp-commands.hx  |  119 
 target-i386/cpu-qom.h|3 +
 target-i386/seg_helper.c |9 +
 trace-events |   28 +
 14 files changed, 1796 insertions(+), 10 deletions(-)
 create mode 100644 hw/misc/vmport_rpc.c

-- 
1.8.4




[Qemu-devel] [PATCH v7 4/9] vmport_rpc: Add the object vmport_rpc

2015-06-12 Thread Don Slutz
This is the 1st part of Add limited support of VMware's hyper-call
rpc.

This patch uses existing infrastructure used by vmmouse.c (provided
by vmport.c) to handle the VMware backdoor command 30.

One of the better on-line references is:

https://sites.google.com/site/chitchatvmback/backdoor

More in next patch.

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 hw/i386/pc.c  |   6 +++
 hw/misc/Makefile.objs |   1 +
 hw/misc/vmport_rpc.c  | 126 ++
 3 files changed, 133 insertions(+)
 create mode 100644 hw/misc/vmport_rpc.c

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 3f0d435..48711c6 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1478,8 +1478,14 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
 i8042 = isa_create_simple(isa_bus, i8042);
 i8042_setup_a20_line(i8042, a20_line[0]);
 if (!no_vmport) {
+ISADevice *vmport_rpc;
+
 vmport_init(isa_bus);
 vmmouse = isa_try_create(isa_bus, vmmouse);
+vmport_rpc = isa_try_create(isa_bus, vmport_rpc);
+if (vmport_rpc) {
+qdev_init_nofail(DEVICE(vmport_rpc));
+}
 } else {
 vmmouse = NULL;
 }
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 4aa76ff..e04c8ac 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -7,6 +7,7 @@ common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o
 common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o
 
 obj-$(CONFIG_VMPORT) += vmport.o
+obj-$(CONFIG_VMPORT) += vmport_rpc.o
 
 # ARM devices
 common-obj-$(CONFIG_PL310) += arm_l2x0.o
diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
new file mode 100644
index 000..b7cd355
--- /dev/null
+++ b/hw/misc/vmport_rpc.c
@@ -0,0 +1,126 @@
+/*
+ * QEMU VMPORT RPC emulation
+ *
+ * Copyright (C) 2015 Verizon Corporation
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License Version 2 (GPLv2)
+ * as published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details. http://www.gnu.org/licenses/.
+ */
+
+/*
+ * One of the better on-line references is:
+ *
+ * https://sites.google.com/site/chitchatvmback/backdoor
+ *
+ * Which points you to:
+ *
+ * http://open-vm-tools.sourceforge.net/
+ *
+ * as a place to get more accurate information by studying.
+ */
+
+#include hw/hw.h
+#include hw/i386/pc.h
+#include hw/qdev.h
+#include trace.h
+#include qmp-commands.h
+#include qapi/qmp/qerror.h
+
+/* #define VMPORT_RPC_DEBUG */
+
+#define TYPE_VMPORT_RPC vmport_rpc
+#define VMPORT_RPC(obj) OBJECT_CHECK(VMPortRpcState, (obj), TYPE_VMPORT_RPC)
+
+/* VMPORT RPC Command */
+#define VMPORT_RPC_COMMAND  30
+
+/* The vmport_rpc object. */
+typedef struct VMPortRpcState {
+ISADevice parent_obj;
+
+/* Properties */
+uint64_t reset_time;
+uint64_t build_number_value;
+uint64_t build_number_time;
+
+/* Private data */
+} VMPortRpcState;
+
+typedef struct {
+uint32_t eax;
+uint32_t ebx;
+uint32_t ecx;
+uint32_t edx;
+uint32_t esi;
+uint32_t edi;
+} vregs;
+
+static uint32_t vmport_rpc_ioport_read(void *opaque, uint32_t addr)
+{
+VMPortRpcState *s = opaque;
+union {
+uint32_t data[6];
+vregs regs;
+} ur;
+
+vmmouse_get_data(ur.data);
+
+s-build_number_time++;
+
+vmmouse_set_data(ur.data);
+return ur.data[0];
+}
+
+static void vmport_rpc_reset(DeviceState *d)
+{
+VMPortRpcState *s = VMPORT_RPC(d);
+
+s-reset_time = 14;
+s-build_number_value = 0;
+s-build_number_time = 0;
+}
+
+static void vmport_rpc_realize(DeviceState *dev, Error **errp)
+{
+VMPortRpcState *s = VMPORT_RPC(dev);
+
+vmport_register(VMPORT_RPC_COMMAND, vmport_rpc_ioport_read, s);
+}
+
+static Property vmport_rpc_properties[] = {
+DEFINE_PROP_UINT64(reset-time, VMPortRpcState, reset_time, 14),
+DEFINE_PROP_UINT64(build-number-value, VMPortRpcState,
+   build_number_value, 0),
+DEFINE_PROP_UINT64(build-number-time, VMPortRpcState,
+   build_number_time, 0),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vmport_rpc_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc-realize = vmport_rpc_realize;
+dc-reset = vmport_rpc_reset;
+dc-props = vmport_rpc_properties;
+}
+
+static const TypeInfo vmport_rpc_info = {
+.name  = TYPE_VMPORT_RPC,
+.parent= TYPE_ISA_DEVICE,
+.instance_size = sizeof(VMPortRpcState),
+.class_init= vmport_rpc_class_init,
+};
+
+static void vmport_rpc_register_types(void)
+{
+type_register_static(vmport_rpc_info);
+}
+
+type_init(vmport_rpc_register_types)
-- 
1.8.4




[Qemu-devel] [PATCH v7 2/9] vmport: Switch to trace

2015-06-12 Thread Don Slutz
Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 hw/misc/vmport.c | 7 +++
 trace-events | 4 
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index 51b64bc..203e892 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -27,7 +27,7 @@
 #include sysemu/kvm.h
 #include hw/qdev.h
 
-//#define VMPORT_DEBUG
+#include trace.h
 
 #define VMPORT_CMD_GETVERSION 0x0a
 #define VMPORT_CMD_GETRAMSIZE 0x14
@@ -71,6 +71,7 @@ static uint64_t vmport_ioport_read(void *opaque, hwaddr addr,
 
 /* Only support 1 address */
 if (addr) {
+trace_vmport_ioport_ignored(addr, size, cs);
 return ~0U;
 }
 cpu_synchronize_state(cs);
@@ -84,9 +85,7 @@ static uint64_t vmport_ioport_read(void *opaque, hwaddr addr,
 return eax;
 if (!s-func[command])
 {
-#ifdef VMPORT_DEBUG
-fprintf(stderr, vmport: unknown command %x\n, command);
-#endif
+trace_vmport_ioport_unknown_command(command);
 return eax;
 }
 
diff --git a/trace-events b/trace-events
index d6c73e6..e229aac 100644
--- a/trace-events
+++ b/trace-events
@@ -883,6 +883,10 @@ pc87312_info_ide(uint32_t base) base 0x%x
 pc87312_info_parallel(uint32_t base, uint32_t irq) base 0x%x, irq %u
 pc87312_info_serial(int n, uint32_t base, uint32_t irq) id=%d, base 0x%x, irq 
%u
 
+# hw/misc/vmport.c
+vmport_ioport_ignored(uint64_t addr, uint32_t size, void *cs) addr=%# PRIx64 
 size=%u cs=%p
+vmport_ioport_unknown_command(unsigned char command) %x
+
 # hw/scsi/vmw_pvscsi.c
 pvscsi_ring_init_data(uint32_t txr_len_log2, uint32_t rxr_len_log2) TX/RX 
rings logarithms set to %d/%d
 pvscsi_ring_init_msg(uint32_t len_log2) MSG ring logarithm set to %d
-- 
1.8.4




[Qemu-devel] [PATCH v7 8/9] vmport: Add VMware all ring hack

2015-06-12 Thread Don Slutz
This is done by adding a new machine property vmware-port-ring3 that
needs to be enabled to have any effect.  It only effects accel=tcg
mode.  It is needed if you want to use VMware tools in accel=tcg
mode.

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 hw/i386/pc.c | 26 +-
 hw/i386/pc_piix.c|  2 +-
 hw/i386/pc_q35.c |  2 +-
 include/hw/i386/pc.h |  6 +-
 target-i386/cpu-qom.h|  3 +++
 target-i386/seg_helper.c |  9 +
 6 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 48711c6..40d4e33 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1042,7 +1042,9 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
 object_unref(OBJECT(cpu));
 }
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+  bool vmware_port_ring3)
 {
 int i;
 X86CPU *cpu = NULL;
@@ -1073,6 +1075,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState 
*icc_bridge)
 error_report_err(error);
 exit(1);
 }
+cpu-allow_vmport_ring3 = vmware_port_ring3;
 object_unref(OBJECT(cpu));
 }
 
@@ -1841,6 +1844,21 @@ static bool pc_machine_get_aligned_dimm(Object *obj, 
Error **errp)
 return pcms-enforce_aligned_dimm;
 }
 
+static bool pc_machine_get_vmware_port_ring3(Object *obj, Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+return pcms-vmware_port_ring3;
+}
+
+static void pc_machine_set_vmware_port_ring3(Object *obj, bool value,
+ Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+pcms-vmware_port_ring3 = value;
+}
+
 static void pc_machine_initfn(Object *obj)
 {
 PCMachineState *pcms = PC_MACHINE(obj);
@@ -1871,6 +1889,12 @@ static void pc_machine_initfn(Object *obj)
 object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM,
  pc_machine_get_aligned_dimm,
  NULL, NULL);
+
+pcms-vmware_port_ring3 = false;
+object_property_add_bool(obj, PC_MACHINE_VMWARE_PORT_RING3,
+ pc_machine_get_vmware_port_ring3,
+ pc_machine_set_vmware_port_ring3,
+ NULL);
 }
 
 static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index e142f75..890c45e 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -146,7 +146,7 @@ static void pc_init1(MachineState *machine)
 object_property_add_child(qdev_get_machine(), icc-bridge,
   OBJECT(icc_bridge), NULL);
 
-pc_cpus_init(machine-cpu_model, icc_bridge);
+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
 
 if (kvm_enabled()  kvmclock_enabled) {
 kvmclock_create();
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index b68263d..3883872 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -137,7 +137,7 @@ static void pc_q35_init(MachineState *machine)
 object_property_add_child(qdev_get_machine(), icc-bridge,
   OBJECT(icc_bridge), NULL);
 
-pc_cpus_init(machine-cpu_model, icc_bridge);
+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
 pc_acpi_init(q35-acpi-dsdt.aml);
 
 kvmclock_create();
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 86c5651..9e648d2 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -40,6 +40,7 @@ struct PCMachineState {
 
 uint64_t max_ram_below_4g;
 OnOffAuto vmport;
+bool vmware_port_ring3;
 bool enforce_aligned_dimm;
 };
 
@@ -48,6 +49,7 @@ struct PCMachineState {
 #define PC_MACHINE_MAX_RAM_BELOW_4G max-ram-below-4g
 #define PC_MACHINE_VMPORT   vmport
 #define PC_MACHINE_ENFORCE_ALIGNED_DIMM enforce-aligned-dimm
+#define PC_MACHINE_VMWARE_PORT_RING3 vmware-port-ring3
 
 /**
  * PCMachineClass:
@@ -161,7 +163,9 @@ extern int fd_bootchk;
 void pc_register_ferr_irq(qemu_irq irq);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+  bool vmware_port_ring3);
 void pc_hot_add_cpu(const int64_t id, Error **errp);
 void pc_acpi_init(const char *default_dsdt);
 
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 7a4fddd..ccbc5bb 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -109,6 +109,9 @@ typedef struct X86CPU {
  */
 bool enable_pmu;
 
+/* allow_vmport_ring3 true says enable VMware port access in ring3 */
+bool allow_vmport_ring3

[Qemu-devel] [Bug 1463463] Re: PCI devices on PCI to PCI bridges stopped being accessable from Xen with QEMU 2.3.0

2015-06-09 Thread Don Slutz
Since Xen's tool stack does not know about PCI to PCI bridges, a config
that shows this issue also requires the correct Linux kernel argument
pci=assign-busses is used.

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

Title:
  PCI devices on PCI to PCI bridges stopped being accessable from Xen
  with QEMU 2.3.0

Status in QEMU:
  New

Bug description:
  The change set:

  commit 3996e85c1822e05c50250f8d2d1e57b6bea1229d
  Author: Paul Durrant paul.durr...@citrix.com
  Date:   Tue Jan 20 11:06:19 2015 +

  Xen: Use the ioreq-server API when available
  ...

  Added calls to xen_map_pcidev()  when available.  However these call
  are only done at startup, not when the guest configures the PCI to PCI
  bridge.  So Xen 4.5.0 (which has these) using a QEMU 2.3.0 or later
  can no longer access PCI devices that are not on a root bridge.

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



[Qemu-devel] [Bug 1463463] [NEW] PCI devices on PCI to PCI bridges stopped being accessable from Xen with QEMU 2.3.0

2015-06-09 Thread Don Slutz
Public bug reported:

The change set:

commit 3996e85c1822e05c50250f8d2d1e57b6bea1229d
Author: Paul Durrant paul.durr...@citrix.com
Date:   Tue Jan 20 11:06:19 2015 +

Xen: Use the ioreq-server API when available
...

Added calls to xen_map_pcidev()  when available.  However these call are
only done at startup, not when the guest configures the PCI to PCI
bridge.  So Xen 4.5.0 (which has these) using a QEMU 2.3.0 or later can
no longer access PCI devices that are not on a root bridge.

** Affects: qemu
 Importance: Undecided
 Status: New

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

Title:
  PCI devices on PCI to PCI bridges stopped being accessable from Xen
  with QEMU 2.3.0

Status in QEMU:
  New

Bug description:
  The change set:

  commit 3996e85c1822e05c50250f8d2d1e57b6bea1229d
  Author: Paul Durrant paul.durr...@citrix.com
  Date:   Tue Jan 20 11:06:19 2015 +

  Xen: Use the ioreq-server API when available
  ...

  Added calls to xen_map_pcidev()  when available.  However these call
  are only done at startup, not when the guest configures the PCI to PCI
  bridge.  So Xen 4.5.0 (which has these) using a QEMU 2.3.0 or later
  can no longer access PCI devices that are not on a root bridge.

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



Re: [Qemu-devel] [PATCH v2 4/4] xen: Fix map/unmap of pcidev to ioreq server

2015-06-09 Thread Don Slutz
On 06/09/15 10:03, Paul Durrant wrote:
 -Original Message-
 From: Don Slutz [mailto:dsl...@verizon.com]
 Sent: 09 June 2015 14:51
 To: Paul Durrant; Slutz, Donald Christopher; qemu-devel@nongnu.org; xen-
 de...@lists.xen.org
 Cc: Michael S. Tsirkin; Stefano Stabellini; Don Slutz
 Subject: Re: [PATCH v2 4/4] xen: Fix map/unmap of pcidev to ioreq server

 On 06/09/15 05:05, Paul Durrant wrote:
 -Original Message-
 From: Don Slutz [mailto:dsl...@verizon.com]
 Sent: 08 June 2015 22:19
 To: qemu-devel@nongnu.org; xen-de...@lists.xen.org
 Cc: Michael S. Tsirkin; Paul Durrant; Stefano Stabellini; Don Slutz; Don 
 Slutz
 Subject: [PATCH v2 4/4] xen: Fix map/unmap of pcidev to ioreq server

 The commit 707ff80021ccd7a68f4b3d2c44eebf87efbb41c4 added usage of
 xc_hvm_map_pcidev_from_ioreq_server() and
 xc_hvm_unmap_pcidev_from_ioreq_server().  These routines only
 correctly work if the PCI BDF of a PCI device is unique.  The 3
 parts (bus, device, and function) of a PCI BDF are not required to
 be unique.

 The PCI BDF is accessed in QEMU:
   buspci_bus_num()
   device PCI_SLOT()
   function   PCI_FUNC()

 Add a hash table to track the current set of PCI BDFs and only call
 on xc_hvm_map_pcidev_from_ioreq_server() and
 xc_hvm_unmap_pcidev_from_ioreq_server() when needed.


 This seems to imply that the devices are being realized multiple times
 without being unrealized?

 Not directly.  The devices are not being realized in QEMU terms.  The
 PCI to PCI brige is changing state, and the BDF for all PCI devices on
 the secondary bus changes when the PCI config named
 PCI_SECONDARY_BUS on
 the PCI to PCI bridge is changed.  This is what patch #2 is all about.

 Is that really the case?


 That is what it looks like to Xen.  But the device listener callbacks
 are not called.
 
 Then what's calling xc_hvm_map_pcidev_from_ioreq_server()?



Currently (without these patches) the calls on
xc_hvm_map_pcidev_from_ioreq_server() are the ones you added.  These are
from QEMU's device realize.  However since on PCI reset (aka start up)
the seconary bus number is zero.  So the call on
pci_bus_num(pci_dev-bus) will return zero in that case.  So using the
subset trace output (copied from below) and adjusted to be the old way:

xen_map_pcidev id: 1 bdf: 00.01.00
xen_map_pcidev id: 1 bdf: 00.01.00
xen_map_pcidev id: 1 bdf: 00.01.00

Is part of what you see.  It may help to have the Xen config that matters:

device_model_args_hvm = [
 -monitor,
 pty,
 -boot,
 menu=on,
 -device,
 pci-bridge,chassis_nr=1,msi=on,id=pciBridge1.0,addr=0x11.0,
 -device,
 pci-bridge,chassis_nr=2,msi=on,id=pciBridge5.0,multifunction=on,addr=0x15.0,
 -device,
 pci-bridge,chassis_nr=3,msi=on,id=pciBridge6.0,multifunction=on,addr=0x16.0,
 -device,
 
pci-bridge,chassis_nr=4,msi=on,id=pciBridge7.0,multifunction=on,bus=pciBridge1.0,addr=0x17.0,
 -device,
 pci-bridge,chassis_nr=5,msi=on,id=pciBridge8.0,multifunction=on,addr=0x18.0,
 -device,
 pvscsi,id=scsi0,bus=pciBridge5.0,addr=0x1.0x0,
 -drive,
 if=none,id=disk0-0,format=raw,file=/dev/etherd/e500.1,
 -device,
 scsi-disk,vendor=VMware,ver=1.0,product=Virtual
disk,bus=scsi0.0,scsi-id=0,drive=disk0-0,
 -device,
 pvscsi,id=sas1,bus=pciBridge7.0,addr=0x1.0x0,
 -drive,
 if=none,id=disk1-1,format=raw,file=/dev/etherd/e500.2,
 -device,
 scsi-disk,vendor=VMware,ver=1.0,product=Virtual
disk,bus=sas1.0,scsi-id=1,drive=disk1-1,
 -device,
 pvscsi,id=scsi2,bus=pciBridge1.0,addr=0x3.0x0,
 -drive,
 if=none,id=disk2-2,format=raw,file=/dev/etherd/e500.3,
 -device,
 scsi-disk,vendor=VMware,ver=1.0,product=Virtual
disk,bus=scsi2.0,scsi-id=2,drive=disk2-2,
 -device,
 
e1000,id=nic2,netdev=net2,mac=00:0c:29:86:44:b4,bus=pciBridge5.0,addr=0x3.0x0,
 -netdev,
 type=tap,id=net2,ifname=vif.2-emu,script=/etc/qemu-ifup,downscript=no,
 -device,
 
vmxnet3,id=nic3,netdev=net3,mac=00:0c:29:86:44:be,bus=pciBridge5.0,addr=0x4.0x0,
 -netdev,
 type=tap,id=net3,ifname=vif.3-emu,script=/etc/qemu-ifup,downscript=no,
]


If you want to try this, you would also need a bootable disk listed in
disk=

 I don't understand why you are having to introduce this to avoid
 duplicate calls?


That is because in general a PCI device's BDF is not fixed.  The only
fixed ones are the ones on the root (host bus).  It might help to look
at the code for pci_bus_num():

int pci_bus_num(PCIBus *s)
{
if (pci_bus_is_root(s))
return 0;   /* pci host bridge */
return s-parent_dev-config[PCI_SECONDARY_BUS];
}

So the bus number this routine returns depends on what the guest has set
in the PCI config space of the PCI to PCI bridge.

The starting (and reset) value is 0.  So for the config above at QEMU
device realized time there are 3 PCI devices (PIIX4, 2 pvscsi disk
controllers).

   -Don Slutz

   Paul



-Don Slutz

   Paul

 Also fix the PCI BDF default stderr trace output: bus is seperated
 by ':', and function is only 1 digit.

 Here is an example of stderr trace output:

 xen_map_pcidev id: 1 bdf: 00:00.0
 xen_map_pcidev

Re: [Qemu-devel] [PATCH v2 0/4] Fix device listener interface for PCI to PCI bridges

2015-06-09 Thread Don Slutz
On 06/09/15 10:27, Michael S. Tsirkin wrote:
 On Tue, Jun 09, 2015 at 02:14:29PM +, Paul Durrant wrote:
 -Original Message-
 From: Michael S. Tsirkin [mailto:m...@redhat.com]
 Sent: 09 June 2015 13:30
 To: Paul Durrant
 Cc: Don Slutz; qemu-devel@nongnu.org; xen-de...@lists.xen.org; Stefano
 Stabellini
 Subject: Re: [PATCH v2 0/4] Fix device listener interface for PCI to PCI 
 bridges

 On Tue, Jun 09, 2015 at 10:58:26AM +, Paul Durrant wrote:
 -Original Message-
 From: Michael S. Tsirkin [mailto:m...@redhat.com]
 Sent: 09 June 2015 11:52
 To: Paul Durrant
 Cc: Don Slutz; qemu-devel@nongnu.org; xen-de...@lists.xen.org;
 Stefano
 Stabellini
 Subject: Re: [PATCH v2 0/4] Fix device listener interface for PCI to PCI
 bridges

 On Tue, Jun 09, 2015 at 09:18:49AM +, Paul Durrant wrote:
 -Original Message-
 From: Michael S. Tsirkin [mailto:m...@redhat.com]
 Sent: 09 June 2015 10:13
 To: Don Slutz
 Cc: qemu-devel@nongnu.org; xen-de...@lists.xen.org; Paul Durrant;
 Stefano Stabellini
 Subject: Re: [PATCH v2 0/4] Fix device listener interface for PCI to PCI
 bridges

 On Mon, Jun 08, 2015 at 05:18:48PM -0400, Don Slutz wrote:
 changes v1 to v2:
   Split v1 patch into 3.

   Added a BUG FIX patch (#1: exec: Do not use MemoryRegion
 after
   free).

 Technically this bug fix should be a separate patch, however this
 issue only seems to reproduce when this patch set is applied.


   Michael S. Tsirkin:
 You need some other API that makes sense, probably PCI
 specific.
   This is basically patch #2: Extend device listener interface...

 This is relying on undocumented assumptions and how specific
 firmware works. There's nothing special about bus number 255,
 and 0 is not very special either (except it happens to be the
 reset value).
   Dropped all checking of 0 and 255.


 Open question by Michael S. Tsirkin:

 On Thu, May 28, 2015 at 07:25:50AM -0400, Don Slutz wrote:
 ...
 It is not clear to me that the complexity of tracking bus
 visibility make sense.  Clearly you do.
 Well what was the point of the change?

 To get config cycles that are valid that you do not get today.

 If you don't care that we get irrelevant config cycles why not
 just send them all to QEMU?


 That would need to be answered by Paul Durrant and/or other
 people
 (see
 below)


 We could broadcast config space ioreqs to all emulators, the
 problem
 is how do we know (in the case of a read) which emulator is actually
 the one supplying the data? At some level Xen needs to know who
 is
 implementing what.

   Paul Durrant

 Can irrelevant emulators all respond with some kind of nack?
 Xen would pick the one that did respond correctly.


 I guess that's possible if we add an extra bit to the ioreq_t, but QEMU
 would still need to know when to nack and when to ack.

 It's simple: ack if we find a device handling the specific BDF.
 The result would at least be contained.
 OTOH detecting master aborts in core is useful since it would
 let us implement error reporting correctly.


 It's still much simpler if qemu updates Xen with exact set of (S)BDFs 
 it's
 handling.

   Paul


 I suspect this calls for a bigger change, you need to re-scan
 all of the tree to detect visible devices.
 Maybe just write some xen-specific code to do this on each
 config access.

 Well, that's the thing really... what triggers the re-scan. Do we really 
 need
 to scan on each access or is there a way to know when the topology is
 changed? Doing the former doesn't really sound wonderfully efficient and, if
 the answer to the second is yes, then that's the time to update Xen with the
 currently valid set of BDFs.

   Paul


 Several things can trigger a topology change.

 Well, IMO those need to be enumerated and suitable hooks need to be put in 
 place so that Xen can be informed of the changes.


This patch adds one of the hooks (the one that lets Xen know of the
change to BDF).

The hook that can report on the accessibility of a given PCI device is
much more complex since there is no simple way to say PCI device pvscsi
#2 is not accessible since there can be multiple PCI devices with the
same name and they can start out all having the BDF.  One would need to
invent a way to describe the PCI tree and pass that around.

   Paul
 
 pci_data_write and pci_data_read already do bus lookups.
 It seems that returning a nack there would just require
 hooks in these two places.
 

Yes, the answer of can QEMU can reach a BDF right now is simple.  And
it may make sense to add.

Returning a set of reachable BDFs is much harder.  I went with returning
the set of BDFs that may be reachable.  I.E. every BDF registered with
Xen should be sent to this QEMU.  At startup there will be ones that
either generate nacks or are reached.

Proper PCI bridge scanning code (which is missing from hvmloader) will
attempt to assign a non-overlapping set of BDF for all PCI devices
found.  With enough PCI to PCI bridges (greater

Re: [Qemu-devel] [PATCH v2 4/4] xen: Fix map/unmap of pcidev to ioreq server

2015-06-09 Thread Don Slutz
On 06/09/15 11:11, Paul Durrant wrote:
 -Original Message-
 From: Don Slutz [mailto:dsl...@verizon.com]
 Sent: 09 June 2015 15:28
 To: Paul Durrant; Slutz, Donald Christopher; qemu-devel@nongnu.org; xen-
 de...@lists.xen.org
 Cc: Michael S. Tsirkin; Stefano Stabellini; Don Slutz
 Subject: Re: [PATCH v2 4/4] xen: Fix map/unmap of pcidev to ioreq server

 On 06/09/15 10:03, Paul Durrant wrote:
 -Original Message-
 From: Don Slutz [mailto:dsl...@verizon.com]
 Sent: 09 June 2015 14:51
 To: Paul Durrant; Slutz, Donald Christopher; qemu-devel@nongnu.org;
 xen-
 de...@lists.xen.org
 Cc: Michael S. Tsirkin; Stefano Stabellini; Don Slutz
 Subject: Re: [PATCH v2 4/4] xen: Fix map/unmap of pcidev to ioreq server

 On 06/09/15 05:05, Paul Durrant wrote:
 -Original Message-
 From: Don Slutz [mailto:dsl...@verizon.com]
 Sent: 08 June 2015 22:19
 To: qemu-devel@nongnu.org; xen-de...@lists.xen.org
 Cc: Michael S. Tsirkin; Paul Durrant; Stefano Stabellini; Don Slutz; Don
 Slutz
 Subject: [PATCH v2 4/4] xen: Fix map/unmap of pcidev to ioreq server

 The commit 707ff80021ccd7a68f4b3d2c44eebf87efbb41c4 added usage
 of
 xc_hvm_map_pcidev_from_ioreq_server() and
 xc_hvm_unmap_pcidev_from_ioreq_server().  These routines only
 correctly work if the PCI BDF of a PCI device is unique.  The 3
 parts (bus, device, and function) of a PCI BDF are not required to
 be unique.

 The PCI BDF is accessed in QEMU:
   buspci_bus_num()
   device PCI_SLOT()
   function   PCI_FUNC()

 Add a hash table to track the current set of PCI BDFs and only call
 on xc_hvm_map_pcidev_from_ioreq_server() and
 xc_hvm_unmap_pcidev_from_ioreq_server() when needed.


 This seems to imply that the devices are being realized multiple times
 without being unrealized?

 Not directly.  The devices are not being realized in QEMU terms.  The
 PCI to PCI brige is changing state, and the BDF for all PCI devices on
 the secondary bus changes when the PCI config named
 PCI_SECONDARY_BUS on
 the PCI to PCI bridge is changed.  This is what patch #2 is all about.

 Is that really the case?


 That is what it looks like to Xen.  But the device listener callbacks
 are not called.

 Then what's calling xc_hvm_map_pcidev_from_ioreq_server()?



 Currently (without these patches) the calls on
 xc_hvm_map_pcidev_from_ioreq_server() are the ones you added.  These
 are
 from QEMU's device realize.  However since on PCI reset (aka start up)
 the seconary bus number is zero.  So the call on
 pci_bus_num(pci_dev-bus) will return zero in that case.  So using the
 subset trace output (copied from below) and adjusted to be the old way:

 xen_map_pcidev id: 1 bdf: 00.01.00
 xen_map_pcidev id: 1 bdf: 00.01.00
 xen_map_pcidev id: 1 bdf: 00.01.00

 Is part of what you see.  It may help to have the Xen config that matters:

 device_model_args_hvm = [
  -monitor,
  pty,
  -boot,
  menu=on,
  -device,
  pci-bridge,chassis_nr=1,msi=on,id=pciBridge1.0,addr=0x11.0,
  -device,
  pci-
 bridge,chassis_nr=2,msi=on,id=pciBridge5.0,multifunction=on,addr=0x15.0,
  -device,
  pci-
 bridge,chassis_nr=3,msi=on,id=pciBridge6.0,multifunction=on,addr=0x16.0,
  -device,
  pci-
 bridge,chassis_nr=4,msi=on,id=pciBridge7.0,multifunction=on,bus=pciBridge
 1.0,addr=0x17.0,
  -device,
  pci-
 bridge,chassis_nr=5,msi=on,id=pciBridge8.0,multifunction=on,addr=0x18.0,
  -device,
  pvscsi,id=scsi0,bus=pciBridge5.0,addr=0x1.0x0,
  -drive,
  if=none,id=disk0-0,format=raw,file=/dev/etherd/e500.1,
  -device,
  scsi-disk,vendor=VMware,ver=1.0,product=Virtual
 disk,bus=scsi0.0,scsi-id=0,drive=disk0-0,
  -device,
  pvscsi,id=sas1,bus=pciBridge7.0,addr=0x1.0x0,
  -drive,
  if=none,id=disk1-1,format=raw,file=/dev/etherd/e500.2,
  -device,
  scsi-disk,vendor=VMware,ver=1.0,product=Virtual
 disk,bus=sas1.0,scsi-id=1,drive=disk1-1,
  -device,
  pvscsi,id=scsi2,bus=pciBridge1.0,addr=0x3.0x0,
  -drive,
  if=none,id=disk2-2,format=raw,file=/dev/etherd/e500.3,
  -device,
  scsi-disk,vendor=VMware,ver=1.0,product=Virtual
 disk,bus=scsi2.0,scsi-id=2,drive=disk2-2,
  -device,

 e1000,id=nic2,netdev=net2,mac=00:0c:29:86:44:b4,bus=pciBridge5.0,addr=0
 x3.0x0,
  -netdev,
  type=tap,id=net2,ifname=vif.2-emu,script=/etc/qemu-
 ifup,downscript=no,
  -device,

 vmxnet3,id=nic3,netdev=net3,mac=00:0c:29:86:44:be,bus=pciBridge5.0,add
 r=0x4.0x0,
  -netdev,
  type=tap,id=net3,ifname=vif.3-emu,script=/etc/qemu-
 ifup,downscript=no,
 ]


 If you want to try this, you would also need a bootable disk listed in
 disk=

 I don't understand why you are having to introduce this to avoid
 duplicate calls?


 That is because in general a PCI device's BDF is not fixed.  The only
 fixed ones are the ones on the root (host bus).
 
 Yes, the code was written with that assumption, which is correct if you use 
 the libxl toolstack. You are bypassing the toolstack and hence running into 
 problems.
 

I am bypassing the libxl toolstack. But this works in QEMU 2.2.0, breaks
in QEMU 2.3.0.  To me that is a bug.

So I do not see have

[Qemu-devel] [Bug 1463463] Re: PCI devices on PCI to PCI bridges stopped being accessable from Xen with QEMU 2.3.0

2015-06-09 Thread Don Slutz
** Attachment added: This is the Xen config file used
   
https://bugs.launchpad.net/qemu/+bug/1463463/+attachment/4412144/+files/C63-min-tools.bridge3.xfg

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

Title:
  PCI devices on PCI to PCI bridges stopped being accessable from Xen
  with QEMU 2.3.0

Status in QEMU:
  New

Bug description:
  The change set:

  commit 3996e85c1822e05c50250f8d2d1e57b6bea1229d
  Author: Paul Durrant paul.durr...@citrix.com
  Date:   Tue Jan 20 11:06:19 2015 +

  Xen: Use the ioreq-server API when available
  ...

  Added calls to xen_map_pcidev()  when available.  However these call
  are only done at startup, not when the guest configures the PCI to PCI
  bridge.  So Xen 4.5.0 (which has these) using a QEMU 2.3.0 or later
  can no longer access PCI devices that are not on a root bridge.

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



Re: [Qemu-devel] [PATCH v2 4/4] xen: Fix map/unmap of pcidev to ioreq server

2015-06-09 Thread Don Slutz
On 06/09/15 05:05, Paul Durrant wrote:
 -Original Message-
 From: Don Slutz [mailto:dsl...@verizon.com]
 Sent: 08 June 2015 22:19
 To: qemu-devel@nongnu.org; xen-de...@lists.xen.org
 Cc: Michael S. Tsirkin; Paul Durrant; Stefano Stabellini; Don Slutz; Don 
 Slutz
 Subject: [PATCH v2 4/4] xen: Fix map/unmap of pcidev to ioreq server

 The commit 707ff80021ccd7a68f4b3d2c44eebf87efbb41c4 added usage of
 xc_hvm_map_pcidev_from_ioreq_server() and
 xc_hvm_unmap_pcidev_from_ioreq_server().  These routines only
 correctly work if the PCI BDF of a PCI device is unique.  The 3
 parts (bus, device, and function) of a PCI BDF are not required to
 be unique.

 The PCI BDF is accessed in QEMU:
   buspci_bus_num()
   device PCI_SLOT()
   function   PCI_FUNC()

 Add a hash table to track the current set of PCI BDFs and only call
 on xc_hvm_map_pcidev_from_ioreq_server() and
 xc_hvm_unmap_pcidev_from_ioreq_server() when needed.

 
 This seems to imply that the devices are being realized multiple times 
 without being unrealized? 

Not directly.  The devices are not being realized in QEMU terms.  The
PCI to PCI brige is changing state, and the BDF for all PCI devices on
the secondary bus changes when the PCI config named PCI_SECONDARY_BUS on
the PCI to PCI bridge is changed.  This is what patch #2 is all about.

 Is that really the case?


That is what it looks like to Xen.  But the device listener callbacks
are not called.

   -Don Slutz

   Paul
 
 Also fix the PCI BDF default stderr trace output: bus is seperated
 by ':', and function is only 1 digit.

 Here is an example of stderr trace output:

 xen_map_pcidev id: 1 bdf: 00:00.0
 xen_map_pcidev id: 1 bdf: 00:01.0
 xen_map_pcidev id: 1 bdf: 00:01.1
 xen_map_pcidev id: 1 bdf: 00:01.3
 xen_map_pcidev id: 1 bdf: 00:02.0
 xen_map_pcidev id: 1 bdf: 00:03.0
 xen_map_pcidev id: 1 bdf: 00:04.0
 xen_map_pcidev id: 1 bdf: 00:05.0
 xen_map_pcidev id: 1 bdf: 00:11.0
 xen_map_pcidev id: 1 bdf: 00:15.0
 xen_map_pcidev id: 1 bdf: 00:16.0
 xen_map_pcidev id: 1 bdf: 00:17.0
 xen_map_pcidev id: 1 bdf: 00:18.0
 xen_map_pcidev_dup id: 1 bdf: 00:01.0 dup: 2
 xen_map_pcidev_dup id: 1 bdf: 00:01.0 dup: 3
 xen_map_pcidev_dup id: 1 bdf: 00:03.0 dup: 2
 xen_map_pcidev_dup id: 1 bdf: 00:03.0 dup: 3
 xen_map_pcidev_dup id: 1 bdf: 00:04.0 dup: 2
 xen_unmap_pcidev_dup id: 1 bdf: 00:03.0 dup: 2
 xen_map_pcidev id: 1 bdf: ff:03.0
 xen_unmap_pcidev id: 1 bdf: 00:17.0
 xen_map_pcidev id: 1 bdf: ff:17.0
 xen_unmap_pcidev_dup id: 1 bdf: 00:01.0 dup: 2
 xen_map_pcidev id: 1 bdf: ff:01.0
 xen_unmap_pcidev_dup id: 1 bdf: 00:03.0 dup: 1
 xen_map_pcidev_dup id: 1 bdf: ff:03.0 dup: 2
 xen_unmap_pcidev_dup id: 1 bdf: 00:04.0 dup: 1
 xen_map_pcidev id: 1 bdf: ff:04.0
 xen_unmap_pcidev_dup id: 1 bdf: ff:03.0 dup: 1
 xen_map_pcidev id: 1 bdf: 01:03.0
 xen_unmap_pcidev id: 1 bdf: ff:17.0
 xen_map_pcidev id: 1 bdf: 01:17.0
 xen_unmap_pcidev_dup id: 1 bdf: 00:01.0 dup: 1
 xen_map_pcidev_dup id: 1 bdf: ff:01.0 dup: 2
 xen_unmap_pcidev_dup id: 1 bdf: ff:01.0 dup: 1
 xen_map_pcidev id: 1 bdf: 02:01.0
 xen_unmap_pcidev id: 1 bdf: ff:01.0
 xen_map_pcidev id: 1 bdf: 03:01.0
 xen_unmap_pcidev id: 1 bdf: ff:03.0
 xen_map_pcidev id: 1 bdf: 03:03.0
 xen_unmap_pcidev id: 1 bdf: ff:04.0
 xen_map_pcidev id: 1 bdf: 03:04.0
 xen_unmap_pcidev id: 1 bdf: 00:04.0
 xen_unmap_pcidev id: 1 bdf: 00:05.0
 xen_unmap_pcidev id: 1 bdf: 01:03.0
 xen_map_pcidev_dup id: 1 bdf: 00:03.0 dup: 2
 xen_unmap_pcidev id: 1 bdf: 01:17.0
 xen_map_pcidev id: 1 bdf: 00:17.0
 xen_unmap_pcidev id: 1 bdf: 03:01.0
 xen_map_pcidev_dup id: 1 bdf: 00:01.0 dup: 2
 xen_unmap_pcidev id: 1 bdf: 03:03.0
 xen_map_pcidev_dup id: 1 bdf: 00:03.0 dup: 3
 xen_unmap_pcidev id: 1 bdf: 03:04.0
 xen_map_pcidev id: 1 bdf: 00:04.0
 xen_unmap_pcidev_dup id: 1 bdf: 00:03.0 dup: 2
 xen_map_pcidev id: 1 bdf: 01:03.0
 xen_unmap_pcidev id: 1 bdf: 00:17.0
 xen_map_pcidev id: 1 bdf: 01:17.0
 xen_unmap_pcidev id: 1 bdf: 02:01.0
 xen_map_pcidev_dup id: 1 bdf: 00:01.0 dup: 3
 xen_unmap_pcidev_dup id: 1 bdf: 00:01.0 dup: 2
 xen_map_pcidev id: 1 bdf: 02:01.0
 xen_unmap_pcidev_dup id: 1 bdf: 00:01.0 dup: 1
 xen_map_pcidev id: 1 bdf: 03:01.0
 xen_unmap_pcidev_dup id: 1 bdf: 00:03.0 dup: 1
 xen_map_pcidev id: 1 bdf: 03:03.0
 xen_unmap_pcidev id: 1 bdf: 00:04.0
 xen_map_pcidev id: 1 bdf: 03:04.0

 Signed-off-by: Don Slutz dsl...@verizon.com
 CC: Don Slutz don.sl...@gmail.com
 ---
  include/hw/xen/xen_common.h | 53
 +++--
  trace-events|  6 +++--
  xen-hvm.c   | 15 -
  3 files changed, 55 insertions(+), 19 deletions(-)

 diff --git a/include/hw/xen/xen_common.h
 b/include/hw/xen/xen_common.h
 index 6579b78..260ee58 100644
 --- a/include/hw/xen/xen_common.h
 +++ b/include/hw/xen/xen_common.h
 @@ -223,12 +223,14 @@ static inline void xen_unmap_io_section(XenXC xc,
 domid_t dom,

  static inline void xen_map_pcidev(XenXC xc, domid_t dom,
ioservid_t ioservid

Re: [Qemu-devel] [PATCH v2 2/4] Extend device listener interface for PCI to PCI bridges

2015-06-09 Thread Don Slutz
On 06/09/15 05:08, Paul Durrant wrote:
 -Original Message-
 From: Don Slutz [mailto:dsl...@verizon.com]
 Sent: 08 June 2015 22:19
 To: qemu-devel@nongnu.org; xen-de...@lists.xen.org
 Cc: Michael S. Tsirkin; Paul Durrant; Stefano Stabellini; Don Slutz; Don 
 Slutz
 Subject: [PATCH v2 2/4] Extend device listener interface for PCI to PCI
 bridges

 The commit 707ff80021ccd7a68f4b3d2c44eebf87efbb41c4 assumed that a
 PCI device has a static address.  This is not true for PCI devices
 that are on the secondary bus of a PCI to PCI bridge.

 BIOS and/or guest OS can change the secondary bus number to a new
 value at any time.

 Extend the device listener interface to be called when ever the
 secondary bus number is set to a new value.  This new interface
 is called for all PCI devices that are on the secondary bridge.

 
 Can't you just make unrealize and realize calls back-to-back when the bus 
 number changes, rather than having a new callback?
 

That is what V1 had.  Michael S. Tsirkin did not like this.

   -Don Slutz

   Paul
 
 Signed-off-by: Don Slutz dsl...@verizon.com
 CC: Don Slutz don.sl...@gmail.com
 ---
  hw/core/qdev.c |  7 +++
  hw/pci/pci_bridge.c| 18 ++
  include/hw/qdev-core.h |  3 +++
  3 files changed, 28 insertions(+)

 diff --git a/hw/core/qdev.c b/hw/core/qdev.c
 index b0f0f84..7728ee7 100644
 --- a/hw/core/qdev.c
 +++ b/hw/core/qdev.c
 @@ -239,6 +239,13 @@ void device_listener_unregister(DeviceListener
 *listener)
  QTAILQ_REMOVE(device_listeners, listener, link);
  }

 +void device_listener_change_pci_bus_num(PCIBus *b, PCIDevice *d, void
 *opaque)
 +{
 +uint8_t oldbus = GPOINTER_TO_INT(opaque);
 +
 +DEVICE_LISTENER_CALL(change_pci_bus_num, Forward, d, oldbus);
 +}
 +
  static void device_realize(DeviceState *dev, Error **errp)
  {
  DeviceClass *dc = DEVICE_GET_CLASS(dev);
 diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
 index 40c97b1..742c4d8 100644
 --- a/hw/pci/pci_bridge.c
 +++ b/hw/pci/pci_bridge.c
 @@ -248,6 +248,7 @@ void pci_bridge_write_config(PCIDevice *d,
  PCIBridge *s = PCI_BRIDGE(d);
  uint16_t oldctl = pci_get_word(d-config + PCI_BRIDGE_CONTROL);
  uint16_t newctl;
 +uint8_t oldbus = pci_get_byte(d-config + PCI_SECONDARY_BUS);

  pci_default_write_config(d, address, val, len);

 @@ -265,6 +266,14 @@ void pci_bridge_write_config(PCIDevice *d,
  pci_bridge_update_mappings(s);
  }

 +if (oldbus != pci_get_byte(d-config + PCI_SECONDARY_BUS)) {
 +PCIBus *sec_bus = pci_bridge_get_sec_bus(s);
 +
 +pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
 +device_listener_change_pci_bus_num,
 +GINT_TO_POINTER(oldbus));
 +}
 +
  newctl = pci_get_word(d-config + PCI_BRIDGE_CONTROL);
  if (~oldctl  newctl  PCI_BRIDGE_CTL_BUS_RESET) {
  /* Trigger hot reset on 0-1 transition. */
 @@ -297,6 +306,7 @@ void pci_bridge_reset(DeviceState *qdev)
  {
  PCIDevice *dev = PCI_DEVICE(qdev);
  uint8_t *conf = dev-config;
 +uint8_t oldbus = conf[PCI_SECONDARY_BUS];

  conf[PCI_PRIMARY_BUS] = 0;
  conf[PCI_SECONDARY_BUS] = 0;
 @@ -329,6 +339,14 @@ void pci_bridge_reset(DeviceState *qdev)
  pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0);

  pci_set_word(conf + PCI_BRIDGE_CONTROL, 0);
 +
 +if (oldbus) {
 +PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(dev));
 +
 +pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
 +device_listener_change_pci_bus_num,
 +GINT_TO_POINTER(oldbus));
 +}
  }

  /* default qdev initialization function for PCI-to-PCI bridge */
 diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
 index d4be92f..154b4c1 100644
 --- a/include/hw/qdev-core.h
 +++ b/include/hw/qdev-core.h
 @@ -168,6 +168,8 @@ struct DeviceState {
  struct DeviceListener {
  void (*realize)(DeviceListener *listener, DeviceState *dev);
  void (*unrealize)(DeviceListener *listener, DeviceState *dev);
 +void (*change_pci_bus_num)(DeviceListener *listener, PCIDevice *d,
 +   uint8_t oldbus);
  QTAILQ_ENTRY(DeviceListener) link;
  };

 @@ -387,5 +389,6 @@ static inline bool qbus_is_hotpluggable(BusState
 *bus)

  void device_listener_register(DeviceListener *listener);
  void device_listener_unregister(DeviceListener *listener);
 +void device_listener_change_pci_bus_num(PCIBus *b, PCIDevice *d, void
 *opaque);

  #endif
 --
 1.8.4
 



Re: [Qemu-devel] [PATCH v2 2/4] Extend device listener interface for PCI to PCI bridges

2015-06-09 Thread Don Slutz
On 06/09/15 09:55, Paul Durrant wrote:
 -Original Message-
 From: Don Slutz [mailto:dsl...@verizon.com]
 Sent: 09 June 2015 14:53
 To: Paul Durrant; Slutz, Donald Christopher; qemu-devel@nongnu.org; xen-
 de...@lists.xen.org
 Cc: Michael S. Tsirkin; Stefano Stabellini; Don Slutz
 Subject: Re: [PATCH v2 2/4] Extend device listener interface for PCI to PCI
 bridges

 On 06/09/15 05:08, Paul Durrant wrote:
 -Original Message-
 From: Don Slutz [mailto:dsl...@verizon.com]
 Sent: 08 June 2015 22:19
 To: qemu-devel@nongnu.org; xen-de...@lists.xen.org
 Cc: Michael S. Tsirkin; Paul Durrant; Stefano Stabellini; Don Slutz; Don 
 Slutz
 Subject: [PATCH v2 2/4] Extend device listener interface for PCI to PCI
 bridges

 The commit 707ff80021ccd7a68f4b3d2c44eebf87efbb41c4 assumed that a
 PCI device has a static address.  This is not true for PCI devices
 that are on the secondary bus of a PCI to PCI bridge.

 BIOS and/or guest OS can change the secondary bus number to a new
 value at any time.

 Extend the device listener interface to be called when ever the
 secondary bus number is set to a new value.  This new interface
 is called for all PCI devices that are on the secondary bridge.


 Can't you just make unrealize and realize calls back-to-back when the bus
 number changes, rather than having a new callback?


 That is what V1 had.  Michael S. Tsirkin did not like this.

 
 I thought he objected to you actually calling the actual bus 
 unrealize/realize functions. All I'm suggesting is calling the device 
 listener unrealize/realize callbacks, rather than adding a new one.
 

Nope.  I added routines that would call on the device listener
callbacks.  Then added the calls to the new routines when the secondary
bus number changed. What you are saying looks real close to what I did
on V1.

   -Don Slutz

   Paul
 
-Don Slutz

   Paul

 Signed-off-by: Don Slutz dsl...@verizon.com
 CC: Don Slutz don.sl...@gmail.com
 ---
  hw/core/qdev.c |  7 +++
  hw/pci/pci_bridge.c| 18 ++
  include/hw/qdev-core.h |  3 +++
  3 files changed, 28 insertions(+)

 diff --git a/hw/core/qdev.c b/hw/core/qdev.c
 index b0f0f84..7728ee7 100644
 --- a/hw/core/qdev.c
 +++ b/hw/core/qdev.c
 @@ -239,6 +239,13 @@ void device_listener_unregister(DeviceListener
 *listener)
  QTAILQ_REMOVE(device_listeners, listener, link);
  }

 +void device_listener_change_pci_bus_num(PCIBus *b, PCIDevice *d,
 void
 *opaque)
 +{
 +uint8_t oldbus = GPOINTER_TO_INT(opaque);
 +
 +DEVICE_LISTENER_CALL(change_pci_bus_num, Forward, d, oldbus);
 +}
 +
  static void device_realize(DeviceState *dev, Error **errp)
  {
  DeviceClass *dc = DEVICE_GET_CLASS(dev);
 diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
 index 40c97b1..742c4d8 100644
 --- a/hw/pci/pci_bridge.c
 +++ b/hw/pci/pci_bridge.c
 @@ -248,6 +248,7 @@ void pci_bridge_write_config(PCIDevice *d,
  PCIBridge *s = PCI_BRIDGE(d);
  uint16_t oldctl = pci_get_word(d-config + PCI_BRIDGE_CONTROL);
  uint16_t newctl;
 +uint8_t oldbus = pci_get_byte(d-config + PCI_SECONDARY_BUS);

  pci_default_write_config(d, address, val, len);

 @@ -265,6 +266,14 @@ void pci_bridge_write_config(PCIDevice *d,
  pci_bridge_update_mappings(s);
  }

 +if (oldbus != pci_get_byte(d-config + PCI_SECONDARY_BUS)) {
 +PCIBus *sec_bus = pci_bridge_get_sec_bus(s);
 +
 +pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
 +device_listener_change_pci_bus_num,
 +GINT_TO_POINTER(oldbus));
 +}
 +
  newctl = pci_get_word(d-config + PCI_BRIDGE_CONTROL);
  if (~oldctl  newctl  PCI_BRIDGE_CTL_BUS_RESET) {
  /* Trigger hot reset on 0-1 transition. */
 @@ -297,6 +306,7 @@ void pci_bridge_reset(DeviceState *qdev)
  {
  PCIDevice *dev = PCI_DEVICE(qdev);
  uint8_t *conf = dev-config;
 +uint8_t oldbus = conf[PCI_SECONDARY_BUS];

  conf[PCI_PRIMARY_BUS] = 0;
  conf[PCI_SECONDARY_BUS] = 0;
 @@ -329,6 +339,14 @@ void pci_bridge_reset(DeviceState *qdev)
  pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0);

  pci_set_word(conf + PCI_BRIDGE_CONTROL, 0);
 +
 +if (oldbus) {
 +PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(dev));
 +
 +pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
 +device_listener_change_pci_bus_num,
 +GINT_TO_POINTER(oldbus));
 +}
  }

  /* default qdev initialization function for PCI-to-PCI bridge */
 diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
 index d4be92f..154b4c1 100644
 --- a/include/hw/qdev-core.h
 +++ b/include/hw/qdev-core.h
 @@ -168,6 +168,8 @@ struct DeviceState {
  struct DeviceListener {
  void (*realize)(DeviceListener *listener, DeviceState *dev);
  void (*unrealize)(DeviceListener *listener, DeviceState *dev);
 +void (*change_pci_bus_num)(DeviceListener *listener, PCIDevice *d

[Qemu-devel] [PATCH v2 2/4] Extend device listener interface for PCI to PCI bridges

2015-06-08 Thread Don Slutz
The commit 707ff80021ccd7a68f4b3d2c44eebf87efbb41c4 assumed that a
PCI device has a static address.  This is not true for PCI devices
that are on the secondary bus of a PCI to PCI bridge.

BIOS and/or guest OS can change the secondary bus number to a new
value at any time.

Extend the device listener interface to be called when ever the
secondary bus number is set to a new value.  This new interface
is called for all PCI devices that are on the secondary bridge.

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 hw/core/qdev.c |  7 +++
 hw/pci/pci_bridge.c| 18 ++
 include/hw/qdev-core.h |  3 +++
 3 files changed, 28 insertions(+)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index b0f0f84..7728ee7 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -239,6 +239,13 @@ void device_listener_unregister(DeviceListener *listener)
 QTAILQ_REMOVE(device_listeners, listener, link);
 }
 
+void device_listener_change_pci_bus_num(PCIBus *b, PCIDevice *d, void *opaque)
+{
+uint8_t oldbus = GPOINTER_TO_INT(opaque);
+
+DEVICE_LISTENER_CALL(change_pci_bus_num, Forward, d, oldbus);
+}
+
 static void device_realize(DeviceState *dev, Error **errp)
 {
 DeviceClass *dc = DEVICE_GET_CLASS(dev);
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 40c97b1..742c4d8 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -248,6 +248,7 @@ void pci_bridge_write_config(PCIDevice *d,
 PCIBridge *s = PCI_BRIDGE(d);
 uint16_t oldctl = pci_get_word(d-config + PCI_BRIDGE_CONTROL);
 uint16_t newctl;
+uint8_t oldbus = pci_get_byte(d-config + PCI_SECONDARY_BUS);
 
 pci_default_write_config(d, address, val, len);
 
@@ -265,6 +266,14 @@ void pci_bridge_write_config(PCIDevice *d,
 pci_bridge_update_mappings(s);
 }
 
+if (oldbus != pci_get_byte(d-config + PCI_SECONDARY_BUS)) {
+PCIBus *sec_bus = pci_bridge_get_sec_bus(s);
+
+pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
+device_listener_change_pci_bus_num,
+GINT_TO_POINTER(oldbus));
+}
+
 newctl = pci_get_word(d-config + PCI_BRIDGE_CONTROL);
 if (~oldctl  newctl  PCI_BRIDGE_CTL_BUS_RESET) {
 /* Trigger hot reset on 0-1 transition. */
@@ -297,6 +306,7 @@ void pci_bridge_reset(DeviceState *qdev)
 {
 PCIDevice *dev = PCI_DEVICE(qdev);
 uint8_t *conf = dev-config;
+uint8_t oldbus = conf[PCI_SECONDARY_BUS];
 
 conf[PCI_PRIMARY_BUS] = 0;
 conf[PCI_SECONDARY_BUS] = 0;
@@ -329,6 +339,14 @@ void pci_bridge_reset(DeviceState *qdev)
 pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0);
 
 pci_set_word(conf + PCI_BRIDGE_CONTROL, 0);
+
+if (oldbus) {
+PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(dev));
+
+pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
+device_listener_change_pci_bus_num,
+GINT_TO_POINTER(oldbus));
+}
 }
 
 /* default qdev initialization function for PCI-to-PCI bridge */
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index d4be92f..154b4c1 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -168,6 +168,8 @@ struct DeviceState {
 struct DeviceListener {
 void (*realize)(DeviceListener *listener, DeviceState *dev);
 void (*unrealize)(DeviceListener *listener, DeviceState *dev);
+void (*change_pci_bus_num)(DeviceListener *listener, PCIDevice *d,
+   uint8_t oldbus);
 QTAILQ_ENTRY(DeviceListener) link;
 };
 
@@ -387,5 +389,6 @@ static inline bool qbus_is_hotpluggable(BusState *bus)
 
 void device_listener_register(DeviceListener *listener);
 void device_listener_unregister(DeviceListener *listener);
+void device_listener_change_pci_bus_num(PCIBus *b, PCIDevice *d, void *opaque);
 
 #endif
-- 
1.8.4




[Qemu-devel] [PATCH v2 3/4] xen: Add usage of device listener interface for PCI to PCI bridges

2015-06-08 Thread Don Slutz
Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 include/hw/xen/xen_common.h | 10 ++
 xen-hvm.c   | 13 -
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h
index 38f29fb..6579b78 100644
--- a/include/hw/xen/xen_common.h
+++ b/include/hw/xen/xen_common.h
@@ -229,7 +229,8 @@ static inline void xen_map_pcidev(XenXC xc, domid_t dom,
 
 static inline void xen_unmap_pcidev(XenXC xc, domid_t dom,
 ioservid_t ioservid,
-PCIDevice *pci_dev)
+PCIDevice *pci_dev,
+uint8_t oldbus)
 {
 }
 
@@ -357,12 +358,13 @@ static inline void xen_map_pcidev(XenXC xc, domid_t dom,
 
 static inline void xen_unmap_pcidev(XenXC xc, domid_t dom,
 ioservid_t ioservid,
-PCIDevice *pci_dev)
+PCIDevice *pci_dev,
+uint8_t oldbus)
 {
-trace_xen_unmap_pcidev(ioservid, pci_bus_num(pci_dev-bus),
+trace_xen_unmap_pcidev(ioservid, oldbus,
PCI_SLOT(pci_dev-devfn), PCI_FUNC(pci_dev-devfn));
 xc_hvm_unmap_pcidev_from_ioreq_server(xc, dom, ioservid,
-  0, pci_bus_num(pci_dev-bus),
+  0, oldbus,
   PCI_SLOT(pci_dev-devfn),
   PCI_FUNC(pci_dev-devfn));
 }
diff --git a/xen-hvm.c b/xen-hvm.c
index 42356b8..7b6d8f1 100644
--- a/xen-hvm.c
+++ b/xen-hvm.c
@@ -590,10 +590,20 @@ static void xen_device_unrealize(DeviceListener *listener,
 if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
 PCIDevice *pci_dev = PCI_DEVICE(dev);
 
-xen_unmap_pcidev(xen_xc, xen_domid, state-ioservid, pci_dev);
+xen_unmap_pcidev(xen_xc, xen_domid, state-ioservid, pci_dev,
+ pci_bus_num(pci_dev-bus));
 }
 }
 
+static void xen_device_change_pci_bus_num(DeviceListener *listener,
+  PCIDevice *pci_dev, uint8_t oldbus)
+{
+XenIOState *state = container_of(listener, XenIOState, device_listener);
+
+xen_unmap_pcidev(xen_xc, xen_domid, state-ioservid, pci_dev, oldbus);
+xen_map_pcidev(xen_xc, xen_domid, state-ioservid, pci_dev);
+}
+
 static void xen_sync_dirty_bitmap(XenIOState *state,
   hwaddr start_addr,
   ram_addr_t size)
@@ -709,6 +719,7 @@ static MemoryListener xen_io_listener = {
 static DeviceListener xen_device_listener = {
 .realize = xen_device_realize,
 .unrealize = xen_device_unrealize,
+.change_pci_bus_num = xen_device_change_pci_bus_num,
 };
 
 /* get the ioreq packets from share mem */
-- 
1.8.4




[Qemu-devel] [PATCH v2 0/4] Fix device listener interface for PCI to PCI bridges

2015-06-08 Thread Don Slutz
changes v1 to v2:
  Split v1 patch into 3.

  Added a BUG FIX patch (#1: exec: Do not use MemoryRegion after
  free).

Technically this bug fix should be a separate patch, however this
issue only seems to reproduce when this patch set is applied.


  Michael S. Tsirkin:
You need some other API that makes sense, probably PCI specific.
  This is basically patch #2: Extend device listener interface...

This is relying on undocumented assumptions and how specific
firmware works. There's nothing special about bus number 255,
and 0 is not very special either (except it happens to be the
reset value).
  Dropped all checking of 0 and 255.


Open question by Michael S. Tsirkin:

 On Thu, May 28, 2015 at 07:25:50AM -0400, Don Slutz wrote:
...
 It is not clear to me that the complexity of tracking bus
 visibility make sense.  Clearly you do.
 Well what was the point of the change?

 To get config cycles that are valid that you do not get today.

 If you don't care that we get irrelevant config cycles why not
 just send them all to QEMU?


 That would need to be answered by Paul Durrant and/or other people (see
 below)


We could broadcast config space ioreqs to all emulators, the problem
is how do we know (in the case of a read) which emulator is actually
the one supplying the data? At some level Xen needs to know who is
implementing what.

  Paul Durrant

So this patch set just adjusts Xen to correctly know the current set
of PCI devices and their bus, device, and function.

It does not attempt to calculate the visibility of the PCI devices.


v1:

Note: Right now hvmloader in Xen does not handle PCI to PCI bridges
and so SeaBIOS does not have access to PCI device(s) on secondary
buses.  How ever domU can setup the secondary bus(es) and this patch
will restore access to these PCI devices.


Don Slutz (4):
  exec: Do not use MemoryRegion after free
  Extend device listener interface for PCI to PCI bridges
  xen: Add usage of device listener interface for PCI to PCI bridges
  xen: Fix map/unmap of pcidev to ioreq server

 exec.c  |  8 --
 hw/core/qdev.c  |  7 ++
 hw/pci/pci_bridge.c | 18 +
 include/hw/qdev-core.h  |  3 +++
 include/hw/xen/xen_common.h | 61 ++---
 trace-events|  6 +++--
 xen-hvm.c   | 20 +--
 7 files changed, 102 insertions(+), 21 deletions(-)

-- 
1.8.4




[Qemu-devel] [BUGFIX][PATCH v2 1/4] exec: Do not use MemoryRegion after free

2015-06-08 Thread Don Slutz
Here is gdb output that shows this happening:

  Breakpoint 3, object_finalize (data=0x7fdf32a14010) at qom/object.c:417
  417 obj-free(obj);
  (gdb) bt
  #0  object_finalize (data=0x7fdf32a14010) at qom/object.c:417
  #1  0x007329d4 in object_unref (obj=0x7fdf32a14010) at 
qom/object.c:720
  #2  0x00468a65 in memory_region_unref (mr=0x7fdf32a168b0) at 
xen/tools/qemu-xen-dir/memory.c:1359
  #3  0x0040eb52 in phys_section_destroy (mr=0x7fdf32a168b0) at 
xen/tools/qemu-xen-dir/exec.c:960
  #4  0x0040ec0a in phys_sections_free (map=0x3e51fc8) at 
xen/tools/qemu-xen-dir/exec.c:973
  #5  0x00411cc9 in address_space_dispatch_free (d=0x3e51fb0) at 
xen/tools/qemu-xen-dir/exec.c:2133
  #6  0x00840ae2 in call_rcu_thread (opaque=0x0) at util/rcu.c:256
  #7  0x0032fdc07d14 in start_thread (arg=0x7fdf34866700) at 
pthread_create.c:309
  #8  0x0032fd4f168d in clone () at 
../sysdeps/unix/sysv/linux/x86_64/clone.S:115
  (gdb) p obj
  $5 = (Object *) 0x7fdf32a14010
  (gdb) p *obj
  $6 = {class = 0x302f380, free = 0x40a1e0 g_free@plt, properties = 
{tqh_first = 0x0, tqh_last = 0x7fdf32a14020},
  ref = 0, parent = 0x0}
  (gdb) up
  #1  0x007329d4 in object_unref (obj=0x7fdf32a14010) at 
qom/object.c:720
  720 object_finalize(obj);
  (gdb) up
  #2  0x00468a65 in memory_region_unref (mr=0x7fdf32a168b0) at 
xen/tools/qemu-xen-dir/memory.c:1359
  1359object_unref(obj-parent);
  (gdb) up
  #3  0x0040eb52 in phys_section_destroy (mr=0x7fdf32a168b0) at 
xen/tools/qemu-xen-dir/exec.c:960
  960 memory_region_unref(mr);
  (gdb) l
  955 return map-sections_nb++;
  956 }
  957
  958 static void phys_section_destroy(MemoryRegion *mr)
  959 {
  960 memory_region_unref(mr);
  961
  962 if (mr-subpage) {
  963 subpage_t *subpage = container_of(mr, subpage_t, iomem);
  964 object_unref(OBJECT(subpage-iomem));
  (gdb) p mr
  $7 = (MemoryRegion *) 0x7fdf32a168b0
  (gdb) p mr-subpage
  $9 = false
  (gdb) n
  419 }
  (gdb) n
  object_unref (obj=0x7fdf32a14010) at qom/object.c:722
  722 }
  (gdb) n
  memory_region_unref (mr=0x7fdf32a168b0) at 
xen/tools/qemu-xen-dir/memory.c:1363
  1363}
  (gdb) n
  phys_section_destroy (mr=0x7fdf32a168b0) at xen/tools/qemu-xen-dir/exec.c:962
  962 if (mr-subpage) {
  (gdb) p mr
  $10 = (MemoryRegion *) 0x7fdf32a168b0
  (gdb) p *mr
  Cannot access memory at address 0x7fdf32a168b0

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 exec.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/exec.c b/exec.c
index 487583b..2f44a80 100644
--- a/exec.c
+++ b/exec.c
@@ -957,10 +957,14 @@ static uint16_t phys_section_add(PhysPageMap *map,
 
 static void phys_section_destroy(MemoryRegion *mr)
 {
-memory_region_unref(mr);
+subpage_t *subpage = NULL;
 
 if (mr-subpage) {
-subpage_t *subpage = container_of(mr, subpage_t, iomem);
+subpage = container_of(mr, subpage_t, iomem);
+}
+memory_region_unref(mr);
+
+if (subpage) {
 object_unref(OBJECT(subpage-iomem));
 g_free(subpage);
 }
-- 
1.8.4




[Qemu-devel] [PATCH v2 4/4] xen: Fix map/unmap of pcidev to ioreq server

2015-06-08 Thread Don Slutz
The commit 707ff80021ccd7a68f4b3d2c44eebf87efbb41c4 added usage of
xc_hvm_map_pcidev_from_ioreq_server() and
xc_hvm_unmap_pcidev_from_ioreq_server().  These routines only
correctly work if the PCI BDF of a PCI device is unique.  The 3
parts (bus, device, and function) of a PCI BDF are not required to
be unique.

The PCI BDF is accessed in QEMU:
  buspci_bus_num()
  device PCI_SLOT()
  function   PCI_FUNC()

Add a hash table to track the current set of PCI BDFs and only call
on xc_hvm_map_pcidev_from_ioreq_server() and
xc_hvm_unmap_pcidev_from_ioreq_server() when needed.

Also fix the PCI BDF default stderr trace output: bus is seperated
by ':', and function is only 1 digit.

Here is an example of stderr trace output:

xen_map_pcidev id: 1 bdf: 00:00.0
xen_map_pcidev id: 1 bdf: 00:01.0
xen_map_pcidev id: 1 bdf: 00:01.1
xen_map_pcidev id: 1 bdf: 00:01.3
xen_map_pcidev id: 1 bdf: 00:02.0
xen_map_pcidev id: 1 bdf: 00:03.0
xen_map_pcidev id: 1 bdf: 00:04.0
xen_map_pcidev id: 1 bdf: 00:05.0
xen_map_pcidev id: 1 bdf: 00:11.0
xen_map_pcidev id: 1 bdf: 00:15.0
xen_map_pcidev id: 1 bdf: 00:16.0
xen_map_pcidev id: 1 bdf: 00:17.0
xen_map_pcidev id: 1 bdf: 00:18.0
xen_map_pcidev_dup id: 1 bdf: 00:01.0 dup: 2
xen_map_pcidev_dup id: 1 bdf: 00:01.0 dup: 3
xen_map_pcidev_dup id: 1 bdf: 00:03.0 dup: 2
xen_map_pcidev_dup id: 1 bdf: 00:03.0 dup: 3
xen_map_pcidev_dup id: 1 bdf: 00:04.0 dup: 2
xen_unmap_pcidev_dup id: 1 bdf: 00:03.0 dup: 2
xen_map_pcidev id: 1 bdf: ff:03.0
xen_unmap_pcidev id: 1 bdf: 00:17.0
xen_map_pcidev id: 1 bdf: ff:17.0
xen_unmap_pcidev_dup id: 1 bdf: 00:01.0 dup: 2
xen_map_pcidev id: 1 bdf: ff:01.0
xen_unmap_pcidev_dup id: 1 bdf: 00:03.0 dup: 1
xen_map_pcidev_dup id: 1 bdf: ff:03.0 dup: 2
xen_unmap_pcidev_dup id: 1 bdf: 00:04.0 dup: 1
xen_map_pcidev id: 1 bdf: ff:04.0
xen_unmap_pcidev_dup id: 1 bdf: ff:03.0 dup: 1
xen_map_pcidev id: 1 bdf: 01:03.0
xen_unmap_pcidev id: 1 bdf: ff:17.0
xen_map_pcidev id: 1 bdf: 01:17.0
xen_unmap_pcidev_dup id: 1 bdf: 00:01.0 dup: 1
xen_map_pcidev_dup id: 1 bdf: ff:01.0 dup: 2
xen_unmap_pcidev_dup id: 1 bdf: ff:01.0 dup: 1
xen_map_pcidev id: 1 bdf: 02:01.0
xen_unmap_pcidev id: 1 bdf: ff:01.0
xen_map_pcidev id: 1 bdf: 03:01.0
xen_unmap_pcidev id: 1 bdf: ff:03.0
xen_map_pcidev id: 1 bdf: 03:03.0
xen_unmap_pcidev id: 1 bdf: ff:04.0
xen_map_pcidev id: 1 bdf: 03:04.0
xen_unmap_pcidev id: 1 bdf: 00:04.0
xen_unmap_pcidev id: 1 bdf: 00:05.0
xen_unmap_pcidev id: 1 bdf: 01:03.0
xen_map_pcidev_dup id: 1 bdf: 00:03.0 dup: 2
xen_unmap_pcidev id: 1 bdf: 01:17.0
xen_map_pcidev id: 1 bdf: 00:17.0
xen_unmap_pcidev id: 1 bdf: 03:01.0
xen_map_pcidev_dup id: 1 bdf: 00:01.0 dup: 2
xen_unmap_pcidev id: 1 bdf: 03:03.0
xen_map_pcidev_dup id: 1 bdf: 00:03.0 dup: 3
xen_unmap_pcidev id: 1 bdf: 03:04.0
xen_map_pcidev id: 1 bdf: 00:04.0
xen_unmap_pcidev_dup id: 1 bdf: 00:03.0 dup: 2
xen_map_pcidev id: 1 bdf: 01:03.0
xen_unmap_pcidev id: 1 bdf: 00:17.0
xen_map_pcidev id: 1 bdf: 01:17.0
xen_unmap_pcidev id: 1 bdf: 02:01.0
xen_map_pcidev_dup id: 1 bdf: 00:01.0 dup: 3
xen_unmap_pcidev_dup id: 1 bdf: 00:01.0 dup: 2
xen_map_pcidev id: 1 bdf: 02:01.0
xen_unmap_pcidev_dup id: 1 bdf: 00:01.0 dup: 1
xen_map_pcidev id: 1 bdf: 03:01.0
xen_unmap_pcidev_dup id: 1 bdf: 00:03.0 dup: 1
xen_map_pcidev id: 1 bdf: 03:03.0
xen_unmap_pcidev id: 1 bdf: 00:04.0
xen_map_pcidev id: 1 bdf: 03:04.0

Signed-off-by: Don Slutz dsl...@verizon.com
CC: Don Slutz don.sl...@gmail.com
---
 include/hw/xen/xen_common.h | 53 +++--
 trace-events|  6 +++--
 xen-hvm.c   | 15 -
 3 files changed, 55 insertions(+), 19 deletions(-)

diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h
index 6579b78..260ee58 100644
--- a/include/hw/xen/xen_common.h
+++ b/include/hw/xen/xen_common.h
@@ -223,12 +223,14 @@ static inline void xen_unmap_io_section(XenXC xc, domid_t 
dom,
 
 static inline void xen_map_pcidev(XenXC xc, domid_t dom,
   ioservid_t ioservid,
+  GHashTable *pci_bdf,
   PCIDevice *pci_dev)
 {
 }
 
 static inline void xen_unmap_pcidev(XenXC xc, domid_t dom,
 ioservid_t ioservid,
+GHashTable *pci_bdf,
 PCIDevice *pci_dev,
 uint8_t oldbus)
 {
@@ -346,27 +348,54 @@ static inline void xen_unmap_io_section(XenXC xc, domid_t 
dom,
 
 static inline void xen_map_pcidev(XenXC xc, domid_t dom,
   ioservid_t ioservid,
+  GHashTable *pci_bdf,
   PCIDevice *pci_dev)
 {
-trace_xen_map_pcidev(ioservid, pci_bus_num(pci_dev-bus),
- PCI_SLOT(pci_dev-devfn), PCI_FUNC(pci_dev-devfn));
-xc_hvm_map_pcidev_to_ioreq_server(xc, dom, ioservid,
-  0, pci_bus_num

[Qemu-devel] [Bug 1462131] Re: qemu mainline regression with xen-unstable: unable to start QMP

2015-06-08 Thread Don Slutz
Fixed in:



commit 779cec4d20907cbccb26fbf5f5c19c6cdee33eff
Author: Markus Armbruster arm...@redhat.com
Date:   Mon Jun 8 10:44:30 2015 +0200

monitor: Fix QMP ABI breakage around id


** Changed in: qemu
   Status: Confirmed = Fix Released

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

Title:
  qemu mainline regression with xen-unstable: unable to start QMP

Status in QEMU:
  Fix Released

Bug description:
  On 06/04/15 11:04, Fabio Fantoni wrote:
   Today after trying xen-unstable build (tested many hours) of some days
   ago I tried update qemu to latest development version (from git master
   commit 6fa6b312765f698dc81b2c30e7eeb9683804a05b) and seems that there is
   a regression:
   xl create /etc/xen/W7.cfg
   Parsing config from /etc/xen/W7.cfg
   libxl: error: libxl_qmp.c:287:qmp_handle_error_response: received an
   error message from QMP server: QMP input object member 'id' is unexpected
   libxl: error: libxl_qmp.c:715:libxl__qmp_initialize: Failed to connect
   to QMP
   

  This is caused by:

  commit 65207c59d99f2260c5f1d3b9c491146616a522aa
  Author: Markus Armbruster arm...@redhat.com
  Date:   Thu Mar 5 14:35:26 2015 +0100

  monitor: Drop broken, unused asynchronous command interface

  
   DomU is working but operations that require QMP not (for example
   save/restore).
   
   Thanks for any reply and sorry for my bad english.

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



[Qemu-devel] [Bug 1462131] Re: qemu mainline regression with xen-unstable: unable to start QMP

2015-06-04 Thread Don Slutz
Subject: Re: [Qemu-devel] [Xen-devel] qemu mainline regression with 
xen-unstable: unable to start QMP
Date: Thu, 04 Jun 2015 16:10:34 -0600
From: Eric Blake ebl...@redhat.com
Organization: Red Hat, Inc.
To: Don Slutz don.sl...@gmail.com, Fabio Fantoni fabio.fant...@m2r.biz, 
qemu-devel@nongnu.org qemu-devel@nongnu.org, xen-devel 
xen-de...@lists.xensource.com, Stefano Stabellini 
stefano.stabell...@eu.citrix.com, Anthony PERARD anthony.per...@citrix.com, 
Ian Campbell ian.campb...@citrix.com, Markus Armbruster arm...@redhat.com

[adding Markus, as author of the regression]

On 06/04/2015 03:59 PM, Don Slutz wrote:
 On 06/04/15 11:04, Fabio Fantoni wrote:
 Today after trying xen-unstable build (tested many hours) of some days
 ago I tried update qemu to latest development version (from git master
 commit 6fa6b312765f698dc81b2c30e7eeb9683804a05b) and seems that there is
 a regression:
 xl create /etc/xen/W7.cfg
 Parsing config from /etc/xen/W7.cfg
 libxl: error: libxl_qmp.c:287:qmp_handle_error_response: received an
 error message from QMP server: QMP input object member 'id' is unexpected
 libxl: error: libxl_qmp.c:715:libxl__qmp_initialize: Failed to connect
 to QMP

 
 This is caused by:
 
 commit 65207c59d99f2260c5f1d3b9c491146616a522aa
 Author: Markus Armbruster arm...@redhat.com
 Date:   Thu Mar 5 14:35:26 2015 +0100
 
 monitor: Drop broken, unused asynchronous command interface
 

 The patch:
 
From 1b0221078353870fe530e49de158cae205f9bce5 Mon Sep 17 00:00:00 2001
 From: Don Slutz dsl...@verizon.com
 Date: Thu, 4 Jun 2015 17:04:42 -0400
 Subject: [PATCH 01/14] monitor: Allow Xen's (broken) usage of asynchronous
  command interface.
 
 commit 65207c59d99f2260c5f1d3b9c491146616a522aa
 Author: Markus Armbruster arm...@redhat.com
 Date:   Thu Mar 5 14:35:26 2015 +0100
 
 monitor: Drop broken, unused asynchronous command interface
 
 Breaks Xen.  Add a hack un unbreak it.

s/un /to /

 
 Xen is only doing synchronous commands, but is including an id.

QMP also uses id, but apparently removes it up front before calling into
this function; so another fix would be having xen remove it up front.

 
 Signed-off-by: Don Slutz dsl...@verizon.com
 ---
  monitor.c | 9 +
  1 file changed, 9 insertions(+)
 
 diff --git a/monitor.c b/monitor.c
 index c7baa91..e9a0747 100644
 --- a/monitor.c
 +++ b/monitor.c
 @@ -4955,6 +4955,15 @@ static QDict *qmp_check_input_obj(QObject
 *input_obj, Error **errp)
arguments, object);
  return NULL;
  }
 +} else if (!strcmp(arg_name, id)) {
 +/*
 + * Fixup Xen's usage. Just ignore the id. See point #5
 + * above.  This was an attempt at an asynchronous
 + * command interface.  However commit
 + * 65207c59d99f2260c5f1d3b9c491146616a522aa is
 + * wrong. Xen does not expect an error when it passes in
 + * id:1, so just continue to ignore it.
 + */

The comment is a bit verbose, particularly since 'id' is a
well-established usage pattern in QMP.  Also, we don't need to call out
why it changed in the comment here, the commit message is sufficient for
that.

  } else {
  error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
  return NULL;
 

-- 
Eric Blake   eblake redhat com+1-919-301-3266
Libvirt virtualization library http://libvirt.org

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

Title:
  qemu mainline regression with xen-unstable: unable to start QMP

Status in QEMU:
  New

Bug description:
  On 06/04/15 11:04, Fabio Fantoni wrote:
   Today after trying xen-unstable build (tested many hours) of some days
   ago I tried update qemu to latest development version (from git master
   commit 6fa6b312765f698dc81b2c30e7eeb9683804a05b) and seems that there is
   a regression:
   xl create /etc/xen/W7.cfg
   Parsing config from /etc/xen/W7.cfg
   libxl: error: libxl_qmp.c:287:qmp_handle_error_response: received an
   error message from QMP server: QMP input object member 'id' is unexpected
   libxl: error: libxl_qmp.c:715:libxl__qmp_initialize: Failed to connect
   to QMP
   

  This is caused by:

  commit 65207c59d99f2260c5f1d3b9c491146616a522aa
  Author: Markus Armbruster arm...@redhat.com
  Date:   Thu Mar 5 14:35:26 2015 +0100

  monitor: Drop broken, unused asynchronous command interface

  
   DomU is working but operations that require QMP not (for example
   save/restore).
   
   Thanks for any reply and sorry for my bad english.

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



Re: [Qemu-devel] [Xen-devel] qemu mainline regression with xen-unstable: unable to start QMP

2015-06-04 Thread Don Slutz
On 06/04/15 11:04, Fabio Fantoni wrote:
 Today after trying xen-unstable build (tested many hours) of some days
 ago I tried update qemu to latest development version (from git master
 commit 6fa6b312765f698dc81b2c30e7eeb9683804a05b) and seems that there is
 a regression:
 xl create /etc/xen/W7.cfg
 Parsing config from /etc/xen/W7.cfg
 libxl: error: libxl_qmp.c:287:qmp_handle_error_response: received an
 error message from QMP server: QMP input object member 'id' is unexpected
 libxl: error: libxl_qmp.c:715:libxl__qmp_initialize: Failed to connect
 to QMP
 

This is caused by:

commit 65207c59d99f2260c5f1d3b9c491146616a522aa
Author: Markus Armbruster arm...@redhat.com
Date:   Thu Mar 5 14:35:26 2015 +0100

monitor: Drop broken, unused asynchronous command interface


 DomU is working but operations that require QMP not (for example
 save/restore).
 
 Thanks for any reply and sorry for my bad english.
 

The patch:

From 1b0221078353870fe530e49de158cae205f9bce5 Mon Sep 17 00:00:00 2001
From: Don Slutz dsl...@verizon.com
Date: Thu, 4 Jun 2015 17:04:42 -0400
Subject: [PATCH 01/14] monitor: Allow Xen's (broken) usage of asynchronous
 command interface.

commit 65207c59d99f2260c5f1d3b9c491146616a522aa
Author: Markus Armbruster arm...@redhat.com
Date:   Thu Mar 5 14:35:26 2015 +0100

monitor: Drop broken, unused asynchronous command interface

Breaks Xen.  Add a hack un unbreak it.

Xen is only doing synchronous commands, but is including an id.

Signed-off-by: Don Slutz dsl...@verizon.com
---
 monitor.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/monitor.c b/monitor.c
index c7baa91..e9a0747 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4955,6 +4955,15 @@ static QDict *qmp_check_input_obj(QObject
*input_obj, Error **errp)
   arguments, object);
 return NULL;
 }
+} else if (!strcmp(arg_name, id)) {
+/*
+ * Fixup Xen's usage. Just ignore the id. See point #5
+ * above.  This was an attempt at an asynchronous
+ * command interface.  However commit
+ * 65207c59d99f2260c5f1d3b9c491146616a522aa is
+ * wrong. Xen does not expect an error when it passes in
+ * id:1, so just continue to ignore it.
+ */
 } else {
 error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
 return NULL;
-- 
1.7.11.7

fixes things for me

   -Don Slutz


 ___
 Xen-devel mailing list
 xen-de...@lists.xen.org
 http://lists.xen.org/xen-devel



Re: [Qemu-devel] [Xen-devel] qemu mainline regression with xen-unstable: unable to start QMP

2015-06-04 Thread Don Slutz
On 06/04/15 17:59, Don Slutz wrote:
 On 06/04/15 11:04, Fabio Fantoni wrote:
 Today after trying xen-unstable build (tested many hours) of some days
 ago I tried update qemu to latest development version (from git master
 commit 6fa6b312765f698dc81b2c30e7eeb9683804a05b) and seems that there is
 a regression:
 xl create /etc/xen/W7.cfg
 Parsing config from /etc/xen/W7.cfg
 libxl: error: libxl_qmp.c:287:qmp_handle_error_response: received an
 error message from QMP server: QMP input object member 'id' is unexpected
 libxl: error: libxl_qmp.c:715:libxl__qmp_initialize: Failed to connect
 to QMP

 
 This is caused by:
 
 commit 65207c59d99f2260c5f1d3b9c491146616a522aa
 Author: Markus Armbruster arm...@redhat.com
 Date:   Thu Mar 5 14:35:26 2015 +0100
 
 monitor: Drop broken, unused asynchronous command interface
 
 
 DomU is working but operations that require QMP not (for example
 save/restore).

 Thanks for any reply and sorry for my bad english.

 

I have created a bug -- Bug #1462131 for this.

   -Don Slutz

 The patch:
 
 From 1b0221078353870fe530e49de158cae205f9bce5 Mon Sep 17 00:00:00 2001
 From: Don Slutz dsl...@verizon.com
 Date: Thu, 4 Jun 2015 17:04:42 -0400
 Subject: [PATCH 01/14] monitor: Allow Xen's (broken) usage of asynchronous
  command interface.
 
 commit 65207c59d99f2260c5f1d3b9c491146616a522aa
 Author: Markus Armbruster arm...@redhat.com
 Date:   Thu Mar 5 14:35:26 2015 +0100
 
 monitor: Drop broken, unused asynchronous command interface
 
 Breaks Xen.  Add a hack un unbreak it.
 
 Xen is only doing synchronous commands, but is including an id.
 
 Signed-off-by: Don Slutz dsl...@verizon.com
 ---
  monitor.c | 9 +
  1 file changed, 9 insertions(+)
 
 diff --git a/monitor.c b/monitor.c
 index c7baa91..e9a0747 100644
 --- a/monitor.c
 +++ b/monitor.c
 @@ -4955,6 +4955,15 @@ static QDict *qmp_check_input_obj(QObject
 *input_obj, Error **errp)
arguments, object);
  return NULL;
  }
 +} else if (!strcmp(arg_name, id)) {
 +/*
 + * Fixup Xen's usage. Just ignore the id. See point #5
 + * above.  This was an attempt at an asynchronous
 + * command interface.  However commit
 + * 65207c59d99f2260c5f1d3b9c491146616a522aa is
 + * wrong. Xen does not expect an error when it passes in
 + * id:1, so just continue to ignore it.
 + */
  } else {
  error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
  return NULL;
 



[Qemu-devel] [Bug 1462131] [NEW] qemu mainline regression with xen-unstable: unable to start QMP

2015-06-04 Thread Don Slutz
Public bug reported:

On 06/04/15 11:04, Fabio Fantoni wrote:
 Today after trying xen-unstable build (tested many hours) of some days
 ago I tried update qemu to latest development version (from git master
 commit 6fa6b312765f698dc81b2c30e7eeb9683804a05b) and seems that there is
 a regression:
 xl create /etc/xen/W7.cfg
 Parsing config from /etc/xen/W7.cfg
 libxl: error: libxl_qmp.c:287:qmp_handle_error_response: received an
 error message from QMP server: QMP input object member 'id' is unexpected
 libxl: error: libxl_qmp.c:715:libxl__qmp_initialize: Failed to connect
 to QMP
 

This is caused by:

commit 65207c59d99f2260c5f1d3b9c491146616a522aa
Author: Markus Armbruster arm...@redhat.com
Date:   Thu Mar 5 14:35:26 2015 +0100

monitor: Drop broken, unused asynchronous command interface


 DomU is working but operations that require QMP not (for example
 save/restore).
 
 Thanks for any reply and sorry for my bad english.

** Affects: qemu
 Importance: Undecided
 Status: New

** Patch added: 
0001-monitor-Allow-Xen-s-broken-usage-of-asynchronous-com.patch
   
https://bugs.launchpad.net/bugs/1462131/+attachment/4410103/+files/0001-monitor-Allow-Xen-s-broken-usage-of-asynchronous-com.patch

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

Title:
  qemu mainline regression with xen-unstable: unable to start QMP

Status in QEMU:
  New

Bug description:
  On 06/04/15 11:04, Fabio Fantoni wrote:
   Today after trying xen-unstable build (tested many hours) of some days
   ago I tried update qemu to latest development version (from git master
   commit 6fa6b312765f698dc81b2c30e7eeb9683804a05b) and seems that there is
   a regression:
   xl create /etc/xen/W7.cfg
   Parsing config from /etc/xen/W7.cfg
   libxl: error: libxl_qmp.c:287:qmp_handle_error_response: received an
   error message from QMP server: QMP input object member 'id' is unexpected
   libxl: error: libxl_qmp.c:715:libxl__qmp_initialize: Failed to connect
   to QMP
   

  This is caused by:

  commit 65207c59d99f2260c5f1d3b9c491146616a522aa
  Author: Markus Armbruster arm...@redhat.com
  Date:   Thu Mar 5 14:35:26 2015 +0100

  monitor: Drop broken, unused asynchronous command interface

  
   DomU is working but operations that require QMP not (for example
   save/restore).
   
   Thanks for any reply and sorry for my bad english.

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



Re: [Qemu-devel] [Xen-devel] qemu mainline regression with xen-unstable: unable to start QMP

2015-06-04 Thread Don Slutz
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 06/04/15 18:10, Eric Blake wrote:
 [adding Markus, as author of the regression]
 
 On 06/04/2015 03:59 PM, Don Slutz wrote:
 On 06/04/15 11:04, Fabio Fantoni wrote:
 Today after trying xen-unstable build (tested many hours) of
 some days ago I tried update qemu to latest development version
 (from git master commit
 6fa6b312765f698dc81b2c30e7eeb9683804a05b) and seems that there
 is a regression:
 xl create /etc/xen/W7.cfg Parsing config from
 /etc/xen/W7.cfg libxl: error:
 libxl_qmp.c:287:qmp_handle_error_response: received an error
 message from QMP server: QMP input object member 'id' is
 unexpected libxl: error:
 libxl_qmp.c:715:libxl__qmp_initialize: Failed to connect to
 QMP
 
 
 This is caused by:
 
 commit 65207c59d99f2260c5f1d3b9c491146616a522aa Author: Markus
 Armbruster arm...@redhat.com Date:   Thu Mar 5 14:35:26 2015
 +0100
 
 monitor: Drop broken, unused asynchronous command interface
 
 
 The patch:
 
 From 1b0221078353870fe530e49de158cae205f9bce5 Mon Sep 17
 00:00:00 2001
 From: Don Slutz dsl...@verizon.com Date: Thu, 4 Jun 2015
 17:04:42 -0400 Subject: [PATCH 01/14] monitor: Allow Xen's
 (broken) usage of asynchronous command interface.
 
 commit 65207c59d99f2260c5f1d3b9c491146616a522aa Author: Markus
 Armbruster arm...@redhat.com Date:   Thu Mar 5 14:35:26 2015
 +0100
 
 monitor: Drop broken, unused asynchronous command interface
 
 Breaks Xen.  Add a hack un unbreak it.
 
 s/un /to /

Sigh, will fix.

 
 
 Xen is only doing synchronous commands, but is including an id.
 
 QMP also uses id, but apparently removes it up front before calling
 into this function; so another fix would be having xen remove it up
 front.
 

Hopefully I will get to a change to Xen.  However getting the Xen
change back-ported to enough version(s) will not be quick...


 
 Signed-off-by: Don Slutz dsl...@verizon.com --- monitor.c | 9
 + 1 file changed, 9 insertions(+)
 
 diff --git a/monitor.c b/monitor.c index c7baa91..e9a0747 100644 
 --- a/monitor.c +++ b/monitor.c @@ -4955,6 +4955,15 @@ static
 QDict *qmp_check_input_obj(QObject *input_obj, Error **errp) 
 arguments, object); return NULL; } +} else if
 (!strcmp(arg_name, id)) { +/* + * Fixup
 Xen's usage. Just ignore the id. See point #5 + *
 above.  This was an attempt at an asynchronous + *
 command interface.  However commit + *
 65207c59d99f2260c5f1d3b9c491146616a522aa is + *
 wrong. Xen does not expect an error when it passes in +
 * id:1, so just continue to ignore it. + */
 
 The comment is a bit verbose, particularly since 'id' is a 
 well-established usage pattern in QMP.  Also, we don't need to call
 out why it changed in the comment here, the commit message is
 sufficient for that.
 

Ok, will also see if Markus has anything to say.

   -Don Slutz

 } else { error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name); return
 NULL;
 
 
-BEGIN PGP SIGNATURE-
Version: GnuPG v2.0.14 (GNU/Linux)

iQIcBAEBAgAGBQJVcM85AAoJEMH0lYjxq9Kcvd0QAK5H6/2NUvqKCO/zje/8cXsT
ueLOYG4keNWJ3x7XGpOAWqIuYc673uYjApEquSpR2TRyhHwB2ZuShEjtCA5bakOH
VJJ03uLq+vrQo0Hxm8oR5/7C2w0L2GkpzGnqUlmZ6/9RNbDHGmGS6PSUC5xbwICM
6v31k0b89HG4AmAxg3/O5qeBe9m/pL+OeDjKXc6zbr7xhUIq4lxtx0VEy4HAGReS
V8+MLDJ73T6o6FUD6U/EcCmK/6GuMMG0jwZsVgbBvbeGmT1tP8Z9YMjpf3X393ZG
Il9LaUNCzhJRcWVOc4UBM8du3FLcHX4fviYyW5uEXt4aJdSoijd4BAv2znyyndmu
oep7vEc5w/VkXKuXxg1hTokCqvkLEK6WYD4M+i1huiBuNs3qQop6euqYV97tEsl3
h3fjhibkZRbIVsm6vrm41Jr75ZDnbftPMAINc9aYvvstNrxBrR7u7sw6gwAY1n6+
e5gyy5l5P6/R3LS4s41oXSOiCk7pndPp3AilOZ863MS5TJFXLfo1z0wEQ471A2hT
NHvi+o4G2iKZ33MAB9Jq6hmWveJbs8sY+Fm/IWeZn/dDt7ohn8V+rFIX3LEYfDMN
cknhMSRpKD9eRSo4LM4xU9kq1J5spaewDbkGkl7e6pHVTWphLlkk/cT2W9crW3ji
PybnLaIJP2/aljcLfdYK
=lEbh
-END PGP SIGNATURE-



Re: [Qemu-devel] [Qemu-trivial] [PATCH] Add .dir-locals.el file to configure emacs coding style

2015-06-04 Thread Don Slutz
On 06/04/15 09:30, Daniel P. Berrange wrote:
 On Wed, Jun 03, 2015 at 09:47:24AM +0200, Markus Armbruster wrote:
 Daniel P. Berrange berra...@redhat.com writes:

 The default emacs setup indents by 2 spaces and uses tabs
 which is counter to the QEMU coding style rules. Adding a
 .dir-locals.el file in the top level of the GIT repo will
 inform emacs about the QEMU coding style, and so assist
 contributors in avoiding common style mistakes before
 they submit patches.

 Yes, please!

 Signed-off-by: Daniel P. Berrange berra...@redhat.com
 ---
  .dir-locals.el | 8 
  1 file changed, 8 insertions(+)
  create mode 100644 .dir-locals.el

 diff --git a/.dir-locals.el b/.dir-locals.el
 new file mode 100644
 index 000..ddb2fae
 --- /dev/null
 +++ b/.dir-locals.el
 @@ -0,0 +1,8 @@
 +(
 + (c-mode . (
 +(c-file-style . KR)
 +(indent-tabs-mode . nil)
 +(c-indent-level . 4)
 +(c-basic-offset . 4)
 +))
 +)
 
 [snip]
 
 Does the following .dir-locals.el work for you equally well?

 ((c-mode . ((c-file-style . stroustrup)
 (indent-tabs-mode . nil
 
 Yes, that is fine too.
 

I got this from someone on the list, see

https://wiki.linaro.org/PeterMaydell/QemuEmacsStyle

Which then allows me to do:

((c-mode . ((c-file-style . qemu

in .dir-locals.el

But this is not a good general change :(

But I would like at least the the stroustrup version.

   -Don Slutz

 Regards,
 Daniel
 



Re: [Qemu-devel] [Qemu-trivial] [PATCH] Add .dir-locals.el file to configure emacs coding style

2015-06-04 Thread Don Slutz
On 06/04/15 09:30, Daniel P. Berrange wrote:
 On Wed, Jun 03, 2015 at 09:47:24AM +0200, Markus Armbruster wrote:
 Daniel P. Berrange berra...@redhat.com writes:

 The default emacs setup indents by 2 spaces and uses tabs
 which is counter to the QEMU coding style rules. Adding a
 .dir-locals.el file in the top level of the GIT repo will
 inform emacs about the QEMU coding style, and so assist
 contributors in avoiding common style mistakes before
 they submit patches.

 Yes, please!

 Signed-off-by: Daniel P. Berrange berra...@redhat.com
 ---
  .dir-locals.el | 8 
  1 file changed, 8 insertions(+)
  create mode 100644 .dir-locals.el

 diff --git a/.dir-locals.el b/.dir-locals.el
 new file mode 100644
 index 000..ddb2fae
 --- /dev/null
 +++ b/.dir-locals.el
 @@ -0,0 +1,8 @@
 +(
 + (c-mode . (
 +(c-file-style . KR)
 +(indent-tabs-mode . nil)
 +(c-indent-level . 4)
 +(c-basic-offset . 4)
 +))
 +)
 
 [snip]
 
 Does the following .dir-locals.el work for you equally well?

 ((c-mode . ((c-file-style . stroustrup)
 (indent-tabs-mode . nil
 
 Yes, that is fine too.
 

I got this from someone on the list, see

https://wiki.linaro.org/PeterMaydell/QemuEmacsStyle

Which then allows me to do:

((c-mode . ((c-file-style . qemu

in .dir-locals.el

But this is not a good general change :(

But I would like at least the the stroustrup version.

   -Don Slutz

 Regards,
 Daniel
 



Re: [Qemu-devel] [PATCH 1/1] Fix device listener interface for PCI to PCI bridges

2015-05-29 Thread Don Slutz
On 05/28/15 17:05, Michael S. Tsirkin wrote:
 On Thu, May 28, 2015 at 11:03:07PM +0200, Michael S. Tsirkin wrote:
 On Thu, May 28, 2015 at 03:09:48PM -0400, Don Slutz wrote:
 On 05/28/15 08:28, Michael S. Tsirkin wrote:
 On Thu, May 28, 2015 at 07:25:50AM -0400, Don Slutz wrote:
 On 05/28/15 05:30, Michael S. Tsirkin wrote:
 On Thu, May 28, 2015 at 04:46:37AM -0400, Don Slutz wrote:
 The commit 707ff80021ccd7a68f4b3d2c44eebf87efbb41c4 assumed that a
 PCI device has a static address.  This is not true for PCI devices
 that are on the secondary bus of a PCI to PCI bridge.


...

 Not really because it's not just secondary bus number.
 Changing subordinate bus numbers can hide/unhide whole buses.

 You are right.  I have no idea what Paul Durrant was thinking about this
 case.
 And this would apply to PCI_SUBORDINATE_BUS not PCI_SECONDARY_BUS.

 Since at QEMU 2.2 Xen sends all pci-config requests to QEMU, things
 worked.
 Why worked?


The issue is that PCI to PCI bridges were not configured by hvmloader
nor by SeaBIOS.  I do have a patch
to Xen that fixes this (I was rebasing on the latest Xen to post it and
my test case stopped working).  So PCI devices that exist on the
secondary side of a PCI to PCI bridge could only be used (by Linux with
at least pci=assign-busses) after booting.


 It is not clear to me that the complexity of tracking bus
 visibility make sense.  Clearly you do.
 Well what was the point of the change?

To get config cycles that are valid that you do not get today.

 If you don't care that we get irrelevant config cycles why not
 just send them all to QEMU?


That would need to be answered by Paul Durrant and/or other people (see
below)


 Would it be better to have:

 void device_listener_change_pci_bus_num(PCIBus *b, PCIDevice *d, void
 *opaque)
 {
 uint8_t oldbus = (uint8_t)opaque;
 DEVICE_LISTENER_CALL(change_pci_bus_num, Forward, d, oldbus);
 }

 So that the above works, or to add a function to convert args?

 To know whether device is accessible to config cycles, you
 really need to scan the hierarchy from root downwards.

 Yes, that is correct.  However what I am doing here is not
 changing how QEMU checks if the device is accessible, but
 changing what pci config Xen sends to QEMU.  If the change
 to PCI_SECONDARY_BUS hides this PCI to PCI bridge, that is
 not an issue.


-Don Slutz


 Imagine a bridge with secondary bus number 5
 behind another one with subordinate numbers 1-3.
 You should not send conf cycles for bus number 5 to qemu.

 That is correct.  How ever unless Paul Durrant has an example of more then 1
 QEMU where this would make a difference, the cases I am aware of are:

 1) Xen does not send it, and returns 0x (or smaller).

 2) QEMU returns 0x (or smaller).

 I will grant that #1 is faster, but it also is only happening during start
 up and so I do not see the clear win to add more complex code to only do #1.

-Don Slutz
 It's not about faster. I assumed you need to get just the correct
 stuff out to QEMU to gain the better security as
 3996e85c1822e05c50250f8d2d1e57b6bea1229d claims.
 And if that's not the case, please educate me.

I do not know enough about this to answer here.  I have added xen-devel
list to this in the hope
that someone there can answer the better security question.

   -Don Slutz


 -- 
 MST




Re: [Qemu-devel] [PATCH 1/1] Fix device listener interface for PCI to PCI bridges

2015-05-28 Thread Don Slutz

On 05/28/15 08:28, Michael S. Tsirkin wrote:

On Thu, May 28, 2015 at 07:25:50AM -0400, Don Slutz wrote:

On 05/28/15 05:30, Michael S. Tsirkin wrote:

On Thu, May 28, 2015 at 04:46:37AM -0400, Don Slutz wrote:

The commit 707ff80021ccd7a68f4b3d2c44eebf87efbb41c4 assumed that a
PCI device has a static address.  This is not true for PCI devices
that are on the secondary bus of a PCI to PCI bridge.

BIOS and/or guest OS can change the secondary bus number to a new
value at any time.

When a PCI to PCI bridge bridge is reset, the secondary bus number
is set to zero.  Normally the BIOS will set it to 255 during PCI bus
scanning so that only the PCI devices on the root can be accessed
via bus 0.  Later it is set to a number between 1 and 254.

Adjust xen_map_pcidev() to not register with Xen for secondary bus
numbers 0 and 255.

Extend the device listener interface to be called when ever the
secondary bus number is set to a usable value.  This includes
a call on unrealize if the secondary bus number was valid.

Signed-off-by: Don Slutz dsl...@verizon.com
---

Note: Right now hvmloader in Xen does not handle PCI to PCI bridges
and so SeaBIOS does not have access to PCI device(s) on secondary
buses.  How ever domU can setup the secondary bus(es) and this patch
will restore access to these PCI devices.

  hw/core/qdev.c  | 10 ++
  hw/pci/pci_bridge.c | 30 ++
  include/hw/qdev-core.h  |  2 ++
  include/hw/xen/xen_common.h | 31 +--
  trace-events|  1 +
  5 files changed, 68 insertions(+), 6 deletions(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index b0f0f84..6a514ee 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -239,6 +239,16 @@ void device_listener_unregister(DeviceListener *listener)
  QTAILQ_REMOVE(device_listeners, listener, link);
  }
  
+void device_listener_realize(DeviceState *dev)

+{
+DEVICE_LISTENER_CALL(realize, Forward, dev);
+}
+
+void device_listener_unrealize(DeviceState *dev)
+{
+DEVICE_LISTENER_CALL(unrealize, Forward, dev);
+}
+
  static void device_realize(DeviceState *dev, Error **errp)
  {
  DeviceClass *dc = DEVICE_GET_CLASS(dev);


This looks wrong.  Devices not accessible to config cycles are still
accessible e.g. to memory or IO.  It's not the same as unrealize.

You need some other API that makes sense,
probably pci specific.


If I am understanding you correctly, you would like:

void device_listener_change_pci_bus_num(PCIDevice *d, uint8_t oldbus)
{
 DEVICE_LISTENER_CALL(change_pci_bus_num, Forward, d, oldbus);
}


I'm not sure what oldbus is but basically ok.


oldbus is the previous value that pci_bus_num(pci_dev-bus) would have 
returned.  Passing it avoids the:


+pci_set_byte(d-config + PCI_SECONDARY_BUS, oldbus);
+pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
+pci_bridge_unrealize_sub, NULL);
+pci_set_byte(d-config + PCI_SECONDARY_BUS, newbus);

hack.  At least xen wants to know the old value so that an unrealize (i.e. unmap 
in xen terms) can be done for the old value and then pci_bus_num(pci_dev-bus) can be 
done to get the new mapping.




And it must be invoked whenever bus visibility changes,
not just its number.


This is not clear to me.  Maybe Paul Durrant has a better understanding.

 I look at this patch as a bug fix in that QEMU 2.2 and before work 
with pci-bridge.  It is only after Paul's change that it stops working.  
Maybe part of what is not clear is that the new routine is called for 
the PCI devices on the secondary bus.


So at start using the example QEMU config (a Xen one):

/usr/lib/xen/bin/qemu-system-i386 \
 -xen-domid \
 13 \
 -chardev \
 socket,id=libxl-cmd,path=/var/run/xen/qmp-libxl-13,server,nowait \
 -no-shutdown \
 -mon \
 chardev=libxl-cmd,mode=control \
 -chardev \
 socket,id=libxenstat-cmd,path=/var/run/xen/qmp-libxenstat-13,server,nowait \
 -mon \
 chardev=libxenstat-cmd,mode=control \
 -nodefaults \
 -name \
 C63-min-tools \
 -vnc \
 127.0.0.1:0,to=99 \
 -display \
 none \
 -serial \
 pty \
 -device \
 cirrus-vga,vgamem_mb=8 \
 -boot \
 order=cda \
 -device \
 vmxnet3,id=nic0,netdev=net0,mac=00:0c:29:86:44:a0 \
 -netdev \
 type=tap,id=net0,ifname=vif13.0-emu,script=no,downscript=no \
 -device \
 e1000,id=nic1,netdev=net1,mac=00:0c:29:86:44:aa \
 -netdev \
 type=tap,id=net1,ifname=vif13.1-emu,script=no,downscript=no \
 -machine \
 xenfv \
 -monitor \
 pty \
 -boot \
 menu=on \
 -device \
 pci-bridge,chassis_nr=1,msi=on,id=pciBridge1.0,addr=0x11.0 \
 -device \
 pci-bridge,chassis_nr=2,msi=on,id=pciBridge5.0,multifunction=on,addr=0x15.0 \
 -device \
 pci-bridge,chassis_nr=3,msi=on,id=pciBridge6.0,multifunction=on,addr=0x16.0 \
 -device \
 
pci-bridge,chassis_nr=4,msi=on,id=pciBridge7.0,multifunction=on,bus=pciBridge1.0,addr=0x17.0
 \
 -device \
 pci-bridge,chassis_nr=5,msi=on,id=pciBridge8.0,multifunction=on,addr=0x18.0 \
 -device \
 pvscsi

[Qemu-devel] [PATCH 1/1] Fix device listener interface for PCI to PCI bridges

2015-05-28 Thread Don Slutz
The commit 707ff80021ccd7a68f4b3d2c44eebf87efbb41c4 assumed that a
PCI device has a static address.  This is not true for PCI devices
that are on the secondary bus of a PCI to PCI bridge.

BIOS and/or guest OS can change the secondary bus number to a new
value at any time.

When a PCI to PCI bridge bridge is reset, the secondary bus number
is set to zero.  Normally the BIOS will set it to 255 during PCI bus
scanning so that only the PCI devices on the root can be accessed
via bus 0.  Later it is set to a number between 1 and 254.

Adjust xen_map_pcidev() to not register with Xen for secondary bus
numbers 0 and 255.

Extend the device listener interface to be called when ever the
secondary bus number is set to a usable value.  This includes
a call on unrealize if the secondary bus number was valid.

Signed-off-by: Don Slutz dsl...@verizon.com
---

Note: Right now hvmloader in Xen does not handle PCI to PCI bridges
and so SeaBIOS does not have access to PCI device(s) on secondary
buses.  How ever domU can setup the secondary bus(es) and this patch
will restore access to these PCI devices.

 hw/core/qdev.c  | 10 ++
 hw/pci/pci_bridge.c | 30 ++
 include/hw/qdev-core.h  |  2 ++
 include/hw/xen/xen_common.h | 31 +--
 trace-events|  1 +
 5 files changed, 68 insertions(+), 6 deletions(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index b0f0f84..6a514ee 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -239,6 +239,16 @@ void device_listener_unregister(DeviceListener *listener)
 QTAILQ_REMOVE(device_listeners, listener, link);
 }
 
+void device_listener_realize(DeviceState *dev)
+{
+DEVICE_LISTENER_CALL(realize, Forward, dev);
+}
+
+void device_listener_unrealize(DeviceState *dev)
+{
+DEVICE_LISTENER_CALL(unrealize, Forward, dev);
+}
+
 static void device_realize(DeviceState *dev, Error **errp)
 {
 DeviceClass *dc = DEVICE_GET_CLASS(dev);
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 40c97b1..042680d 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -241,6 +241,18 @@ void pci_bridge_update_mappings(PCIBridge *br)
 pci_bridge_region_cleanup(br, w);
 }
 
+static void pci_bridge_realize_sub(PCIBus *b, PCIDevice *d,
+   void *opaque)
+{
+device_listener_realize(DEVICE(d));
+}
+
+static void pci_bridge_unrealize_sub(PCIBus *b, PCIDevice *d,
+ void *opaque)
+{
+device_listener_unrealize(DEVICE(d));
+}
+
 /* default write_config function for PCI-to-PCI bridge */
 void pci_bridge_write_config(PCIDevice *d,
  uint32_t address, uint32_t val, int len)
@@ -248,6 +260,8 @@ void pci_bridge_write_config(PCIDevice *d,
 PCIBridge *s = PCI_BRIDGE(d);
 uint16_t oldctl = pci_get_word(d-config + PCI_BRIDGE_CONTROL);
 uint16_t newctl;
+uint8_t oldbus = pci_get_byte(d-config + PCI_SECONDARY_BUS);
+uint8_t newbus;
 
 pci_default_write_config(d, address, val, len);
 
@@ -265,6 +279,22 @@ void pci_bridge_write_config(PCIDevice *d,
 pci_bridge_update_mappings(s);
 }
 
+newbus = pci_get_byte(d-config + PCI_SECONDARY_BUS);
+if (newbus != oldbus) {
+PCIBus *sec_bus = pci_bridge_get_sec_bus(s);
+
+if (oldbus  oldbus != 255) {
+pci_set_byte(d-config + PCI_SECONDARY_BUS, oldbus);
+pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
+pci_bridge_unrealize_sub, NULL);
+pci_set_byte(d-config + PCI_SECONDARY_BUS, newbus);
+}
+if (newbus  newbus != 255) {
+pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
+pci_bridge_realize_sub, NULL);
+}
+}
+
 newctl = pci_get_word(d-config + PCI_BRIDGE_CONTROL);
 if (~oldctl  newctl  PCI_BRIDGE_CTL_BUS_RESET) {
 /* Trigger hot reset on 0-1 transition. */
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index d4be92f..8bd38af 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -387,5 +387,7 @@ static inline bool qbus_is_hotpluggable(BusState *bus)
 
 void device_listener_register(DeviceListener *listener);
 void device_listener_unregister(DeviceListener *listener);
+void device_listener_realize(DeviceState *dev);
+void device_listener_unrealize(DeviceState *dev);
 
 #endif
diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h
index 38f29fb..1c27d51 100644
--- a/include/hw/xen/xen_common.h
+++ b/include/hw/xen/xen_common.h
@@ -347,12 +347,31 @@ static inline void xen_map_pcidev(XenXC xc, domid_t dom,
   ioservid_t ioservid,
   PCIDevice *pci_dev)
 {
-trace_xen_map_pcidev(ioservid, pci_bus_num(pci_dev-bus),
- PCI_SLOT(pci_dev-devfn), PCI_FUNC(pci_dev-devfn));
-xc_hvm_map_pcidev_to_ioreq_server(xc, dom, ioservid

Re: [Qemu-devel] [PATCH 1/1] Fix device listener interface for PCI to PCI bridges

2015-05-28 Thread Don Slutz
On 05/28/15 05:30, Michael S. Tsirkin wrote:
 On Thu, May 28, 2015 at 04:46:37AM -0400, Don Slutz wrote:
 The commit 707ff80021ccd7a68f4b3d2c44eebf87efbb41c4 assumed that a
 PCI device has a static address.  This is not true for PCI devices
 that are on the secondary bus of a PCI to PCI bridge.

 BIOS and/or guest OS can change the secondary bus number to a new
 value at any time.

 When a PCI to PCI bridge bridge is reset, the secondary bus number
 is set to zero.  Normally the BIOS will set it to 255 during PCI bus
 scanning so that only the PCI devices on the root can be accessed
 via bus 0.  Later it is set to a number between 1 and 254.

 Adjust xen_map_pcidev() to not register with Xen for secondary bus
 numbers 0 and 255.

 Extend the device listener interface to be called when ever the
 secondary bus number is set to a usable value.  This includes
 a call on unrealize if the secondary bus number was valid.

 Signed-off-by: Don Slutz dsl...@verizon.com
 ---

 Note: Right now hvmloader in Xen does not handle PCI to PCI bridges
 and so SeaBIOS does not have access to PCI device(s) on secondary
 buses.  How ever domU can setup the secondary bus(es) and this patch
 will restore access to these PCI devices.

  hw/core/qdev.c  | 10 ++
  hw/pci/pci_bridge.c | 30 ++
  include/hw/qdev-core.h  |  2 ++
  include/hw/xen/xen_common.h | 31 +--
  trace-events|  1 +
  5 files changed, 68 insertions(+), 6 deletions(-)

 diff --git a/hw/core/qdev.c b/hw/core/qdev.c
 index b0f0f84..6a514ee 100644
 --- a/hw/core/qdev.c
 +++ b/hw/core/qdev.c
 @@ -239,6 +239,16 @@ void device_listener_unregister(DeviceListener 
 *listener)
  QTAILQ_REMOVE(device_listeners, listener, link);
  }
  
 +void device_listener_realize(DeviceState *dev)
 +{
 +DEVICE_LISTENER_CALL(realize, Forward, dev);
 +}
 +
 +void device_listener_unrealize(DeviceState *dev)
 +{
 +DEVICE_LISTENER_CALL(unrealize, Forward, dev);
 +}
 +
  static void device_realize(DeviceState *dev, Error **errp)
  {
  DeviceClass *dc = DEVICE_GET_CLASS(dev);
 
 
 This looks wrong.  Devices not accessible to config cycles are still
 accessible e.g. to memory or IO.  It's not the same as unrealize.
 
 You need some other API that makes sense,
 probably pci specific.
 

If I am understanding you correctly, you would like:

void device_listener_change_pci_bus_num(PCIDevice *d, uint8_t oldbus)
{
DEVICE_LISTENER_CALL(change_pci_bus_num, Forward, d, oldbus);
}


 
 
 diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
 index 40c97b1..042680d 100644
 --- a/hw/pci/pci_bridge.c
 +++ b/hw/pci/pci_bridge.c
 @@ -241,6 +241,18 @@ void pci_bridge_update_mappings(PCIBridge *br)
  pci_bridge_region_cleanup(br, w);
  }
  
 +static void pci_bridge_realize_sub(PCIBus *b, PCIDevice *d,
 +   void *opaque)
 +{
 +device_listener_realize(DEVICE(d));
 +}
 +
 +static void pci_bridge_unrealize_sub(PCIBus *b, PCIDevice *d,
 + void *opaque)
 +{
 +device_listener_unrealize(DEVICE(d));
 +}
 +
  /* default write_config function for PCI-to-PCI bridge */
  void pci_bridge_write_config(PCIDevice *d,
   uint32_t address, uint32_t val, int len)
 @@ -248,6 +260,8 @@ void pci_bridge_write_config(PCIDevice *d,
  PCIBridge *s = PCI_BRIDGE(d);
  uint16_t oldctl = pci_get_word(d-config + PCI_BRIDGE_CONTROL);
  uint16_t newctl;
 +uint8_t oldbus = pci_get_byte(d-config + PCI_SECONDARY_BUS);
 +uint8_t newbus;
  
  pci_default_write_config(d, address, val, len);
  
 @@ -265,6 +279,22 @@ void pci_bridge_write_config(PCIDevice *d,
  pci_bridge_update_mappings(s);
  }
  
 +newbus = pci_get_byte(d-config + PCI_SECONDARY_BUS);
 +if (newbus != oldbus) {
 +PCIBus *sec_bus = pci_bridge_get_sec_bus(s);
 +
 +if (oldbus  oldbus != 255) {
 +pci_set_byte(d-config + PCI_SECONDARY_BUS, oldbus);
 +pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
 +pci_bridge_unrealize_sub, NULL);
 +pci_set_byte(d-config + PCI_SECONDARY_BUS, newbus);
 +}
 +if (newbus  newbus != 255) {
 +pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
 +pci_bridge_realize_sub, NULL);
 +}
 +}
 +
 
 
 This is relying on undocumented assumptions and how specific firmware
 works. There's nothing special about bus number 255, and 0 is not very
 special either (except it happens to be the reset value).
 

Ok, using the above it would change to (almost):


if (newbus != oldbus) {
pci_for_each_device(pci_bridge_get_sec_bus(s),
pci_bus_num(sec_bus),
device_listener_change_pci_bus_num,
oldbus);
}

Would it be better to have:

void device_listener_change_pci_bus_num(PCIBus *b

[Qemu-devel] Ping [PATCH 1/1] xen-hvm: Add trace to ioreq

2015-05-13 Thread Don Slutz
On 04/30/15 14:27, Don Slutz wrote:
 Signed-off-by: Don Slutz dsl...@verizon.com
 (cherry picked from commit b72adbe7510d0a30053d32334665ee887bec9e43)
 ---
  trace-events |  7 +++
  xen-hvm.c| 21 +
  2 files changed, 28 insertions(+)
 
 diff --git a/trace-events b/trace-events
 index 30eba92..4666dad 100644
 --- a/trace-events
 +++ b/trace-events
 @@ -932,6 +932,13 @@ xen_map_portio_range(uint32_t id, uint64_t start_addr, 
 uint64_t end_addr) id: %
  xen_unmap_portio_range(uint32_t id, uint64_t start_addr, uint64_t end_addr) 
 id: %u start: %#PRIx64 end: %#PRIx64
  xen_map_pcidev(uint32_t id, uint8_t bus, uint8_t dev, uint8_t func) id: %u 
 bdf: %02x.%02x.%02x
  xen_unmap_pcidev(uint32_t id, uint8_t bus, uint8_t dev, uint8_t func) id: 
 %u bdf: %02x.%02x.%02x
 +handle_ioreq(void *req, uint32_t type, uint32_t dir, uint32_t df, uint32_t 
 data_is_ptr, uint64_t addr, uint64_t data, uint32_t count, uint32_t size) 
 I/O=%p type=%d dir=%d df=%d ptr=%d port=%#PRIx64 data=%#PRIx64 count=%d 
 size=%d
 +handle_ioreq_read(void *req, uint32_t type, uint32_t df, uint32_t 
 data_is_ptr, uint64_t addr, uint64_t data, uint32_t count, uint32_t size) 
 I/O=%p read type=%d df=%d ptr=%d port=%#PRIx64 data=%#PRIx64 count=%d 
 size=%d
 +handle_ioreq_write(void *req, uint32_t type, uint32_t df, uint32_t 
 data_is_ptr, uint64_t addr, uint64_t data, uint32_t count, uint32_t size) 
 I/O=%p write type=%d df=%d ptr=%d port=%#PRIx64 data=%#PRIx64 count=%d 
 size=%d
 +cpu_ioreq_pio(void *req, uint32_t dir, uint32_t df, uint32_t data_is_ptr, 
 uint64_t addr, uint64_t data, uint32_t count, uint32_t size) I/O=%p pio 
 dir=%d df=%d ptr=%d port=%#PRIx64 data=%#PRIx64 count=%d size=%d
 +cpu_ioreq_pio_read_reg(void *req, uint64_t data, uint64_t addr, uint32_t 
 size) I/O=%p pio read reg data=%#PRIx64 port=%#PRIx64 size=%d
 +cpu_ioreq_pio_write_reg(void *req, uint64_t data, uint64_t addr, uint32_t 
 size) I/O=%p pio write reg data=%#PRIx64 port=%#PRIx64 size=%d
 +cpu_ioreq_move(void *req, uint32_t dir, uint32_t df, uint32_t data_is_ptr, 
 uint64_t addr, uint64_t data, uint32_t count, uint32_t size) I/O=%p copy 
 dir=%d df=%d ptr=%d port=%#PRIx64 data=%#PRIx64 count=%d size=%d
  
  # xen-mapcache.c
  xen_map_cache(uint64_t phys_addr) want %#PRIx64
 diff --git a/xen-hvm.c b/xen-hvm.c
 index 315864c..6fdba98 100644
 --- a/xen-hvm.c
 +++ b/xen-hvm.c
 @@ -832,9 +832,14 @@ static void cpu_ioreq_pio(ioreq_t *req)
  {
  uint32_t i;
  
 +trace_cpu_ioreq_pio(req, req-dir, req-df, req-data_is_ptr, req-addr,
 + req-data, req-count, req-size);
 +
  if (req-dir == IOREQ_READ) {
  if (!req-data_is_ptr) {
  req-data = do_inp(req-addr, req-size);
 +trace_cpu_ioreq_pio_read_reg(req, req-data, req-addr,
 + req-size);
  } else {
  uint32_t tmp;
  
 @@ -845,6 +850,8 @@ static void cpu_ioreq_pio(ioreq_t *req)
  }
  } else if (req-dir == IOREQ_WRITE) {
  if (!req-data_is_ptr) {
 +trace_cpu_ioreq_pio_write_reg(req, req-data, req-addr,
 +  req-size);
  do_outp(req-addr, req-size, req-data);
  } else {
  for (i = 0; i  req-count; i++) {
 @@ -861,6 +868,9 @@ static void cpu_ioreq_move(ioreq_t *req)
  {
  uint32_t i;
  
 +trace_cpu_ioreq_move(req, req-dir, req-df, req-data_is_ptr, req-addr,
 + req-data, req-count, req-size);
 +
  if (!req-data_is_ptr) {
  if (req-dir == IOREQ_READ) {
  for (i = 0; i  req-count; i++) {
 @@ -933,11 +943,18 @@ static void handle_vmport_ioreq(XenIOState *state, 
 ioreq_t *req)
  
  static void handle_ioreq(XenIOState *state, ioreq_t *req)
  {
 +trace_handle_ioreq(req, req-type, req-dir, req-df, req-data_is_ptr,
 +   req-addr, req-data, req-count, req-size);
 +
  if (!req-data_is_ptr  (req-dir == IOREQ_WRITE) 
  (req-size  sizeof (target_ulong))) {
  req-data = ((target_ulong) 1  (8 * req-size)) - 1;
  }
  
 +if (req-dir == IOREQ_WRITE)
 +trace_handle_ioreq_write(req, req-type, req-df, req-data_is_ptr,
 + req-addr, req-data, req-count, 
 req-size);
 +
  switch (req-type) {
  case IOREQ_TYPE_PIO:
  cpu_ioreq_pio(req);
 @@ -977,6 +994,10 @@ static void handle_ioreq(XenIOState *state, ioreq_t *req)
  default:
  hw_error(Invalid ioreq type 0x%x\n, req-type);
  }
 +if (req-dir == IOREQ_READ) {
 +trace_handle_ioreq_read(req, req-type, req-df, req-data_is_ptr,
 +req-addr, req-data, req-count, req-size);
 +}
  }
  
  static int handle_buffered_iopage(XenIOState *state)
 



[Qemu-devel] [PATCH v6 2/7] vmport_rpc: Add the object vmport_rpc

2015-05-12 Thread Don Slutz
This is the 1st part of Add limited support of VMware's hyper-call
rpc.

This patch uses existing infrastructure used by vmmouse.c (provided
by vmport.c) to handle the VMware backdoor command 30.

One of the better on-line references is:

https://sites.google.com/site/chitchatvmback/backdoor

More in next patch.

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/i386/pc.c  |   6 +++
 hw/misc/Makefile.objs |   1 +
 hw/misc/vmport_rpc.c  | 126 ++
 3 files changed, 133 insertions(+)
 create mode 100644 hw/misc/vmport_rpc.c

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 769eb25..4d2e004 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1471,8 +1471,14 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
 i8042 = isa_create_simple(isa_bus, i8042);
 i8042_setup_a20_line(i8042, a20_line[0]);
 if (!no_vmport) {
+ISADevice *vmport_rpc;
+
 vmport_init(isa_bus);
 vmmouse = isa_try_create(isa_bus, vmmouse);
+vmport_rpc = isa_try_create(isa_bus, vmport_rpc);
+if (vmport_rpc) {
+qdev_init_nofail(DEVICE(vmport_rpc));
+}
 } else {
 vmmouse = NULL;
 }
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 4aa76ff..e04c8ac 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -7,6 +7,7 @@ common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o
 common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o
 
 obj-$(CONFIG_VMPORT) += vmport.o
+obj-$(CONFIG_VMPORT) += vmport_rpc.o
 
 # ARM devices
 common-obj-$(CONFIG_PL310) += arm_l2x0.o
diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
new file mode 100644
index 000..b7cd355
--- /dev/null
+++ b/hw/misc/vmport_rpc.c
@@ -0,0 +1,126 @@
+/*
+ * QEMU VMPORT RPC emulation
+ *
+ * Copyright (C) 2015 Verizon Corporation
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License Version 2 (GPLv2)
+ * as published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details. http://www.gnu.org/licenses/.
+ */
+
+/*
+ * One of the better on-line references is:
+ *
+ * https://sites.google.com/site/chitchatvmback/backdoor
+ *
+ * Which points you to:
+ *
+ * http://open-vm-tools.sourceforge.net/
+ *
+ * as a place to get more accurate information by studying.
+ */
+
+#include hw/hw.h
+#include hw/i386/pc.h
+#include hw/qdev.h
+#include trace.h
+#include qmp-commands.h
+#include qapi/qmp/qerror.h
+
+/* #define VMPORT_RPC_DEBUG */
+
+#define TYPE_VMPORT_RPC vmport_rpc
+#define VMPORT_RPC(obj) OBJECT_CHECK(VMPortRpcState, (obj), TYPE_VMPORT_RPC)
+
+/* VMPORT RPC Command */
+#define VMPORT_RPC_COMMAND  30
+
+/* The vmport_rpc object. */
+typedef struct VMPortRpcState {
+ISADevice parent_obj;
+
+/* Properties */
+uint64_t reset_time;
+uint64_t build_number_value;
+uint64_t build_number_time;
+
+/* Private data */
+} VMPortRpcState;
+
+typedef struct {
+uint32_t eax;
+uint32_t ebx;
+uint32_t ecx;
+uint32_t edx;
+uint32_t esi;
+uint32_t edi;
+} vregs;
+
+static uint32_t vmport_rpc_ioport_read(void *opaque, uint32_t addr)
+{
+VMPortRpcState *s = opaque;
+union {
+uint32_t data[6];
+vregs regs;
+} ur;
+
+vmmouse_get_data(ur.data);
+
+s-build_number_time++;
+
+vmmouse_set_data(ur.data);
+return ur.data[0];
+}
+
+static void vmport_rpc_reset(DeviceState *d)
+{
+VMPortRpcState *s = VMPORT_RPC(d);
+
+s-reset_time = 14;
+s-build_number_value = 0;
+s-build_number_time = 0;
+}
+
+static void vmport_rpc_realize(DeviceState *dev, Error **errp)
+{
+VMPortRpcState *s = VMPORT_RPC(dev);
+
+vmport_register(VMPORT_RPC_COMMAND, vmport_rpc_ioport_read, s);
+}
+
+static Property vmport_rpc_properties[] = {
+DEFINE_PROP_UINT64(reset-time, VMPortRpcState, reset_time, 14),
+DEFINE_PROP_UINT64(build-number-value, VMPortRpcState,
+   build_number_value, 0),
+DEFINE_PROP_UINT64(build-number-time, VMPortRpcState,
+   build_number_time, 0),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vmport_rpc_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc-realize = vmport_rpc_realize;
+dc-reset = vmport_rpc_reset;
+dc-props = vmport_rpc_properties;
+}
+
+static const TypeInfo vmport_rpc_info = {
+.name  = TYPE_VMPORT_RPC,
+.parent= TYPE_ISA_DEVICE,
+.instance_size = sizeof(VMPortRpcState),
+.class_init= vmport_rpc_class_init,
+};
+
+static void vmport_rpc_register_types(void)
+{
+type_register_static(vmport_rpc_info);
+}
+
+type_init(vmport_rpc_register_types)
-- 
1.8.4




[Qemu-devel] [PATCH v6 0/7] Add limited support of VMware's hyper-call rpc

2015-05-12 Thread Don Slutz
Changes v5 to v6:

  Rebase to master

  Eric Blake
Returning a non-dictionary is not extensible.
  Added new type VmportGuestInfoValue.
  s/VmportGuestInfo/VmportGuestInfoKey/
  s/type/struct/
Issues with examples
  Fixed.


Changes v4 to v5:

  Paolo Bonzini
What is VMPORT_SHORT about?
  Dropped this.
Why not use a bool in CPUX86State?
  Took his sugestion and moved to a bool in X86CPU.

Changes v3 to v4:

  Paolo Bonzini on vmort_rpc: Add QMP access to vmport_rpc
Does this compile on non-x86 targets?
  Nope.  Fixed.

Changes v2 to v3:

  s/2.3/2.4

Changes v1 to v2:

   Added live migration code.
   Adjust data structures for migration.
   Switch to GHashTable.

  Eric Blake
s/spawened/spawned/
  Done
s/traceing/tracing/
  Done
Change error_set(errp, ERROR_CLASS_GENERIC_ERROR,  to
error_setg(errp, 
  Done
Why two commands (inject-vmport-reboot, inject-vmport-halt)?
  Switched to inject-vmport-action.
format=base64 bug statements.
  Dropped.

Much more on format=base64:

If there is a bug it is in GLIB.  However the Glib reference manual
refers to RFC 1421 and RFC 2045 and MIME encoding.  Based on all
that (which seems to match:

http://en.wikipedia.org/wiki/Base64

) MIME states that all characters outside the (base64) alphabet are
to be ignored.  Testing shows that g_base64_decode() does this.

The confusion is that most non-MIME uses reject a base64 string that
contain characters outside the alphabet.  I was just following the
other uses of base64 in this file.

DataFormat refers to RFC 3548, which has the info:


   Implementations MUST reject the encoding if it contains
   characters outside the base alphabet when interpreting base
   encoded data, unless the specification referring to this document
   explicitly states otherwise.  Such specifications may, as MIME
   does, instead state that characters outside the base encoding
   alphabet should simply be ignored when interpreting data (be
   liberal in what you accept).


So with GLIB going the MIME way, I do not think this is a QEMU bug
(you could consider this a GLIB bug, but the document I found says
that GLIB goes the MIME way and so does not reject anything).

---


The support included is enough to allow VMware tools to install in a
guest and provide guestinfo support.  guestinfo support is provided
by what is known as VMware RPC support.

One of the better on-line references is:

https://sites.google.com/site/chitchatvmback/backdoor

As a place to get more accurate information by studying:

http://open-vm-tools.sourceforge.net/

With vmware tools installed, you can do:

---
Last login: Fri Jan 30 16:03:08 2015
[root@C63-min-tools ~]# vmtoolsd --cmd info-get guestinfo.joejoel
No value found
[root@C63-min-tools ~]# vmtoolsd --cmd info-set guestinfo.joejoel bar

[root@C63-min-tools ~]# vmtoolsd --cmd info-get guestinfo.joejoel
bar
[root@C63-min-tools ~]# 
---

to access guest info.  QMP access is also provided.

The live migration code is still in progress.

Don Slutz (7):
  vmport.c: Fix vmport_cmd_ram_size
  vmport_rpc: Add the object vmport_rpc
  vmport_rpc: Add limited support of VMware's hyper-call rpc
  vmport_rpc: Add QMP access to vmport_rpc object.
  vmport_rpc: Add migration
  vmport:  Add VMware all ring hack
  MAINTAINERS: add VMware port

 MAINTAINERS  |7 +
 hw/i386/pc.c |   32 +-
 hw/i386/pc_piix.c|2 +-
 hw/i386/pc_q35.c |2 +-
 hw/misc/Makefile.objs|1 +
 hw/misc/vmport.c |2 +-
 hw/misc/vmport_rpc.c | 1441 ++
 include/hw/i386/pc.h |6 +-
 monitor.c|   24 +
 qapi-schema.json |  101 
 qmp-commands.hx  |  120 
 target-i386/cpu-qom.h|3 +
 target-i386/seg_helper.c |9 +
 trace-events |   24 +
 14 files changed, 1769 insertions(+), 5 deletions(-)
 create mode 100644 hw/misc/vmport_rpc.c

-- 
1.8.4




[Qemu-devel] [PATCH v6 1/7] vmport.c: Fix vmport_cmd_ram_size

2015-05-12 Thread Don Slutz
Based on

https://sites.google.com/site/chitchatvmback/backdoor

and testing on ESXi, this should be in MB not bytes.

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index 7fcc00d..6b350ce 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -110,7 +110,7 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t 
addr)
 X86CPU *cpu = X86_CPU(current_cpu);
 
 cpu-env.regs[R_EBX] = 0x1177;
-return ram_size;
+return ram_size  20; /* in MB */
 }
 
 static uint32_t vmport_cmd_xtest(void *opaque, uint32_t addr)
-- 
1.8.4




[Qemu-devel] [PATCH v6 3/7] vmport_rpc: Add limited support of VMware's hyper-call rpc

2015-05-12 Thread Don Slutz
The support included is enough to allow VMware tools to install in a
guest and provide guestinfo support.  guestinfo support is provided
by what is known as VMware RPC support.

If the guest is running VMware tools, then the build version of
the tools is also available via the property build-number-value of
the vmport_rpc object.  The build-number-time property is changed
every time the VMware tools running in the guest sends the
build version via the rpc.

The property reset-time controls how often to request them in
seconds minus 1.  The minus 1 is to handle to 0 case.  I.E. the
fastest that can be selected is every second.  The default is 4
times a minute.

The VMware RPC support includes the notion of channels that are
opened, active and closed.  All RPC messages sent via a channel
starts with normal ASCII text.  The message some times does include
binary data.

Currently there are 2 protocols defined for VMware RPC.  They
determine the direction for data flow, guest to tool stack or tool
stack to guest.

There is no provided interrupt for VMware RPC.

Getting VMPORT_RPC_DEBUG will provide a higher level trace calls
that are simpler to understand.

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport_rpc.c | 799 ++-
 trace-events |  22 ++
 2 files changed, 820 insertions(+), 1 deletion(-)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index b7cd355..927c0bf 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -40,6 +40,123 @@
 /* VMPORT RPC Command */
 #define VMPORT_RPC_COMMAND  30
 
+/* Limits on amount of non guest memory to use */
+#define MAX_KEY_LEN  128
+#define MIN_VAL_LEN  64
+#define MAX_VAL_LEN  8192
+#define MAX_NUM_KEY  256
+#define MAX_BKTS 4
+/* Max number of channels. */
+#define GUESTMSG_MAX_CHANNEL 8
+
+/*
+ * All of VMware's rpc is based on 32bit registers.  So this is the
+ * number of bytes in ebx.
+ */
+#define CHAR_PER_CALL   sizeof(uint32_t)
+/* Room for basic commands */
+#define EXTRA_SEND 22
+/* Status code and NULL */
+#define EXTRA_RECV 2
+#define MAX_SEND_BUF DIV_ROUND_UP(EXTRA_SEND + MAX_KEY_LEN + MAX_VAL_LEN, \
+  CHAR_PER_CALL)
+#define MAX_RECV_BUF DIV_ROUND_UP(EXTRA_RECV + MAX_VAL_LEN, CHAR_PER_CALL)
+#define MIN_SEND_BUF DIV_ROUND_UP(EXTRA_SEND + MAX_KEY_LEN + MIN_VAL_LEN, \
+  CHAR_PER_CALL)
+
+/* Reply statuses */
+/*  The basic request succeeded */
+#define MESSAGE_STATUS_SUCCESS  0x0001
+/*  vmware has a message available for its party */
+#define MESSAGE_STATUS_DORECV   0x0002
+/*  The channel has been closed */
+#define MESSAGE_STATUS_CLOSED   0x0004
+/*  vmware removed the message before the party fetched it */
+#define MESSAGE_STATUS_UNSENT   0x0008
+/*  A checkpoint occurred */
+#define MESSAGE_STATUS_CPT  0x0010
+/*  An underlying device is powering off */
+#define MESSAGE_STATUS_POWEROFF 0x0020
+/*  vmware has detected a timeout on the channel */
+#define MESSAGE_STATUS_TIMEOUT  0x0040
+/*  vmware supports high-bandwidth for sending and receiving the payload */
+#define MESSAGE_STATUS_HB   0x0080
+
+/* Max number of channels. */
+#define GUESTMSG_MAX_CHANNEL 8
+
+/* Flags to open a channel. */
+#define GUESTMSG_FLAG_COOKIE 0x8000
+
+/* Data to guest */
+#define VMWARE_PROTO_TO_GUEST   0x4f4c4354
+/* Data from guest */
+#define VMWARE_PROTO_FROM_GUEST 0x49435052
+
+/*
+ * Error return values used only in this file.  The routine
+ * convert_local_rc() is used to convert these to an Error
+ * object.
+ */
+#define VMPORT_DEVICE_NOT_FOUND -1
+#define SEND_NOT_OPEN   -2
+#define SEND_SKIPPED-3
+#define SEND_TRUCATED   -4
+#define SEND_NO_MEMORY  -5
+#define GUESTINFO_NOTFOUND  -6
+#define GUESTINFO_VALTOOLONG-7
+#define GUESTINFO_KEYTOOLONG-8
+#define GUESTINFO_TOOMANYKEYS   -9
+#define GUESTINFO_NO_MEMORY -10
+
+
+/* The VMware RPC guest info storage . */
+typedef struct {
+char *val_data;
+uint16_t val_len;
+uint16_t val_max;
+} guestinfo_t;
+
+/* The VMware RPC bucket control. */
+typedef struct {
+uint16_t recv_len;
+uint16_t recv_idx;
+uint16_t recv_buf_max;
+} bucket_control_t;
+
+/* The VMware RPC bucket info. */
+typedef struct {
+union {
+uint32_t *words;
+char *bytes;
+} recv;
+bucket_control_t ctl;
+} bucket_t;
+
+
+/* The VMware RPC channel control. */
+typedef struct {
+uint64_t active_time;
+uint32_t chan_id;
+uint32_t cookie;
+uint32_t proto_num;
+uint16_t send_len;
+uint16_t send_idx;
+uint16_t send_buf_max;
+uint8_t recv_read;
+uint8_t recv_write;
+} channel_control_t;
+
+/* The VMware RPC channel info. */
+typedef struct {
+union {
+uint32_t *words;
+char *bytes;
+} send;
+channel_control_t ctl;
+bucket_t recv_bkt[MAX_BKTS];
+} channel_t;
+
 /* The vmport_rpc

[Qemu-devel] [PATCH v6 4/7] vmport_rpc: Add QMP access to vmport_rpc object.

2015-05-12 Thread Don Slutz
This adds one new inject command:

inject-vmport-action

And three guest info commands:

vmport-guestinfo-set
vmport-guestinfo-get
query-vmport-guestinfo

More details in qmp-commands.hx

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport_rpc.c | 268 +++
 monitor.c|  24 +
 qapi-schema.json | 101 +++
 qmp-commands.hx  | 120 +++
 4 files changed, 513 insertions(+)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index 927c0bf..9a32c6f 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -215,6 +215,56 @@ typedef struct {
 uint32_t edi;
 } vregs;
 
+/*
+ * Run func() for every VMPortRpc device, traverse the tree for
+ * everything else.  Note: This routine expects that opaque is a
+ * VMPortRpcFind pointer and not NULL.
+ */
+static int find_VMPortRpc_device(Object *obj, void *opaque)
+{
+VMPortRpcFind *find = opaque;
+Object *dev;
+VMPortRpcState *s;
+
+if (find-found) {
+return 0;
+}
+dev = object_dynamic_cast(obj, TYPE_VMPORT_RPC);
+s = (VMPortRpcState *)dev;
+
+if (!s) {
+/* Container, traverse it for children */
+return object_child_foreach(obj, find_VMPortRpc_device, opaque);
+}
+
+find-found++;
+find-rc = find-func(s, find-arg);
+
+return 0;
+}
+
+/*
+ * Loop through all dynamically created VMPortRpc devices and call
+ * func() for each instance.
+ */
+static int foreach_dynamic_vmport_rpc_device(FindVMPortRpcDeviceFunc *func,
+ void *arg)
+{
+VMPortRpcFind find = {
+.func = func,
+.arg = arg,
+};
+
+/* Loop through all VMPortRpc devices that were spawned outside
+ * the machine */
+find_VMPortRpc_device(qdev_get_machine(), find);
+if (find.found) {
+return find.rc;
+} else {
+return VMPORT_DEVICE_NOT_FOUND;
+}
+}
+
 #ifdef VMPORT_RPC_DEBUG
 /*
  * Add helper function for tracing.  This routine will convert
@@ -464,6 +514,23 @@ static int get_guestinfo(VMPortRpcState *s,
 return GUESTINFO_NOTFOUND;
 }
 
+static int get_qmp_guestinfo(VMPortRpcState *s,
+ unsigned int a_key_len, char *a_info_key,
+ unsigned int *a_value_len, void **a_value_data)
+{
+gpointer key = g_strndup(a_info_key, a_key_len);
+guestinfo_t *gi = (guestinfo_t *)g_hash_table_lookup(s-guestinfo, key);
+
+g_free(key);
+if (gi) {
+*a_value_len = gi-val_len;
+*a_value_data = gi-val_data;
+return 0;
+}
+
+return GUESTINFO_NOTFOUND;
+}
+
 static int set_guestinfo(VMPortRpcState *s, int a_key_len,
  unsigned int a_val_len, char *a_info_key, char *val)
 {
@@ -851,6 +918,207 @@ static uint32_t vmport_rpc_ioport_read(void *opaque, 
uint32_t addr)
 return ur.data[0];
 }
 
+static int vmport_rpc_find_send(VMPortRpcState *s, void *arg)
+{
+return vmport_rpc_ctrl_send(s, arg);
+}
+
+static void convert_local_rc(Error **errp, int rc)
+{
+switch (rc) {
+case 0:
+break;
+case VMPORT_DEVICE_NOT_FOUND:
+error_set(errp, QERR_DEVICE_NOT_FOUND, TYPE_VMPORT_RPC);
+break;
+case SEND_NOT_OPEN:
+error_setg(errp, VMWare rpc not open);
+break;
+case SEND_SKIPPED:
+error_setg(errp, VMWare rpc send skipped);
+break;
+case SEND_TRUCATED:
+error_setg(errp, VMWare rpc send trucated);
+break;
+case SEND_NO_MEMORY:
+error_setg(errp, VMWare rpc send out of memory);
+break;
+case GUESTINFO_NOTFOUND:
+error_setg(errp, VMWare guestinfo not found);
+break;
+case GUESTINFO_VALTOOLONG:
+error_setg(errp, VMWare guestinfo value too long);
+break;
+case GUESTINFO_KEYTOOLONG:
+error_setg(errp, VMWare guestinfo key too long);
+break;
+case GUESTINFO_TOOMANYKEYS:
+error_setg(errp, VMWare guestinfo too many keys);
+break;
+case GUESTINFO_NO_MEMORY:
+error_setg(errp, VMWare guestinfo out of memory);
+break;
+default:
+error_setg(errp, VMWare rpc send rc=%d unknown, rc);
+break;
+}
+}
+
+void qmp_inject_vmport_action(enum VmportAction action, Error **errp)
+{
+int rc;
+
+switch (action) {
+case VMPORT_ACTION_REBOOT:
+rc = foreach_dynamic_vmport_rpc_device(vmport_rpc_find_send,
+   (void *)OS_Reboot);
+break;
+case VMPORT_ACTION_HALT:
+rc = foreach_dynamic_vmport_rpc_device(vmport_rpc_find_send,
+   (void *)OS_Halt);
+break;
+case VMPORT_ACTION_MAX:
+assert(action != VMPORT_ACTION_MAX);
+rc = 0; /* Should be impossible to get here. */
+break;
+}
+convert_local_rc(errp, rc);
+}
+
+typedef struct keyValue {
+void *key_data

[Qemu-devel] [PATCH v6 7/7] MAINTAINERS: add VMware port

2015-05-12 Thread Don Slutz
Signed-off-by: Don Slutz dsl...@verizon.com
---
 MAINTAINERS | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index b3552b2..6945d30d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -766,6 +766,13 @@ M: Jiri Pirko j...@resnulli.us
 S: Maintained
 F: hw/net/rocker/
 
+VMware port
+M: Don Slutz dsl...@verizon.com
+S: Maintained
+F: hw/misc/vmport.c
+F: hw/input/vmmouse.c
+F: hw/misc/vmport_rpc.c
+
 Subsystems
 --
 Audio
-- 
1.8.4




[Qemu-devel] [PATCH v6 5/7] vmport_rpc: Add migration

2015-05-12 Thread Don Slutz
Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport_rpc.c | 250 +++
 trace-events |   8 +-
 2 files changed, 255 insertions(+), 3 deletions(-)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index 9a32c6f..fe9cfc5 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -171,6 +171,14 @@ typedef struct VMPortRpcState {
 uint32_t open_cookie;
 channel_t chans[GUESTMSG_MAX_CHANNEL];
 GHashTable *guestinfo;
+/* Temporary cache for migration purposes */
+int32_t mig_chan_num;
+int32_t mig_bucket_num;
+uint32_t mig_guestinfo_size;
+uint32_t mig_guestinfo_off;
+uint8_t *mig_guestinfo_buf;
+channel_control_t *mig_chans;
+bucket_control_t *mig_buckets;
 #ifdef VMPORT_RPC_DEBUG
 unsigned int end;
 unsigned int last;
@@ -1167,6 +1175,247 @@ static Property vmport_rpc_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static const VMStateDescription vmstate_vmport_rpc_chan = {
+.name = vmport_rpc/chan,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField [])
+{
+VMSTATE_UINT64(active_time, channel_control_t),
+VMSTATE_UINT32(chan_id, channel_control_t),
+VMSTATE_UINT32(cookie, channel_control_t),
+VMSTATE_UINT32(proto_num, channel_control_t),
+VMSTATE_UINT16(send_len, channel_control_t),
+VMSTATE_UINT16(send_idx, channel_control_t),
+VMSTATE_UINT16(send_buf_max, channel_control_t),
+VMSTATE_UINT8(recv_read, channel_control_t),
+VMSTATE_UINT8(recv_write, channel_control_t),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static const VMStateDescription vmstate_vmport_rpc_bucket = {
+.name = vmport_rpc/bucket,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField [])
+{
+VMSTATE_UINT16(recv_len, bucket_control_t),
+VMSTATE_UINT16(recv_idx, bucket_control_t),
+VMSTATE_UINT16(recv_buf_max, bucket_control_t),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void vmport_rpc_size_mig_guestinfo(gpointer key, gpointer value,
+  gpointer opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int key_len = strlen(key) + 1;
+guestinfo_t *gi = value;
+
+s-mig_guestinfo_size += 1 + key_len + 4 + gi-val_max;
+}
+
+static void vmport_rpc_fill_mig_guestinfo(gpointer key, gpointer value,
+  gpointer opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int key_len = strlen(key) + 1;
+guestinfo_t *gi = value;
+
+assert(gi-val_len = gi-val_max);
+trace_vmport_rpc_fill_mig_guestinfo(key_len, key_len, key, gi-val_len,
+gi-val_len, gi-val_data);
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = key_len;
+memcpy(s-mig_guestinfo_buf + s-mig_guestinfo_off, key, key_len);
+s-mig_guestinfo_off += key_len;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_len  8;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_len;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_max  8;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_max;
+memcpy(s-mig_guestinfo_buf + s-mig_guestinfo_off, gi-val_data,
+   gi-val_max);
+s-mig_guestinfo_off += gi-val_max;
+}
+
+static int vmport_rpc_pre_load(void *opaque)
+{
+VMPortRpcState *s = opaque;
+
+g_free(s-mig_guestinfo_buf);
+s-mig_guestinfo_buf = NULL;
+s-mig_guestinfo_size = 0;
+s-mig_guestinfo_off = 0;
+g_free(s-mig_chans);
+s-mig_chans = NULL;
+s-mig_chan_num = 0;
+g_free(s-mig_buckets);
+s-mig_buckets = NULL;
+s-mig_bucket_num = 0;
+
+return 0;
+}
+
+static void vmport_rpc_pre_save(void *opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int i;
+unsigned int mig_chan_idx = 0;
+unsigned int mig_bucket_idx = 0;
+
+(void)vmport_rpc_pre_load(opaque);
+for (i = 0; i  GUESTMSG_MAX_CHANNEL; ++i) {
+channel_t *c = s-chans[i];
+
+if (c-ctl.proto_num) {
+unsigned int j;
+
+s-mig_chan_num++;
+for (j = 0; j  MAX_BKTS; ++j) {
+bucket_t *b = c-recv_bkt[j];
+
+s-mig_bucket_num++;
+s-mig_guestinfo_size +=
+(b-ctl.recv_buf_max + 1) * CHAR_PER_CALL;
+}
+s-mig_guestinfo_size += (c-ctl.send_buf_max + 1) * CHAR_PER_CALL;
+}
+}
+g_hash_table_foreach(s-guestinfo, vmport_rpc_size_mig_guestinfo, s);
+s-mig_guestinfo_size++;
+s-mig_guestinfo_buf = g_malloc(s-mig_guestinfo_size);
+s-mig_chans = g_malloc(s-mig_chan_num * sizeof(channel_control_t));
+s-mig_buckets = g_malloc(s-mig_bucket_num * sizeof(bucket_control_t));
+
+for (i = 0; i  GUESTMSG_MAX_CHANNEL; ++i) {
+channel_t *c = s-chans[i];
+
+if (c-ctl.proto_num) {
+unsigned int j

Re: [Qemu-devel] [PATCH v5 4/7] vmport_rpc: Add QMP access to vmport_rpc object.

2015-05-12 Thread Don Slutz
On 05/05/15 09:02, Eric Blake wrote:
 On 04/30/2015 12:20 PM, Don Slutz wrote:
 This adds one new inject command:

 inject-vmport-action

 And three guest info commands:

 vmport-guestinfo-set
 vmport-guestinfo-get
 query-vmport-guestinfo

 More details in qmp-commands.hx

 Signed-off-by: Don Slutz dsl...@verizon.com
 ---
 
 +++ b/qapi-schema.json
 @@ -1295,6 +1295,96 @@
  { 'command': 'inject-nmi' }
  
 
 +##
 +# @vmport-guestinfo-get:
 +#
 +# Get a VMWare Tools guestinfo value for a key
 +#
 +# @key: the key to get
 +#
 +# @format: #optional data encoding (default 'utf8').
 +#  - base64: the value is returned in base64 encoding.
 +#  - utf8: the value is interpreted as UTF-8.
 +#
 +# Returns: value for the guest info key
 +#
 +# Since: 2.4
 +##
 +{ 'command': 'vmport-guestinfo-get',
 +  'data': {'key': 'str', '*format': 'DataFormat'},
 +  'returns': 'str' }
 
 Returning a non-dictionary is not extensible.  Once my qapi nested
 struct series is applied, you'd have to modify the whitelist to allow
 this command.  Better would be to return things in a dictionary, as in:
 
 { 'command': 'vmport-guestinfo-get',
   'data': {'key': 'str', '*format': 'DataFormat'},
   'returns': {'data':'str'} }
 

Will change to something like this.

 +
 +##
 +# @VmportGuestInfo:
 +#
 +# Information about a single VMWare Tools guestinfo
 +#
 +# @key: The known key
 +#
 +# Since: 2.4
 +##
 +{ 'type': 'VmportGuestInfo', 'data': {'key': 'str'} }
 
 Also, once my series is in, you'll need to s/type/struct/
 
 

Looks like your series is in, adjusting.

 +++ b/qmp-commands.hx
 @@ -490,6 +490,126 @@ Note: inject-nmi fails when the guest doesn't support 
 injecting.
  EQMP
  
  {
 +.name   = inject-vmport-action,
 +.args_type  = action:s,
 +.mhandler.cmd_new = qmp_marshal_input_inject_vmport_action,
 +},
 +
 +SQMP
 +inject-vmport-action
 +--
 
 Cosmetic, but the majority of the file matches the length of the -
 to the command it is underlining.
 
 

Will Do

 +
 +- { execute: vmport-guestinfo-get,
 +arguments: { key: foo,
 +   format: utf8 } }
 +- {return: abcdefgh}
 
 Again, I don't like the notion of returning a non-dictionary without
 good cause.
 
 

Will adjust.

 +- { execute: query-vmport-guestinfo }
 +- {
 +  return: [
 + {
 +key: ip,
 + },
 
 Invalid JSON - no trailing commas allowed in the objects.
 

Will Fix

   -Don Slutz



signature.asc
Description: OpenPGP digital signature


[Qemu-devel] [PATCH v6 6/7] vmport: Add VMware all ring hack

2015-05-12 Thread Don Slutz
This is done by adding a new machine property vmware-port-ring3 that
needs to be enabled to have any effect.  It only effects accel=tcg
mode.  It is needed if you want to use VMware tools in accel=tcg
mode.

Signed-off-by: Don Slutz dsl...@verizon.com
(cherry picked from commit 6d99c91fc9ae27b476e89a8cc880b4a46e237536)
---
 hw/i386/pc.c | 26 +-
 hw/i386/pc_piix.c|  2 +-
 hw/i386/pc_q35.c |  2 +-
 include/hw/i386/pc.h |  6 +-
 target-i386/cpu-qom.h|  3 +++
 target-i386/seg_helper.c |  9 +
 6 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 4d2e004..b637ab8 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1056,7 +1056,9 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
 pc_new_cpu(current_cpu_model, apic_id, icc_bridge, errp);
 }
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+  bool vmware_port_ring3)
 {
 int i;
 X86CPU *cpu = NULL;
@@ -1087,6 +1089,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState 
*icc_bridge)
 error_report_err(error);
 exit(1);
 }
+cpu-allow_vmport_ring3 = vmware_port_ring3;
 }
 
 /* map APIC MMIO area if CPU has APIC */
@@ -1878,6 +1881,21 @@ static bool pc_machine_get_aligned_dimm(Object *obj, 
Error **errp)
 return pcms-enforce_aligned_dimm;
 }
 
+static bool pc_machine_get_vmware_port_ring3(Object *obj, Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+return pcms-vmware_port_ring3;
+}
+
+static void pc_machine_set_vmware_port_ring3(Object *obj, bool value,
+ Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+pcms-vmware_port_ring3 = value;
+}
+
 static void pc_machine_initfn(Object *obj)
 {
 PCMachineState *pcms = PC_MACHINE(obj);
@@ -1908,6 +1926,12 @@ static void pc_machine_initfn(Object *obj)
 object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM,
  pc_machine_get_aligned_dimm,
  NULL, NULL);
+
+pcms-vmware_port_ring3 = false;
+object_property_add_bool(obj, PC_MACHINE_VMWARE_PORT_RING3,
+ pc_machine_get_vmware_port_ring3,
+ pc_machine_set_vmware_port_ring3,
+ NULL);
 }
 
 static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 212e263..ee7c640 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -147,7 +147,7 @@ static void pc_init1(MachineState *machine,
 object_property_add_child(qdev_get_machine(), icc-bridge,
   OBJECT(icc_bridge), NULL);
 
-pc_cpus_init(machine-cpu_model, icc_bridge);
+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
 
 if (kvm_enabled()  kvmclock_enabled) {
 kvmclock_create();
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index e67f2de..7e79116 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -136,7 +136,7 @@ static void pc_q35_init(MachineState *machine)
 object_property_add_child(qdev_get_machine(), icc-bridge,
   OBJECT(icc_bridge), NULL);
 
-pc_cpus_init(machine-cpu_model, icc_bridge);
+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
 pc_acpi_init(q35-acpi-dsdt.aml);
 
 kvmclock_create();
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 1b35168..2119d5d 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -40,6 +40,7 @@ struct PCMachineState {
 
 uint64_t max_ram_below_4g;
 OnOffAuto vmport;
+bool vmware_port_ring3;
 bool enforce_aligned_dimm;
 };
 
@@ -48,6 +49,7 @@ struct PCMachineState {
 #define PC_MACHINE_MAX_RAM_BELOW_4G max-ram-below-4g
 #define PC_MACHINE_VMPORT   vmport
 #define PC_MACHINE_ENFORCE_ALIGNED_DIMM enforce-aligned-dimm
+#define PC_MACHINE_VMWARE_PORT_RING3 vmware-port-ring3
 
 /**
  * PCMachineClass:
@@ -163,7 +165,9 @@ extern int fd_bootchk;
 void pc_register_ferr_irq(qemu_irq irq);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+  bool vmware_port_ring3);
 void pc_hot_add_cpu(const int64_t id, Error **errp);
 void pc_acpi_init(const char *default_dsdt);
 
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 31a0c1e..a173c96 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -108,6 +108,9 @@ typedef struct X86CPU {
  */
 bool enable_pmu;
 
+/* allow_vmport_ring3 true says

Re: [Qemu-devel] [PATCH v6 4/7] vmport_rpc: Add QMP access to vmport_rpc object.

2015-05-12 Thread Don Slutz
On 05/12/15 15:50, Eric Blake wrote:
 On 05/12/2015 01:03 PM, Don Slutz wrote:
 This adds one new inject command:

 inject-vmport-action

 And three guest info commands:

 vmport-guestinfo-set
 vmport-guestinfo-get
 query-vmport-guestinfo
vmport-guestinfo-get key=foo
 More details in qmp-commands.hx

 Signed-off-by: Don Slutz dsl...@verizon.com
 ---
 
 +/*
 + * Run func() for every VMPortRpc device, traverse the tree for
 + * everything else.  Note: This routine expects that opaque is a
 + * VMPortRpcFind pointer and not NULL.
 + */
 +static int find_VMPortRpc_device(Object *obj, void *opaque)
 +{
 +VMPortRpcFind *find = opaque;
 +Object *dev;
 +VMPortRpcState *s;
 +
 +if (find-found) {
 
 Why not assert(find) instead of leaving it to the comment?

My memory says that someone complained about too many asserts used,
so I just commented it.

I have no issue with adding an assert() and dropping the comment,
and so plan on doing this.

 
 +/*
 + * Loop through all dynamically created VMPortRpc devices and call
 + * func() for each instance.
 + */
 +static int foreach_dynamic_vmport_rpc_device(FindVMPortRpcDeviceFunc *func,
 + void *arg)
 +{
 +VMPortRpcFind find = {
 +.func = func,
 +.arg = arg,
 
 Is it worth marking arg const here and in the VMPortRpcFind struct...

See below

 
 
 +void qmp_inject_vmport_action(enum VmportAction action, Error **errp)
 +{
 +int rc;
 +
 +switch (action) {
 +case VMPORT_ACTION_REBOOT:
 +rc = foreach_dynamic_vmport_rpc_device(vmport_rpc_find_send,
 +   (void *)OS_Reboot);
 
 ...so that you don't have to cast away const here?
 

Not sure.  I still need 2 casts:

-static int vmport_rpc_find_list(VMPortRpcState *s, void *arg)
+static int vmport_rpc_find_list(VMPortRpcState *s, const void *arg)
 {
-g_hash_table_foreach(s-guestinfo, vmport_rpc_find_list_one, arg);
+g_hash_table_foreach(s-guestinfo, vmport_rpc_find_list_one,
(gpointer)arg);
 return 0;
 }


and


-static int find_get(VMPortRpcState *s, void *arg)
+static int find_get(VMPortRpcState *s, const void *arg)
 {
-keyValue *key_value = arg;
+keyValue *key_value = (void *)arg;

get_qmp_guestinfo() does change parts of key_value.

So are these casts better or worse?


 +break;
 +case VMPORT_ACTION_HALT:
 +rc = foreach_dynamic_vmport_rpc_device(vmport_rpc_find_send,
 +   (void *)OS_Halt);
 +break;
 +case VMPORT_ACTION_MAX:
 +assert(action != VMPORT_ACTION_MAX);
 +rc = 0; /* Should be impossible to get here. */
 
 I'd rather abort() if someone compiled with -NDEBUG.

Ok, will change to abort.

 
 +break;
 +}
 +convert_local_rc(errp, rc);
 +}
 +
 +typedef struct keyValue {
 +void *key_data;
 +void *value_data;
 +unsigned int key_len;
 +unsigned int value_len;
 
 Should these be size_t?

There is no need to.  There is a limit on the max values that can be
used here (because without the max check it is possible for the guest
to request a lot of memory outside of the memory provided to the guest
as ram.

Currently using unsigned char for key_len and unsigned short for
value_len will work, but I went with unsigned int to avoid strange
issues if someone in the future changes the allowed maxes.

However this is not important to me and so if you want them
to be size_t, I am happy to change them.


 
 +void qmp_vmport_guestinfo_set(const char *key, const char *value,
 +  bool has_format, enum DataFormat format,
 +  Error **errp)
 +{
 +int rc;
 +keyValue key_value;
 +
 +if (strncmp(key, guestinfo., strlen(guestinfo.)) == 0) {
 +key_value.key_data = (void *)(key + strlen(guestinfo.));
 +key_value.key_len = strlen(key) - strlen(guestinfo.);
 +} else {
 +key_value.key_data = (void *)key;
 
 Casting to (void*) looks awkward; should key_data should be typed 'const
 void *' to avoid the need for a cast?  For that matter, why is it void*,
 why not 'const char *'?

Not sure.  Best guess is that I was focused on the value being binary
data, and just did the same for the key.  The change to
const char *key_data; works, and so I will do this.


 
 
 +++ b/qmp-commands.hx
 @@ -490,6 +490,126 @@ Note: inject-nmi fails when the guest doesn't support 
 injecting.
  EQMP
 
 +SQMP
 +vmport-guestinfo-set
 +--
 
 Still mismatches on  line length (several sites).

Sigh, will fix.

 
 +- { execute: vmport-guestinfo-get,
 +arguments: { key: guestinfo.foo,
 +   format: utf8 } }
 +- {return: {value: abcdefgh}}
 +
 +
 +EQMP
 +
 +{
 +.name   = query-vmport-guestinfo,
 +.args_type  = ,
 +.mhandler.cmd_new = qmp_marshal_input_query_vmport_guestinfo,
 +},
 +
 +SQMP
 +query-vmport-guestinfo

[Qemu-devel] [PATCH v4 1/7] vmport.c: Fix vmport_cmd_ram_size

2015-04-30 Thread Don Slutz
Based on

https://sites.google.com/site/chitchatvmback/backdoor

and testing on ESXi, this should be in MB not bytes.

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index 7fcc00d..6b350ce 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -110,7 +110,7 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t 
addr)
 X86CPU *cpu = X86_CPU(current_cpu);
 
 cpu-env.regs[R_EBX] = 0x1177;
-return ram_size;
+return ram_size  20; /* in MB */
 }
 
 static uint32_t vmport_cmd_xtest(void *opaque, uint32_t addr)
-- 
1.8.4




[Qemu-devel] [PATCH v4 2/7] vmport_rpc: Add the object vmport_rpc

2015-04-30 Thread Don Slutz
This is the 1st part of Add limited support of VMware's hyper-call
rpc.

This patch uses existing infrastructure used by vmmouse.c (provided
by vmport.c) to handle the VMware backdoor command 30.

One of the better on-line references is:

https://sites.google.com/site/chitchatvmback/backdoor

More in next patch.

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/i386/pc.c  |   6 +++
 hw/misc/Makefile.objs |   1 +
 hw/misc/vmport_rpc.c  | 126 ++
 3 files changed, 133 insertions(+)
 create mode 100644 hw/misc/vmport_rpc.c

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index a8e6be1..e5b7167 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1471,8 +1471,14 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
 i8042 = isa_create_simple(isa_bus, i8042);
 i8042_setup_a20_line(i8042, a20_line[0]);
 if (!no_vmport) {
+ISADevice *vmport_rpc;
+
 vmport_init(isa_bus);
 vmmouse = isa_try_create(isa_bus, vmmouse);
+vmport_rpc = isa_try_create(isa_bus, vmport_rpc);
+if (vmport_rpc) {
+qdev_init_nofail(DEVICE(vmport_rpc));
+}
 } else {
 vmmouse = NULL;
 }
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 4aa76ff..e04c8ac 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -7,6 +7,7 @@ common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o
 common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o
 
 obj-$(CONFIG_VMPORT) += vmport.o
+obj-$(CONFIG_VMPORT) += vmport_rpc.o
 
 # ARM devices
 common-obj-$(CONFIG_PL310) += arm_l2x0.o
diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
new file mode 100644
index 000..b7cd355
--- /dev/null
+++ b/hw/misc/vmport_rpc.c
@@ -0,0 +1,126 @@
+/*
+ * QEMU VMPORT RPC emulation
+ *
+ * Copyright (C) 2015 Verizon Corporation
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License Version 2 (GPLv2)
+ * as published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details. http://www.gnu.org/licenses/.
+ */
+
+/*
+ * One of the better on-line references is:
+ *
+ * https://sites.google.com/site/chitchatvmback/backdoor
+ *
+ * Which points you to:
+ *
+ * http://open-vm-tools.sourceforge.net/
+ *
+ * as a place to get more accurate information by studying.
+ */
+
+#include hw/hw.h
+#include hw/i386/pc.h
+#include hw/qdev.h
+#include trace.h
+#include qmp-commands.h
+#include qapi/qmp/qerror.h
+
+/* #define VMPORT_RPC_DEBUG */
+
+#define TYPE_VMPORT_RPC vmport_rpc
+#define VMPORT_RPC(obj) OBJECT_CHECK(VMPortRpcState, (obj), TYPE_VMPORT_RPC)
+
+/* VMPORT RPC Command */
+#define VMPORT_RPC_COMMAND  30
+
+/* The vmport_rpc object. */
+typedef struct VMPortRpcState {
+ISADevice parent_obj;
+
+/* Properties */
+uint64_t reset_time;
+uint64_t build_number_value;
+uint64_t build_number_time;
+
+/* Private data */
+} VMPortRpcState;
+
+typedef struct {
+uint32_t eax;
+uint32_t ebx;
+uint32_t ecx;
+uint32_t edx;
+uint32_t esi;
+uint32_t edi;
+} vregs;
+
+static uint32_t vmport_rpc_ioport_read(void *opaque, uint32_t addr)
+{
+VMPortRpcState *s = opaque;
+union {
+uint32_t data[6];
+vregs regs;
+} ur;
+
+vmmouse_get_data(ur.data);
+
+s-build_number_time++;
+
+vmmouse_set_data(ur.data);
+return ur.data[0];
+}
+
+static void vmport_rpc_reset(DeviceState *d)
+{
+VMPortRpcState *s = VMPORT_RPC(d);
+
+s-reset_time = 14;
+s-build_number_value = 0;
+s-build_number_time = 0;
+}
+
+static void vmport_rpc_realize(DeviceState *dev, Error **errp)
+{
+VMPortRpcState *s = VMPORT_RPC(dev);
+
+vmport_register(VMPORT_RPC_COMMAND, vmport_rpc_ioport_read, s);
+}
+
+static Property vmport_rpc_properties[] = {
+DEFINE_PROP_UINT64(reset-time, VMPortRpcState, reset_time, 14),
+DEFINE_PROP_UINT64(build-number-value, VMPortRpcState,
+   build_number_value, 0),
+DEFINE_PROP_UINT64(build-number-time, VMPortRpcState,
+   build_number_time, 0),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vmport_rpc_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc-realize = vmport_rpc_realize;
+dc-reset = vmport_rpc_reset;
+dc-props = vmport_rpc_properties;
+}
+
+static const TypeInfo vmport_rpc_info = {
+.name  = TYPE_VMPORT_RPC,
+.parent= TYPE_ISA_DEVICE,
+.instance_size = sizeof(VMPortRpcState),
+.class_init= vmport_rpc_class_init,
+};
+
+static void vmport_rpc_register_types(void)
+{
+type_register_static(vmport_rpc_info);
+}
+
+type_init(vmport_rpc_register_types)
-- 
1.8.4




[Qemu-devel] [PATCH v4 4/7] vmport_rpc: Add QMP access to vmport_rpc object.

2015-04-30 Thread Don Slutz
This adds one new inject command:

inject-vmport-action

And three guest info commands:

vmport-guestinfo-set
vmport-guestinfo-get
query-vmport-guestinfo

More details in qmp-commands.hx

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport_rpc.c | 269 +++
 monitor.c|  23 +
 qapi-schema.json |  90 +
 qmp-commands.hx  | 120 +++
 4 files changed, 502 insertions(+)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index 927c0bf..0ba3319 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -215,6 +215,56 @@ typedef struct {
 uint32_t edi;
 } vregs;
 
+/*
+ * Run func() for every VMPortRpc device, traverse the tree for
+ * everything else.  Note: This routine expects that opaque is a
+ * VMPortRpcFind pointer and not NULL.
+ */
+static int find_VMPortRpc_device(Object *obj, void *opaque)
+{
+VMPortRpcFind *find = opaque;
+Object *dev;
+VMPortRpcState *s;
+
+if (find-found) {
+return 0;
+}
+dev = object_dynamic_cast(obj, TYPE_VMPORT_RPC);
+s = (VMPortRpcState *)dev;
+
+if (!s) {
+/* Container, traverse it for children */
+return object_child_foreach(obj, find_VMPortRpc_device, opaque);
+}
+
+find-found++;
+find-rc = find-func(s, find-arg);
+
+return 0;
+}
+
+/*
+ * Loop through all dynamically created VMPortRpc devices and call
+ * func() for each instance.
+ */
+static int foreach_dynamic_vmport_rpc_device(FindVMPortRpcDeviceFunc *func,
+ void *arg)
+{
+VMPortRpcFind find = {
+.func = func,
+.arg = arg,
+};
+
+/* Loop through all VMPortRpc devices that were spawned outside
+ * the machine */
+find_VMPortRpc_device(qdev_get_machine(), find);
+if (find.found) {
+return find.rc;
+} else {
+return VMPORT_DEVICE_NOT_FOUND;
+}
+}
+
 #ifdef VMPORT_RPC_DEBUG
 /*
  * Add helper function for tracing.  This routine will convert
@@ -464,6 +514,23 @@ static int get_guestinfo(VMPortRpcState *s,
 return GUESTINFO_NOTFOUND;
 }
 
+static int get_qmp_guestinfo(VMPortRpcState *s,
+ unsigned int a_key_len, char *a_info_key,
+ unsigned int *a_value_len, void **a_value_data)
+{
+gpointer key = g_strndup(a_info_key, a_key_len);
+guestinfo_t *gi = (guestinfo_t *)g_hash_table_lookup(s-guestinfo, key);
+
+g_free(key);
+if (gi) {
+*a_value_len = gi-val_len;
+*a_value_data = gi-val_data;
+return 0;
+}
+
+return GUESTINFO_NOTFOUND;
+}
+
 static int set_guestinfo(VMPortRpcState *s, int a_key_len,
  unsigned int a_val_len, char *a_info_key, char *val)
 {
@@ -851,6 +918,208 @@ static uint32_t vmport_rpc_ioport_read(void *opaque, 
uint32_t addr)
 return ur.data[0];
 }
 
+static int vmport_rpc_find_send(VMPortRpcState *s, void *arg)
+{
+return vmport_rpc_ctrl_send(s, arg);
+}
+
+static void convert_local_rc(Error **errp, int rc)
+{
+switch (rc) {
+case 0:
+break;
+case VMPORT_DEVICE_NOT_FOUND:
+error_set(errp, QERR_DEVICE_NOT_FOUND, TYPE_VMPORT_RPC);
+break;
+case SEND_NOT_OPEN:
+error_setg(errp, VMWare rpc not open);
+break;
+case SEND_SKIPPED:
+error_setg(errp, VMWare rpc send skipped);
+break;
+case SEND_TRUCATED:
+error_setg(errp, VMWare rpc send trucated);
+break;
+case SEND_NO_MEMORY:
+error_setg(errp, VMWare rpc send out of memory);
+break;
+case GUESTINFO_NOTFOUND:
+error_setg(errp, VMWare guestinfo not found);
+break;
+case GUESTINFO_VALTOOLONG:
+error_setg(errp, VMWare guestinfo value too long);
+break;
+case GUESTINFO_KEYTOOLONG:
+error_setg(errp, VMWare guestinfo key too long);
+break;
+case GUESTINFO_TOOMANYKEYS:
+error_setg(errp, VMWare guestinfo too many keys);
+break;
+case GUESTINFO_NO_MEMORY:
+error_setg(errp, VMWare guestinfo out of memory);
+break;
+default:
+error_setg(errp, VMWare rpc send rc=%d unknown, rc);
+break;
+}
+}
+
+void qmp_inject_vmport_action(enum VmportAction action, Error **errp)
+{
+int rc;
+
+switch (action) {
+case VMPORT_ACTION_REBOOT:
+rc = foreach_dynamic_vmport_rpc_device(vmport_rpc_find_send,
+   (void *)OS_Reboot);
+break;
+case VMPORT_ACTION_HALT:
+rc = foreach_dynamic_vmport_rpc_device(vmport_rpc_find_send,
+   (void *)OS_Halt);
+break;
+case VMPORT_ACTION_MAX:
+assert(action != VMPORT_ACTION_MAX);
+rc = 0; /* Should be impossible to get here. */
+break;
+}
+convert_local_rc(errp, rc);
+}
+
+typedef struct keyValue {
+void *key_data

[Qemu-devel] [PATCH v4 3/7] vmport_rpc: Add limited support of VMware's hyper-call rpc

2015-04-30 Thread Don Slutz
The support included is enough to allow VMware tools to install in a
guest and provide guestinfo support.  guestinfo support is provided
by what is known as VMware RPC support.

If the guest is running VMware tools, then the build version of
the tools is also available via the property build-number-value of
the vmport_rpc object.  The build-number-time property is changed
every time the VMware tools running in the guest sends the
build version via the rpc.

The property reset-time controls how often to request them in
seconds minus 1.  The minus 1 is to handle to 0 case.  I.E. the
fastest that can be selected is every second.  The default is 4
times a minute.

The VMware RPC support includes the notion of channels that are
opened, active and closed.  All RPC messages sent via a channel
starts with normal ASCII text.  The message some times does include
binary data.

Currently there are 2 protocols defined for VMware RPC.  They
determine the direction for data flow, guest to tool stack or tool
stack to guest.

There is no provided interrupt for VMware RPC.

Getting VMPORT_RPC_DEBUG will provide a higher level trace calls
that are simpler to understand.

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport_rpc.c | 799 ++-
 trace-events |  22 ++
 2 files changed, 820 insertions(+), 1 deletion(-)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index b7cd355..927c0bf 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -40,6 +40,123 @@
 /* VMPORT RPC Command */
 #define VMPORT_RPC_COMMAND  30
 
+/* Limits on amount of non guest memory to use */
+#define MAX_KEY_LEN  128
+#define MIN_VAL_LEN  64
+#define MAX_VAL_LEN  8192
+#define MAX_NUM_KEY  256
+#define MAX_BKTS 4
+/* Max number of channels. */
+#define GUESTMSG_MAX_CHANNEL 8
+
+/*
+ * All of VMware's rpc is based on 32bit registers.  So this is the
+ * number of bytes in ebx.
+ */
+#define CHAR_PER_CALL   sizeof(uint32_t)
+/* Room for basic commands */
+#define EXTRA_SEND 22
+/* Status code and NULL */
+#define EXTRA_RECV 2
+#define MAX_SEND_BUF DIV_ROUND_UP(EXTRA_SEND + MAX_KEY_LEN + MAX_VAL_LEN, \
+  CHAR_PER_CALL)
+#define MAX_RECV_BUF DIV_ROUND_UP(EXTRA_RECV + MAX_VAL_LEN, CHAR_PER_CALL)
+#define MIN_SEND_BUF DIV_ROUND_UP(EXTRA_SEND + MAX_KEY_LEN + MIN_VAL_LEN, \
+  CHAR_PER_CALL)
+
+/* Reply statuses */
+/*  The basic request succeeded */
+#define MESSAGE_STATUS_SUCCESS  0x0001
+/*  vmware has a message available for its party */
+#define MESSAGE_STATUS_DORECV   0x0002
+/*  The channel has been closed */
+#define MESSAGE_STATUS_CLOSED   0x0004
+/*  vmware removed the message before the party fetched it */
+#define MESSAGE_STATUS_UNSENT   0x0008
+/*  A checkpoint occurred */
+#define MESSAGE_STATUS_CPT  0x0010
+/*  An underlying device is powering off */
+#define MESSAGE_STATUS_POWEROFF 0x0020
+/*  vmware has detected a timeout on the channel */
+#define MESSAGE_STATUS_TIMEOUT  0x0040
+/*  vmware supports high-bandwidth for sending and receiving the payload */
+#define MESSAGE_STATUS_HB   0x0080
+
+/* Max number of channels. */
+#define GUESTMSG_MAX_CHANNEL 8
+
+/* Flags to open a channel. */
+#define GUESTMSG_FLAG_COOKIE 0x8000
+
+/* Data to guest */
+#define VMWARE_PROTO_TO_GUEST   0x4f4c4354
+/* Data from guest */
+#define VMWARE_PROTO_FROM_GUEST 0x49435052
+
+/*
+ * Error return values used only in this file.  The routine
+ * convert_local_rc() is used to convert these to an Error
+ * object.
+ */
+#define VMPORT_DEVICE_NOT_FOUND -1
+#define SEND_NOT_OPEN   -2
+#define SEND_SKIPPED-3
+#define SEND_TRUCATED   -4
+#define SEND_NO_MEMORY  -5
+#define GUESTINFO_NOTFOUND  -6
+#define GUESTINFO_VALTOOLONG-7
+#define GUESTINFO_KEYTOOLONG-8
+#define GUESTINFO_TOOMANYKEYS   -9
+#define GUESTINFO_NO_MEMORY -10
+
+
+/* The VMware RPC guest info storage . */
+typedef struct {
+char *val_data;
+uint16_t val_len;
+uint16_t val_max;
+} guestinfo_t;
+
+/* The VMware RPC bucket control. */
+typedef struct {
+uint16_t recv_len;
+uint16_t recv_idx;
+uint16_t recv_buf_max;
+} bucket_control_t;
+
+/* The VMware RPC bucket info. */
+typedef struct {
+union {
+uint32_t *words;
+char *bytes;
+} recv;
+bucket_control_t ctl;
+} bucket_t;
+
+
+/* The VMware RPC channel control. */
+typedef struct {
+uint64_t active_time;
+uint32_t chan_id;
+uint32_t cookie;
+uint32_t proto_num;
+uint16_t send_len;
+uint16_t send_idx;
+uint16_t send_buf_max;
+uint8_t recv_read;
+uint8_t recv_write;
+} channel_control_t;
+
+/* The VMware RPC channel info. */
+typedef struct {
+union {
+uint32_t *words;
+char *bytes;
+} send;
+channel_control_t ctl;
+bucket_t recv_bkt[MAX_BKTS];
+} channel_t;
+
 /* The vmport_rpc

[Qemu-devel] [PATCH v4 5/7] vmport_rpc: Add migration

2015-04-30 Thread Don Slutz
Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport_rpc.c | 250 +++
 trace-events |   8 +-
 2 files changed, 255 insertions(+), 3 deletions(-)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index 0ba3319..a147561 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -171,6 +171,14 @@ typedef struct VMPortRpcState {
 uint32_t open_cookie;
 channel_t chans[GUESTMSG_MAX_CHANNEL];
 GHashTable *guestinfo;
+/* Temporary cache for migration purposes */
+int32_t mig_chan_num;
+int32_t mig_bucket_num;
+uint32_t mig_guestinfo_size;
+uint32_t mig_guestinfo_off;
+uint8_t *mig_guestinfo_buf;
+channel_control_t *mig_chans;
+bucket_control_t *mig_buckets;
 #ifdef VMPORT_RPC_DEBUG
 unsigned int end;
 unsigned int last;
@@ -1168,6 +1176,247 @@ static Property vmport_rpc_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static const VMStateDescription vmstate_vmport_rpc_chan = {
+.name = vmport_rpc/chan,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField [])
+{
+VMSTATE_UINT64(active_time, channel_control_t),
+VMSTATE_UINT32(chan_id, channel_control_t),
+VMSTATE_UINT32(cookie, channel_control_t),
+VMSTATE_UINT32(proto_num, channel_control_t),
+VMSTATE_UINT16(send_len, channel_control_t),
+VMSTATE_UINT16(send_idx, channel_control_t),
+VMSTATE_UINT16(send_buf_max, channel_control_t),
+VMSTATE_UINT8(recv_read, channel_control_t),
+VMSTATE_UINT8(recv_write, channel_control_t),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static const VMStateDescription vmstate_vmport_rpc_bucket = {
+.name = vmport_rpc/bucket,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField [])
+{
+VMSTATE_UINT16(recv_len, bucket_control_t),
+VMSTATE_UINT16(recv_idx, bucket_control_t),
+VMSTATE_UINT16(recv_buf_max, bucket_control_t),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void vmport_rpc_size_mig_guestinfo(gpointer key, gpointer value,
+  gpointer opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int key_len = strlen(key) + 1;
+guestinfo_t *gi = value;
+
+s-mig_guestinfo_size += 1 + key_len + 4 + gi-val_max;
+}
+
+static void vmport_rpc_fill_mig_guestinfo(gpointer key, gpointer value,
+  gpointer opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int key_len = strlen(key) + 1;
+guestinfo_t *gi = value;
+
+assert(gi-val_len = gi-val_max);
+trace_vmport_rpc_fill_mig_guestinfo(key_len, key_len, key, gi-val_len,
+gi-val_len, gi-val_data);
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = key_len;
+memcpy(s-mig_guestinfo_buf + s-mig_guestinfo_off, key, key_len);
+s-mig_guestinfo_off += key_len;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_len  8;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_len;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_max  8;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_max;
+memcpy(s-mig_guestinfo_buf + s-mig_guestinfo_off, gi-val_data,
+   gi-val_max);
+s-mig_guestinfo_off += gi-val_max;
+}
+
+static int vmport_rpc_pre_load(void *opaque)
+{
+VMPortRpcState *s = opaque;
+
+g_free(s-mig_guestinfo_buf);
+s-mig_guestinfo_buf = NULL;
+s-mig_guestinfo_size = 0;
+s-mig_guestinfo_off = 0;
+g_free(s-mig_chans);
+s-mig_chans = NULL;
+s-mig_chan_num = 0;
+g_free(s-mig_buckets);
+s-mig_buckets = NULL;
+s-mig_bucket_num = 0;
+
+return 0;
+}
+
+static void vmport_rpc_pre_save(void *opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int i;
+unsigned int mig_chan_idx = 0;
+unsigned int mig_bucket_idx = 0;
+
+(void)vmport_rpc_pre_load(opaque);
+for (i = 0; i  GUESTMSG_MAX_CHANNEL; ++i) {
+channel_t *c = s-chans[i];
+
+if (c-ctl.proto_num) {
+unsigned int j;
+
+s-mig_chan_num++;
+for (j = 0; j  MAX_BKTS; ++j) {
+bucket_t *b = c-recv_bkt[j];
+
+s-mig_bucket_num++;
+s-mig_guestinfo_size +=
+(b-ctl.recv_buf_max + 1) * CHAR_PER_CALL;
+}
+s-mig_guestinfo_size += (c-ctl.send_buf_max + 1) * CHAR_PER_CALL;
+}
+}
+g_hash_table_foreach(s-guestinfo, vmport_rpc_size_mig_guestinfo, s);
+s-mig_guestinfo_size++;
+s-mig_guestinfo_buf = g_malloc(s-mig_guestinfo_size);
+s-mig_chans = g_malloc(s-mig_chan_num * sizeof(channel_control_t));
+s-mig_buckets = g_malloc(s-mig_bucket_num * sizeof(bucket_control_t));
+
+for (i = 0; i  GUESTMSG_MAX_CHANNEL; ++i) {
+channel_t *c = s-chans[i];
+
+if (c-ctl.proto_num) {
+unsigned int j

[Qemu-devel] [PATCH v4 0/7] Add limited support of VMware's hyper-call rpc

2015-04-30 Thread Don Slutz
Changes v4 to v4:

  Paolo Bonzini on vmort_rpc: Add QMP access to vmport_rpc
Does this compile on non-x86 targets?
  Nope.  Fixed.

Changes v2 to v3:

  s/2.3/2.4

Changes v1 to v2:

   Added live migration code.
   Adjust data structures for migration.
   Switch to GHashTable.

  Eric Blake
s/spawened/spawned/
  Done
s/traceing/tracing/
  Done
Change error_set(errp, ERROR_CLASS_GENERIC_ERROR,  to
error_setg(errp, 
  Done
Why two commands (inject-vmport-reboot, inject-vmport-halt)?
  Switched to inject-vmport-action.
format=base64 bug statements.
  Dropped.

Much more on format=base64:

If there is a bug it is in GLIB.  However the Glib reference manual
refers to RFC 1421 and RFC 2045 and MIME encoding.  Based on all
that (which seems to match:

http://en.wikipedia.org/wiki/Base64

) MIME states that all characters outside the (base64) alphabet are
to be ignored.  Testing shows that g_base64_decode() does this.

The confusion is that most non-MIME uses reject a base64 string that
contain characters outside the alphabet.  I was just following the
other uses of base64 in this file.

DataFormat refers to RFC 3548, which has the info:


   Implementations MUST reject the encoding if it contains
   characters outside the base alphabet when interpreting base
   encoded data, unless the specification referring to this document
   explicitly states otherwise.  Such specifications may, as MIME
   does, instead state that characters outside the base encoding
   alphabet should simply be ignored when interpreting data (be
   liberal in what you accept).


So with GLIB going the MIME way, I do not think this is a QEMU bug
(you could consider this a GLIB bug, but the document I found says
that GLIB goes the MIME way and so does not reject anything).

---


The support included is enough to allow VMware tools to install in a
guest and provide guestinfo support.  guestinfo support is provided
by what is known as VMware RPC support.

One of the better on-line references is:

https://sites.google.com/site/chitchatvmback/backdoor

As a place to get more accurate information by studying:

http://open-vm-tools.sourceforge.net/

With vmware tools installed, you can do:

---
Last login: Fri Jan 30 16:03:08 2015
[root@C63-min-tools ~]# vmtoolsd --cmd info-get guestinfo.joejoel
No value found
[root@C63-min-tools ~]# vmtoolsd --cmd info-set guestinfo.joejoel bar

[root@C63-min-tools ~]# vmtoolsd --cmd info-get guestinfo.joejoel
bar
[root@C63-min-tools ~]# 
---

to access guest info.  QMP access is also provided.

The live migration code is still in progress.

Don Slutz (7):
  vmport.c: Fix vmport_cmd_ram_size
  vmport_rpc: Add the object vmport_rpc
  vmport_rpc: Add limited support of VMware's hyper-call rpc
  vmport_rpc: Add QMP access to vmport_rpc object.
  vmport_rpc: Add migration
  vmport:  Add VMware all ring hack
  MAINTAINERS: add VMware port

 MAINTAINERS  |7 +
 hw/i386/pc.c |   34 +-
 hw/i386/pc_piix.c|2 +-
 hw/i386/pc_q35.c |2 +-
 hw/misc/Makefile.objs|1 +
 hw/misc/vmport.c |2 +-
 hw/misc/vmport_rpc.c | 1442 ++
 include/hw/i386/pc.h |6 +-
 monitor.c|   23 +
 qapi-schema.json |   90 +++
 qmp-commands.hx  |  120 
 target-i386/cpu.c|4 +
 target-i386/cpu.h|2 +
 target-i386/seg_helper.c |6 +
 trace-events |   24 +
 15 files changed, 1760 insertions(+), 5 deletions(-)
 create mode 100644 hw/misc/vmport_rpc.c

-- 
1.8.4




[Qemu-devel] [PATCH v4 6/7] vmport: Add VMware all ring hack

2015-04-30 Thread Don Slutz
This is done by adding a new machine property vmware-port-ring3 that
needs to be enabled to have any effect.  It only effects accel=tcg
mode.  It is needed if you want to use VMware tools in accel=tcg
mode.

Signed-off-by: Don Slutz dsl...@verizon.com
(cherry picked from commit 6d99c91fc9ae27b476e89a8cc880b4a46e237536)
---
 hw/i386/pc.c | 28 +++-
 hw/i386/pc_piix.c|  2 +-
 hw/i386/pc_q35.c |  2 +-
 include/hw/i386/pc.h |  6 +-
 target-i386/cpu.c|  4 
 target-i386/cpu.h|  2 ++
 target-i386/seg_helper.c |  6 ++
 7 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e5b7167..ec78c76 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1056,7 +1056,9 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
 pc_new_cpu(current_cpu_model, apic_id, icc_bridge, errp);
 }
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+  bool vmware_port_ring3)
 {
 int i;
 X86CPU *cpu = NULL;
@@ -1087,6 +1089,9 @@ void pc_cpus_init(const char *cpu_model, DeviceState 
*icc_bridge)
 error_report_err(error);
 exit(1);
 }
+if (vmware_port_ring3) {
+cpu-env.hflags2 |= HF2_VMPORT_HACK_MASK;
+}
 }
 
 /* map APIC MMIO area if CPU has APIC */
@@ -1824,6 +1829,21 @@ static bool pc_machine_get_aligned_dimm(Object *obj, 
Error **errp)
 return pcms-enforce_aligned_dimm;
 }
 
+static bool pc_machine_get_vmware_port_ring3(Object *obj, Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+return pcms-vmware_port_ring3;
+}
+
+static void pc_machine_set_vmware_port_ring3(Object *obj, bool value,
+ Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+pcms-vmware_port_ring3 = value;
+}
+
 static void pc_machine_initfn(Object *obj)
 {
 PCMachineState *pcms = PC_MACHINE(obj);
@@ -1854,6 +1874,12 @@ static void pc_machine_initfn(Object *obj)
 object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM,
  pc_machine_get_aligned_dimm,
  NULL, NULL);
+
+pcms-vmware_port_ring3 = false;
+object_property_add_bool(obj, PC_MACHINE_VMWARE_PORT_RING3,
+ pc_machine_get_vmware_port_ring3,
+ pc_machine_set_vmware_port_ring3,
+ NULL);
 }
 
 static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 1fe7bfb..4fa21c9 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -147,7 +147,7 @@ static void pc_init1(MachineState *machine,
 object_property_add_child(qdev_get_machine(), icc-bridge,
   OBJECT(icc_bridge), NULL);
 
-pc_cpus_init(machine-cpu_model, icc_bridge);
+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
 
 if (kvm_enabled()  kvmclock_enabled) {
 kvmclock_create();
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index dcc17c0..1e47b97 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -136,7 +136,7 @@ static void pc_q35_init(MachineState *machine)
 object_property_add_child(qdev_get_machine(), icc-bridge,
   OBJECT(icc_bridge), NULL);
 
-pc_cpus_init(machine-cpu_model, icc_bridge);
+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
 pc_acpi_init(q35-acpi-dsdt.aml);
 
 kvmclock_create();
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 1b35168..2119d5d 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -40,6 +40,7 @@ struct PCMachineState {
 
 uint64_t max_ram_below_4g;
 OnOffAuto vmport;
+bool vmware_port_ring3;
 bool enforce_aligned_dimm;
 };
 
@@ -48,6 +49,7 @@ struct PCMachineState {
 #define PC_MACHINE_MAX_RAM_BELOW_4G max-ram-below-4g
 #define PC_MACHINE_VMPORT   vmport
 #define PC_MACHINE_ENFORCE_ALIGNED_DIMM enforce-aligned-dimm
+#define PC_MACHINE_VMWARE_PORT_RING3 vmware-port-ring3
 
 /**
  * PCMachineClass:
@@ -163,7 +165,9 @@ extern int fd_bootchk;
 void pc_register_ferr_irq(qemu_irq irq);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+  bool vmware_port_ring3);
 void pc_hot_add_cpu(const int64_t id, Error **errp);
 void pc_acpi_init(const char *default_dsdt);
 
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 3305e09..5085f29 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2592,6 +2592,7 @@ static void x86_cpu_reset

[Qemu-devel] [PATCH v4 7/7] MAINTAINERS: add VMware port

2015-04-30 Thread Don Slutz
Signed-off-by: Don Slutz dsl...@verizon.com
---
 MAINTAINERS | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index b5ab755..4bbda42 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -755,6 +755,13 @@ S: Maintained
 F: hw/net/vmxnet*
 F: hw/scsi/vmw_pvscsi*
 
+VMware port
+M: Don Slutz dsl...@verizon.com
+S: Maintained
+F: hw/misc/vmport.c
+F: hw/input/vmmouse.c
+F: hw/misc/vmport_rpc.c
+
 Subsystems
 --
 Audio
-- 
1.8.4




[Qemu-devel] [PATCH v5 2/7] vmport_rpc: Add the object vmport_rpc

2015-04-30 Thread Don Slutz
This is the 1st part of Add limited support of VMware's hyper-call
rpc.

This patch uses existing infrastructure used by vmmouse.c (provided
by vmport.c) to handle the VMware backdoor command 30.

One of the better on-line references is:

https://sites.google.com/site/chitchatvmback/backdoor

More in next patch.

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/i386/pc.c  |   6 +++
 hw/misc/Makefile.objs |   1 +
 hw/misc/vmport_rpc.c  | 126 ++
 3 files changed, 133 insertions(+)
 create mode 100644 hw/misc/vmport_rpc.c

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index a8e6be1..e5b7167 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1471,8 +1471,14 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
 i8042 = isa_create_simple(isa_bus, i8042);
 i8042_setup_a20_line(i8042, a20_line[0]);
 if (!no_vmport) {
+ISADevice *vmport_rpc;
+
 vmport_init(isa_bus);
 vmmouse = isa_try_create(isa_bus, vmmouse);
+vmport_rpc = isa_try_create(isa_bus, vmport_rpc);
+if (vmport_rpc) {
+qdev_init_nofail(DEVICE(vmport_rpc));
+}
 } else {
 vmmouse = NULL;
 }
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 4aa76ff..e04c8ac 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -7,6 +7,7 @@ common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o
 common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o
 
 obj-$(CONFIG_VMPORT) += vmport.o
+obj-$(CONFIG_VMPORT) += vmport_rpc.o
 
 # ARM devices
 common-obj-$(CONFIG_PL310) += arm_l2x0.o
diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
new file mode 100644
index 000..b7cd355
--- /dev/null
+++ b/hw/misc/vmport_rpc.c
@@ -0,0 +1,126 @@
+/*
+ * QEMU VMPORT RPC emulation
+ *
+ * Copyright (C) 2015 Verizon Corporation
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License Version 2 (GPLv2)
+ * as published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details. http://www.gnu.org/licenses/.
+ */
+
+/*
+ * One of the better on-line references is:
+ *
+ * https://sites.google.com/site/chitchatvmback/backdoor
+ *
+ * Which points you to:
+ *
+ * http://open-vm-tools.sourceforge.net/
+ *
+ * as a place to get more accurate information by studying.
+ */
+
+#include hw/hw.h
+#include hw/i386/pc.h
+#include hw/qdev.h
+#include trace.h
+#include qmp-commands.h
+#include qapi/qmp/qerror.h
+
+/* #define VMPORT_RPC_DEBUG */
+
+#define TYPE_VMPORT_RPC vmport_rpc
+#define VMPORT_RPC(obj) OBJECT_CHECK(VMPortRpcState, (obj), TYPE_VMPORT_RPC)
+
+/* VMPORT RPC Command */
+#define VMPORT_RPC_COMMAND  30
+
+/* The vmport_rpc object. */
+typedef struct VMPortRpcState {
+ISADevice parent_obj;
+
+/* Properties */
+uint64_t reset_time;
+uint64_t build_number_value;
+uint64_t build_number_time;
+
+/* Private data */
+} VMPortRpcState;
+
+typedef struct {
+uint32_t eax;
+uint32_t ebx;
+uint32_t ecx;
+uint32_t edx;
+uint32_t esi;
+uint32_t edi;
+} vregs;
+
+static uint32_t vmport_rpc_ioport_read(void *opaque, uint32_t addr)
+{
+VMPortRpcState *s = opaque;
+union {
+uint32_t data[6];
+vregs regs;
+} ur;
+
+vmmouse_get_data(ur.data);
+
+s-build_number_time++;
+
+vmmouse_set_data(ur.data);
+return ur.data[0];
+}
+
+static void vmport_rpc_reset(DeviceState *d)
+{
+VMPortRpcState *s = VMPORT_RPC(d);
+
+s-reset_time = 14;
+s-build_number_value = 0;
+s-build_number_time = 0;
+}
+
+static void vmport_rpc_realize(DeviceState *dev, Error **errp)
+{
+VMPortRpcState *s = VMPORT_RPC(dev);
+
+vmport_register(VMPORT_RPC_COMMAND, vmport_rpc_ioport_read, s);
+}
+
+static Property vmport_rpc_properties[] = {
+DEFINE_PROP_UINT64(reset-time, VMPortRpcState, reset_time, 14),
+DEFINE_PROP_UINT64(build-number-value, VMPortRpcState,
+   build_number_value, 0),
+DEFINE_PROP_UINT64(build-number-time, VMPortRpcState,
+   build_number_time, 0),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vmport_rpc_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc-realize = vmport_rpc_realize;
+dc-reset = vmport_rpc_reset;
+dc-props = vmport_rpc_properties;
+}
+
+static const TypeInfo vmport_rpc_info = {
+.name  = TYPE_VMPORT_RPC,
+.parent= TYPE_ISA_DEVICE,
+.instance_size = sizeof(VMPortRpcState),
+.class_init= vmport_rpc_class_init,
+};
+
+static void vmport_rpc_register_types(void)
+{
+type_register_static(vmport_rpc_info);
+}
+
+type_init(vmport_rpc_register_types)
-- 
1.8.4




Re: [Qemu-devel] [PATCH v4 6/7] vmport: Add VMware all ring hack

2015-04-30 Thread Don Slutz
On 04/30/15 11:23, Paolo Bonzini wrote:
 
 
 On 30/04/2015 17:15, Don Slutz wrote:
 That is a possibility.  It did not look simple to access CPUX86State
 where I needed to check HF2_VMPORT_HACK_MASK.  Instead of the
 save/restore I could add it both places.
 
 Why not?  This:
 
 @@ -2566,6 +2566,12 @@ static inline void check_io(CPUX86State *env, int 
 addr, int size)
  {
  int io_offset, val, mask;
  
 +/* vmport hack: skip iopl checking for VMware port 0x5658 (see
 + * vmport_realizefn()) */
 +if ((env-hflags2  HF2_VMPORT_HACK_MASK)  (addr == 0x5658)) {
 +return;
 +}
 +
 
 could simply be if (addr == 0x5658  env-allow_vmport_ring3) if you
 add it to CPUX86State.  Alternatively, and probably better, you can add
 it to X86CPU and do:
 
 if (addr == 0x5658) {
 X86CPU *cpu = x86_env_get_cpu(env);
 if (cpu-allow_vmport_ring3) {
 return;
 }
 }
 

I guess I was too focused on stuff in env.  This way does work fine.  v5
will be sent soon.

   -Don Slutz


 Paolo
 



[Qemu-devel] [PATCH 1/1] xen-hvm: Add trace to ioreq

2015-04-30 Thread Don Slutz
Signed-off-by: Don Slutz dsl...@verizon.com
(cherry picked from commit b72adbe7510d0a30053d32334665ee887bec9e43)
---
 trace-events |  7 +++
 xen-hvm.c| 21 +
 2 files changed, 28 insertions(+)

diff --git a/trace-events b/trace-events
index 30eba92..4666dad 100644
--- a/trace-events
+++ b/trace-events
@@ -932,6 +932,13 @@ xen_map_portio_range(uint32_t id, uint64_t start_addr, 
uint64_t end_addr) id: %
 xen_unmap_portio_range(uint32_t id, uint64_t start_addr, uint64_t end_addr) 
id: %u start: %#PRIx64 end: %#PRIx64
 xen_map_pcidev(uint32_t id, uint8_t bus, uint8_t dev, uint8_t func) id: %u 
bdf: %02x.%02x.%02x
 xen_unmap_pcidev(uint32_t id, uint8_t bus, uint8_t dev, uint8_t func) id: %u 
bdf: %02x.%02x.%02x
+handle_ioreq(void *req, uint32_t type, uint32_t dir, uint32_t df, uint32_t 
data_is_ptr, uint64_t addr, uint64_t data, uint32_t count, uint32_t size) 
I/O=%p type=%d dir=%d df=%d ptr=%d port=%#PRIx64 data=%#PRIx64 count=%d 
size=%d
+handle_ioreq_read(void *req, uint32_t type, uint32_t df, uint32_t data_is_ptr, 
uint64_t addr, uint64_t data, uint32_t count, uint32_t size) I/O=%p read 
type=%d df=%d ptr=%d port=%#PRIx64 data=%#PRIx64 count=%d size=%d
+handle_ioreq_write(void *req, uint32_t type, uint32_t df, uint32_t 
data_is_ptr, uint64_t addr, uint64_t data, uint32_t count, uint32_t size) 
I/O=%p write type=%d df=%d ptr=%d port=%#PRIx64 data=%#PRIx64 count=%d 
size=%d
+cpu_ioreq_pio(void *req, uint32_t dir, uint32_t df, uint32_t data_is_ptr, 
uint64_t addr, uint64_t data, uint32_t count, uint32_t size) I/O=%p pio dir=%d 
df=%d ptr=%d port=%#PRIx64 data=%#PRIx64 count=%d size=%d
+cpu_ioreq_pio_read_reg(void *req, uint64_t data, uint64_t addr, uint32_t size) 
I/O=%p pio read reg data=%#PRIx64 port=%#PRIx64 size=%d
+cpu_ioreq_pio_write_reg(void *req, uint64_t data, uint64_t addr, uint32_t 
size) I/O=%p pio write reg data=%#PRIx64 port=%#PRIx64 size=%d
+cpu_ioreq_move(void *req, uint32_t dir, uint32_t df, uint32_t data_is_ptr, 
uint64_t addr, uint64_t data, uint32_t count, uint32_t size) I/O=%p copy 
dir=%d df=%d ptr=%d port=%#PRIx64 data=%#PRIx64 count=%d size=%d
 
 # xen-mapcache.c
 xen_map_cache(uint64_t phys_addr) want %#PRIx64
diff --git a/xen-hvm.c b/xen-hvm.c
index 315864c..6fdba98 100644
--- a/xen-hvm.c
+++ b/xen-hvm.c
@@ -832,9 +832,14 @@ static void cpu_ioreq_pio(ioreq_t *req)
 {
 uint32_t i;
 
+trace_cpu_ioreq_pio(req, req-dir, req-df, req-data_is_ptr, req-addr,
+ req-data, req-count, req-size);
+
 if (req-dir == IOREQ_READ) {
 if (!req-data_is_ptr) {
 req-data = do_inp(req-addr, req-size);
+trace_cpu_ioreq_pio_read_reg(req, req-data, req-addr,
+ req-size);
 } else {
 uint32_t tmp;
 
@@ -845,6 +850,8 @@ static void cpu_ioreq_pio(ioreq_t *req)
 }
 } else if (req-dir == IOREQ_WRITE) {
 if (!req-data_is_ptr) {
+trace_cpu_ioreq_pio_write_reg(req, req-data, req-addr,
+  req-size);
 do_outp(req-addr, req-size, req-data);
 } else {
 for (i = 0; i  req-count; i++) {
@@ -861,6 +868,9 @@ static void cpu_ioreq_move(ioreq_t *req)
 {
 uint32_t i;
 
+trace_cpu_ioreq_move(req, req-dir, req-df, req-data_is_ptr, req-addr,
+ req-data, req-count, req-size);
+
 if (!req-data_is_ptr) {
 if (req-dir == IOREQ_READ) {
 for (i = 0; i  req-count; i++) {
@@ -933,11 +943,18 @@ static void handle_vmport_ioreq(XenIOState *state, 
ioreq_t *req)
 
 static void handle_ioreq(XenIOState *state, ioreq_t *req)
 {
+trace_handle_ioreq(req, req-type, req-dir, req-df, req-data_is_ptr,
+   req-addr, req-data, req-count, req-size);
+
 if (!req-data_is_ptr  (req-dir == IOREQ_WRITE) 
 (req-size  sizeof (target_ulong))) {
 req-data = ((target_ulong) 1  (8 * req-size)) - 1;
 }
 
+if (req-dir == IOREQ_WRITE)
+trace_handle_ioreq_write(req, req-type, req-df, req-data_is_ptr,
+ req-addr, req-data, req-count, req-size);
+
 switch (req-type) {
 case IOREQ_TYPE_PIO:
 cpu_ioreq_pio(req);
@@ -977,6 +994,10 @@ static void handle_ioreq(XenIOState *state, ioreq_t *req)
 default:
 hw_error(Invalid ioreq type 0x%x\n, req-type);
 }
+if (req-dir == IOREQ_READ) {
+trace_handle_ioreq_read(req, req-type, req-df, req-data_is_ptr,
+req-addr, req-data, req-count, req-size);
+}
 }
 
 static int handle_buffered_iopage(XenIOState *state)
-- 
1.8.4




[Qemu-devel] [PATCH v5 4/7] vmport_rpc: Add QMP access to vmport_rpc object.

2015-04-30 Thread Don Slutz
This adds one new inject command:

inject-vmport-action

And three guest info commands:

vmport-guestinfo-set
vmport-guestinfo-get
query-vmport-guestinfo

More details in qmp-commands.hx

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport_rpc.c | 265 +++
 monitor.c|  23 +
 qapi-schema.json |  90 +
 qmp-commands.hx  | 120 +++
 4 files changed, 498 insertions(+)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index 927c0bf..2403f52 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -215,6 +215,56 @@ typedef struct {
 uint32_t edi;
 } vregs;
 
+/*
+ * Run func() for every VMPortRpc device, traverse the tree for
+ * everything else.  Note: This routine expects that opaque is a
+ * VMPortRpcFind pointer and not NULL.
+ */
+static int find_VMPortRpc_device(Object *obj, void *opaque)
+{
+VMPortRpcFind *find = opaque;
+Object *dev;
+VMPortRpcState *s;
+
+if (find-found) {
+return 0;
+}
+dev = object_dynamic_cast(obj, TYPE_VMPORT_RPC);
+s = (VMPortRpcState *)dev;
+
+if (!s) {
+/* Container, traverse it for children */
+return object_child_foreach(obj, find_VMPortRpc_device, opaque);
+}
+
+find-found++;
+find-rc = find-func(s, find-arg);
+
+return 0;
+}
+
+/*
+ * Loop through all dynamically created VMPortRpc devices and call
+ * func() for each instance.
+ */
+static int foreach_dynamic_vmport_rpc_device(FindVMPortRpcDeviceFunc *func,
+ void *arg)
+{
+VMPortRpcFind find = {
+.func = func,
+.arg = arg,
+};
+
+/* Loop through all VMPortRpc devices that were spawned outside
+ * the machine */
+find_VMPortRpc_device(qdev_get_machine(), find);
+if (find.found) {
+return find.rc;
+} else {
+return VMPORT_DEVICE_NOT_FOUND;
+}
+}
+
 #ifdef VMPORT_RPC_DEBUG
 /*
  * Add helper function for tracing.  This routine will convert
@@ -464,6 +514,23 @@ static int get_guestinfo(VMPortRpcState *s,
 return GUESTINFO_NOTFOUND;
 }
 
+static int get_qmp_guestinfo(VMPortRpcState *s,
+ unsigned int a_key_len, char *a_info_key,
+ unsigned int *a_value_len, void **a_value_data)
+{
+gpointer key = g_strndup(a_info_key, a_key_len);
+guestinfo_t *gi = (guestinfo_t *)g_hash_table_lookup(s-guestinfo, key);
+
+g_free(key);
+if (gi) {
+*a_value_len = gi-val_len;
+*a_value_data = gi-val_data;
+return 0;
+}
+
+return GUESTINFO_NOTFOUND;
+}
+
 static int set_guestinfo(VMPortRpcState *s, int a_key_len,
  unsigned int a_val_len, char *a_info_key, char *val)
 {
@@ -851,6 +918,204 @@ static uint32_t vmport_rpc_ioport_read(void *opaque, 
uint32_t addr)
 return ur.data[0];
 }
 
+static int vmport_rpc_find_send(VMPortRpcState *s, void *arg)
+{
+return vmport_rpc_ctrl_send(s, arg);
+}
+
+static void convert_local_rc(Error **errp, int rc)
+{
+switch (rc) {
+case 0:
+break;
+case VMPORT_DEVICE_NOT_FOUND:
+error_set(errp, QERR_DEVICE_NOT_FOUND, TYPE_VMPORT_RPC);
+break;
+case SEND_NOT_OPEN:
+error_setg(errp, VMWare rpc not open);
+break;
+case SEND_SKIPPED:
+error_setg(errp, VMWare rpc send skipped);
+break;
+case SEND_TRUCATED:
+error_setg(errp, VMWare rpc send trucated);
+break;
+case SEND_NO_MEMORY:
+error_setg(errp, VMWare rpc send out of memory);
+break;
+case GUESTINFO_NOTFOUND:
+error_setg(errp, VMWare guestinfo not found);
+break;
+case GUESTINFO_VALTOOLONG:
+error_setg(errp, VMWare guestinfo value too long);
+break;
+case GUESTINFO_KEYTOOLONG:
+error_setg(errp, VMWare guestinfo key too long);
+break;
+case GUESTINFO_TOOMANYKEYS:
+error_setg(errp, VMWare guestinfo too many keys);
+break;
+case GUESTINFO_NO_MEMORY:
+error_setg(errp, VMWare guestinfo out of memory);
+break;
+default:
+error_setg(errp, VMWare rpc send rc=%d unknown, rc);
+break;
+}
+}
+
+void qmp_inject_vmport_action(enum VmportAction action, Error **errp)
+{
+int rc;
+
+switch (action) {
+case VMPORT_ACTION_REBOOT:
+rc = foreach_dynamic_vmport_rpc_device(vmport_rpc_find_send,
+   (void *)OS_Reboot);
+break;
+case VMPORT_ACTION_HALT:
+rc = foreach_dynamic_vmport_rpc_device(vmport_rpc_find_send,
+   (void *)OS_Halt);
+break;
+case VMPORT_ACTION_MAX:
+assert(action != VMPORT_ACTION_MAX);
+rc = 0; /* Should be impossible to get here. */
+break;
+}
+convert_local_rc(errp, rc);
+}
+
+typedef struct keyValue {
+void *key_data

[Qemu-devel] [PATCH v5 5/7] vmport_rpc: Add migration

2015-04-30 Thread Don Slutz
Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport_rpc.c | 250 +++
 trace-events |   8 +-
 2 files changed, 255 insertions(+), 3 deletions(-)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index 2403f52..caa82ef 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -171,6 +171,14 @@ typedef struct VMPortRpcState {
 uint32_t open_cookie;
 channel_t chans[GUESTMSG_MAX_CHANNEL];
 GHashTable *guestinfo;
+/* Temporary cache for migration purposes */
+int32_t mig_chan_num;
+int32_t mig_bucket_num;
+uint32_t mig_guestinfo_size;
+uint32_t mig_guestinfo_off;
+uint8_t *mig_guestinfo_buf;
+channel_control_t *mig_chans;
+bucket_control_t *mig_buckets;
 #ifdef VMPORT_RPC_DEBUG
 unsigned int end;
 unsigned int last;
@@ -1164,6 +1172,247 @@ static Property vmport_rpc_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static const VMStateDescription vmstate_vmport_rpc_chan = {
+.name = vmport_rpc/chan,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField [])
+{
+VMSTATE_UINT64(active_time, channel_control_t),
+VMSTATE_UINT32(chan_id, channel_control_t),
+VMSTATE_UINT32(cookie, channel_control_t),
+VMSTATE_UINT32(proto_num, channel_control_t),
+VMSTATE_UINT16(send_len, channel_control_t),
+VMSTATE_UINT16(send_idx, channel_control_t),
+VMSTATE_UINT16(send_buf_max, channel_control_t),
+VMSTATE_UINT8(recv_read, channel_control_t),
+VMSTATE_UINT8(recv_write, channel_control_t),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static const VMStateDescription vmstate_vmport_rpc_bucket = {
+.name = vmport_rpc/bucket,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField [])
+{
+VMSTATE_UINT16(recv_len, bucket_control_t),
+VMSTATE_UINT16(recv_idx, bucket_control_t),
+VMSTATE_UINT16(recv_buf_max, bucket_control_t),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void vmport_rpc_size_mig_guestinfo(gpointer key, gpointer value,
+  gpointer opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int key_len = strlen(key) + 1;
+guestinfo_t *gi = value;
+
+s-mig_guestinfo_size += 1 + key_len + 4 + gi-val_max;
+}
+
+static void vmport_rpc_fill_mig_guestinfo(gpointer key, gpointer value,
+  gpointer opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int key_len = strlen(key) + 1;
+guestinfo_t *gi = value;
+
+assert(gi-val_len = gi-val_max);
+trace_vmport_rpc_fill_mig_guestinfo(key_len, key_len, key, gi-val_len,
+gi-val_len, gi-val_data);
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = key_len;
+memcpy(s-mig_guestinfo_buf + s-mig_guestinfo_off, key, key_len);
+s-mig_guestinfo_off += key_len;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_len  8;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_len;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_max  8;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_max;
+memcpy(s-mig_guestinfo_buf + s-mig_guestinfo_off, gi-val_data,
+   gi-val_max);
+s-mig_guestinfo_off += gi-val_max;
+}
+
+static int vmport_rpc_pre_load(void *opaque)
+{
+VMPortRpcState *s = opaque;
+
+g_free(s-mig_guestinfo_buf);
+s-mig_guestinfo_buf = NULL;
+s-mig_guestinfo_size = 0;
+s-mig_guestinfo_off = 0;
+g_free(s-mig_chans);
+s-mig_chans = NULL;
+s-mig_chan_num = 0;
+g_free(s-mig_buckets);
+s-mig_buckets = NULL;
+s-mig_bucket_num = 0;
+
+return 0;
+}
+
+static void vmport_rpc_pre_save(void *opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int i;
+unsigned int mig_chan_idx = 0;
+unsigned int mig_bucket_idx = 0;
+
+(void)vmport_rpc_pre_load(opaque);
+for (i = 0; i  GUESTMSG_MAX_CHANNEL; ++i) {
+channel_t *c = s-chans[i];
+
+if (c-ctl.proto_num) {
+unsigned int j;
+
+s-mig_chan_num++;
+for (j = 0; j  MAX_BKTS; ++j) {
+bucket_t *b = c-recv_bkt[j];
+
+s-mig_bucket_num++;
+s-mig_guestinfo_size +=
+(b-ctl.recv_buf_max + 1) * CHAR_PER_CALL;
+}
+s-mig_guestinfo_size += (c-ctl.send_buf_max + 1) * CHAR_PER_CALL;
+}
+}
+g_hash_table_foreach(s-guestinfo, vmport_rpc_size_mig_guestinfo, s);
+s-mig_guestinfo_size++;
+s-mig_guestinfo_buf = g_malloc(s-mig_guestinfo_size);
+s-mig_chans = g_malloc(s-mig_chan_num * sizeof(channel_control_t));
+s-mig_buckets = g_malloc(s-mig_bucket_num * sizeof(bucket_control_t));
+
+for (i = 0; i  GUESTMSG_MAX_CHANNEL; ++i) {
+channel_t *c = s-chans[i];
+
+if (c-ctl.proto_num) {
+unsigned int j

[Qemu-devel] [PATCH v5 3/7] vmport_rpc: Add limited support of VMware's hyper-call rpc

2015-04-30 Thread Don Slutz
The support included is enough to allow VMware tools to install in a
guest and provide guestinfo support.  guestinfo support is provided
by what is known as VMware RPC support.

If the guest is running VMware tools, then the build version of
the tools is also available via the property build-number-value of
the vmport_rpc object.  The build-number-time property is changed
every time the VMware tools running in the guest sends the
build version via the rpc.

The property reset-time controls how often to request them in
seconds minus 1.  The minus 1 is to handle to 0 case.  I.E. the
fastest that can be selected is every second.  The default is 4
times a minute.

The VMware RPC support includes the notion of channels that are
opened, active and closed.  All RPC messages sent via a channel
starts with normal ASCII text.  The message some times does include
binary data.

Currently there are 2 protocols defined for VMware RPC.  They
determine the direction for data flow, guest to tool stack or tool
stack to guest.

There is no provided interrupt for VMware RPC.

Getting VMPORT_RPC_DEBUG will provide a higher level trace calls
that are simpler to understand.

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport_rpc.c | 799 ++-
 trace-events |  22 ++
 2 files changed, 820 insertions(+), 1 deletion(-)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index b7cd355..927c0bf 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -40,6 +40,123 @@
 /* VMPORT RPC Command */
 #define VMPORT_RPC_COMMAND  30
 
+/* Limits on amount of non guest memory to use */
+#define MAX_KEY_LEN  128
+#define MIN_VAL_LEN  64
+#define MAX_VAL_LEN  8192
+#define MAX_NUM_KEY  256
+#define MAX_BKTS 4
+/* Max number of channels. */
+#define GUESTMSG_MAX_CHANNEL 8
+
+/*
+ * All of VMware's rpc is based on 32bit registers.  So this is the
+ * number of bytes in ebx.
+ */
+#define CHAR_PER_CALL   sizeof(uint32_t)
+/* Room for basic commands */
+#define EXTRA_SEND 22
+/* Status code and NULL */
+#define EXTRA_RECV 2
+#define MAX_SEND_BUF DIV_ROUND_UP(EXTRA_SEND + MAX_KEY_LEN + MAX_VAL_LEN, \
+  CHAR_PER_CALL)
+#define MAX_RECV_BUF DIV_ROUND_UP(EXTRA_RECV + MAX_VAL_LEN, CHAR_PER_CALL)
+#define MIN_SEND_BUF DIV_ROUND_UP(EXTRA_SEND + MAX_KEY_LEN + MIN_VAL_LEN, \
+  CHAR_PER_CALL)
+
+/* Reply statuses */
+/*  The basic request succeeded */
+#define MESSAGE_STATUS_SUCCESS  0x0001
+/*  vmware has a message available for its party */
+#define MESSAGE_STATUS_DORECV   0x0002
+/*  The channel has been closed */
+#define MESSAGE_STATUS_CLOSED   0x0004
+/*  vmware removed the message before the party fetched it */
+#define MESSAGE_STATUS_UNSENT   0x0008
+/*  A checkpoint occurred */
+#define MESSAGE_STATUS_CPT  0x0010
+/*  An underlying device is powering off */
+#define MESSAGE_STATUS_POWEROFF 0x0020
+/*  vmware has detected a timeout on the channel */
+#define MESSAGE_STATUS_TIMEOUT  0x0040
+/*  vmware supports high-bandwidth for sending and receiving the payload */
+#define MESSAGE_STATUS_HB   0x0080
+
+/* Max number of channels. */
+#define GUESTMSG_MAX_CHANNEL 8
+
+/* Flags to open a channel. */
+#define GUESTMSG_FLAG_COOKIE 0x8000
+
+/* Data to guest */
+#define VMWARE_PROTO_TO_GUEST   0x4f4c4354
+/* Data from guest */
+#define VMWARE_PROTO_FROM_GUEST 0x49435052
+
+/*
+ * Error return values used only in this file.  The routine
+ * convert_local_rc() is used to convert these to an Error
+ * object.
+ */
+#define VMPORT_DEVICE_NOT_FOUND -1
+#define SEND_NOT_OPEN   -2
+#define SEND_SKIPPED-3
+#define SEND_TRUCATED   -4
+#define SEND_NO_MEMORY  -5
+#define GUESTINFO_NOTFOUND  -6
+#define GUESTINFO_VALTOOLONG-7
+#define GUESTINFO_KEYTOOLONG-8
+#define GUESTINFO_TOOMANYKEYS   -9
+#define GUESTINFO_NO_MEMORY -10
+
+
+/* The VMware RPC guest info storage . */
+typedef struct {
+char *val_data;
+uint16_t val_len;
+uint16_t val_max;
+} guestinfo_t;
+
+/* The VMware RPC bucket control. */
+typedef struct {
+uint16_t recv_len;
+uint16_t recv_idx;
+uint16_t recv_buf_max;
+} bucket_control_t;
+
+/* The VMware RPC bucket info. */
+typedef struct {
+union {
+uint32_t *words;
+char *bytes;
+} recv;
+bucket_control_t ctl;
+} bucket_t;
+
+
+/* The VMware RPC channel control. */
+typedef struct {
+uint64_t active_time;
+uint32_t chan_id;
+uint32_t cookie;
+uint32_t proto_num;
+uint16_t send_len;
+uint16_t send_idx;
+uint16_t send_buf_max;
+uint8_t recv_read;
+uint8_t recv_write;
+} channel_control_t;
+
+/* The VMware RPC channel info. */
+typedef struct {
+union {
+uint32_t *words;
+char *bytes;
+} send;
+channel_control_t ctl;
+bucket_t recv_bkt[MAX_BKTS];
+} channel_t;
+
 /* The vmport_rpc

[Qemu-devel] [PATCH v5 7/7] MAINTAINERS: add VMware port

2015-04-30 Thread Don Slutz
Signed-off-by: Don Slutz dsl...@verizon.com
---
 MAINTAINERS | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index b5ab755..4bbda42 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -755,6 +755,13 @@ S: Maintained
 F: hw/net/vmxnet*
 F: hw/scsi/vmw_pvscsi*
 
+VMware port
+M: Don Slutz dsl...@verizon.com
+S: Maintained
+F: hw/misc/vmport.c
+F: hw/input/vmmouse.c
+F: hw/misc/vmport_rpc.c
+
 Subsystems
 --
 Audio
-- 
1.8.4




[Qemu-devel] [PATCH v5 1/7] vmport.c: Fix vmport_cmd_ram_size

2015-04-30 Thread Don Slutz
Based on

https://sites.google.com/site/chitchatvmback/backdoor

and testing on ESXi, this should be in MB not bytes.

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index 7fcc00d..6b350ce 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -110,7 +110,7 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t 
addr)
 X86CPU *cpu = X86_CPU(current_cpu);
 
 cpu-env.regs[R_EBX] = 0x1177;
-return ram_size;
+return ram_size  20; /* in MB */
 }
 
 static uint32_t vmport_cmd_xtest(void *opaque, uint32_t addr)
-- 
1.8.4




[Qemu-devel] [PATCH v5 6/7] vmport: Add VMware all ring hack

2015-04-30 Thread Don Slutz
This is done by adding a new machine property vmware-port-ring3 that
needs to be enabled to have any effect.  It only effects accel=tcg
mode.  It is needed if you want to use VMware tools in accel=tcg
mode.

Signed-off-by: Don Slutz dsl...@verizon.com
(cherry picked from commit 6d99c91fc9ae27b476e89a8cc880b4a46e237536)
---
 hw/i386/pc.c | 26 +-
 hw/i386/pc_piix.c|  2 +-
 hw/i386/pc_q35.c |  2 +-
 include/hw/i386/pc.h |  6 +-
 target-i386/cpu-qom.h|  3 +++
 target-i386/seg_helper.c |  9 +
 6 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e5b7167..4101aa9 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1056,7 +1056,9 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
 pc_new_cpu(current_cpu_model, apic_id, icc_bridge, errp);
 }
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+  bool vmware_port_ring3)
 {
 int i;
 X86CPU *cpu = NULL;
@@ -1087,6 +1089,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState 
*icc_bridge)
 error_report_err(error);
 exit(1);
 }
+cpu-allow_vmport_ring3 = vmware_port_ring3;
 }
 
 /* map APIC MMIO area if CPU has APIC */
@@ -1824,6 +1827,21 @@ static bool pc_machine_get_aligned_dimm(Object *obj, 
Error **errp)
 return pcms-enforce_aligned_dimm;
 }
 
+static bool pc_machine_get_vmware_port_ring3(Object *obj, Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+return pcms-vmware_port_ring3;
+}
+
+static void pc_machine_set_vmware_port_ring3(Object *obj, bool value,
+ Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+pcms-vmware_port_ring3 = value;
+}
+
 static void pc_machine_initfn(Object *obj)
 {
 PCMachineState *pcms = PC_MACHINE(obj);
@@ -1854,6 +1872,12 @@ static void pc_machine_initfn(Object *obj)
 object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM,
  pc_machine_get_aligned_dimm,
  NULL, NULL);
+
+pcms-vmware_port_ring3 = false;
+object_property_add_bool(obj, PC_MACHINE_VMWARE_PORT_RING3,
+ pc_machine_get_vmware_port_ring3,
+ pc_machine_set_vmware_port_ring3,
+ NULL);
 }
 
 static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 1fe7bfb..4fa21c9 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -147,7 +147,7 @@ static void pc_init1(MachineState *machine,
 object_property_add_child(qdev_get_machine(), icc-bridge,
   OBJECT(icc_bridge), NULL);
 
-pc_cpus_init(machine-cpu_model, icc_bridge);
+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
 
 if (kvm_enabled()  kvmclock_enabled) {
 kvmclock_create();
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index dcc17c0..1e47b97 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -136,7 +136,7 @@ static void pc_q35_init(MachineState *machine)
 object_property_add_child(qdev_get_machine(), icc-bridge,
   OBJECT(icc_bridge), NULL);
 
-pc_cpus_init(machine-cpu_model, icc_bridge);
+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
 pc_acpi_init(q35-acpi-dsdt.aml);
 
 kvmclock_create();
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 1b35168..2119d5d 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -40,6 +40,7 @@ struct PCMachineState {
 
 uint64_t max_ram_below_4g;
 OnOffAuto vmport;
+bool vmware_port_ring3;
 bool enforce_aligned_dimm;
 };
 
@@ -48,6 +49,7 @@ struct PCMachineState {
 #define PC_MACHINE_MAX_RAM_BELOW_4G max-ram-below-4g
 #define PC_MACHINE_VMPORT   vmport
 #define PC_MACHINE_ENFORCE_ALIGNED_DIMM enforce-aligned-dimm
+#define PC_MACHINE_VMWARE_PORT_RING3 vmware-port-ring3
 
 /**
  * PCMachineClass:
@@ -163,7 +165,9 @@ extern int fd_bootchk;
 void pc_register_ferr_irq(qemu_irq irq);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+  bool vmware_port_ring3);
 void pc_hot_add_cpu(const int64_t id, Error **errp);
 void pc_acpi_init(const char *default_dsdt);
 
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 31a0c1e..a173c96 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -108,6 +108,9 @@ typedef struct X86CPU {
  */
 bool enable_pmu;
 
+/* allow_vmport_ring3 true says

[Qemu-devel] [PATCH v5 0/7] Add limited support of VMware's hyper-call rpc

2015-04-30 Thread Don Slutz
Changes v4 to v5:

  Paolo Bonzini
What is VMPORT_SHORT about?
  Dropped this.
Why not use a bool in CPUX86State?
  Took his sugestion and moved to a bool in X86CPU.

Changes v3 to v4:

  Paolo Bonzini on vmort_rpc: Add QMP access to vmport_rpc
Does this compile on non-x86 targets?
  Nope.  Fixed.

Changes v2 to v3:

  s/2.3/2.4

Changes v1 to v2:

   Added live migration code.
   Adjust data structures for migration.
   Switch to GHashTable.

  Eric Blake
s/spawened/spawned/
  Done
s/traceing/tracing/
  Done
Change error_set(errp, ERROR_CLASS_GENERIC_ERROR,  to
error_setg(errp, 
  Done
Why two commands (inject-vmport-reboot, inject-vmport-halt)?
  Switched to inject-vmport-action.
format=base64 bug statements.
  Dropped.

Much more on format=base64:

If there is a bug it is in GLIB.  However the Glib reference manual
refers to RFC 1421 and RFC 2045 and MIME encoding.  Based on all
that (which seems to match:

http://en.wikipedia.org/wiki/Base64

) MIME states that all characters outside the (base64) alphabet are
to be ignored.  Testing shows that g_base64_decode() does this.

The confusion is that most non-MIME uses reject a base64 string that
contain characters outside the alphabet.  I was just following the
other uses of base64 in this file.

DataFormat refers to RFC 3548, which has the info:


   Implementations MUST reject the encoding if it contains
   characters outside the base alphabet when interpreting base
   encoded data, unless the specification referring to this document
   explicitly states otherwise.  Such specifications may, as MIME
   does, instead state that characters outside the base encoding
   alphabet should simply be ignored when interpreting data (be
   liberal in what you accept).


So with GLIB going the MIME way, I do not think this is a QEMU bug
(you could consider this a GLIB bug, but the document I found says
that GLIB goes the MIME way and so does not reject anything).

---


The support included is enough to allow VMware tools to install in a
guest and provide guestinfo support.  guestinfo support is provided
by what is known as VMware RPC support.

One of the better on-line references is:

https://sites.google.com/site/chitchatvmback/backdoor

As a place to get more accurate information by studying:

http://open-vm-tools.sourceforge.net/

With vmware tools installed, you can do:

---
Last login: Fri Jan 30 16:03:08 2015
[root@C63-min-tools ~]# vmtoolsd --cmd info-get guestinfo.joejoel
No value found
[root@C63-min-tools ~]# vmtoolsd --cmd info-set guestinfo.joejoel bar

[root@C63-min-tools ~]# vmtoolsd --cmd info-get guestinfo.joejoel
bar
[root@C63-min-tools ~]# 
---

to access guest info.  QMP access is also provided.

The live migration code is still in progress.

Don Slutz (7):
  vmport.c: Fix vmport_cmd_ram_size
  vmport_rpc: Add the object vmport_rpc
  vmport_rpc: Add limited support of VMware's hyper-call rpc
  vmport_rpc: Add QMP access to vmport_rpc object.
  vmport_rpc: Add migration
  vmport:  Add VMware all ring hack
  MAINTAINERS: add VMware port

 MAINTAINERS  |7 +
 hw/i386/pc.c |   32 +-
 hw/i386/pc_piix.c|2 +-
 hw/i386/pc_q35.c |2 +-
 hw/misc/Makefile.objs|1 +
 hw/misc/vmport.c |2 +-
 hw/misc/vmport_rpc.c | 1438 ++
 include/hw/i386/pc.h |6 +-
 monitor.c|   23 +
 qapi-schema.json |   90 +++
 qmp-commands.hx  |  120 
 target-i386/cpu-qom.h|3 +
 target-i386/seg_helper.c |9 +
 trace-events |   24 +
 14 files changed, 1754 insertions(+), 5 deletions(-)
 create mode 100644 hw/misc/vmport_rpc.c

-- 
1.8.4




[Qemu-devel] [PATCH 1/1] vl.c: Since the help says that 'disk_image' is a raw hard disk image, pass format=raw

2015-04-30 Thread Don Slutz
~/qemu/out/master/x86_64-softmmu/qemu-system-x86_64 -h | head
QEMU emulator version 2.3.50, Copyright (c) 2003-2008 Fabrice Bellard
usage: qemu-system-x86_64 [options] [disk_image]

'disk_image' is a raw hard disk image for IDE hard disk 0

Standard options:
...

Signed-off-by: Don Slutz dsl...@verizon.com
---
 vl.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/vl.c b/vl.c
index 74c2681..93e674f 100644
--- a/vl.c
+++ b/vl.c
@@ -1084,6 +1084,7 @@ static int cleanup_add_fd(QemuOpts *opts, void *opaque)
 /* QEMU Block devices */
 
 #define HD_OPTS media=disk
+#define HD_OPTS_RAW media=disk,format=raw
 #define CDROM_OPTS media=cdrom
 #define FD_OPTS 
 #define PFLASH_OPTS 
@@ -2862,7 +2863,7 @@ int main(int argc, char **argv, char **envp)
 if (optind = argc)
 break;
 if (argv[optind][0] != '-') {
-hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS);
+hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS_RAW);
 } else {
 const QEMUOption *popt;
 
-- 
1.8.4




Re: [Qemu-devel] [PATCH 1/1] vl.c: Since the help says that 'disk_image' is a raw hard disk image, pass format=raw

2015-04-30 Thread Don Slutz
On 04/30/15 16:15, Kevin Wolf wrote:
 Am 30.04.2015 um 21:15 hat Eric Blake geschrieben:
 [adding qemu-block]
 
 On 04/30/2015 12:23 PM, Don Slutz wrote:
 ~/qemu/out/master/x86_64-softmmu/qemu-system-x86_64 -h | head 
 QEMU emulator version 2.3.50, Copyright (c) 2003-2008 Fabrice
 Bellard usage: qemu-system-x86_64 [options] [disk_image]
 
 'disk_image' is a raw hard disk image for IDE hard disk 0
 
 Standard options: ...
 
 Signed-off-by: Don Slutz dsl...@verizon.com --- vl.c | 3 ++- 
 1 file changed, 2 insertions(+), 1 deletion(-)
 
 Reviewed-by: Eric Blake ebl...@redhat.com
 
 Without this, qemu will try to probe formats.  It is  arguably is
 more convenient when using the shorthand of supplying a disk
 image to let qemu pick the format; but as the --help text says
 the image is raw, it's better to be explicit and avoid probing.
 Besides, we can always use longhand to specify actual format
 and/or probing if we don't like the shorthand.
 
 I don't think you can take an outdated help text as a justification
 for breaking backwards compatibility.
 

Is this a hard no, soft no, or TBD?

The following is what prompted this:

WARNING: Image format was not specified for '/dev/etherd/e500.1' and
probing guessed raw.
 Automatically detecting the format is dangerous for raw
images, write operations on block 0 will be restricted.
 Specify the 'raw' format explicitly to remove the restrictions.


which I would say also breaks backwards compatibility.  However I do
agree that this is the right change to have done.  However there
currently is no way to specify that the 'disk_image' is raw.

Also the old options (-hda, -hdb, -hdc, and -hdd) all have similar issues.

So do you want a more complex patch that allows the format to be
specified?

Only for 'disk_image'?

Include -hd* ?

Change the help message also?

   -Don Slutz

 Kevin
 
 
 diff --git a/vl.c b/vl.c index 74c2681..93e674f 100644 ---
 a/vl.c +++ b/vl.c @@ -1084,6 +1084,7 @@ static int
 cleanup_add_fd(QemuOpts *opts, void *opaque) /* QEMU Block
 devices */
 
 #define HD_OPTS media=disk +#define HD_OPTS_RAW
 media=disk,format=raw #define CDROM_OPTS media=cdrom 
 #define FD_OPTS  #define PFLASH_OPTS  @@ -2862,7 +2863,7 @@
 int main(int argc, char **argv, char **envp) if (optind =
 argc) break; if (argv[optind][0] != '-') { -
 hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS); +
 hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++],
 HD_OPTS_RAW); } else { const QEMUOption *popt;
 
 
 
 -- Eric Blake   eblake redhat com+1-919-301-3266 Libvirt
 virtualization library http://libvirt.org
 
 
 



Re: [Qemu-devel] [PATCH v4 4/7] vmport_rpc: Add QMP access to vmport_rpc object.

2015-04-30 Thread Don Slutz
On 04/30/15 09:55, Paolo Bonzini wrote:
 
 
 On 30/04/2015 15:32, Don Slutz wrote:
 +#ifdef VMPORT_SHORT
 +info-value-key = g_strdup(ckey);
 +#else
 +info-value-key = g_strdup_printf(guestinfo.%s, ckey);
 +#endif
 
 What is VMPORT_SHORT for?
 

Simpler code.  Looks like a left over before I found g_strdup_printf()
and it worked.  Will plan to remove.
   -Don Slutz

 Paolo
 



Re: [Qemu-devel] [PATCH v4 6/7] vmport: Add VMware all ring hack

2015-04-30 Thread Don Slutz
On 04/30/15 09:54, Paolo Bonzini wrote:
 On 30/04/2015 15:32, Don Slutz wrote:
 This is done by adding a new machine property vmware-port-ring3 that
 needs to be enabled to have any effect.  It only effects accel=tcg
 mode.  It is needed if you want to use VMware tools in accel=tcg
 mode.
 
 How does it work on KVM or Xen?
 

Xen change is in progress (patch posted).  I have not done any work on
HVM yet.



 diff --git a/target-i386/cpu.c b/target-i386/cpu.c
 index 3305e09..5085f29 100644
 --- a/target-i386/cpu.c
 +++ b/target-i386/cpu.c
 @@ -2592,6 +2592,7 @@ static void x86_cpu_reset(CPUState *s)
  X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
  CPUX86State *env = cpu-env;
  int i;
 +bool save_vmware_port_ring3 = env-hflags2  HF2_VMPORT_HACK_MASK;
  
  xcc-parent_reset(s);
  
 @@ -2607,6 +2608,9 @@ static void x86_cpu_reset(CPUState *s)
  env-hflags |= HF_SOFTMMU_MASK;
  #endif
  env-hflags2 |= HF2_GIF_MASK;
 +if (save_vmware_port_ring3) {
 +env-hflags2 |= HF2_VMPORT_HACK_MASK;
 +}
  
  cpu_x86_update_cr0(env, 0x6010);
  env-a20_mask = ~0x0;
 
 The save/restore suggests that you want a new bool-typed field in
 CPUX86State instead of a bit env-hflags2.
 

That is a possibility.  It did not look simple to access CPUX86State
where I needed to check HF2_VMPORT_HACK_MASK.  Instead of the
save/restore I could add it both places.

   -Don Slutz


 Paolo
 



Re: [Qemu-devel] [PATCH v2 4/7] vmport_rpc: Add QMP access to vmport_rpc object.

2015-04-28 Thread Don Slutz
On 04/28/15 04:13, Paolo Bonzini wrote:
 
 
 On 28/04/2015 00:46, Don Slutz wrote:
 This adds one new inject command:

 inject-vmport-action

 And three guest info commands:

 vmport-guestinfo-set
 vmport-guestinfo-get
 query-vmport-guestinfo

 More details in qmp-commands.hx

 Signed-off-by: Don Slutz dsl...@verizon.com
 ---
  hw/misc/vmport_rpc.c | 269 
 +++
  qapi-schema.json |  90 +
  qmp-commands.hx  | 120 +++
  3 files changed, 479 insertions(+)
 
 Does this compile on non-x86 targets?
 

Sigh, it does not.  Will fix.
   -Don Slutz


 Paolo
 



[Qemu-devel] [PATCH v2 1/7] vmport.c: Fix vmport_cmd_ram_size

2015-04-27 Thread Don Slutz
Based on

https://sites.google.com/site/chitchatvmback/backdoor

and testing on ESXi, this should be in MB not bytes.

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index 7fcc00d..6b350ce 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -110,7 +110,7 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t 
addr)
 X86CPU *cpu = X86_CPU(current_cpu);
 
 cpu-env.regs[R_EBX] = 0x1177;
-return ram_size;
+return ram_size  20; /* in MB */
 }
 
 static uint32_t vmport_cmd_xtest(void *opaque, uint32_t addr)
-- 
1.8.4




[Qemu-devel] [PATCH v2 4/7] vmport_rpc: Add QMP access to vmport_rpc object.

2015-04-27 Thread Don Slutz
This adds one new inject command:

inject-vmport-action

And three guest info commands:

vmport-guestinfo-set
vmport-guestinfo-get
query-vmport-guestinfo

More details in qmp-commands.hx

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport_rpc.c | 269 +++
 qapi-schema.json |  90 +
 qmp-commands.hx  | 120 +++
 3 files changed, 479 insertions(+)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index 927c0bf..0ba3319 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -215,6 +215,56 @@ typedef struct {
 uint32_t edi;
 } vregs;
 
+/*
+ * Run func() for every VMPortRpc device, traverse the tree for
+ * everything else.  Note: This routine expects that opaque is a
+ * VMPortRpcFind pointer and not NULL.
+ */
+static int find_VMPortRpc_device(Object *obj, void *opaque)
+{
+VMPortRpcFind *find = opaque;
+Object *dev;
+VMPortRpcState *s;
+
+if (find-found) {
+return 0;
+}
+dev = object_dynamic_cast(obj, TYPE_VMPORT_RPC);
+s = (VMPortRpcState *)dev;
+
+if (!s) {
+/* Container, traverse it for children */
+return object_child_foreach(obj, find_VMPortRpc_device, opaque);
+}
+
+find-found++;
+find-rc = find-func(s, find-arg);
+
+return 0;
+}
+
+/*
+ * Loop through all dynamically created VMPortRpc devices and call
+ * func() for each instance.
+ */
+static int foreach_dynamic_vmport_rpc_device(FindVMPortRpcDeviceFunc *func,
+ void *arg)
+{
+VMPortRpcFind find = {
+.func = func,
+.arg = arg,
+};
+
+/* Loop through all VMPortRpc devices that were spawned outside
+ * the machine */
+find_VMPortRpc_device(qdev_get_machine(), find);
+if (find.found) {
+return find.rc;
+} else {
+return VMPORT_DEVICE_NOT_FOUND;
+}
+}
+
 #ifdef VMPORT_RPC_DEBUG
 /*
  * Add helper function for tracing.  This routine will convert
@@ -464,6 +514,23 @@ static int get_guestinfo(VMPortRpcState *s,
 return GUESTINFO_NOTFOUND;
 }
 
+static int get_qmp_guestinfo(VMPortRpcState *s,
+ unsigned int a_key_len, char *a_info_key,
+ unsigned int *a_value_len, void **a_value_data)
+{
+gpointer key = g_strndup(a_info_key, a_key_len);
+guestinfo_t *gi = (guestinfo_t *)g_hash_table_lookup(s-guestinfo, key);
+
+g_free(key);
+if (gi) {
+*a_value_len = gi-val_len;
+*a_value_data = gi-val_data;
+return 0;
+}
+
+return GUESTINFO_NOTFOUND;
+}
+
 static int set_guestinfo(VMPortRpcState *s, int a_key_len,
  unsigned int a_val_len, char *a_info_key, char *val)
 {
@@ -851,6 +918,208 @@ static uint32_t vmport_rpc_ioport_read(void *opaque, 
uint32_t addr)
 return ur.data[0];
 }
 
+static int vmport_rpc_find_send(VMPortRpcState *s, void *arg)
+{
+return vmport_rpc_ctrl_send(s, arg);
+}
+
+static void convert_local_rc(Error **errp, int rc)
+{
+switch (rc) {
+case 0:
+break;
+case VMPORT_DEVICE_NOT_FOUND:
+error_set(errp, QERR_DEVICE_NOT_FOUND, TYPE_VMPORT_RPC);
+break;
+case SEND_NOT_OPEN:
+error_setg(errp, VMWare rpc not open);
+break;
+case SEND_SKIPPED:
+error_setg(errp, VMWare rpc send skipped);
+break;
+case SEND_TRUCATED:
+error_setg(errp, VMWare rpc send trucated);
+break;
+case SEND_NO_MEMORY:
+error_setg(errp, VMWare rpc send out of memory);
+break;
+case GUESTINFO_NOTFOUND:
+error_setg(errp, VMWare guestinfo not found);
+break;
+case GUESTINFO_VALTOOLONG:
+error_setg(errp, VMWare guestinfo value too long);
+break;
+case GUESTINFO_KEYTOOLONG:
+error_setg(errp, VMWare guestinfo key too long);
+break;
+case GUESTINFO_TOOMANYKEYS:
+error_setg(errp, VMWare guestinfo too many keys);
+break;
+case GUESTINFO_NO_MEMORY:
+error_setg(errp, VMWare guestinfo out of memory);
+break;
+default:
+error_setg(errp, VMWare rpc send rc=%d unknown, rc);
+break;
+}
+}
+
+void qmp_inject_vmport_action(enum VmportAction action, Error **errp)
+{
+int rc;
+
+switch (action) {
+case VMPORT_ACTION_REBOOT:
+rc = foreach_dynamic_vmport_rpc_device(vmport_rpc_find_send,
+   (void *)OS_Reboot);
+break;
+case VMPORT_ACTION_HALT:
+rc = foreach_dynamic_vmport_rpc_device(vmport_rpc_find_send,
+   (void *)OS_Halt);
+break;
+case VMPORT_ACTION_MAX:
+assert(action != VMPORT_ACTION_MAX);
+rc = 0; /* Should be impossible to get here. */
+break;
+}
+convert_local_rc(errp, rc);
+}
+
+typedef struct keyValue {
+void *key_data;
+void *value_data

[Qemu-devel] [PATCH v2 2/7] vmport_rpc: Add the object vmport_rpc

2015-04-27 Thread Don Slutz
This is the 1st part of Add limited support of VMware's hyper-call
rpc.

This patch uses existing infrastructure used by vmmouse.c (provided
by vmport.c) to handle the VMware backdoor command 30.

One of the better on-line references is:

https://sites.google.com/site/chitchatvmback/backdoor

More in next patch.

Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/i386/pc.c  |   6 +++
 hw/misc/Makefile.objs |   1 +
 hw/misc/vmport_rpc.c  | 126 ++
 3 files changed, 133 insertions(+)
 create mode 100644 hw/misc/vmport_rpc.c

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index a8e6be1..e5b7167 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1471,8 +1471,14 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
 i8042 = isa_create_simple(isa_bus, i8042);
 i8042_setup_a20_line(i8042, a20_line[0]);
 if (!no_vmport) {
+ISADevice *vmport_rpc;
+
 vmport_init(isa_bus);
 vmmouse = isa_try_create(isa_bus, vmmouse);
+vmport_rpc = isa_try_create(isa_bus, vmport_rpc);
+if (vmport_rpc) {
+qdev_init_nofail(DEVICE(vmport_rpc));
+}
 } else {
 vmmouse = NULL;
 }
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 4aa76ff..e04c8ac 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -7,6 +7,7 @@ common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o
 common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o
 
 obj-$(CONFIG_VMPORT) += vmport.o
+obj-$(CONFIG_VMPORT) += vmport_rpc.o
 
 # ARM devices
 common-obj-$(CONFIG_PL310) += arm_l2x0.o
diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
new file mode 100644
index 000..b7cd355
--- /dev/null
+++ b/hw/misc/vmport_rpc.c
@@ -0,0 +1,126 @@
+/*
+ * QEMU VMPORT RPC emulation
+ *
+ * Copyright (C) 2015 Verizon Corporation
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License Version 2 (GPLv2)
+ * as published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details. http://www.gnu.org/licenses/.
+ */
+
+/*
+ * One of the better on-line references is:
+ *
+ * https://sites.google.com/site/chitchatvmback/backdoor
+ *
+ * Which points you to:
+ *
+ * http://open-vm-tools.sourceforge.net/
+ *
+ * as a place to get more accurate information by studying.
+ */
+
+#include hw/hw.h
+#include hw/i386/pc.h
+#include hw/qdev.h
+#include trace.h
+#include qmp-commands.h
+#include qapi/qmp/qerror.h
+
+/* #define VMPORT_RPC_DEBUG */
+
+#define TYPE_VMPORT_RPC vmport_rpc
+#define VMPORT_RPC(obj) OBJECT_CHECK(VMPortRpcState, (obj), TYPE_VMPORT_RPC)
+
+/* VMPORT RPC Command */
+#define VMPORT_RPC_COMMAND  30
+
+/* The vmport_rpc object. */
+typedef struct VMPortRpcState {
+ISADevice parent_obj;
+
+/* Properties */
+uint64_t reset_time;
+uint64_t build_number_value;
+uint64_t build_number_time;
+
+/* Private data */
+} VMPortRpcState;
+
+typedef struct {
+uint32_t eax;
+uint32_t ebx;
+uint32_t ecx;
+uint32_t edx;
+uint32_t esi;
+uint32_t edi;
+} vregs;
+
+static uint32_t vmport_rpc_ioport_read(void *opaque, uint32_t addr)
+{
+VMPortRpcState *s = opaque;
+union {
+uint32_t data[6];
+vregs regs;
+} ur;
+
+vmmouse_get_data(ur.data);
+
+s-build_number_time++;
+
+vmmouse_set_data(ur.data);
+return ur.data[0];
+}
+
+static void vmport_rpc_reset(DeviceState *d)
+{
+VMPortRpcState *s = VMPORT_RPC(d);
+
+s-reset_time = 14;
+s-build_number_value = 0;
+s-build_number_time = 0;
+}
+
+static void vmport_rpc_realize(DeviceState *dev, Error **errp)
+{
+VMPortRpcState *s = VMPORT_RPC(dev);
+
+vmport_register(VMPORT_RPC_COMMAND, vmport_rpc_ioport_read, s);
+}
+
+static Property vmport_rpc_properties[] = {
+DEFINE_PROP_UINT64(reset-time, VMPortRpcState, reset_time, 14),
+DEFINE_PROP_UINT64(build-number-value, VMPortRpcState,
+   build_number_value, 0),
+DEFINE_PROP_UINT64(build-number-time, VMPortRpcState,
+   build_number_time, 0),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vmport_rpc_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc-realize = vmport_rpc_realize;
+dc-reset = vmport_rpc_reset;
+dc-props = vmport_rpc_properties;
+}
+
+static const TypeInfo vmport_rpc_info = {
+.name  = TYPE_VMPORT_RPC,
+.parent= TYPE_ISA_DEVICE,
+.instance_size = sizeof(VMPortRpcState),
+.class_init= vmport_rpc_class_init,
+};
+
+static void vmport_rpc_register_types(void)
+{
+type_register_static(vmport_rpc_info);
+}
+
+type_init(vmport_rpc_register_types)
-- 
1.8.4




[Qemu-devel] [PATCH v2 6/7] vmport: Add VMware all ring hack

2015-04-27 Thread Don Slutz
This is done by adding a new machine property vmware-port-ring3 that
needs to be enabled to have any effect.  It only effects accel=tcg
mode.  It is needed if you want to use VMware tools in accel=tcg
mode.

Signed-off-by: Don Slutz dsl...@verizon.com
(cherry picked from commit 6d99c91fc9ae27b476e89a8cc880b4a46e237536)
---
 hw/i386/pc.c | 28 +++-
 hw/i386/pc_piix.c|  2 +-
 hw/i386/pc_q35.c |  2 +-
 include/hw/i386/pc.h |  6 +-
 target-i386/cpu.c|  4 
 target-i386/cpu.h|  2 ++
 target-i386/seg_helper.c |  6 ++
 7 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e5b7167..ec78c76 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1056,7 +1056,9 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
 pc_new_cpu(current_cpu_model, apic_id, icc_bridge, errp);
 }
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+  bool vmware_port_ring3)
 {
 int i;
 X86CPU *cpu = NULL;
@@ -1087,6 +1089,9 @@ void pc_cpus_init(const char *cpu_model, DeviceState 
*icc_bridge)
 error_report_err(error);
 exit(1);
 }
+if (vmware_port_ring3) {
+cpu-env.hflags2 |= HF2_VMPORT_HACK_MASK;
+}
 }
 
 /* map APIC MMIO area if CPU has APIC */
@@ -1824,6 +1829,21 @@ static bool pc_machine_get_aligned_dimm(Object *obj, 
Error **errp)
 return pcms-enforce_aligned_dimm;
 }
 
+static bool pc_machine_get_vmware_port_ring3(Object *obj, Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+return pcms-vmware_port_ring3;
+}
+
+static void pc_machine_set_vmware_port_ring3(Object *obj, bool value,
+ Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+pcms-vmware_port_ring3 = value;
+}
+
 static void pc_machine_initfn(Object *obj)
 {
 PCMachineState *pcms = PC_MACHINE(obj);
@@ -1854,6 +1874,12 @@ static void pc_machine_initfn(Object *obj)
 object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM,
  pc_machine_get_aligned_dimm,
  NULL, NULL);
+
+pcms-vmware_port_ring3 = false;
+object_property_add_bool(obj, PC_MACHINE_VMWARE_PORT_RING3,
+ pc_machine_get_vmware_port_ring3,
+ pc_machine_set_vmware_port_ring3,
+ NULL);
 }
 
 static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 1fe7bfb..4fa21c9 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -147,7 +147,7 @@ static void pc_init1(MachineState *machine,
 object_property_add_child(qdev_get_machine(), icc-bridge,
   OBJECT(icc_bridge), NULL);
 
-pc_cpus_init(machine-cpu_model, icc_bridge);
+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
 
 if (kvm_enabled()  kvmclock_enabled) {
 kvmclock_create();
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index dcc17c0..1e47b97 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -136,7 +136,7 @@ static void pc_q35_init(MachineState *machine)
 object_property_add_child(qdev_get_machine(), icc-bridge,
   OBJECT(icc_bridge), NULL);
 
-pc_cpus_init(machine-cpu_model, icc_bridge);
+pc_cpus_init(machine-cpu_model, icc_bridge, 
pc_machine-vmware_port_ring3);
 pc_acpi_init(q35-acpi-dsdt.aml);
 
 kvmclock_create();
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 1b35168..2119d5d 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -40,6 +40,7 @@ struct PCMachineState {
 
 uint64_t max_ram_below_4g;
 OnOffAuto vmport;
+bool vmware_port_ring3;
 bool enforce_aligned_dimm;
 };
 
@@ -48,6 +49,7 @@ struct PCMachineState {
 #define PC_MACHINE_MAX_RAM_BELOW_4G max-ram-below-4g
 #define PC_MACHINE_VMPORT   vmport
 #define PC_MACHINE_ENFORCE_ALIGNED_DIMM enforce-aligned-dimm
+#define PC_MACHINE_VMWARE_PORT_RING3 vmware-port-ring3
 
 /**
  * PCMachineClass:
@@ -163,7 +165,9 @@ extern int fd_bootchk;
 void pc_register_ferr_irq(qemu_irq irq);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+  bool vmware_port_ring3);
 void pc_hot_add_cpu(const int64_t id, Error **errp);
 void pc_acpi_init(const char *default_dsdt);
 
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 03b33cf..7951880 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2631,6 +2631,7 @@ static void x86_cpu_reset

[Qemu-devel] [PATCH v2 5/7] vmport_rpc: Add migration

2015-04-27 Thread Don Slutz
Signed-off-by: Don Slutz dsl...@verizon.com
---
 hw/misc/vmport_rpc.c | 250 +++
 trace-events |   8 +-
 2 files changed, 255 insertions(+), 3 deletions(-)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index 0ba3319..a147561 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -171,6 +171,14 @@ typedef struct VMPortRpcState {
 uint32_t open_cookie;
 channel_t chans[GUESTMSG_MAX_CHANNEL];
 GHashTable *guestinfo;
+/* Temporary cache for migration purposes */
+int32_t mig_chan_num;
+int32_t mig_bucket_num;
+uint32_t mig_guestinfo_size;
+uint32_t mig_guestinfo_off;
+uint8_t *mig_guestinfo_buf;
+channel_control_t *mig_chans;
+bucket_control_t *mig_buckets;
 #ifdef VMPORT_RPC_DEBUG
 unsigned int end;
 unsigned int last;
@@ -1168,6 +1176,247 @@ static Property vmport_rpc_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static const VMStateDescription vmstate_vmport_rpc_chan = {
+.name = vmport_rpc/chan,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField [])
+{
+VMSTATE_UINT64(active_time, channel_control_t),
+VMSTATE_UINT32(chan_id, channel_control_t),
+VMSTATE_UINT32(cookie, channel_control_t),
+VMSTATE_UINT32(proto_num, channel_control_t),
+VMSTATE_UINT16(send_len, channel_control_t),
+VMSTATE_UINT16(send_idx, channel_control_t),
+VMSTATE_UINT16(send_buf_max, channel_control_t),
+VMSTATE_UINT8(recv_read, channel_control_t),
+VMSTATE_UINT8(recv_write, channel_control_t),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static const VMStateDescription vmstate_vmport_rpc_bucket = {
+.name = vmport_rpc/bucket,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField [])
+{
+VMSTATE_UINT16(recv_len, bucket_control_t),
+VMSTATE_UINT16(recv_idx, bucket_control_t),
+VMSTATE_UINT16(recv_buf_max, bucket_control_t),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void vmport_rpc_size_mig_guestinfo(gpointer key, gpointer value,
+  gpointer opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int key_len = strlen(key) + 1;
+guestinfo_t *gi = value;
+
+s-mig_guestinfo_size += 1 + key_len + 4 + gi-val_max;
+}
+
+static void vmport_rpc_fill_mig_guestinfo(gpointer key, gpointer value,
+  gpointer opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int key_len = strlen(key) + 1;
+guestinfo_t *gi = value;
+
+assert(gi-val_len = gi-val_max);
+trace_vmport_rpc_fill_mig_guestinfo(key_len, key_len, key, gi-val_len,
+gi-val_len, gi-val_data);
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = key_len;
+memcpy(s-mig_guestinfo_buf + s-mig_guestinfo_off, key, key_len);
+s-mig_guestinfo_off += key_len;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_len  8;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_len;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_max  8;
+s-mig_guestinfo_buf[s-mig_guestinfo_off++] = gi-val_max;
+memcpy(s-mig_guestinfo_buf + s-mig_guestinfo_off, gi-val_data,
+   gi-val_max);
+s-mig_guestinfo_off += gi-val_max;
+}
+
+static int vmport_rpc_pre_load(void *opaque)
+{
+VMPortRpcState *s = opaque;
+
+g_free(s-mig_guestinfo_buf);
+s-mig_guestinfo_buf = NULL;
+s-mig_guestinfo_size = 0;
+s-mig_guestinfo_off = 0;
+g_free(s-mig_chans);
+s-mig_chans = NULL;
+s-mig_chan_num = 0;
+g_free(s-mig_buckets);
+s-mig_buckets = NULL;
+s-mig_bucket_num = 0;
+
+return 0;
+}
+
+static void vmport_rpc_pre_save(void *opaque)
+{
+VMPortRpcState *s = opaque;
+unsigned int i;
+unsigned int mig_chan_idx = 0;
+unsigned int mig_bucket_idx = 0;
+
+(void)vmport_rpc_pre_load(opaque);
+for (i = 0; i  GUESTMSG_MAX_CHANNEL; ++i) {
+channel_t *c = s-chans[i];
+
+if (c-ctl.proto_num) {
+unsigned int j;
+
+s-mig_chan_num++;
+for (j = 0; j  MAX_BKTS; ++j) {
+bucket_t *b = c-recv_bkt[j];
+
+s-mig_bucket_num++;
+s-mig_guestinfo_size +=
+(b-ctl.recv_buf_max + 1) * CHAR_PER_CALL;
+}
+s-mig_guestinfo_size += (c-ctl.send_buf_max + 1) * CHAR_PER_CALL;
+}
+}
+g_hash_table_foreach(s-guestinfo, vmport_rpc_size_mig_guestinfo, s);
+s-mig_guestinfo_size++;
+s-mig_guestinfo_buf = g_malloc(s-mig_guestinfo_size);
+s-mig_chans = g_malloc(s-mig_chan_num * sizeof(channel_control_t));
+s-mig_buckets = g_malloc(s-mig_bucket_num * sizeof(bucket_control_t));
+
+for (i = 0; i  GUESTMSG_MAX_CHANNEL; ++i) {
+channel_t *c = s-chans[i];
+
+if (c-ctl.proto_num) {
+unsigned int j

[Qemu-devel] [PATCH v2 7/7] MAINTAINERS: add VMware port

2015-04-27 Thread Don Slutz
Signed-off-by: Don Slutz dsl...@verizon.com
---
 MAINTAINERS | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index d7e9ba2..8672e00 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -754,6 +754,13 @@ S: Maintained
 F: hw/net/vmxnet*
 F: hw/scsi/vmw_pvscsi*
 
+VMware port
+M: Don Slutz dsl...@verizon.com
+S: Maintained
+F: hw/misc/vmport.c
+F: hw/input/vmmouse.c
+F: hw/misc/vmport_rpc.c
+
 Subsystems
 --
 Audio
-- 
1.8.4




  1   2   3   4   5   6   >