]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
xen/pvh: Extend vcpu_guest_context, p2m, event, and XenBus.
authorMukesh Rathor <mukesh.rathor@oracle.com>
Mon, 22 Oct 2012 15:37:57 +0000 (11:37 -0400)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Sat, 1 Dec 2012 13:45:30 +0000 (08:45 -0500)
Make gdt_frames[]/gdt_ents into a union with {gdtaddr, gdtsz},
as PVH only needs to send down gdtaddr and gdtsz in the
vcpu_guest_context structure..

For interrupts, PVH uses native_irq_ops so we can skip most of the
PV ones. In the future we can support the pirq_eoi_map..
Also VCPU hotplug is currently not available for PVH.

For events (and IRQs) we follow what PVHVM does - so use callback
vector.  Lastly, for XenBus we use the same logic that is used in
the PVHVM case.

Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Mukesh Rathor <mukesh.rathor@oracle.com>
[v2: Rebased it]
[v3: Move 64-bit ifdef and based on Stefan add extra comments.]
[v4: Rebased it once more]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
arch/x86/include/asm/xen/interface.h
arch/x86/xen/irq.c
arch/x86/xen/p2m.c
arch/x86/xen/smp.c
drivers/xen/cpu_hotplug.c
drivers/xen/events.c
drivers/xen/xenbus/xenbus_client.c

