2 * Copyright 2004 James Cleverdon, IBM.
3 * Subject to the GNU Public License, v.2
5 * Xen APIC subarch code. Maximum 8 CPUs, logical delivery.
7 * Hacked for x86-64 by James Cleverdon from i386 architecture code by
8 * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
11 * Hacked to pieces for Xen by Chris Wright.
13 #include <linux/threads.h>
14 #include <linux/cpumask.h>
15 #include <linux/string.h>
16 #include <linux/kernel.h>
17 #include <linux/ctype.h>
18 #include <linux/init.h>
19 #ifdef CONFIG_XEN_PRIVILEGED_GUEST
24 #include <asm/apicdef.h>
25 #include <asm/genapic.h>
27 #include <xen/evtchn.h>
29 DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]);
31 static inline void __send_IPI_one(unsigned int cpu, int vector)
33 int irq = per_cpu(ipi_to_irq, cpu)[vector];
35 notify_remote_via_irq(irq);
38 void xen_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest)
44 __send_IPI_one(smp_processor_id(), vector);
46 case APIC_DEST_ALLBUT:
47 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
48 if (cpu == smp_processor_id())
50 if (cpu_isset(cpu, cpu_online_map)) {
51 __send_IPI_one(cpu, vector);
55 case APIC_DEST_ALLINC:
56 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
57 if (cpu_isset(cpu, cpu_online_map)) {
58 __send_IPI_one(cpu, vector);
63 printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
69 static cpumask_t xen_target_cpus(void)
71 return cpu_online_map;
75 * Set up the logical destination ID.
76 * Do nothing, not called now.
78 static void xen_init_apic_ldr(void)
80 Dprintk("%s\n", __FUNCTION__);
84 static void xen_send_IPI_mask(cpumask_t cpumask, int vector)
86 unsigned long mask = cpus_addr(cpumask)[0];
90 Dprintk("%s\n", __FUNCTION__);
91 local_irq_save(flags);
92 WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
94 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
95 if (cpu_isset(cpu, cpumask)) {
96 __send_IPI_one(cpu, vector);
99 local_irq_restore(flags);
102 static void xen_send_IPI_allbutself(int vector)
104 #ifdef CONFIG_HOTPLUG_CPU
110 * if there are no other CPUs in the system then
111 * we get an APIC send error if we try to broadcast.
112 * thus we have to avoid sending IPIs in this case.
114 Dprintk("%s\n", __FUNCTION__);
115 if (hotplug || vector == NMI_VECTOR) {
116 cpumask_t allbutme = cpu_online_map;
118 cpu_clear(smp_processor_id(), allbutme);
120 if (!cpus_empty(allbutme))
121 xen_send_IPI_mask(allbutme, vector);
122 } else if (num_online_cpus() > 1) {
123 xen_send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_LOGICAL);
127 static void xen_send_IPI_all(int vector)
129 Dprintk("%s\n", __FUNCTION__);
130 if (vector == NMI_VECTOR)
131 xen_send_IPI_mask(cpu_online_map, vector);
133 xen_send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
136 #ifdef CONFIG_XEN_PRIVILEGED_GUEST
137 static int xen_apic_id_registered(void)
140 Dprintk("%s\n", __FUNCTION__);
141 return physid_isset(smp_processor_id(), phys_cpu_present_map);
145 static unsigned int xen_cpu_mask_to_apicid(cpumask_t cpumask)
147 Dprintk("%s\n", __FUNCTION__);
148 return cpus_addr(cpumask)[0] & APIC_ALL_CPUS;
151 static unsigned int phys_pkg_id(int index_msb)
154 Dprintk("%s\n", __FUNCTION__);
156 return ((ebx >> 24) & 0xFF) >> index_msb;
159 struct genapic apic_xen = {
161 #ifdef CONFIG_XEN_PRIVILEGED_GUEST
162 .int_delivery_mode = dest_LowestPrio,
164 .int_dest_mode = (APIC_DEST_LOGICAL != 0),
165 .int_delivery_dest = APIC_DEST_LOGICAL | APIC_DM_LOWEST,
166 .target_cpus = xen_target_cpus,
167 #ifdef CONFIG_XEN_PRIVILEGED_GUEST
168 .apic_id_registered = xen_apic_id_registered,
170 .init_apic_ldr = xen_init_apic_ldr,
171 .send_IPI_all = xen_send_IPI_all,
172 .send_IPI_allbutself = xen_send_IPI_allbutself,
173 .send_IPI_mask = xen_send_IPI_mask,
174 .cpu_mask_to_apicid = xen_cpu_mask_to_apicid,
175 .phys_pkg_id = phys_pkg_id,