[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC v1 33/74] x86/guest: enable event channels upcalls
From: Sergey Dyasli <sergey.dyasli@xxxxxxxxxx> Signed-off-by: Sergey Dyasli <sergey.dyasli@xxxxxxxxxx> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- xen/arch/x86/guest/xen.c | 74 +++++++++++++++++++++++++++++++++++ xen/arch/x86/smpboot.c | 4 ++ xen/include/asm-x86/guest/hypercall.h | 17 ++++++++ xen/include/asm-x86/guest/xen.h | 5 +++ 4 files changed, 100 insertions(+) diff --git a/xen/arch/x86/guest/xen.c b/xen/arch/x86/guest/xen.c index 594eae0828..781bfa493b 100644 --- a/xen/arch/x86/guest/xen.c +++ b/xen/arch/x86/guest/xen.c @@ -21,6 +21,7 @@ #include <xen/init.h> #include <xen/types.h> +#include <asm/apic.h> #include <asm/guest.h> #include <asm/msr.h> #include <asm/processor.h> @@ -30,6 +31,7 @@ bool xen_guest; static uint32_t xen_cpuid_base; +static uint8_t evtchn_upcall_vector; extern char hypercall_page[]; static void __init find_xen_leaves(void) @@ -91,9 +93,81 @@ static void map_shared_info(struct e820map *e820) set_fixmap(FIX_XEN_SHARED_INFO, frame); } +static void xen_evtchn_upcall(struct cpu_user_regs *regs) +{ + unsigned int cpu = smp_processor_id(); + struct vcpu_info *vcpu_info = &XEN_shared_info->vcpu_info[cpu]; + + vcpu_info->evtchn_upcall_pending = 0; + xchg(&vcpu_info->evtchn_pending_sel, 0); + + ack_APIC_irq(); +} + +static void ap_setup_event_channels(bool clear) +{ + unsigned int i, cpu = smp_processor_id(); + struct vcpu_info *vcpu_info = &XEN_shared_info->vcpu_info[cpu]; + int rc; + + ASSERT(evtchn_upcall_vector); + ASSERT(cpu < ARRAY_SIZE(XEN_shared_info->vcpu_info)); + + if ( !clear ) + { + /* + * This is necessary to ensure that a CPU will be interrupted in case + * of an event channel notification. + */ + ASSERT(vcpu_info->evtchn_upcall_pending == 0); + ASSERT(vcpu_info->evtchn_pending_sel == 0); + } + + rc = xen_hypercall_set_evtchn_upcall_vector(cpu, evtchn_upcall_vector); + if ( rc ) + panic("Unable to set evtchn upcall vector: %d", rc); + + if ( clear ) + { + /* + * Clear any pending upcall bits. This makes us effectively ignore any + * previous upcalls which might be suboptimal. + */ + vcpu_info->evtchn_upcall_pending = 0; + xchg(&vcpu_info->evtchn_pending_sel, 0); + + /* + * evtchn_pending can be cleared only on the boot CPU because it's + * located in a shared structure. + */ + for ( i = 0; i < 8; i++ ) + xchg(&XEN_shared_info->evtchn_pending[i], 0); + } +} + +static void __init init_evtchn(void) +{ + unsigned int i; + + alloc_direct_apic_vector(&evtchn_upcall_vector, xen_evtchn_upcall); + + /* Mask all upcalls */ + for ( i = 0; i < 8; i++ ) + xchg(&XEN_shared_info->evtchn_mask[i], ~0ul); + + ap_setup_event_channels(true); +} + void __init hypervisor_early_setup(struct e820map *e820) { map_shared_info(e820); + + init_evtchn(); +} + +void hypervisor_ap_setup(void) +{ + ap_setup_event_channels(false); } /* diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 7b97ff86cb..9a9fbc6ee0 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -45,6 +45,7 @@ #include <mach_apic.h> #include <mach_wakecpu.h> #include <smpboot_hooks.h> +#include <asm/guest.h> /* Override macros from asm/page.h to make them work with mfn_t */ #undef mfn_to_page @@ -372,6 +373,9 @@ void start_secondary(void *unused) cpumask_set_cpu(cpu, &cpu_online_map); unlock_vector_lock(); + if ( xen_guest ) + hypervisor_ap_setup(); + /* We can take interrupts now: we're officially "up". */ local_irq_enable(); mtrr_ap_init(); diff --git a/xen/include/asm-x86/guest/hypercall.h b/xen/include/asm-x86/guest/hypercall.h index d5fe535c03..d6d4d1946b 100644 --- a/xen/include/asm-x86/guest/hypercall.h +++ b/xen/include/asm-x86/guest/hypercall.h @@ -23,6 +23,7 @@ #include <public/xen.h> #include <public/sched.h> +#include <public/hvm/hvm_op.h> #ifdef CONFIG_XEN_GUEST @@ -96,6 +97,11 @@ static inline long xen_hypercall_memory_op(unsigned int cmd, void *arg) return _hypercall64_2(long, __HYPERVISOR_memory_op, cmd, arg); } +static inline long xen_hypercall_hvm_op(unsigned int op, void *arg) +{ + return _hypercall64_2(long, __HYPERVISOR_hvm_op, op, arg); +} + /* * Higher level hypercall helpers */ @@ -111,6 +117,17 @@ static inline long xen_hypercall_shutdown(unsigned int reason) return xen_hypercall_sched_op(SCHEDOP_shutdown, &reason); } +static inline long xen_hypercall_set_evtchn_upcall_vector( + unsigned int cpu, unsigned int vector) +{ + struct xen_hvm_evtchn_upcall_vector a = { + .vcpu = cpu, + .vector = vector, + }; + + return xen_hypercall_hvm_op(HVMOP_set_evtchn_upcall_vector, &a); +} + #else /* CONFIG_XEN_GUEST */ static inline void xen_hypercall_console_write( diff --git a/xen/include/asm-x86/guest/xen.h b/xen/include/asm-x86/guest/xen.h index 2f3bcd2fe4..56cabb1934 100644 --- a/xen/include/asm-x86/guest/xen.h +++ b/xen/include/asm-x86/guest/xen.h @@ -32,6 +32,7 @@ extern bool xen_guest; void probe_hypervisor(void); void hypervisor_early_setup(struct e820map *e820); +void hypervisor_ap_setup(void); #else @@ -42,6 +43,10 @@ static inline void hypervisor_early_setup(struct e820map *e820) { ASSERT_UNREACHABLE(); }; +static inline void hypervisor_ap_setup(void) +{ + ASSERT_UNREACHABLE(); +}; #endif /* CONFIG_XEN_GUEST */ #endif /* __X86_GUEST_XEN_H__ */ -- 2.11.0 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |