1 #include <linux/init.h>
3 #include <asm/x86_init.h>
5 #include <asm/xen/hypercall.h>
8 #include <xen/interface/physdev.h>
13 static unsigned int xen_io_apic_read(unsigned apic
, unsigned reg
)
15 struct physdev_apic apic_op
;
18 apic_op
.apic_physbase
= mpc_ioapic_addr(apic
);
20 ret
= HYPERVISOR_physdev_op(PHYSDEVOP_apic_read
, &apic_op
);
24 /* fallback to return an emulated IO_APIC values */
33 static unsigned long xen_set_apic_id(unsigned int x
)
39 static unsigned int xen_get_apic_id(unsigned long x
)
41 return ((x
)>>24) & 0xFFu
;
44 static u32
xen_apic_read(u32 reg
)
46 struct xen_platform_op op
= {
47 .cmd
= XENPF_get_cpuinfo
,
48 .interface_version
= XENPF_INTERFACE_VERSION
,
49 .u
.pcpu_info
.xen_cpuid
= 0,
53 /* Shouldn't need this as APIC is turned off for PV, and we only
54 * get called on the bootup processor. But just in case. */
55 if (!xen_initial_domain() || smp_processor_id())
62 return SET_APIC_LOGICAL_ID(1UL << smp_processor_id());
67 ret
= HYPERVISOR_platform_op(&op
);
69 op
.u
.pcpu_info
.apic_id
= BAD_APICID
;
71 return op
.u
.pcpu_info
.apic_id
<< 24;
74 static void xen_apic_write(u32 reg
, u32 val
)
76 if (reg
== APIC_LVTPC
) {
77 (void)pmu_apic_update(reg
);
81 /* Warn to see if there's any stray references */
82 WARN(1,"register: %x, value: %x\n", reg
, val
);
85 static u64
xen_apic_icr_read(void)
90 static void xen_apic_icr_write(u32 low
, u32 id
)
92 /* Warn to see if there's any stray references */
96 static u32
xen_safe_apic_wait_icr_idle(void)
101 static int xen_apic_probe_pv(void)
109 static int xen_madt_oem_check(char *oem_id
, char *oem_table_id
)
111 return xen_pv_domain();
114 static int xen_id_always_valid(int apicid
)
119 static int xen_id_always_registered(void)
124 static int xen_phys_pkg_id(int initial_apic_id
, int index_msb
)
126 return initial_apic_id
>> index_msb
;
130 static int xen_x86_32_early_logical_apicid(int cpu
)
132 /* Match with APIC_LDR read. Otherwise setup_local_APIC complains. */
137 static void xen_noop(void)
141 static void xen_silent_inquire(int apicid
)
145 static int xen_cpu_present_to_apicid(int cpu
)
147 if (cpu_present(cpu
))
148 return cpu_data(cpu
).apicid
;
153 static struct apic xen_pv_apic
= {
155 .probe
= xen_apic_probe_pv
,
156 .acpi_madt_oem_check
= xen_madt_oem_check
,
157 .apic_id_valid
= xen_id_always_valid
,
158 .apic_id_registered
= xen_id_always_registered
,
160 /* .irq_delivery_mode - used in native_compose_msi_msg only */
161 /* .irq_dest_mode - used in native_compose_msi_msg only */
163 .target_cpus
= default_target_cpus
,
165 /* .dest_logical - default_send_IPI_ use it but we use our own. */
166 .check_apicid_used
= default_check_apicid_used
, /* Used on 32-bit */
168 .vector_allocation_domain
= flat_vector_allocation_domain
,
169 .init_apic_ldr
= xen_noop
, /* setup_local_APIC calls it */
171 .ioapic_phys_id_map
= default_ioapic_phys_id_map
, /* Used on 32-bit */
172 .setup_apic_routing
= NULL
,
173 .cpu_present_to_apicid
= xen_cpu_present_to_apicid
,
174 .apicid_to_cpu_present
= physid_set_mask_of_physid
, /* Used on 32-bit */
175 .check_phys_apicid_present
= default_check_phys_apicid_present
, /* smp_sanity_check needs it */
176 .phys_pkg_id
= xen_phys_pkg_id
, /* detect_ht */
178 .get_apic_id
= xen_get_apic_id
,
179 .set_apic_id
= xen_set_apic_id
, /* Can be NULL on 32-bit. */
181 .cpu_mask_to_apicid_and
= flat_cpu_mask_to_apicid_and
,
184 .send_IPI_mask
= xen_send_IPI_mask
,
185 .send_IPI_mask_allbutself
= xen_send_IPI_mask_allbutself
,
186 .send_IPI_allbutself
= xen_send_IPI_allbutself
,
187 .send_IPI_all
= xen_send_IPI_all
,
188 .send_IPI_self
= xen_send_IPI_self
,
190 /* .wait_for_init_deassert- used by AP bootup - smp_callin which we don't use */
191 .inquire_remote_apic
= xen_silent_inquire
,
193 .read
= xen_apic_read
,
194 .write
= xen_apic_write
,
195 .eoi_write
= xen_apic_write
,
197 .icr_read
= xen_apic_icr_read
,
198 .icr_write
= xen_apic_icr_write
,
199 .wait_icr_idle
= xen_noop
,
200 .safe_wait_icr_idle
= xen_safe_apic_wait_icr_idle
,
203 /* generic_processor_info and setup_local_APIC. */
204 .x86_32_early_logical_apicid
= xen_x86_32_early_logical_apicid
,
208 static void __init
xen_apic_check(void)
210 if (apic
== &xen_pv_apic
)
213 pr_info("Switched APIC routing from %s to %s.\n", apic
->name
,
217 void __init
xen_init_apic(void)
219 x86_io_apic_ops
.read
= xen_io_apic_read
;
220 /* On PV guests the APIC CPUID bit is disabled so none of the
221 * routines end up executing. */
222 if (!xen_initial_domain())
225 x86_platform
.apic_post_init
= xen_apic_check
;
227 apic_driver(xen_pv_apic
);