0001
0002 #include <linux/init.h>
0003 #include <linux/thread_info.h>
0004
0005 #include <asm/x86_init.h>
0006 #include <asm/apic.h>
0007 #include <asm/io_apic.h>
0008 #include <asm/xen/hypercall.h>
0009
0010 #include <xen/xen.h>
0011 #include <xen/interface/physdev.h>
0012 #include "xen-ops.h"
0013 #include "pmu.h"
0014 #include "smp.h"
0015
0016 static unsigned int xen_io_apic_read(unsigned apic, unsigned reg)
0017 {
0018 struct physdev_apic apic_op;
0019 int ret;
0020
0021 apic_op.apic_physbase = mpc_ioapic_addr(apic);
0022 apic_op.reg = reg;
0023 ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
0024 if (!ret)
0025 return apic_op.value;
0026
0027
0028 if (reg == 0x1)
0029 return 0x00170020;
0030 else if (reg == 0x0)
0031 return apic << 24;
0032
0033 return 0xfd;
0034 }
0035
0036 static u32 xen_set_apic_id(unsigned int x)
0037 {
0038 WARN_ON(1);
0039 return x;
0040 }
0041
0042 static unsigned int xen_get_apic_id(unsigned long x)
0043 {
0044 return ((x)>>24) & 0xFFu;
0045 }
0046
0047 static u32 xen_apic_read(u32 reg)
0048 {
0049 struct xen_platform_op op = {
0050 .cmd = XENPF_get_cpuinfo,
0051 .interface_version = XENPF_INTERFACE_VERSION,
0052 .u.pcpu_info.xen_cpuid = 0,
0053 };
0054 int ret;
0055
0056
0057
0058 if (!xen_initial_domain() || smp_processor_id())
0059 return 0;
0060
0061 if (reg == APIC_LVR)
0062 return 0x14;
0063 if (reg != APIC_ID)
0064 return 0;
0065
0066 ret = HYPERVISOR_platform_op(&op);
0067 if (ret)
0068 op.u.pcpu_info.apic_id = BAD_APICID;
0069
0070 return op.u.pcpu_info.apic_id << 24;
0071 }
0072
0073 static void xen_apic_write(u32 reg, u32 val)
0074 {
0075 if (reg == APIC_LVTPC) {
0076 (void)pmu_apic_update(reg);
0077 return;
0078 }
0079
0080
0081 WARN(1,"register: %x, value: %x\n", reg, val);
0082 }
0083
0084 static u64 xen_apic_icr_read(void)
0085 {
0086 return 0;
0087 }
0088
0089 static void xen_apic_icr_write(u32 low, u32 id)
0090 {
0091
0092 WARN_ON(1);
0093 }
0094
0095 static u32 xen_safe_apic_wait_icr_idle(void)
0096 {
0097 return 0;
0098 }
0099
0100 static int xen_apic_probe_pv(void)
0101 {
0102 if (xen_pv_domain())
0103 return 1;
0104
0105 return 0;
0106 }
0107
0108 static int xen_madt_oem_check(char *oem_id, char *oem_table_id)
0109 {
0110 return xen_pv_domain();
0111 }
0112
0113 static int xen_id_always_valid(u32 apicid)
0114 {
0115 return 1;
0116 }
0117
0118 static int xen_id_always_registered(void)
0119 {
0120 return 1;
0121 }
0122
0123 static int xen_phys_pkg_id(int initial_apic_id, int index_msb)
0124 {
0125 return initial_apic_id >> index_msb;
0126 }
0127
0128 static void xen_noop(void)
0129 {
0130 }
0131
0132 static void xen_silent_inquire(int apicid)
0133 {
0134 }
0135
0136 static int xen_cpu_present_to_apicid(int cpu)
0137 {
0138 if (cpu_present(cpu))
0139 return cpu_data(cpu).apicid;
0140 else
0141 return BAD_APICID;
0142 }
0143
0144 static struct apic xen_pv_apic = {
0145 .name = "Xen PV",
0146 .probe = xen_apic_probe_pv,
0147 .acpi_madt_oem_check = xen_madt_oem_check,
0148 .apic_id_valid = xen_id_always_valid,
0149 .apic_id_registered = xen_id_always_registered,
0150
0151
0152
0153 .disable_esr = 0,
0154
0155 .check_apicid_used = default_check_apicid_used,
0156 .init_apic_ldr = xen_noop,
0157 .ioapic_phys_id_map = default_ioapic_phys_id_map,
0158 .setup_apic_routing = NULL,
0159 .cpu_present_to_apicid = xen_cpu_present_to_apicid,
0160 .apicid_to_cpu_present = physid_set_mask_of_physid,
0161 .check_phys_apicid_present = default_check_phys_apicid_present,
0162 .phys_pkg_id = xen_phys_pkg_id,
0163
0164 .get_apic_id = xen_get_apic_id,
0165 .set_apic_id = xen_set_apic_id,
0166
0167 .calc_dest_apicid = apic_flat_calc_apicid,
0168
0169 #ifdef CONFIG_SMP
0170 .send_IPI_mask = xen_send_IPI_mask,
0171 .send_IPI_mask_allbutself = xen_send_IPI_mask_allbutself,
0172 .send_IPI_allbutself = xen_send_IPI_allbutself,
0173 .send_IPI_all = xen_send_IPI_all,
0174 .send_IPI_self = xen_send_IPI_self,
0175 #endif
0176
0177 .inquire_remote_apic = xen_silent_inquire,
0178
0179 .read = xen_apic_read,
0180 .write = xen_apic_write,
0181 .eoi_write = xen_apic_write,
0182
0183 .icr_read = xen_apic_icr_read,
0184 .icr_write = xen_apic_icr_write,
0185 .wait_icr_idle = xen_noop,
0186 .safe_wait_icr_idle = xen_safe_apic_wait_icr_idle,
0187 };
0188
0189 static void __init xen_apic_check(void)
0190 {
0191 if (apic == &xen_pv_apic)
0192 return;
0193
0194 pr_info("Switched APIC routing from %s to %s.\n", apic->name,
0195 xen_pv_apic.name);
0196 apic = &xen_pv_apic;
0197 }
0198 void __init xen_init_apic(void)
0199 {
0200 x86_apic_ops.io_apic_read = xen_io_apic_read;
0201
0202
0203 if (!xen_initial_domain())
0204 apic = &xen_pv_apic;
0205
0206 x86_platform.apic_post_init = xen_apic_check;
0207 }
0208 apic_driver(xen_pv_apic);