Re: [PATCH v3 6/9] kvmvapic: Introduce TPR access optimization for Windows guests

2012-02-16 Thread Avi Kivity
On 02/14/2012 05:13 PM, Jan Kiszka wrote:
 This enables acceleration for MMIO-based TPR registers accesses of
 32-bit Windows guest systems. It is mostly useful with KVM enabled,
 either on older Intel CPUs (without flexpriority feature, can also be
 manually disabled for testing) or any current AMD processor.

 The approach introduced here is derived from the original version of
 qemu-kvm. It was refactored, documented, and extended by support for
 user space APIC emulation, both with and without KVM acceleration. The
 VMState format was kept compatible, so was the ABI to the option ROM
 that implements the guest-side para-virtualized driver service. This
 enables seamless migration from qemu-kvm to upstream or, one day,
 between KVM and TCG mode.


 +printf(patch @%lx\n, (long)ip);

Debug code


-- 
error compiling committee.c: too many arguments to function

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 6/9] kvmvapic: Introduce TPR access optimization for Windows guests

2012-02-14 Thread Jan Kiszka
This enables acceleration for MMIO-based TPR registers accesses of
32-bit Windows guest systems. It is mostly useful with KVM enabled,
either on older Intel CPUs (without flexpriority feature, can also be
manually disabled for testing) or any current AMD processor.

The approach introduced here is derived from the original version of
qemu-kvm. It was refactored, documented, and extended by support for
user space APIC emulation, both with and without KVM acceleration. The
VMState format was kept compatible, so was the ABI to the option ROM
that implements the guest-side para-virtualized driver service. This
enables seamless migration from qemu-kvm to upstream or, one day,
between KVM and TCG mode.

The basic concept goes like this:
 - VAPIC PV interface consisting of I/O port 0x7e and (for KVM in-kernel
   irqchip) a vmcall hypercall is registered
 - VAPIC option ROM is loaded into guest
 - option ROM activates TPR MMIO access reporting via port 0x7e
 - TPR accesses are trapped and patched in the guest to call into option
   ROM instead, VAPIC support is enabled
 - option ROM TPR helpers track state in memory and invoke hypercall to
   poll for pending IRQs if required

Signed-off-by: Jan Kiszka jan.kis...@siemens.com
---
 Makefile.target|3 +-
 hw/apic.c  |  126 -
 hw/apic_common.c   |   64 -
 hw/apic_internal.h |   27 ++
 hw/kvm/apic.c  |   32 ++
 hw/kvmvapic.c  |  803 
 6 files changed, 1041 insertions(+), 14 deletions(-)
 create mode 100644 hw/kvmvapic.c

diff --git a/Makefile.target b/Makefile.target
index 68481a3..ec7eff8 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -230,7 +230,8 @@ obj-y += device-hotplug.o
 
 # Hardware support
 obj-i386-y += mc146818rtc.o pc.o
-obj-i386-y += sga.o apic_common.o apic.o ioapic_common.o ioapic.o piix_pci.o
+obj-i386-y += apic_common.o apic.o kvmvapic.o
+obj-i386-y += sga.o ioapic_common.o ioapic.o piix_pci.o
 obj-i386-y += vmport.o
 obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
diff --git a/hw/apic.c b/hw/apic.c
index 086c544..2ebf3ca 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -35,6 +35,10 @@
 #define MSI_ADDR_DEST_ID_SHIFT 12
 #defineMSI_ADDR_DEST_ID_MASK   0x000
 
+#define SYNC_FROM_VAPIC 0x1
+#define SYNC_TO_VAPIC   0x2
+#define SYNC_ISR_IRR_TO_VAPIC   0x4
+
 static APICCommonState *local_apics[MAX_APICS + 1];
 
 static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode);
@@ -78,6 +82,70 @@ static inline int get_bit(uint32_t *tab, int index)
 return !!(tab[i]  mask);
 }
 
+/* return -1 if no bit is set */
+static int get_highest_priority_int(uint32_t *tab)
+{
+int i;
+for (i = 7; i = 0; i--) {
+if (tab[i] != 0) {
+return i * 32 + fls_bit(tab[i]);
+}
+}
+return -1;
+}
+
+static void apic_sync_vapic(APICCommonState *s, int sync_type)
+{
+VAPICState vapic_state;
+size_t length;
+off_t start;
+int vector;
+
+if (!s-vapic_paddr) {
+return;
+}
+if (sync_type  SYNC_FROM_VAPIC) {
+cpu_physical_memory_rw(s-vapic_paddr, (void *)vapic_state,
+   sizeof(vapic_state), 0);
+s-tpr = vapic_state.tpr;
+}
+if (sync_type  (SYNC_TO_VAPIC | SYNC_ISR_IRR_TO_VAPIC)) {
+start = offsetof(VAPICState, isr);
+length = offsetof(VAPICState, enabled) - offsetof(VAPICState, isr);
+
+if (sync_type  SYNC_TO_VAPIC) {
+assert(qemu_cpu_is_self(s-cpu_env));
+
+vapic_state.tpr = s-tpr;
+vapic_state.enabled = 1;
+start = 0;
+length = sizeof(VAPICState);
+}
+
+vector = get_highest_priority_int(s-isr);
+if (vector  0) {
+vector = 0;
+}
+vapic_state.isr = vector  0xf0;
+
+vapic_state.zero = 0;
+
+vector = get_highest_priority_int(s-irr);
+if (vector  0) {
+vector = 0;
+}
+vapic_state.irr = vector  0xff;
+
+cpu_physical_memory_write_rom(s-vapic_paddr + start,
+  ((void *)vapic_state) + start, length);
+}
+}
+
+static void apic_vapic_base_update(APICCommonState *s)
+{
+apic_sync_vapic(s, SYNC_TO_VAPIC);
+}
+
 static void apic_local_deliver(APICCommonState *s, int vector)
 {
 uint32_t lvt = s-lvt[vector];
@@ -239,20 +307,17 @@ static void apic_set_base(APICCommonState *s, uint64_t 
val)
 
 static void apic_set_tpr(APICCommonState *s, uint8_t val)
 {
-s-tpr = (val  0x0f)  4;
-apic_update_irq(s);
+/* Updates from cr8 are ignored while the VAPIC is active */
+if (!s-vapic_paddr) {
+s-tpr = val  4;
+apic_update_irq(s);
+}
 }
 
-/* return -1 if no bit is set */
-static int get_highest_priority_int(uint32_t *tab)
+static uint8_t apic_get_tpr(APICCommonState *s)
 {
-int i;
-for(i