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/config.h>
14 #include <linux/threads.h>
15 #include <linux/cpumask.h>
16 #include <linux/string.h>
17 #include <linux/kernel.h>
18 #include <linux/ctype.h>
19 #include <linux/init.h>
20 #ifdef CONFIG_XEN_PRIVILEGED_GUEST
25 #include <asm/apicdef.h>
26 #include <asm/genapic.h>
28 #include <xen/evtchn.h>
30 DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]);
32 static inline void __send_IPI_one(unsigned int cpu, int vector)
34 int irq = per_cpu(ipi_to_irq, cpu)[vector];
36 notify_remote_via_irq(irq);
39 void xen_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest)
45 __send_IPI_one(smp_processor_id(), vector);
47 case APIC_DEST_ALLBUT:
48 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
49 if (cpu == smp_processor_id())
51 if (cpu_isset(cpu, cpu_online_map)) {
52 __send_IPI_one(cpu, vector);
56 case APIC_DEST_ALLINC:
57 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
58 if (cpu_isset(cpu, cpu_online_map)) {
59 __send_IPI_one(cpu, vector);
64 printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
70 static cpumask_t xen_target_cpus(void)
72 return cpu_online_map;
76 * Set up the logical destination ID.
77 * Do nothing, not called now.
79 static void xen_init_apic_ldr(void)
81 Dprintk("%s\n", __FUNCTION__);
85 static void xen_send_IPI_allbutself(int vector)
88 * if there are no other CPUs in the system then
89 * we get an APIC send error if we try to broadcast.
90 * thus we have to avoid sending IPIs in this case.
92 Dprintk("%s\n", __FUNCTION__);
93 if (num_online_cpus() > 1)
94 xen_send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_LOGICAL);
97 static void xen_send_IPI_all(int vector)
99 Dprintk("%s\n", __FUNCTION__);
100 xen_send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
103 static void xen_send_IPI_mask(cpumask_t cpumask, int vector)
105 unsigned long mask = cpus_addr(cpumask)[0];
109 Dprintk("%s\n", __FUNCTION__);
110 local_irq_save(flags);
111 WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
113 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
114 if (cpu_isset(cpu, cpumask)) {
115 __send_IPI_one(cpu, vector);
118 local_irq_restore(flags);
121 #ifdef CONFIG_XEN_PRIVILEGED_GUEST
122 static int xen_apic_id_registered(void)
125 Dprintk("%s\n", __FUNCTION__);
126 return physid_isset(smp_processor_id(), phys_cpu_present_map);
130 static unsigned int xen_cpu_mask_to_apicid(cpumask_t cpumask)
132 Dprintk("%s\n", __FUNCTION__);
133 return cpus_addr(cpumask)[0] & APIC_ALL_CPUS;
136 static unsigned int phys_pkg_id(int index_msb)
140 Dprintk("%s\n", __FUNCTION__);
142 return ((ebx >> 24) & 0xFF) >> index_msb;
145 struct genapic apic_xen = {
147 #ifdef CONFIG_XEN_PRIVILEGED_GUEST
148 .int_delivery_mode = dest_LowestPrio,
150 .int_dest_mode = (APIC_DEST_LOGICAL != 0),
151 .int_delivery_dest = APIC_DEST_LOGICAL | APIC_DM_LOWEST,
152 .target_cpus = xen_target_cpus,
153 #ifdef CONFIG_XEN_PRIVILEGED_GUEST
154 .apic_id_registered = xen_apic_id_registered,
156 .init_apic_ldr = xen_init_apic_ldr,
157 .send_IPI_all = xen_send_IPI_all,
158 .send_IPI_allbutself = xen_send_IPI_allbutself,
159 .send_IPI_mask = xen_send_IPI_mask,
160 .cpu_mask_to_apicid = xen_cpu_mask_to_apicid,
161 .phys_pkg_id = phys_pkg_id,