aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/smp.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-08-19 12:53:46 +0100
committerKeir Fraser <keir.fraser@citrix.com>2009-08-19 12:53:46 +0100
commit487a1cffd71a34d729c05c9a379ff05ea39b9fe2 (patch)
treef049fe8aaeee2f2abdf21e49e176a6f993bf84ce /xen/arch/x86/smp.c
parentb07b22f961709fc4639b550450caa4681881977d (diff)
downloadxen-487a1cffd71a34d729c05c9a379ff05ea39b9fe2.tar.gz
xen-487a1cffd71a34d729c05c9a379ff05ea39b9fe2.tar.bz2
xen-487a1cffd71a34d729c05c9a379ff05ea39b9fe2.zip
x86: Implement per-cpu vector for xen hypervisor
Since Xen and Linux has big differece in code base, it is very hard to port Linux's patch and apply it to Xen directly, so this patch only adopts core logic of Linux, and make it work for Xen. Key changes: 1. vector allocation algorithm 2. all IRQ chips' set_affinity logic 3. IRQ migration when cpu hot remove. 4. Break assumptions which depend on global vector policy. Signed-off-by: Xiantao Zhang <xiantao.zhang@intel.com>
Diffstat (limited to 'xen/arch/x86/smp.c')
-rw-r--r--xen/arch/x86/smp.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/xen/arch/x86/smp.c b/xen/arch/x86/smp.c
index 5c1bdb10ed..b2f1eadfad 100644
--- a/xen/arch/x86/smp.c
+++ b/xen/arch/x86/smp.c
@@ -26,7 +26,11 @@
* send_IPI_mask(cpumask, vector): sends @vector IPI to CPUs in @cpumask,
* excluding the local CPU. @cpumask may be empty.
*/
-#define send_IPI_mask (genapic->send_IPI_mask)
+
+void send_IPI_mask(const cpumask_t *mask, int vector)
+{
+ genapic->send_IPI_mask(mask, vector);
+}
/*
* Some notes on x86 processor bugs affecting SMP operation:
@@ -89,6 +93,41 @@ void apic_wait_icr_idle(void)
cpu_relax();
}
+static void __default_send_IPI_shortcut(unsigned int shortcut, int vector,
+ unsigned int dest)
+{
+ unsigned int cfg;
+
+ /*
+ * Wait for idle.
+ */
+ apic_wait_icr_idle();
+
+ /*
+ * prepare target chip field
+ */
+ cfg = __prepare_ICR(shortcut, vector) | dest;
+ /*
+ * Send the IPI. The write to APIC_ICR fires this off.
+ */
+ apic_write_around(APIC_ICR, cfg);
+}
+
+void send_IPI_self_flat(int vector)
+{
+ __default_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
+}
+
+void send_IPI_self_phys(int vector)
+{
+ __default_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
+}
+
+void send_IPI_self_x2apic(int vector)
+{
+ apic_write(APIC_SELF_IPI, vector);
+}
+
void send_IPI_mask_flat(const cpumask_t *cpumask, int vector)
{
unsigned long mask = cpus_addr(*cpumask)[0];
@@ -337,8 +376,10 @@ void smp_send_nmi_allbutself(void)
fastcall void smp_event_check_interrupt(struct cpu_user_regs *regs)
{
+ struct cpu_user_regs *old_regs = set_irq_regs(regs);
ack_APIC_irq();
perfc_incr(ipis);
+ set_irq_regs(old_regs);
}
static void __smp_call_function_interrupt(void)
@@ -369,7 +410,10 @@ static void __smp_call_function_interrupt(void)
fastcall void smp_call_function_interrupt(struct cpu_user_regs *regs)
{
+ struct cpu_user_regs *old_regs = set_irq_regs(regs);
+
ack_APIC_irq();
perfc_incr(ipis);
__smp_call_function_interrupt();
+ set_irq_regs(old_regs);
}