From 04b181575e74610639514c373467b8501e17d6ad Mon Sep 17 00:00:00 2001 From: Mukesh Rathor Date: Wed, 17 Oct 2012 10:26:15 -0700 Subject: xen/pvh: Support ParaVirtualized Hardware extensions. PVH allows PV linux guest to utilize hardware extended capabilities, such as running MMU updates in a HVM container. This patch allows it to be configured and enabled. Also, basic header file changes to add new subcalls to physmap hypercall. Lastly, mfn_to_local_pfn must return mfn for paging mode translate (since we let the hypervisor - or CPU - do them for us). Acked-by: Stefano Stabellini Signed-off-by: Mukesh Rathor Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/include/asm/xen/page.h | 3 +++ arch/x86/xen/Kconfig | 10 ++++++++++ arch/x86/xen/xen-head.S | 11 ++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) (limited to 'arch/x86') diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index 6aef9fbc09b7..3143a8a300ed 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h @@ -159,6 +159,9 @@ static inline xpaddr_t machine_to_phys(xmaddr_t machine) static inline unsigned long mfn_to_local_pfn(unsigned long mfn) { unsigned long pfn = mfn_to_pfn(mfn); + + if (xen_feature(XENFEAT_auto_translated_physmap)) + return mfn; if (get_phys_to_machine(pfn) != mfn) return -1; /* force !pfn_valid() */ return pfn; diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig index 131dacd2748a..93ff4e1833f1 100644 --- a/arch/x86/xen/Kconfig +++ b/arch/x86/xen/Kconfig @@ -51,3 +51,13 @@ config XEN_DEBUG_FS Enable statistics output and various tuning options in debugfs. Enabling this option may incur a significant performance overhead. +config XEN_X86_PVH + bool "Support for running as a PVH guest (EXPERIMENTAL)" + depends on X86_64 && XEN && EXPERIMENTAL + default n + help + This option enables support for running as a PVH guest (PV guest + using hardware extensions) under a suitably capable hypervisor. + This option is EXPERIMENTAL because the hypervisor interfaces + which it uses is not yet considered stable therefore backwards and + forwards compatibility is not yet guaranteed. If unsure, say N. diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S index 7faed5869e5b..1a6bca11cc28 100644 --- a/arch/x86/xen/xen-head.S +++ b/arch/x86/xen/xen-head.S @@ -13,6 +13,15 @@ #include #include +#ifdef CONFIG_XEN_X86_PVH +#define FEATURES_PVH "|writable_descriptor_tables" \ + "|auto_translated_physmap" \ + "|supervisor_mode_kernel" \ + "|hvm_callback_vector" +#else +#define FEATURES_PVH /* Not supported */ +#endif + __INIT ENTRY(startup_xen) cld @@ -95,7 +104,7 @@ NEXT_HYPERCALL(arch_6) #endif ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, _ASM_PTR startup_xen) ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page) - ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .asciz "!writable_page_tables|pae_pgdir_above_4gb") + ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .asciz "!writable_page_tables|pae_pgdir_above_4gb"FEATURES_PVH) ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz "yes") ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic") ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, -- cgit v1.2.3 From 23b0133ec3f56694af06100296c3032b046a6894 Mon Sep 17 00:00:00 2001 From: Mukesh Rathor Date: Mon, 22 Oct 2012 11:37:57 -0400 Subject: xen/pvh: Extend vcpu_guest_context, p2m, event, and XenBus. 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 Signed-off-by: Mukesh Rathor [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 --- arch/x86/include/asm/xen/interface.h | 11 +++++++++- arch/x86/xen/irq.c | 5 ++++- arch/x86/xen/p2m.c | 2 +- arch/x86/xen/smp.c | 39 +++++++++++++++++++++++++++--------- drivers/xen/cpu_hotplug.c | 4 +++- drivers/xen/events.c | 9 ++++++++- drivers/xen/xenbus/xenbus_client.c | 3 ++- 7 files changed, 57 insertions(+), 16 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h index fd9cb7695b5f..20e738a90763 100644 --- a/arch/x86/include/asm/xen/interface.h +++ b/arch/x86/include/asm/xen/interface.h @@ -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) */ diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c index 01a4dc015ae1..fcbe56acd88c 100644 --- a/arch/x86/xen/irq.c +++ b/arch/x86/xen/irq.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -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; } diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 95fb2aa5927e..ea553c864ff3 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -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; } diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 09ea61d2e02f..222d737b4e06 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -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; diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c index 084041d42c9a..b0b87dd145f6 100644 --- a/drivers/xen/cpu_hotplug.c +++ b/drivers/xen/cpu_hotplug.c @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -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); diff --git a/drivers/xen/events.c b/drivers/xen/events.c index d17aa41a9041..9bc87b4b2f38 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -1797,7 +1797,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. */ @@ -1859,6 +1859,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); diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index 61786be9138b..4d9bb0a515b5 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "xenbus_probe.h" @@ -742,7 +743,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; -- cgit v1.2.3 From 87546f0e5827741c0223c99153e58f4be1ae1b59 Mon Sep 17 00:00:00 2001 From: Mukesh Rathor Date: Wed, 17 Oct 2012 13:37:49 -0700 Subject: xen/pvh: Implement MMU changes for PVH. .. which are surprinsingly small compared to the amount for PV. First the set/clear mmio pte function make a hypercall to update the P2M in Xen with 1:1 mapping. Since PVH uses mostly native mmu ops, we leave the generic (native_*) for the majority and just overwrite the baremetal with the ones we need. Two local functions are introduced to add to Xen physmap for Xen remap interface. Xen unmap interface is introduced so that the privcmd PTe entries can be cleared in Xen P2M table. ijc -- rebase on top of ARM privcmd changes rather than vice versa, xen_remap_domain_mfn_range (and unmap) split into a separate patch earlier in the series. Signed-off-by: Mukesh Rathor Signed-off-by: Ian Campbell [v1: Rebase on x86, mm, Xen: Remove mapping_pagetable_reserve()] Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/mmu.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++-- arch/x86/xen/mmu.h | 2 + 2 files changed, 144 insertions(+), 5 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index e8e34938c57d..e78763a835b1 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -74,6 +74,7 @@ #include #include #include +#include #include "multicalls.h" #include "mmu.h" @@ -332,6 +333,20 @@ static void xen_set_pte(pte_t *ptep, pte_t pteval) __xen_set_pte(ptep, pteval); } +void xen_set_clr_mmio_pvh_pte(unsigned long pfn, unsigned long mfn, + int nr_mfns, int add_mapping) +{ + struct physdev_map_iomem iomem; + + iomem.first_gfn = pfn; + iomem.first_mfn = mfn; + iomem.nr_mfns = nr_mfns; + iomem.add_mapping = add_mapping; + + if (HYPERVISOR_physdev_op(PHYSDEVOP_map_iomem, &iomem)) + BUG(); +} + static void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval) { @@ -1207,6 +1222,8 @@ static void __init xen_pagetable_init(void) #endif paging_init(); xen_setup_shared_info(); + if (xen_feature(XENFEAT_auto_translated_physmap)) + return; #ifdef CONFIG_X86_64 if (!xen_feature(XENFEAT_auto_translated_physmap)) { unsigned long new_mfn_list; @@ -1558,6 +1575,10 @@ static void __init xen_set_pte_init(pte_t *ptep, pte_t pte) static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) { struct mmuext_op op; + + if (xen_feature(XENFEAT_writable_page_tables)) + return; + op.cmd = cmd; op.arg1.mfn = pfn_to_mfn(pfn); if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) @@ -1755,6 +1776,10 @@ static void set_page_prot(void *addr, pgprot_t prot) unsigned long pfn = __pa(addr) >> PAGE_SHIFT; pte_t pte = pfn_pte(pfn, prot); + /* recall for PVH, page tables are native. */ + if (xen_feature(XENFEAT_auto_translated_physmap)) + return; + if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0)) BUG(); } @@ -1832,6 +1857,9 @@ static void convert_pfn_mfn(void *v) pte_t *pte = v; int i; + if (xen_feature(XENFEAT_auto_translated_physmap)) + return; + /* All levels are converted the same way, so just treat them as ptes. */ for (i = 0; i < PTRS_PER_PTE; i++) @@ -1851,6 +1879,7 @@ static void __init check_pt_base(unsigned long *pt_base, unsigned long *pt_end, (*pt_end)--; } } + /* * Set up the initial kernel pagetable. * @@ -1861,6 +1890,7 @@ static void __init check_pt_base(unsigned long *pt_base, unsigned long *pt_end, * but that's enough to get __va working. We need to fill in the rest * of the physical mapping once some sort of allocator has been set * up. + * NOTE: for PVH, the page tables are native. */ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) { @@ -1938,10 +1968,13 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) * structure to attach it to, so make sure we just set kernel * pgd. */ - xen_mc_batch(); - __xen_write_cr3(true, __pa(init_level4_pgt)); - xen_mc_issue(PARAVIRT_LAZY_CPU); - + if (xen_feature(XENFEAT_writable_page_tables)) { + native_write_cr3(__pa(init_level4_pgt)); + } else { + xen_mc_batch(); + __xen_write_cr3(true, __pa(init_level4_pgt)); + xen_mc_issue(PARAVIRT_LAZY_CPU); + } /* We can't that easily rip out L3 and L2, as the Xen pagetables are * set out this way: [L4], [L1], [L2], [L3], [L1], [L1] ... for * the initial domain. For guests using the toolstack, they are in: @@ -2205,6 +2238,11 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = { void __init xen_init_mmu_ops(void) { x86_init.paging.pagetable_init = xen_pagetable_init; + + if (xen_feature(XENFEAT_auto_translated_physmap)) { + pv_mmu_ops.flush_tlb_others = xen_flush_tlb_others; + return; + } pv_mmu_ops = xen_mmu_ops; memset(dummy_mapping, 0xff, PAGE_SIZE); @@ -2480,6 +2518,89 @@ void __init xen_hvm_init_mmu_ops(void) } #endif +/* Map foreign gmfn, fgmfn, to local pfn, lpfn. This for the user space + * creating new guest on PVH dom0 and needs to map domU pages. + */ +static int pvh_add_to_xen_p2m(unsigned long lpfn, unsigned long fgmfn, + unsigned int domid) +{ + int rc; + struct xen_add_to_physmap xatp = { .foreign_domid = domid }; + + xatp.gpfn = lpfn; + xatp.idx = fgmfn; + xatp.domid = DOMID_SELF; + xatp.space = XENMAPSPACE_gmfn_foreign; + rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp); + if (rc) + pr_warn("d0: Failed to map pfn (0x%lx) to mfn (0x%lx) rc:%d\n", + lpfn, fgmfn, rc); + return rc; +} + +static int pvh_rem_xen_p2m(unsigned long spfn, int count) +{ + struct xen_remove_from_physmap xrp; + int i, rc; + + for (i = 0; i < count; i++) { + xrp.domid = DOMID_SELF; + xrp.gpfn = spfn+i; + rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp); + if (rc) { + pr_warn("Failed to unmap pfn:%lx rc:%d done:%d\n", + spfn+i, rc, i); + return 1; + } + } + return 0; +} + +struct pvh_remap_data { + unsigned long fgmfn; /* foreign domain's gmfn */ + pgprot_t prot; + domid_t domid; + int index; + struct page **pages; +}; + +static int pvh_map_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr, + void *data) +{ + int rc; + struct pvh_remap_data *remap = data; + unsigned long pfn = page_to_pfn(remap->pages[remap->index++]); + pte_t pteval = pte_mkspecial(pfn_pte(pfn, remap->prot)); + + rc = pvh_add_to_xen_p2m(pfn, remap->fgmfn, remap->domid); + if (rc) + return rc; + native_set_pte(ptep, pteval); + + return 0; +} + +static int pvh_remap_gmfn_range(struct vm_area_struct *vma, + unsigned long addr, unsigned long mfn, int nr, + pgprot_t prot, unsigned domid, + struct page **pages) +{ + int err; + struct pvh_remap_data pvhdata; + + BUG_ON(!pages); + + pvhdata.fgmfn = mfn; + pvhdata.prot = prot; + pvhdata.domid = domid; + pvhdata.index = 0; + pvhdata.pages = pages; + err = apply_to_page_range(vma->vm_mm, addr, nr << PAGE_SHIFT, + pvh_map_pte_fn, &pvhdata); + flush_tlb_all(); + return err; +} + #define REMAP_BATCH_SIZE 16 struct remap_data { @@ -2521,6 +2642,10 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO))); + if (xen_feature(XENFEAT_auto_translated_physmap)) { + /* We need to update the local page tables and the xen HAP */ + return pvh_remap_gmfn_range(vma, addr, mfn, nr, prot, domid, pages); + } rmd.mfn = mfn; rmd.prot = prot; @@ -2558,6 +2683,18 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma, if (!pages || !xen_feature(XENFEAT_auto_translated_physmap)) return 0; - return -EINVAL; + while (numpgs--) { + + /* the mmu has already cleaned up the process mmu resources at + * this point (lookup_address will return NULL). */ + unsigned long pfn = page_to_pfn(pages[numpgs]); + + pvh_rem_xen_p2m(pfn, 1); + } + /* We don't need to flush tlbs because as part of pvh_rem_xen_p2m(), + * the hypervisor will do tlb flushes after removing the p2m entries + * from the EPT/NPT */ + + return 0; } EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range); diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h index 73809bb951b4..6d0bb56a6e82 100644 --- a/arch/x86/xen/mmu.h +++ b/arch/x86/xen/mmu.h @@ -23,4 +23,6 @@ unsigned long xen_read_cr2_direct(void); extern void xen_init_mmu_ops(void); extern void xen_hvm_init_mmu_ops(void); +extern void xen_set_clr_mmio_pvh_pte(unsigned long pfn, unsigned long mfn, + int nr_mfns, int add_mapping); #endif /* _XEN_MMU_H */ -- cgit v1.2.3 From 7335622a391476fcbdf0acbce093ecaeb2c23d96 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 4 Mar 2013 10:30:32 -0500 Subject: xen/pvh: bootup and setup (E820) related changes. In the bootup code for PVH we can trap cpuid via vmexit, so don't need to use emulated prefix call. We also check for vector callback early on, as it is a required feature. PVH also runs at default kernel IOPL. In setup.c which deals with E820, in xen_add_extra_mem() we can skip updating P2M as it's managed by Xen. PVH maps the entire IO space, but only RAM pages need to be repopulated. Finally, pure PV settings are moved to a separate function that are only called for pure PV, ie, pv with pvmmu. Signed-off-by: Mukesh Rathor Signed-off-by: Konrad Rzeszutek Wilk [ ijc -- rebase onto xen PVonHVM: use E820_Reserved area for shared_info ] [v2: Rebase on v3.9-rc1 with MMIO/Kexec reverted] --- arch/x86/xen/enlighten.c | 77 ++++++++++++++++++++++++++++++++++++------------ arch/x86/xen/setup.c | 64 ++++++++++++++++++++++++++++++++-------- 2 files changed, 110 insertions(+), 31 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index c8e1c7b95c3b..83c744e8b8b9 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -106,6 +107,9 @@ RESERVE_BRK(shared_info_page_brk, PAGE_SIZE); __read_mostly int xen_have_vector_callback; EXPORT_SYMBOL_GPL(xen_have_vector_callback); +#define xen_pvh_domain() (xen_pv_domain() && \ + xen_feature(XENFEAT_auto_translated_physmap) && \ + xen_have_vector_callback) /* * Point at some empty memory to start with. We map the real shared_info * page as soon as fixmap is up and running. @@ -219,8 +223,9 @@ static void __init xen_banner(void) struct xen_extraversion extra; HYPERVISOR_xen_version(XENVER_extraversion, &extra); - printk(KERN_INFO "Booting paravirtualized kernel on %s\n", - pv_info.name); + pr_info("Booting paravirtualized kernel %son %s\n", + xen_feature(XENFEAT_auto_translated_physmap) ? + "with PVH extensions " : "", pv_info.name); printk(KERN_INFO "Xen version: %d.%d%s%s\n", version >> 16, version & 0xffff, extra.extraversion, xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); @@ -288,12 +293,15 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx, break; } - asm(XEN_EMULATE_PREFIX "cpuid" - : "=a" (*ax), - "=b" (*bx), - "=c" (*cx), - "=d" (*dx) - : "0" (*ax), "2" (*cx)); + if (xen_pvh_domain()) + native_cpuid(ax, bx, cx, dx); + else + asm(XEN_EMULATE_PREFIX "cpuid" + : "=a" (*ax), + "=b" (*bx), + "=c" (*cx), + "=d" (*dx) + : "0" (*ax), "2" (*cx)); *bx &= maskebx; *cx &= maskecx; @@ -1076,6 +1084,10 @@ void xen_setup_shared_info(void) HYPERVISOR_shared_info = (struct shared_info *)__va(xen_start_info->shared_info); + /* PVH TBD/FIXME: vcpu info placement in phase 2 */ + if (xen_pvh_domain()) + return; + #ifndef CONFIG_SMP /* In UP this is as good a place as any to set up shared info */ xen_setup_vcpu_info_placement(); @@ -1313,6 +1325,11 @@ static const struct machine_ops xen_machine_ops __initconst = { */ static void __init xen_setup_stackprotector(void) { + /* PVH TBD/FIXME: investigate setup_stack_canary_segment */ + if (xen_feature(XENFEAT_auto_translated_physmap)) { + switch_to_new_gdt(0); + return; + } pv_cpu_ops.write_gdt_entry = xen_write_gdt_entry_boot; pv_cpu_ops.load_gdt = xen_load_gdt_boot; @@ -1323,6 +1340,19 @@ static void __init xen_setup_stackprotector(void) pv_cpu_ops.load_gdt = xen_load_gdt; } +static void __init xen_pvh_early_guest_init(void) +{ + if (xen_feature(XENFEAT_hvm_callback_vector)) + xen_have_vector_callback = 1; + +#ifdef CONFIG_X86_32 + if (xen_feature(XENFEAT_auto_translated_physmap)) { + xen_raw_printk("ERROR: 32bit PVH guests are not supported\n"); + BUG(); + } +#endif +} + /* First C function to be called on Xen boot */ asmlinkage void __init xen_start_kernel(void) { @@ -1334,13 +1364,18 @@ asmlinkage void __init xen_start_kernel(void) xen_domain_type = XEN_PV_DOMAIN; + xen_setup_features(); + xen_pvh_early_guest_init(); xen_setup_machphys_mapping(); /* Install Xen paravirt ops */ pv_info = xen_info; pv_init_ops = xen_init_ops; - pv_cpu_ops = xen_cpu_ops; pv_apic_ops = xen_apic_ops; + if (xen_pvh_domain()) + pv_cpu_ops.cpuid = xen_cpuid; + else + pv_cpu_ops = xen_cpu_ops; x86_init.resources.memory_setup = xen_memory_setup; x86_init.oem.arch_setup = xen_arch_setup; @@ -1372,8 +1407,6 @@ asmlinkage void __init xen_start_kernel(void) /* Work out if we support NX */ x86_configure_nx(); - xen_setup_features(); - /* Get mfn list */ if (!xen_feature(XENFEAT_auto_translated_physmap)) xen_build_dynamic_phys_to_machine(); @@ -1451,14 +1484,18 @@ asmlinkage void __init xen_start_kernel(void) /* set the limit of our address space */ xen_reserve_top(); - /* We used to do this in xen_arch_setup, but that is too late on AMD - * were early_cpu_init (run before ->arch_setup()) calls early_amd_init - * which pokes 0xcf8 port. - */ - set_iopl.iopl = 1; - rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl); - if (rc != 0) - xen_raw_printk("physdev_op failed %d\n", rc); + /* PVH: runs at default kernel iopl of 0 */ + if (!xen_pvh_domain()) { + /* + * We used to do this in xen_arch_setup, but that is too late + * on AMD were early_cpu_init (run before ->arch_setup()) calls + * early_amd_init which pokes 0xcf8 port. + */ + set_iopl.iopl = 1; + rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl); + if (rc != 0) + xen_raw_printk("physdev_op failed %d\n", rc); + } #ifdef CONFIG_X86_32 /* set up basic CPUID stuff */ @@ -1526,6 +1563,8 @@ asmlinkage void __init xen_start_kernel(void) } void __ref xen_hvm_init_shared_info(void) +/* Use a pfn in RAM, may move to MMIO before kexec. + * This function also called for PVH dom0 */ { int cpu; struct xen_add_to_physmap xatp; diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 94eac5c85cdc..d2cf86406a59 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -27,6 +27,7 @@ #include #include #include +#include "mmu.h" #include "xen-ops.h" #include "vdso.h" @@ -78,6 +79,9 @@ static void __init xen_add_extra_mem(u64 start, u64 size) memblock_reserve(start, size); + if (xen_feature(XENFEAT_auto_translated_physmap)) + return; + xen_max_p2m_pfn = PFN_DOWN(start + size); for (pfn = PFN_DOWN(start); pfn < xen_max_p2m_pfn; pfn++) { unsigned long mfn = pfn_to_mfn(pfn); @@ -100,6 +104,7 @@ static unsigned long __init xen_do_chunk(unsigned long start, .domid = DOMID_SELF }; unsigned long len = 0; + int xlated_phys = xen_feature(XENFEAT_auto_translated_physmap); unsigned long pfn; int ret; @@ -113,7 +118,7 @@ static unsigned long __init xen_do_chunk(unsigned long start, continue; frame = mfn; } else { - if (mfn != INVALID_P2M_ENTRY) + if (!xlated_phys && mfn != INVALID_P2M_ENTRY) continue; frame = pfn; } @@ -230,6 +235,27 @@ static void __init xen_set_identity_and_release_chunk( *identity += set_phys_range_identity(start_pfn, end_pfn); } +/* For PVH, the pfns [0..MAX] are mapped to mfn's in the EPT/NPT. The mfns + * are released as part of this 1:1 mapping hypercall back to the dom heap. + * Also, we map the entire IO space, ie, beyond max_pfn_mapped. + */ +static void __init xen_pvh_identity_map_chunk(unsigned long start_pfn, + unsigned long end_pfn, unsigned long *released, + unsigned long *identity, unsigned long max_pfn) +{ + unsigned long pfn; + int numpfns = 1, add_mapping = 1; + + for (pfn = start_pfn; pfn < end_pfn; pfn++) + xen_set_clr_mmio_pvh_pte(pfn, pfn, numpfns, add_mapping); + + if (start_pfn <= max_pfn) { + unsigned long end = min(max_pfn_mapped, end_pfn); + *released += end - start_pfn; + } + *identity += end_pfn - start_pfn; +} + static unsigned long __init xen_set_identity_and_release( const struct e820entry *list, size_t map_size, unsigned long nr_pages) { @@ -238,6 +264,7 @@ static unsigned long __init xen_set_identity_and_release( unsigned long identity = 0; const struct e820entry *entry; int i; + int xlated_phys = xen_feature(XENFEAT_auto_translated_physmap); /* * Combine non-RAM regions and gaps until a RAM region (or the @@ -259,11 +286,17 @@ static unsigned long __init xen_set_identity_and_release( if (entry->type == E820_RAM) end_pfn = PFN_UP(entry->addr); - if (start_pfn < end_pfn) - xen_set_identity_and_release_chunk( - start_pfn, end_pfn, nr_pages, - &released, &identity); - + if (start_pfn < end_pfn) { + if (xlated_phys) { + xen_pvh_identity_map_chunk(start_pfn, + end_pfn, &released, &identity, + nr_pages); + } else { + xen_set_identity_and_release_chunk( + start_pfn, end_pfn, nr_pages, + &released, &identity); + } + } start = end; } } @@ -526,16 +559,14 @@ void __cpuinit xen_enable_syscall(void) #endif /* CONFIG_X86_64 */ } -void __init xen_arch_setup(void) +/* Non auto translated PV domain, ie, it's not PVH. */ +static __init void xen_pvmmu_arch_setup(void) { - xen_panic_handler_init(); - HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments); HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables); - if (!xen_feature(XENFEAT_auto_translated_physmap)) - HYPERVISOR_vm_assist(VMASST_CMD_enable, - VMASST_TYPE_pae_extended_cr3); + HYPERVISOR_vm_assist(VMASST_CMD_enable, + VMASST_TYPE_pae_extended_cr3); if (register_callback(CALLBACKTYPE_event, xen_hypervisor_callback) || register_callback(CALLBACKTYPE_failsafe, xen_failsafe_callback)) @@ -543,6 +574,15 @@ void __init xen_arch_setup(void) xen_enable_sysenter(); xen_enable_syscall(); +} + +/* This function not called for HVM domain */ +void __init xen_arch_setup(void) +{ + xen_panic_handler_init(); + + if (!xen_feature(XENFEAT_auto_translated_physmap)) + xen_pvmmu_arch_setup(); #ifdef CONFIG_ACPI if (!(xen_start_info->flags & SIF_INITDOMAIN)) { -- cgit v1.2.3 From 3df23796f492aec9a72b5b4b3bb4e3602563b03a Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 17 Oct 2012 09:51:25 +0100 Subject: xen: x86 pvh: use XENMEM_add_to_physmap_range for foreign gmfn mappings Squeezing the necessary fields into the existing XENMEM_add_to_physmap interface was proving to be a bit tricky so we have decided to go with a new interface upstream (the XENMAPSPACE_gmfn_foreign interface using XENMEM_add_to_physmap was never committed anywhere). This interface also allows for batching which was impossible to support at the same time as foreign mfns in the old interface. This reverts the relevant parts of "PVH: basic and header changes, elfnote changes, ..." and followups and trivially converts pvh_add_to_xen_p2m over. Acked-by: Mukesh Rathor Acked-by: Stefano Stabellini Signed-off-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/mmu.c | 18 ++++++++++++------ include/xen/interface/memory.h | 5 +---- 2 files changed, 13 insertions(+), 10 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index e78763a835b1..6bf7b1d65493 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -2525,13 +2525,19 @@ static int pvh_add_to_xen_p2m(unsigned long lpfn, unsigned long fgmfn, unsigned int domid) { int rc; - struct xen_add_to_physmap xatp = { .foreign_domid = domid }; + struct xen_add_to_physmap_range xatp = { + .domid = DOMID_SELF, + .foreign_domid = domid, + .size = 1, + .space = XENMAPSPACE_gmfn_foreign, + }; + xen_ulong_t idx = fgmfn; + xen_pfn_t gpfn = lpfn; + + set_xen_guest_handle(xatp.idxs, &idx); + set_xen_guest_handle(xatp.gpfns, &gpfn); - xatp.gpfn = lpfn; - xatp.idx = fgmfn; - xatp.domid = DOMID_SELF; - xatp.space = XENMAPSPACE_gmfn_foreign; - rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp); + rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp); if (rc) pr_warn("d0: Failed to map pfn (0x%lx) to mfn (0x%lx) rc:%d\n", lpfn, fgmfn, rc); diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h index a1221646c922..2ecfe4f700d9 100644 --- a/include/xen/interface/memory.h +++ b/include/xen/interface/memory.h @@ -175,10 +175,7 @@ struct xen_add_to_physmap { uint16_t size; /* Source mapping space. */ - uint16_t space; - domid_t foreign_domid; /* IFF XENMAPSPACE_gmfn_foreign */ - -#define XENMAPIDX_grant_table_status 0x80000000 + unsigned int space; /* Index into source mapping space. */ xen_ulong_t idx; -- cgit v1.2.3 From 87b1a6e0e4a9d39110ee12958de12a46a9d12995 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 1 Nov 2012 16:17:59 +0800 Subject: xen/x86: remove duplicated include from enlighten.c Remove duplicated include. dpatch engine is used to auto generate this patch. (https://github.com/weiyj/dpatch) Signed-off-by: Wei Yongjun Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/enlighten.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 83c744e8b8b9..a7ee39f670e9 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From d02699241b446d7871178cd23554c51fe4106d24 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 16 Nov 2012 13:45:25 -0800 Subject: x86/xen: Use __pa_symbol instead of __pa on C visible symbols This change updates a few of the functions to use __pa_symbol when translating C visible symbols instead of __pa. By using __pa_symbol we are able to drop a few extra lines of code as don't have to test to see if the virtual pointer is a part of the kernel text or just standard virtual memory. Cc: Konrad Rzeszutek Wilk Signed-off-by: Alexander Duyck Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/mmu.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 6bf7b1d65493..b09a3f2b1cc4 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1510,7 +1510,8 @@ static int xen_pgd_alloc(struct mm_struct *mm) if (user_pgd != NULL) { user_pgd[pgd_index(VSYSCALL_START)] = - __pgd(__pa(level3_user_vsyscall) | _PAGE_TABLE); + __pgd(__pa_symbol(level3_user_vsyscall) | + _PAGE_TABLE); ret = 0; } @@ -1969,10 +1970,10 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) * pgd. */ if (xen_feature(XENFEAT_writable_page_tables)) { - native_write_cr3(__pa(init_level4_pgt)); + native_write_cr3(__pa_symbol(init_level4_pgt)); } else { xen_mc_batch(); - __xen_write_cr3(true, __pa(init_level4_pgt)); + __xen_write_cr3(true, __pa_symbol(init_level4_pgt)); xen_mc_issue(PARAVIRT_LAZY_CPU); } /* We can't that easily rip out L3 and L2, as the Xen pagetables are @@ -1995,10 +1996,10 @@ static RESERVE_BRK_ARRAY(pmd_t, swapper_kernel_pmd, PTRS_PER_PMD); static void __init xen_write_cr3_init(unsigned long cr3) { - unsigned long pfn = PFN_DOWN(__pa(swapper_pg_dir)); + unsigned long pfn = PFN_DOWN(__pa_symbol(swapper_pg_dir)); - BUG_ON(read_cr3() != __pa(initial_page_table)); - BUG_ON(cr3 != __pa(swapper_pg_dir)); + BUG_ON(read_cr3() != __pa_symbol(initial_page_table)); + BUG_ON(cr3 != __pa_symbol(swapper_pg_dir)); /* * We are switching to swapper_pg_dir for the first time (from @@ -2022,7 +2023,7 @@ static void __init xen_write_cr3_init(unsigned long cr3) pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, pfn); pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, - PFN_DOWN(__pa(initial_page_table))); + PFN_DOWN(__pa_symbol(initial_page_table))); set_page_prot(initial_page_table, PAGE_KERNEL); set_page_prot(initial_kernel_pmd, PAGE_KERNEL); @@ -2047,7 +2048,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) copy_page(initial_page_table, pgd); initial_page_table[KERNEL_PGD_BOUNDARY] = - __pgd(__pa(initial_kernel_pmd) | _PAGE_PRESENT); + __pgd(__pa_symbol(initial_kernel_pmd) | _PAGE_PRESENT); set_page_prot(initial_kernel_pmd, PAGE_KERNEL_RO); set_page_prot(initial_page_table, PAGE_KERNEL_RO); @@ -2056,8 +2057,8 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, - PFN_DOWN(__pa(initial_page_table))); - xen_write_cr3(__pa(initial_page_table)); + PFN_DOWN(__pa_symbol(initial_page_table))); + xen_write_cr3(__pa_symbol(initial_page_table)); memblock_reserve(__pa(xen_start_info->pt_base), xen_start_info->nr_pt_frames * PAGE_SIZE); -- cgit v1.2.3 From 5caed269ea867f36225376a6546411ed7c106226 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 4 Jan 2013 14:04:12 +0000 Subject: xen: implement updated XENMEM_add_to_physmap_range ABI Allows for more fine grained error reporting. Only used by PVH and ARM both of which are marked EXPERIMENTAL precisely because the ABI is not yet stable Signed-off-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/mmu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index b09a3f2b1cc4..6698cf31e1f9 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -2534,14 +2534,16 @@ static int pvh_add_to_xen_p2m(unsigned long lpfn, unsigned long fgmfn, }; xen_ulong_t idx = fgmfn; xen_pfn_t gpfn = lpfn; + int err = 0; set_xen_guest_handle(xatp.idxs, &idx); set_xen_guest_handle(xatp.gpfns, &gpfn); + set_xen_guest_handle(xatp.errs, &err); rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp); - if (rc) - pr_warn("d0: Failed to map pfn (0x%lx) to mfn (0x%lx) rc:%d\n", - lpfn, fgmfn, rc); + if (rc || err) + pr_warn("d0: Failed to map pfn (0x%lx) to mfn (0x%lx) rc:%d:%d\n", + lpfn, fgmfn, rc, err); return rc; } -- cgit v1.2.3 From 916d0d8955b690c043d28e17409e7763c801b6b2 Mon Sep 17 00:00:00 2001 From: Mukesh Rathor Date: Wed, 23 Jan 2013 14:43:47 -0800 Subject: xen/pvh: specify xen features strings cleanly for PVH Use .ascii and .asciz to define xen feature string. Note, the PVH string must be in a single line (not multiple lines with \) to keep the assembler from putting null char after each string before \. Signed-off-by: Mukesh Rathor Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/xen-head.S | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S index 1a6bca11cc28..45226cb9493a 100644 --- a/arch/x86/xen/xen-head.S +++ b/arch/x86/xen/xen-head.S @@ -14,12 +14,11 @@ #include #ifdef CONFIG_XEN_X86_PVH -#define FEATURES_PVH "|writable_descriptor_tables" \ - "|auto_translated_physmap" \ - "|supervisor_mode_kernel" \ - "|hvm_callback_vector" + +#define PVH_FEATURES_STR "|writable_descriptor_tables|auto_translated_physmap|supervisor_mode_kernel|hvm_callback_vector" + #else -#define FEATURES_PVH /* Not supported */ +#define PVH_FEATURES_STR "" #endif __INIT @@ -104,7 +103,7 @@ NEXT_HYPERCALL(arch_6) #endif ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, _ASM_PTR startup_xen) ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page) - ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .asciz "!writable_page_tables|pae_pgdir_above_4gb"FEATURES_PVH) + ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .ascii "!writable_page_tables|pae_pgdir_above_4gb"; .asciz PVH_FEATURES_STR); ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz "yes") ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic") ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, -- cgit v1.2.3 From 929ae465247fd2746e564238c605d9002b80fe91 Mon Sep 17 00:00:00 2001 From: Mukesh Rathor Date: Wed, 30 Jan 2013 14:55:29 -0800 Subject: xen/pvh: remove code to map iomem from guest It was decided during xen patch review that xen map the iomem transparently, so remove xen_set_clr_mmio_pvh_pte() and the sub hypercall PHYSDEVOP_map_iomem. Signed-off-by: Mukesh Rathor [v1: Fixed up the comment] Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/mmu.c | 14 -------------- arch/x86/xen/setup.c | 17 ++++++----------- include/xen/interface/physdev.h | 10 ---------- 3 files changed, 6 insertions(+), 35 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 6698cf31e1f9..31cc1ef4ac4b 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -333,20 +333,6 @@ static void xen_set_pte(pte_t *ptep, pte_t pteval) __xen_set_pte(ptep, pteval); } -void xen_set_clr_mmio_pvh_pte(unsigned long pfn, unsigned long mfn, - int nr_mfns, int add_mapping) -{ - struct physdev_map_iomem iomem; - - iomem.first_gfn = pfn; - iomem.first_mfn = mfn; - iomem.nr_mfns = nr_mfns; - iomem.add_mapping = add_mapping; - - if (HYPERVISOR_physdev_op(PHYSDEVOP_map_iomem, &iomem)) - BUG(); -} - static void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval) { diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index d2cf86406a59..c4874c05774b 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -235,20 +235,15 @@ static void __init xen_set_identity_and_release_chunk( *identity += set_phys_range_identity(start_pfn, end_pfn); } -/* For PVH, the pfns [0..MAX] are mapped to mfn's in the EPT/NPT. The mfns - * are released as part of this 1:1 mapping hypercall back to the dom heap. - * Also, we map the entire IO space, ie, beyond max_pfn_mapped. + +/* + * PVH: xen has already mapped the IO space in the EPT/NPT for us, so we + * just need to adjust the released and identity count. */ -static void __init xen_pvh_identity_map_chunk(unsigned long start_pfn, +static void __init xen_pvh_adjust_stats(unsigned long start_pfn, unsigned long end_pfn, unsigned long *released, unsigned long *identity, unsigned long max_pfn) { - unsigned long pfn; - int numpfns = 1, add_mapping = 1; - - for (pfn = start_pfn; pfn < end_pfn; pfn++) - xen_set_clr_mmio_pvh_pte(pfn, pfn, numpfns, add_mapping); - if (start_pfn <= max_pfn) { unsigned long end = min(max_pfn_mapped, end_pfn); *released += end - start_pfn; @@ -288,7 +283,7 @@ static unsigned long __init xen_set_identity_and_release( if (start_pfn < end_pfn) { if (xlated_phys) { - xen_pvh_identity_map_chunk(start_pfn, + xen_pvh_adjust_stats(start_pfn, end_pfn, &released, &identity, nr_pages); } else { diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h index 83050d32bf46..1844d31f4552 100644 --- a/include/xen/interface/physdev.h +++ b/include/xen/interface/physdev.h @@ -274,16 +274,6 @@ struct physdev_dbgp_op { } u; }; -#define PHYSDEVOP_map_iomem 30 -struct physdev_map_iomem { - /* IN */ - uint64_t first_gfn; - uint64_t first_mfn; - uint32_t nr_mfns; - uint32_t add_mapping; /* 1 == add mapping; 0 == unmap */ - -}; - /* * Notify that some PIRQ-bound event channels have been unmasked. * ** This command is obsolete since interface version 0x00030202 and is ** -- cgit v1.2.3 From 0e0764358c7833a8a2a721c8db6c30c3e7cd3df7 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 28 Feb 2013 13:56:40 -0800 Subject: x86/xen: remove depends on CONFIG_EXPERIMENTAL The CONFIG_EXPERIMENTAL config item has not carried much meaning for a while now and is almost always enabled by default. As agreed during the Linux kernel summit, remove it from any "depends on" lines in Kconfigs. Signed-off-by: Kees Cook Cc: Stefano Stabellini Cc: Mukesh Rathor Cc: Konrad Rzeszutek Wilk Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/Kconfig | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig index 93ff4e1833f1..6c5802fe8b1e 100644 --- a/arch/x86/xen/Kconfig +++ b/arch/x86/xen/Kconfig @@ -52,12 +52,10 @@ config XEN_DEBUG_FS Enabling this option may incur a significant performance overhead. config XEN_X86_PVH - bool "Support for running as a PVH guest (EXPERIMENTAL)" - depends on X86_64 && XEN && EXPERIMENTAL + bool "Support for running as a PVH guest" + depends on X86_64 && XEN default n help This option enables support for running as a PVH guest (PV guest using hardware extensions) under a suitably capable hypervisor. - This option is EXPERIMENTAL because the hypervisor interfaces - which it uses is not yet considered stable therefore backwards and - forwards compatibility is not yet guaranteed. If unsure, say N. + If unsure, say N. -- cgit v1.2.3