diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 615e188..7791d31 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -1,7 +1,7 @@ menu "Kernel hacking" config TRACE_IRQFLAGS_SUPPORT - def_bool y + def_bool n source "lib/Kconfig.debug" diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 91f3e08..bdd7022 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -238,7 +238,8 @@ extern const char * const x86_power_flags[32]; #define cpu_has_fpu boot_cpu_has(X86_FEATURE_FPU) #define cpu_has_vme boot_cpu_has(X86_FEATURE_VME) #define cpu_has_de boot_cpu_has(X86_FEATURE_DE) -#define cpu_has_pse boot_cpu_has(X86_FEATURE_PSE) +#define cpu_has_pse 0 +/* #define cpu_has_pse boot_cpu_has(X86_FEATURE_PSE) */ #define cpu_has_tsc boot_cpu_has(X86_FEATURE_TSC) #define cpu_has_pae boot_cpu_has(X86_FEATURE_PAE) #define cpu_has_pge boot_cpu_has(X86_FEATURE_PGE) diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h index 7a15153..f0bbb51 100644 --- a/arch/x86/include/asm/hypervisor.h +++ b/arch/x86/include/asm/hypervisor.h @@ -49,6 +49,7 @@ extern const struct hypervisor_x86 *x86_hyper; extern const struct hypervisor_x86 x86_hyper_vmware; extern const struct hypervisor_x86 x86_hyper_ms_hyperv; extern const struct hypervisor_x86 x86_hyper_xen_hvm; +extern const struct hypervisor_x86 x86_hyper_xen_hybrid; static inline bool hypervisor_x2apic_available(void) { diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c index 8095f86..5ec8dbb 100644 --- a/arch/x86/kernel/cpu/hypervisor.c +++ b/arch/x86/kernel/cpu/hypervisor.c @@ -37,6 +37,7 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] = #ifdef CONFIG_XEN_PVHVM &x86_hyper_xen_hvm, #endif + &x86_hyper_xen_hybrid, }; const struct hypervisor_x86 *x86_hyper; diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c index bd33620..89bfe86 100644 --- a/arch/x86/pci/direct.c +++ b/arch/x86/pci/direct.c @@ -282,6 +282,9 @@ int __init pci_direct_probe(void) { struct resource *region, *region2; + if (xen_hybrid_domain()) + return 0; + if ((pci_probe & PCI_PROBE_CONF1) == 0) goto type2; region = request_region(0xCF8, 8, "PCI conf1"); diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index e3c6a06..53ceae0 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -110,7 +110,7 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; * * 0: not available, 1: available */ -static int have_vcpu_info_placement = 1; +static int have_vcpu_info_placement = 0; static void clamp_max_cpus(void) { @@ -195,6 +195,13 @@ static void __init xen_banner(void) 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)" : ""); + + if (xen_hybrid_domain()) { + printk(KERN_INFO "MUK: is MUK HYBRID domain...."); + if (xen_feature(XENFEAT_auto_translated_physmap)) + printk(KERN_INFO "with EPT..."); + printk(KERN_INFO "\n"); + } } static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0; @@ -222,8 +229,10 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx, maskebx = 0; break; } - - asm(XEN_EMULATE_PREFIX "cpuid" + if (xen_hybrid_domain()) { + native_cpuid(ax, bx, cx, dx); + } else + asm(XEN_EMULATE_PREFIX "cpuid" : "=a" (*ax), "=b" (*bx), "=c" (*cx), @@ -244,6 +253,7 @@ static __init void xen_init_cpuid_mask(void) ~((1 << X86_FEATURE_MCE) | /* disable MCE */ (1 << X86_FEATURE_MCA) | /* disable MCA */ (1 << X86_FEATURE_MTRR) | /* disable MTRR */ + (1 << X86_FEATURE_PSE) | /* disable 2M pages */ (1 << X86_FEATURE_ACC)); /* thermal monitoring */ if (!xen_initial_domain()) @@ -393,6 +403,10 @@ static void xen_load_gdt(const struct desc_ptr *dtr) make_lowmem_page_readonly(virt); } + if (xen_hybrid_domain()) { + native_load_gdt(dtr); + return; + } if (HYPERVISOR_set_gdt(frames, size / sizeof(struct desc_struct))) BUG(); } @@ -431,6 +445,10 @@ static __init void xen_load_gdt_boot(const struct desc_ptr *dtr) frames[f] = mfn; } + if (xen_hybrid_domain()) { + native_load_gdt(dtr); + return; + } if (HYPERVISOR_set_gdt(frames, size / sizeof(struct desc_struct))) BUG(); } @@ -849,9 +867,11 @@ void xen_setup_shared_info(void) HYPERVISOR_shared_info = (struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP); - } else + } else { HYPERVISOR_shared_info = (struct shared_info *)__va(xen_start_info->shared_info); + return; + } #ifndef CONFIG_SMP /* In UP this is as good a place as any to set up shared info */ @@ -944,6 +964,71 @@ static const struct pv_init_ops xen_init_ops __initdata = { .patch = xen_patch, }; +extern void native_iret(void); +extern void native_irq_enable_sysexit(void); +extern void native_usergs_sysret32(void); +extern void native_usergs_sysret64(void); + +static const struct pv_cpu_ops xen_hybrid_cpu_ops __initdata = { + .cpuid = xen_cpuid, + + .set_debugreg = xen_set_debugreg, + .get_debugreg = xen_get_debugreg, + + .clts = xen_clts, + + .read_cr0 = xen_read_cr0, + .write_cr0 = xen_write_cr0, + + .read_cr4 = native_read_cr4, + .read_cr4_safe = native_read_cr4_safe, + .write_cr4 = native_write_cr4, + + .wbinvd = native_wbinvd, + + .read_msr = native_read_msr_safe, + .write_msr = native_write_msr_safe, + .read_tsc = native_read_tsc, + .read_pmc = native_read_pmc, + + .iret = native_iret, + .irq_enable_sysexit = native_irq_enable_sysexit, +#ifdef CONFIG_X86_64 + .usergs_sysret32 = native_usergs_sysret32, + .usergs_sysret64 = native_usergs_sysret64, +#endif + + .load_tr_desc = native_load_tr_desc, + .set_ldt = native_set_ldt, + .load_gdt = native_load_gdt, + .load_idt = native_load_idt, + .load_tls = native_load_tls, +#ifdef CONFIG_X86_64 + .load_gs_index = native_load_gs_index, +#endif + + .alloc_ldt = paravirt_nop, + .free_ldt = paravirt_nop, + + .store_gdt = native_store_gdt, + .store_idt = native_store_idt, + .store_tr = native_store_tr, + + .write_ldt_entry = native_write_ldt_entry, + .write_gdt_entry = native_write_gdt_entry, + .write_idt_entry = native_write_idt_entry, + .load_sp0 = native_load_sp0, + + .set_iopl_mask = native_set_iopl_mask, + .io_delay = xen_io_delay, + + /* Xen takes care of %gs when switching to usermode for us */ + .swapgs = native_swapgs, + + .start_context_switch = paravirt_start_context_switch, + .end_context_switch = xen_end_context_switch, +}; + static const struct pv_cpu_ops xen_cpu_ops __initdata = { .cpuid = xen_cpuid, @@ -1010,6 +1095,11 @@ static const struct pv_apic_ops xen_apic_ops __initdata = { #endif }; +static void __init xen_hybrid_override_autox_cpu_ops(void) +{ + pv_cpu_ops.cpuid = xen_cpuid; +} + static void xen_reboot(int reason) { struct sched_shutdown r = { .reason = reason }; @@ -1071,6 +1161,10 @@ static const struct machine_ops __initdata xen_machine_ops = { */ static void __init xen_setup_stackprotector(void) { + if (xen_hybrid_domain()) { + 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; @@ -1093,14 +1187,22 @@ asmlinkage void __init xen_start_kernel(void) xen_domain_type = XEN_PV_DOMAIN; + xen_setup_features(); 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_hybrid_domain()) { + if (xen_feature(XENFEAT_auto_translated_physmap)) + xen_hybrid_override_autox_cpu_ops(); + else + pv_cpu_ops = xen_hybrid_cpu_ops; + } else + pv_cpu_ops = xen_cpu_ops; + x86_init.resources.memory_setup = xen_memory_setup; x86_init.oem.arch_setup = xen_arch_setup; x86_init.oem.banner = xen_banner; @@ -1129,7 +1231,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)) @@ -1214,10 +1315,12 @@ asmlinkage void __init xen_start_kernel(void) * 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); + if (!xen_hybrid_domain()) { + 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 */ @@ -1388,3 +1491,29 @@ const __refconst struct hypervisor_x86 x86_hyper_xen_hvm = { }; EXPORT_SYMBOL(x86_hyper_xen_hvm); #endif + +static bool __init xen_hybrid_platform_detect(void) +{ + return (xen_hybrid_domain()); +} + + +const int xen_hybrid_rsvd_top_frames = 48; /* 32 for grant + future */ +static void __init xen_hybrid_guest_init(void) +{ + if (xen_feature(XENFEAT_hvm_callback_vector)) + xen_have_vector_callback = 1; + + /* xen_hvm_smp_init(); */ /* <======================== */ + + /* adjust iomem_resource set in setup_arch() and reserve some frames + * for grant table etc for us */ + iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1 + - xen_hybrid_rsvd_top_frames; +} + +const __refconst struct hypervisor_x86 x86_hyper_xen_hybrid = { + .name = "Xen Hybrid", + .detect = xen_hybrid_platform_detect, + .init_platform = xen_hybrid_guest_init, +}; diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c index 6a6fe89..1a161db 100644 --- a/arch/x86/xen/irq.c +++ b/arch/x86/xen/irq.c @@ -100,6 +100,9 @@ PV_CALLEE_SAVE_REGS_THUNK(xen_irq_enable); static void xen_safe_halt(void) { + if (xen_hybrid_domain()) + local_irq_enable(); + /* Blocking includes an implicit local_irq_enable(). */ if (HYPERVISOR_sched_op(SCHEDOP_block, NULL) != 0) BUG(); @@ -113,6 +116,19 @@ static void xen_halt(void) xen_safe_halt(); } +static const struct pv_irq_ops xen_hybrid_irq_ops __initdata = { + .save_fl = __PV_IS_CALLEE_SAVE(native_save_fl), + .restore_fl = __PV_IS_CALLEE_SAVE(native_restore_fl), + .irq_disable = __PV_IS_CALLEE_SAVE(native_irq_disable), + .irq_enable = __PV_IS_CALLEE_SAVE(native_irq_enable), + + .safe_halt = xen_safe_halt, + .halt = xen_halt, +#ifdef CONFIG_X86_64 + .adjust_exception_frame = paravirt_nop, +#endif +}; + static const struct pv_irq_ops xen_irq_ops __initdata = { .save_fl = PV_CALLEE_SAVE(xen_save_fl), .restore_fl = PV_CALLEE_SAVE(xen_restore_fl), @@ -128,6 +144,9 @@ static const struct pv_irq_ops xen_irq_ops __initdata = { void __init xen_init_irq_ops(void) { - pv_irq_ops = xen_irq_ops; + if (xen_hybrid_domain()) + pv_irq_ops = xen_hybrid_irq_ops; + else + pv_irq_ops = xen_irq_ops; x86_init.irqs.intr_init = xen_init_IRQ; } diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index f298bd7..2c50554 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1294,6 +1294,10 @@ static void xen_post_allocator_init(void); static __init void xen_pagetable_setup_done(pgd_t *base) { xen_setup_shared_info(); + + if (xen_feature(XENFEAT_auto_translated_physmap)) + return; + xen_post_allocator_init(); } @@ -1685,15 +1689,18 @@ static void set_page_prot(void *addr, pgprot_t prot) unsigned long pfn = __pa(addr) >> PAGE_SHIFT; pte_t pte = pfn_pte(pfn, prot); - if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0)) + if (xen_feature(XENFEAT_auto_translated_physmap)) { + return; + } + if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0)) BUG(); } -static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) +static __init int xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) { - unsigned pmdidx, pteidx; - unsigned ident_pte; - unsigned long pfn; + unsigned int pmdidx, pteidx; + unsigned int ident_pte; + unsigned int long pfn; level1_ident_pgt = extend_brk(sizeof(pte_t) * LEVEL1_IDENT_ENTRIES, PAGE_SIZE); @@ -1728,13 +1735,10 @@ static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) pte_page[pteidx] = pte; } } - - for (pteidx = 0; pteidx < ident_pte; pteidx += PTRS_PER_PTE) - set_page_prot(&level1_ident_pgt[pteidx], PAGE_KERNEL_RO); - - set_page_prot(pmd, PAGE_KERNEL_RO); + return ident_pte; } +/* TBD: DON'T NEED THIS FOR HYBRID EPT???? */ void __init xen_setup_machphys_mapping(void) { struct xen_machphys_mapping mapping; @@ -1775,6 +1779,7 @@ static void convert_pfn_mfn(void *v) __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) { + unsigned int pteidx, ident_ptes; pud_t *l3; pmd_t *l2; @@ -1787,11 +1792,12 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, /* Zap identity mapping */ init_level4_pgt[0] = __pgd(0); - /* Pre-constructed entries are in pfn, so convert to mfn */ - convert_pfn_mfn(init_level4_pgt); - convert_pfn_mfn(level3_ident_pgt); - convert_pfn_mfn(level3_kernel_pgt); - + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + /* Pre-constructed entries are in pfn, so convert to mfn */ + convert_pfn_mfn(init_level4_pgt); + convert_pfn_mfn(level3_ident_pgt); + convert_pfn_mfn(level3_kernel_pgt); + } l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd); l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud); @@ -1803,7 +1809,11 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, memcpy(level2_fixmap_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD); /* Set up identity map */ - xen_map_identity_early(level2_ident_pgt, max_pfn); + ident_ptes = xen_map_identity_early(level2_ident_pgt, max_pfn); + + for (pteidx = 0; pteidx < ident_ptes; pteidx += PTRS_PER_PTE) + set_page_prot(&level1_ident_pgt[pteidx], PAGE_KERNEL_RO); + set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO); /* Make pagetable pieces RO */ set_page_prot(init_level4_pgt, PAGE_KERNEL_RO); @@ -1813,12 +1823,14 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); - /* Pin down new L4 */ - pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, - PFN_DOWN(__pa_symbol(init_level4_pgt))); + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + /* Pin down new L4 */ + pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, + PFN_DOWN(__pa_symbol(init_level4_pgt))); - /* Unpin Xen-provided one */ - pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); + /* Unpin Xen-provided one */ + pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); + } /* Switch over */ pgd = init_level4_pgt; @@ -1828,9 +1840,13 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, * structure to attach it to, so make sure we just set kernel * pgd. */ - xen_mc_batch(); - __xen_write_cr3(true, __pa(pgd)); - xen_mc_issue(PARAVIRT_LAZY_CPU); + if (xen_feature(XENFEAT_auto_translated_physmap)) { + native_write_cr3(__pa(pgd)); + } else { + xen_mc_batch(); + __xen_write_cr3(true, __pa(pgd)); + xen_mc_issue(PARAVIRT_LAZY_CPU); + } memblock_x86_reserve_range(__pa(xen_start_info->pt_base), __pa(xen_start_info->pt_base + @@ -2117,14 +2133,26 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = { .set_fixmap = xen_set_fixmap, }; +static __init void xen_hyb_override_mmu_ops(void) +{ + pv_mmu_ops.read_cr2 = native_read_cr2; + pv_mmu_ops.write_cr2 = native_write_cr2; +} + void __init xen_init_mmu_ops(void) { + memset(dummy_mapping, 0xff, PAGE_SIZE); + x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done; + + if (xen_feature(XENFEAT_auto_translated_physmap)) + return; + x86_init.mapping.pagetable_reserve = xen_mapping_pagetable_reserve; x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start; - x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done; - pv_mmu_ops = xen_mmu_ops; + pv_mmu_ops = xen_mmu_ops; - memset(dummy_mapping, 0xff, PAGE_SIZE); + if (xen_hybrid_domain()) /* hybrid without EPT, ie, pv paging. */ + xen_hyb_override_mmu_ops(); } /* Protected by xen_reservation_lock. */ diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index adaf127..9a2a576 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -391,12 +391,9 @@ void __cpuinit xen_enable_syscall(void) #endif /* CONFIG_X86_64 */ } -void __init xen_arch_setup(void) +static __init void xen_nonhybrid_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, @@ -415,6 +412,14 @@ void __init xen_arch_setup(void) disable_acpi(); } #endif +} + +void __init xen_arch_setup(void) +{ + xen_panic_handler_init(); + HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables); + if (!xen_hybrid_domain()) + xen_nonhybrid_arch_setup(); memcpy(boot_command_line, xen_start_info->cmd_line, MAX_GUEST_CMDLINE > COMMAND_LINE_SIZE ? diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 3061244..0b0464e 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -195,10 +195,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_auto_translated_physmap)) { + /* 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(); } diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index 6611535..1a3ebbc 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c @@ -3294,6 +3294,9 @@ static int __init serial8250_init(void) { int ret; + if (xen_hybrid_domain()) + return -ENODEV; + if (nr_uarts > UART_NR) nr_uarts = UART_NR; diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c index 14e2d99..631a019 100644 --- a/drivers/xen/cpu_hotplug.c +++ b/drivers/xen/cpu_hotplug.c @@ -99,7 +99,7 @@ static int __init setup_vcpu_hotplug_event(void) static struct notifier_block xsn_cpu = { .notifier_call = setup_cpu_watcher }; - if (!xen_pv_domain()) + if (!xen_pv_domain() || xen_hybrid_domain()) return -ENODEV; register_xenstore_notifier(&xsn_cpu); diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 33167b4..69bad2e 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -1632,5 +1632,7 @@ void __init xen_init_IRQ(void) irq_ctx_init(smp_processor_id()); if (xen_initial_domain()) xen_setup_pirqs(); + if (xen_hybrid_domain()) + xen_callback_vector(); } } diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 3745a31..ff57b55 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -46,6 +46,8 @@ #include #include +#include +#include #include #include @@ -503,6 +505,56 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, } EXPORT_SYMBOL_GPL(gnttab_unmap_refs); +static int ptefunc(pte_t *pte, pgtable_t table, unsigned long addr, void *data) +{ + pte_t pteval = pfn_pte(virt_to_pfn(addr), PAGE_KERNEL); + set_pte(pte, pteval); + return 0; +} + + +extern int xen_hybrid_rsvd_top_frames; +static int gnttab_map_hyb_autox(unsigned int start_idx, unsigned int end_idx) +{ + struct xen_add_to_physmap xatp; + unsigned int i = end_idx; + unsigned int nr_gframes = end_idx + 1; + int rc = 0; + + if (shared == NULL) { + unsigned long numgf = gnttab_max_grant_frames(); + unsigned long maxp = (1ULL << boot_cpu_data.x86_phys_bits) - 1; + unsigned long gntpfn = (maxp >> PAGE_SHIFT) - numgf; + + BUG_ON(numgf > xen_hybrid_rsvd_top_frames); + shared = __va(gntpfn << PAGE_SHIFT); + } + + /* will reinsert entries in shared[0...n-1], but its OK */ + rc = apply_to_page_range(&init_mm, shared, + PAGE_SIZE*nr_gframes, ptefunc, NULL); + BUG_ON(rc); + + /* + * Loop backwards, so that the first hypercall has the largest + * index, ensuring that the table will grow only once. + */ + do { + xatp.domid = DOMID_SELF; + xatp.idx = i; + xatp.space = XENMAPSPACE_grant_table; + xatp.gpfn = (virt_to_pfn(shared)) + i; + rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp); + if (rc != 0) { + printk(KERN_WARNING + "grant table add_to_physmap failed, err=%d\n", rc); + break; + } + } while (i-- > start_idx); + + return rc; +} + static int gnttab_map(unsigned int start_idx, unsigned int end_idx) { struct gnttab_setup_table setup; @@ -510,6 +562,9 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx) unsigned int nr_gframes = end_idx + 1; int rc; + if (xen_hybrid_autoxlate_domain()) + return gnttab_map_hyb_autox(start_idx, end_idx); + if (xen_hvm_domain()) { struct xen_add_to_physmap xatp; unsigned int i = end_idx; diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 7397695..2429d0e 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -737,7 +737,13 @@ static int __init xenbus_init(void) xen_store_interface = mfn_to_virt(xen_store_mfn); } else { - if (xen_hvm_domain()) { + if (xen_hybrid_autoxlate_domain()) { + xen_store_evtchn = xen_start_info->store_evtchn; + xen_store_mfn = xen_start_info->store_mfn; /* pfn */ + xen_store_interface = __va(xen_store_mfn<flags & SIF_IS_HYBRID)) +#define xen_hybrid_autoxlate_domain() (xen_hybrid_domain() && \ + (xen_feature(XENFEAT_auto_translated_physmap))) #ifdef CONFIG_XEN_DOM0 #include #include