|
[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 |