index fd9cb7695b5f444266abebafe6c3fcfa59e2d66b..20e738a907632a465e69b519a8b9fe3abd5e29dd 100644 (file)
@@ -145,7 +145,16 @@ struct vcpu_guest_context {
     struct cpu_user_regs user_regs;         /* User-level CPU registers     */
     struct trap_info trap_ctxt[256];        /* Virtual IDT                  */
     unsigned long ldt_base, ldt_ents;       /* LDT (linear address, # ents) */
-    unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
+    union {
+       struct {
+               /* PV: GDT (machine frames, # ents).*/
+               unsigned long gdt_frames[16], gdt_ents;
+       } pv;
+       struct {
+               /* PVH: GDTR addr and size */
+               unsigned long gdtaddr, gdtsz;
+       } pvh;
+    } u;
     unsigned long kernel_ss, kernel_sp;     /* Virtual TSS (only SS1/SP1)   */
     /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
     unsigned long ctrlreg[8];               /* CR0-CR7 (control registers)  */
index 01a4dc015ae1e37206469df5ea45b3437da19cad..fcbe56acd88c063af110b5a9112be4a7f502e905 100644 (file)
@@ -5,6 +5,7 @@
 #include <xen/interface/xen.h>
 #include <xen/interface/sched.h>
 #include <xen/interface/vcpu.h>
+#include <xen/features.h>
 #include <xen/events.h>
 
 #include <asm/xen/hypercall.h>
@@ -129,6 +130,8 @@ static const struct pv_irq_ops xen_irq_ops __initconst = {
 
 void __init xen_init_irq_ops(void)
 {
-       pv_irq_ops = xen_irq_ops;
+       /* For PVH we use default pv_irq_ops settings */
+       if (!xen_feature(XENFEAT_hvm_callback_vector))
+               pv_irq_ops = xen_irq_ops;
        x86_init.irqs.intr_init = xen_init_IRQ;
 }
index 95fb2aa5927efc4678eccd8a51d91044b4dd9adb..ea553c864ff3f46d6fd5f6c2c075c34d283c803f 100644 (file)
@@ -798,7 +798,7 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
        unsigned topidx, mididx, idx;
 
-       if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
+       if (xen_feature(XENFEAT_auto_translated_physmap)) {
                BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
                return true;
        }
index 6947c4ef978e5569a1ad34e4cc85656ba57fba2a..448f737c64257d1e2f0813ea9280e652f1cf3988 100644 (file)
@@ -68,9 +68,11 @@ static void __cpuinit cpu_bringup(void)
        touch_softlockup_watchdog();
        preempt_disable();
 
-       xen_enable_sysenter();
-       xen_enable_syscall();
-
+       /* PVH runs in ring 0 and allows us to do native syscalls. Yay! */
+       if (!xen_feature(XENFEAT_supervisor_mode_kernel)) {
+               xen_enable_sysenter();
+               xen_enable_syscall();
+       }
        cpu = smp_processor_id();
        smp_store_cpu_info(cpu);
        cpu_data(cpu).x86_max_cores = 1;
@@ -230,10 +232,11 @@ static void __init xen_smp_prepare_boot_cpu(void)
        BUG_ON(smp_processor_id() != 0);
        native_smp_prepare_boot_cpu();
 
-       /* We've switched to the "real" per-cpu gdt, so make sure the
-          old memory can be recycled */
-       make_lowmem_page_readwrite(xen_initial_gdt);
-
+       if (!xen_feature(XENFEAT_writable_page_tables)) {
+               /* We've switched to the "real" per-cpu gdt, so make sure the
+                * old memory can be recycled */
+               make_lowmem_page_readwrite(xen_initial_gdt);
+       }
        xen_filter_cpu_maps();
        xen_setup_vcpu_info_placement();
 }
@@ -311,7 +314,23 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
 
        memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
 
-       {
+       if (xen_feature(XENFEAT_auto_translated_physmap) &&
+           xen_feature(XENFEAT_supervisor_mode_kernel)) {
+               /* Note: PVH is not supported on x86_32. */
+#ifdef CONFIG_X86_64
+               ctxt->user_regs.ds = __KERNEL_DS;
+               ctxt->user_regs.es = 0;
+               ctxt->user_regs.gs = 0;
+
+               /* GUEST_GDTR_BASE and */
+               ctxt->u.pvh.gdtaddr = (unsigned long)gdt;
+               /* GUEST_GDTR_LIMIT in the VMCS. */
+               ctxt->u.pvh.gdtsz = (unsigned long)(GDT_SIZE - 1);
+
+               ctxt->gs_base_user = (unsigned long)
+                                       per_cpu(irq_stack_union.gs_base, cpu);
+#endif
+       } else {
                ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */
                ctxt->user_regs.ds = __USER_DS;
                ctxt->user_regs.es = __USER_DS;
@@ -326,8 +345,8 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
                make_lowmem_page_readonly(gdt);
                make_lowmem_page_readonly(mfn_to_virt(gdt_mfn));
 
-               ctxt->gdt_frames[0] = gdt_mfn;
-               ctxt->gdt_ents      = GDT_ENTRIES;
+               ctxt->u.pv.gdt_frames[0] = gdt_mfn;
+               ctxt->u.pv.gdt_ents      = GDT_ENTRIES;
 
                ctxt->kernel_ss = __KERNEL_DS;
                ctxt->kernel_sp = idle->thread.sp0;
index 4dcfced107f50e41c518405b28747064d62d78bc..de6bcf9353ba552243db58464e27b4fa1668d3a6 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <xen/xen.h>
 #include <xen/xenbus.h>
+#include <xen/features.h>
 
 #include <asm/xen/hypervisor.h>
 #include <asm/cpu.h>
@@ -100,7 +101,8 @@ static int __init setup_vcpu_hotplug_event(void)
        static struct notifier_block xsn_cpu = {
                .notifier_call = setup_cpu_watcher };
 
-       if (!xen_pv_domain())
+       /* PVH TBD/FIXME: future work */
+       if (!xen_pv_domain() || xen_feature(XENFEAT_auto_translated_physmap))
                return -ENODEV;
 
        register_xenstore_notifier(&xsn_cpu);
index 912ac81b6dbff5e2b9f48c2b2662083bf00ce476..51780b6c184b536dad3d24329e4e0befcdff24f7 100644 (file)
@@ -1778,7 +1778,7 @@ int xen_set_callback_via(uint64_t via)
 }
 EXPORT_SYMBOL_GPL(xen_set_callback_via);
 
-#ifdef CONFIG_XEN_PVHVM
+#ifdef CONFIG_X86
 /* Vector callbacks are better than PCI interrupts to receive event
  * channel notifications because we can receive vector callbacks on any
  * vcpu and we don't need PCI support or APIC interactions. */
@@ -1839,6 +1839,13 @@ void __init xen_init_IRQ(void)
                if (xen_initial_domain())
                        pci_xen_initial_domain();
 
+               if (xen_feature(XENFEAT_hvm_callback_vector)) {
+                       xen_callback_vector();
+                       return;
+               }
+
+               /* PVH: TBD/FIXME: debug and fix eio map to work with pvh */
+
                pirq_eoi_map = (void *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
                eoi_gmfn.gmfn = virt_to_mfn(pirq_eoi_map);
                rc = HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn_v2, &eoi_gmfn);
index bcf3ba4a6ec1543a7500ef0de36269dec1ff728d..356461e6cbd2879b2b7c157d71783f05ab1fc68c 100644 (file)
@@ -44,6 +44,7 @@
 #include <xen/grant_table.h>
 #include <xen/xenbus.h>
 #include <xen/xen.h>
+#include <xen/features.h>
 
 #include "xenbus_probe.h"
 
@@ -741,7 +742,7 @@ static const struct xenbus_ring_ops ring_ops_hvm = {
 
 void __init xenbus_ring_ops_init(void)
 {
-       if (xen_pv_domain())
+       if (xen_pv_domain() && !xen_feature(XENFEAT_auto_translated_physmap))
                ring_ops = &ring_ops_pv;
        else
                ring_ops = &ring_ops_hvm;