[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH 06/16] x86/xen: add shared_info support to xenhost_t
HYPERVISOR_shared_info is used for irq/evtchn communication between the guest and the host. Abstract out the setup/reset in xenhost_t such that nested configurations can use both xenhosts simultaneously. In addition to irq/evtchn communication, shared_info is also used for pvclock and p2m related state. For both of those, remote xenhost is not of interest so we only use the default xenhost. Signed-off-by: Ankur Arora <ankur.a.arora@xxxxxxxxxx> --- arch/x86/include/asm/xen/hypervisor.h | 1 - arch/x86/xen/enlighten.c | 10 ++----- arch/x86/xen/enlighten_hvm.c | 38 +++++++++++++++++--------- arch/x86/xen/enlighten_pv.c | 28 ++++++++++++++++--- arch/x86/xen/p2m.c | 24 ++++++++--------- arch/x86/xen/suspend_hvm.c | 6 ++++- arch/x86/xen/suspend_pv.c | 14 +++++----- arch/x86/xen/time.c | 4 +-- arch/x86/xen/xen-ops.h | 2 -- arch/x86/xen/xenhost.c | 13 ++++++++- drivers/xen/events/events_2l.c | 16 +++++------ include/xen/xenhost.h | 39 +++++++++++++++++++++++++++ 12 files changed, 138 insertions(+), 57 deletions(-) diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h index 6c4cdcdf997d..3e6bd455fbd0 100644 --- a/arch/x86/include/asm/xen/hypervisor.h +++ b/arch/x86/include/asm/xen/hypervisor.h @@ -33,7 +33,6 @@ #ifndef _ASM_X86_XEN_HYPERVISOR_H #define _ASM_X86_XEN_HYPERVISOR_H -extern struct shared_info *HYPERVISOR_shared_info; extern struct start_info *xen_start_info; #include <asm/processor.h> diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index f88bb14da3f2..20e0de844442 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -72,12 +72,6 @@ EXPORT_SYMBOL_GPL(xen_have_vector_callback); uint32_t xen_start_flags __attribute__((section(".data"))) = 0; EXPORT_SYMBOL(xen_start_flags); -/* - * Point at some empty memory to start with. We map the real shared_info - * page as soon as fixmap is up and running. - */ -struct shared_info *HYPERVISOR_shared_info = &xen_dummy_shared_info; - /* * Flag to determine whether vcpu info placement is available on all * VCPUs. We assume it is to start with, and then set it to zero on @@ -187,7 +181,7 @@ void xen_vcpu_info_reset(int cpu) { if (xen_vcpu_nr(cpu) < MAX_VIRT_CPUS) { per_cpu(xen_vcpu, cpu) = - &HYPERVISOR_shared_info->vcpu_info[xen_vcpu_nr(cpu)]; + &xh_default->HYPERVISOR_shared_info->vcpu_info[xen_vcpu_nr(cpu)]; } else { /* Set to NULL so that if somebody accesses it we get an OOPS */ per_cpu(xen_vcpu, cpu) = NULL; @@ -200,7 +194,7 @@ int xen_vcpu_setup(int cpu) int err; struct vcpu_info *vcpup; - BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info); + BUG_ON(xh_default->HYPERVISOR_shared_info == &xen_dummy_shared_info); /* * This path is called on PVHVM at bootup (xen_hvm_smp_prepare_boot_cpu) diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c index a118b61a1a8a..0e53363f9d1f 100644 --- a/arch/x86/xen/enlighten_hvm.c +++ b/arch/x86/xen/enlighten_hvm.c @@ -26,21 +26,25 @@ #include "mmu.h" #include "smp.h" -static unsigned long shared_info_pfn; - -void xen_hvm_init_shared_info(void) +static void xen_hvm_init_shared_info(xenhost_t *xh) { struct xen_add_to_physmap xatp; xatp.domid = DOMID_SELF; xatp.idx = 0; xatp.space = XENMAPSPACE_shared_info; - xatp.gpfn = shared_info_pfn; - if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) + xatp.gpfn = xh->shared_info_pfn; + if (hypervisor_memory_op(xh, XENMEM_add_to_physmap, &xatp)) BUG(); } -static void __init reserve_shared_info(void) +static void xen_hvm_reset_shared_info(xenhost_t *xh) +{ + early_memunmap(xh->HYPERVISOR_shared_info, PAGE_SIZE); + xh->HYPERVISOR_shared_info = __va(PFN_PHYS(xh->shared_info_pfn)); +} + +static void __init reserve_shared_info(xenhost_t *xh) { u64 pa; @@ -58,16 +62,18 @@ static void __init reserve_shared_info(void) pa += PAGE_SIZE) ; - shared_info_pfn = PHYS_PFN(pa); + xh->shared_info_pfn = PHYS_PFN(pa); memblock_reserve(pa, PAGE_SIZE); - HYPERVISOR_shared_info = early_memremap(pa, PAGE_SIZE); + xh->HYPERVISOR_shared_info = early_memremap(pa, PAGE_SIZE); } static void __init xen_hvm_init_mem_mapping(void) { - early_memunmap(HYPERVISOR_shared_info, PAGE_SIZE); - HYPERVISOR_shared_info = __va(PFN_PHYS(shared_info_pfn)); + xenhost_t **xh; + + for_each_xenhost(xh) + xenhost_reset_shared_info(*xh); /* * The virtual address of the shared_info page has changed, so @@ -79,6 +85,7 @@ static void __init xen_hvm_init_mem_mapping(void) * * It is, in any case, bad to have a stale vcpu_info pointer * so reset it now. + * For now, this uses xh_default implictly. */ xen_vcpu_info_reset(0); } @@ -99,6 +106,8 @@ void xen_hvm_setup_hypercall_page(xenhost_t *xh) xenhost_ops_t xh_hvm_ops = { .cpuid_base = xen_pv_cpuid_base, .setup_hypercall_page = xen_hvm_setup_hypercall_page, + .setup_shared_info = xen_hvm_init_shared_info, + .reset_shared_info = xen_hvm_reset_shared_info, }; xenhost_ops_t xh_hvm_nested_ops = { @@ -204,6 +213,8 @@ static int xen_cpu_dead_hvm(unsigned int cpu) static void __init xen_hvm_guest_init(void) { + xenhost_t **xh; + if (xen_pv_domain()) return; /* @@ -215,13 +226,16 @@ static void __init xen_hvm_guest_init(void) init_hvm_pv_info(); - reserve_shared_info(); - xen_hvm_init_shared_info(); + for_each_xenhost(xh) { + reserve_shared_info(*xh); + xenhost_setup_shared_info(*xh); + } /* * xen_vcpu is a pointer to the vcpu_info struct in the shared_info * page, we use it in the event channel upcall and in some pvclock * related functions. + * For now, this uses xh_default implictly. */ xen_vcpu_info_reset(0); diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index 484968ff16a4..1a9eded4b76b 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -122,12 +122,15 @@ static void __init xen_banner(void) static void __init xen_pv_init_platform(void) { + xenhost_t **xh; + populate_extra_pte(fix_to_virt(FIX_PARAVIRT_BOOTMAP)); - set_fixmap(FIX_PARAVIRT_BOOTMAP, xen_start_info->shared_info); - HYPERVISOR_shared_info = (void *)fix_to_virt(FIX_PARAVIRT_BOOTMAP); + for_each_xenhost(xh) + xenhost_setup_shared_info(*xh); /* xen clock uses per-cpu vcpu_info, need to init it for boot cpu */ + /* For now this uses xh_default implicitly. */ xen_vcpu_info_reset(0); /* pvclock is in shared info area */ @@ -1109,10 +1112,10 @@ static unsigned char xen_get_nmi_reason(void) /* Construct a value which looks like it came from port 0x61. */ if (test_bit(_XEN_NMIREASON_io_error, - &HYPERVISOR_shared_info->arch.nmi_reason)) + &xh_default->HYPERVISOR_shared_info->arch.nmi_reason)) reason |= NMI_REASON_IOCHK; if (test_bit(_XEN_NMIREASON_pci_serr, - &HYPERVISOR_shared_info->arch.nmi_reason)) + &xh_default->HYPERVISOR_shared_info->arch.nmi_reason)) reason |= NMI_REASON_SERR; return reason; @@ -1205,10 +1208,27 @@ static void xen_pv_setup_hypercall_page(xenhost_t *xh) xh->hypercall_page = xen_hypercall_page; } +static void xen_pv_setup_shared_info(xenhost_t *xh) +{ + set_fixmap(FIX_PARAVIRT_BOOTMAP, xen_start_info->shared_info); + xh->HYPERVISOR_shared_info = (void *)fix_to_virt(FIX_PARAVIRT_BOOTMAP); +} + +static void xen_pv_reset_shared_info(xenhost_t *xh) +{ + xh->HYPERVISOR_shared_info = &xen_dummy_shared_info; + if (hypervisor_update_va_mapping(xh, fix_to_virt(FIX_PARAVIRT_BOOTMAP), + __pte_ma(0), 0)) + BUG(); +} + xenhost_ops_t xh_pv_ops = { .cpuid_base = xen_pv_cpuid_base, .setup_hypercall_page = xen_pv_setup_hypercall_page, + + .setup_shared_info = xen_pv_setup_shared_info, + .reset_shared_info = xen_pv_reset_shared_info, }; xenhost_ops_t xh_pv_nested_ops = { diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 055e37e43541..8200a9582246 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -270,17 +270,17 @@ void __ref xen_build_mfn_list_list(void) void xen_setup_mfn_list_list(void) { - BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info); + BUG_ON(xh_default->HYPERVISOR_shared_info == &xen_dummy_shared_info); if (xen_start_info->flags & SIF_VIRT_P2M_4TOOLS) - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = ~0UL; + xh_default->HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = ~0UL; else - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = + xh_default->HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = virt_to_mfn(p2m_top_mfn); - HYPERVISOR_shared_info->arch.max_pfn = xen_p2m_last_pfn; - HYPERVISOR_shared_info->arch.p2m_generation = 0; - HYPERVISOR_shared_info->arch.p2m_vaddr = (unsigned long)xen_p2m_addr; - HYPERVISOR_shared_info->arch.p2m_cr3 = + xh_default->HYPERVISOR_shared_info->arch.max_pfn = xen_p2m_last_pfn; + xh_default->HYPERVISOR_shared_info->arch.p2m_generation = 0; + xh_default->HYPERVISOR_shared_info->arch.p2m_vaddr = (unsigned long)xen_p2m_addr; + xh_default->HYPERVISOR_shared_info->arch.p2m_cr3 = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir)); } @@ -496,12 +496,12 @@ static pte_t *alloc_p2m_pmd(unsigned long addr, pte_t *pte_pg) ptechk = lookup_address(vaddr, &level); if (ptechk == pte_pg) { - HYPERVISOR_shared_info->arch.p2m_generation++; + xh_default->HYPERVISOR_shared_info->arch.p2m_generation++; wmb(); /* Tools are synchronizing via p2m_generation. */ set_pmd(pmdp, __pmd(__pa(pte_newpg[i]) | _KERNPG_TABLE)); wmb(); /* Tools are synchronizing via p2m_generation. */ - HYPERVISOR_shared_info->arch.p2m_generation++; + xh_default->HYPERVISOR_shared_info->arch.p2m_generation++; pte_newpg[i] = NULL; } @@ -597,12 +597,12 @@ int xen_alloc_p2m_entry(unsigned long pfn) spin_lock_irqsave(&p2m_update_lock, flags); if (pte_pfn(*ptep) == p2m_pfn) { - HYPERVISOR_shared_info->arch.p2m_generation++; + xh_default->HYPERVISOR_shared_info->arch.p2m_generation++; wmb(); /* Tools are synchronizing via p2m_generation. */ set_pte(ptep, pfn_pte(PFN_DOWN(__pa(p2m)), PAGE_KERNEL)); wmb(); /* Tools are synchronizing via p2m_generation. */ - HYPERVISOR_shared_info->arch.p2m_generation++; + xh_default->HYPERVISOR_shared_info->arch.p2m_generation++; if (mid_mfn) mid_mfn[p2m_mid_index(pfn)] = virt_to_mfn(p2m); p2m = NULL; @@ -617,7 +617,7 @@ int xen_alloc_p2m_entry(unsigned long pfn) /* Expanded the p2m? */ if (pfn > xen_p2m_last_pfn) { xen_p2m_last_pfn = pfn; - HYPERVISOR_shared_info->arch.max_pfn = xen_p2m_last_pfn; + xh_default->HYPERVISOR_shared_info->arch.max_pfn = xen_p2m_last_pfn; } return 0; diff --git a/arch/x86/xen/suspend_hvm.c b/arch/x86/xen/suspend_hvm.c index e666b614cf6d..cc9a0163845c 100644 --- a/arch/x86/xen/suspend_hvm.c +++ b/arch/x86/xen/suspend_hvm.c @@ -2,6 +2,7 @@ #include <linux/types.h> #include <xen/xen.h> +#include <xen/xenhost.h> #include <xen/features.h> #include <xen/interface/features.h> @@ -10,7 +11,10 @@ void xen_hvm_post_suspend(int suspend_cancelled) { if (!suspend_cancelled) { - xen_hvm_init_shared_info(); + xenhost_t **xh; + + for_each_xenhost(xh) + xenhost_setup_shared_info(*xh); xen_vcpu_restore(); } xen_callback_vector(); diff --git a/arch/x86/xen/suspend_pv.c b/arch/x86/xen/suspend_pv.c index 8303b58c79a9..87af0c0cc66f 100644 --- a/arch/x86/xen/suspend_pv.c +++ b/arch/x86/xen/suspend_pv.c @@ -10,6 +10,8 @@ void xen_pv_pre_suspend(void) { + xenhost_t **xh; + xen_mm_pin_all(); xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn); @@ -18,17 +20,17 @@ void xen_pv_pre_suspend(void) BUG_ON(!irqs_disabled()); - HYPERVISOR_shared_info = &xen_dummy_shared_info; - if (HYPERVISOR_update_va_mapping(fix_to_virt(FIX_PARAVIRT_BOOTMAP), - __pte_ma(0), 0)) - BUG(); + for_each_xenhost(xh) + xenhost_reset_shared_info(*xh); } void xen_pv_post_suspend(int suspend_cancelled) { + xenhost_t **xh; + xen_build_mfn_list_list(); - set_fixmap(FIX_PARAVIRT_BOOTMAP, xen_start_info->shared_info); - HYPERVISOR_shared_info = (void *)fix_to_virt(FIX_PARAVIRT_BOOTMAP); + for_each_xenhost(xh) + xenhost_setup_shared_info(*xh); xen_setup_mfn_list_list(); if (suspend_cancelled) { diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 6e29794573b7..d4bb1f8b4f58 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -37,7 +37,7 @@ static u64 xen_sched_clock_offset __read_mostly; static unsigned long xen_tsc_khz(void) { struct pvclock_vcpu_time_info *info = - &HYPERVISOR_shared_info->vcpu_info[0].time; + &xh_default->HYPERVISOR_shared_info->vcpu_info[0].time; return pvclock_tsc_khz(info); } @@ -66,7 +66,7 @@ static u64 xen_sched_clock(void) static void xen_read_wallclock(struct timespec64 *ts) { - struct shared_info *s = HYPERVISOR_shared_info; + struct shared_info *s = xh_default->HYPERVISOR_shared_info; struct pvclock_wall_clock *wall_clock = &(s->wc); struct pvclock_vcpu_time_info *vcpu_time; diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 0e60bd918695..5085ce88a8d7 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -28,7 +28,6 @@ DECLARE_PER_CPU(unsigned long, xen_current_cr3); extern struct start_info *xen_start_info; extern struct shared_info xen_dummy_shared_info; -extern struct shared_info *HYPERVISOR_shared_info; void xen_setup_mfn_list_list(void); void xen_build_mfn_list_list(void); @@ -56,7 +55,6 @@ void xen_enable_syscall(void); void xen_vcpu_restore(void); void xen_callback_vector(void); -void xen_hvm_init_shared_info(void); void xen_unplug_emulated_devices(void); void __init xen_build_dynamic_phys_to_machine(void); diff --git a/arch/x86/xen/xenhost.c b/arch/x86/xen/xenhost.c index ca90acd7687e..3d8ccef89dcd 100644 --- a/arch/x86/xen/xenhost.c +++ b/arch/x86/xen/xenhost.c @@ -2,8 +2,19 @@ #include <linux/bug.h> #include <xen/xen.h> #include <xen/xenhost.h> +#include "xen-ops.h" -xenhost_t xenhosts[2]; +/* + * Point at some empty memory to start with. On PV, we map the real shared_info + * page as soon as fixmap is up and running and PVH* doesn't use this. + */ +xenhost_t xenhosts[2] = { + /* + * We should probably have two separate dummy shared_info pages. + */ + [0].HYPERVISOR_shared_info = &xen_dummy_shared_info, + [1].HYPERVISOR_shared_info = &xen_dummy_shared_info, +}; /* * xh_default: interface to the regular hypervisor. xenhost_type is xenhost_r0 * or xenhost_r1. diff --git a/drivers/xen/events/events_2l.c b/drivers/xen/events/events_2l.c index 8edef51c92e5..f09dbe4e9c33 100644 --- a/drivers/xen/events/events_2l.c +++ b/drivers/xen/events/events_2l.c @@ -55,37 +55,37 @@ static void evtchn_2l_bind_to_cpu(struct irq_info *info, unsigned cpu) static void evtchn_2l_clear_pending(unsigned port) { - struct shared_info *s = HYPERVISOR_shared_info; + struct shared_info *s = xh_default->HYPERVISOR_shared_info; sync_clear_bit(port, BM(&s->evtchn_pending[0])); } static void evtchn_2l_set_pending(unsigned port) { - struct shared_info *s = HYPERVISOR_shared_info; + struct shared_info *s = xh_default->HYPERVISOR_shared_info; sync_set_bit(port, BM(&s->evtchn_pending[0])); } static bool evtchn_2l_is_pending(unsigned port) { - struct shared_info *s = HYPERVISOR_shared_info; + struct shared_info *s = xh_default->HYPERVISOR_shared_info; return sync_test_bit(port, BM(&s->evtchn_pending[0])); } static bool evtchn_2l_test_and_set_mask(unsigned port) { - struct shared_info *s = HYPERVISOR_shared_info; + struct shared_info *s = xh_default->HYPERVISOR_shared_info; return sync_test_and_set_bit(port, BM(&s->evtchn_mask[0])); } static void evtchn_2l_mask(unsigned port) { - struct shared_info *s = HYPERVISOR_shared_info; + struct shared_info *s = xh_default->HYPERVISOR_shared_info; sync_set_bit(port, BM(&s->evtchn_mask[0])); } static void evtchn_2l_unmask(unsigned port) { - struct shared_info *s = HYPERVISOR_shared_info; + struct shared_info *s = xh_default->HYPERVISOR_shared_info; unsigned int cpu = get_cpu(); int do_hypercall = 0, evtchn_pending = 0; @@ -167,7 +167,7 @@ static void evtchn_2l_handle_events(unsigned cpu) int start_word_idx, start_bit_idx; int word_idx, bit_idx; int i; - struct shared_info *s = HYPERVISOR_shared_info; + struct shared_info *s = xh_default->HYPERVISOR_shared_info; struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); /* Timer interrupt has highest priority. */ @@ -264,7 +264,7 @@ static void evtchn_2l_handle_events(unsigned cpu) irqreturn_t xen_debug_interrupt(int irq, void *dev_id) { - struct shared_info *sh = HYPERVISOR_shared_info; + struct shared_info *sh = xh_default->HYPERVISOR_shared_info; int cpu = smp_processor_id(); xen_ulong_t *cpu_evtchn = per_cpu(cpu_evtchn_mask, cpu); int i; diff --git a/include/xen/xenhost.h b/include/xen/xenhost.h index dd1e2b64f50d..7c19c361d16e 100644 --- a/include/xen/xenhost.h +++ b/include/xen/xenhost.h @@ -82,6 +82,14 @@ typedef struct { * bounce callbacks via L1-Xen. */ u8 features[XENFEAT_NR_SUBMAPS * 32]; + + /* + * shared-info to communicate with this xenhost instance. + */ + struct { + struct shared_info *HYPERVISOR_shared_info; + unsigned long shared_info_pfn; + }; } xenhost_t; typedef struct xenhost_ops { @@ -111,6 +119,26 @@ typedef struct xenhost_ops { * to decide which particular L1-guest was the caller. */ void (*setup_hypercall_page)(xenhost_t *xenhost); + + /* + * shared_info: needed before vcpu-info setup. + * + * Needed early because Xen needs it for irq_disable() and such. + * On PV first a dummy_shared_info is setup which eventually gets + * switched to the real one so this needs to support switching + * xenhost. + * + * Reset for PV is done differently from HVM, so provide a + * separate interface. + * + * xenhost_r0: point xenhost->HYPERVISOR_shared_info to a + * newly allocated shared_info page. + * xenhost_r1: similar to what we do now. + * xenhost_r2: new remote hypercall to setup a shared_info page. + * This is where we would now handle L0-Xen irq/evtchns. + */ + void (*setup_shared_info)(xenhost_t *xenhost); + void (*reset_shared_info)(xenhost_t *xenhost); } xenhost_ops_t; extern xenhost_t *xh_default, *xh_remote; @@ -146,4 +174,15 @@ static inline void xenhost_setup_hypercall_page(xenhost_t *xh) (xh->ops->setup_hypercall_page)(xh); } + +static inline void xenhost_setup_shared_info(xenhost_t *xh) +{ + (xh->ops->setup_shared_info)(xh); +} + +static inline void xenhost_reset_shared_info(xenhost_t *xh) +{ + (xh->ops->reset_shared_info)(xh); +} + #endif /* __XENHOST_H */ -- 2.20.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |