diff options
| -rw-r--r-- | arch/x86/xen/apic.c | 180 | ||||
| -rw-r--r-- | arch/x86/xen/enlighten.c | 90 |
2 files changed, 181 insertions, 89 deletions
diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c index 7005ced5d1ad..5e0ecaf4c336 100644 --- a/arch/x86/xen/apic.c +++ b/arch/x86/xen/apic.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <xen/xen.h> | 7 | #include <xen/xen.h> |
| 8 | #include <xen/interface/physdev.h> | 8 | #include <xen/interface/physdev.h> |
| 9 | #include "xen-ops.h" | 9 | #include "xen-ops.h" |
| 10 | #include "smp.h" | ||
| 10 | 11 | ||
| 11 | static unsigned int xen_io_apic_read(unsigned apic, unsigned reg) | 12 | static unsigned int xen_io_apic_read(unsigned apic, unsigned reg) |
| 12 | { | 13 | { |
| @@ -28,7 +29,186 @@ static unsigned int xen_io_apic_read(unsigned apic, unsigned reg) | |||
| 28 | return 0xfd; | 29 | return 0xfd; |
| 29 | } | 30 | } |
| 30 | 31 | ||
| 32 | static unsigned long xen_set_apic_id(unsigned int x) | ||
| 33 | { | ||
| 34 | WARN_ON(1); | ||
| 35 | return x; | ||
| 36 | } | ||
| 37 | |||
| 38 | static unsigned int xen_get_apic_id(unsigned long x) | ||
| 39 | { | ||
| 40 | return ((x)>>24) & 0xFFu; | ||
| 41 | } | ||
| 42 | |||
| 43 | static u32 xen_apic_read(u32 reg) | ||
| 44 | { | ||
| 45 | struct xen_platform_op op = { | ||
| 46 | .cmd = XENPF_get_cpuinfo, | ||
| 47 | .interface_version = XENPF_INTERFACE_VERSION, | ||
| 48 | .u.pcpu_info.xen_cpuid = 0, | ||
| 49 | }; | ||
| 50 | int ret = 0; | ||
| 51 | |||
| 52 | /* Shouldn't need this as APIC is turned off for PV, and we only | ||
| 53 | * get called on the bootup processor. But just in case. */ | ||
| 54 | if (!xen_initial_domain() || smp_processor_id()) | ||
| 55 | return 0; | ||
| 56 | |||
| 57 | if (reg == APIC_LVR) | ||
| 58 | return 0x10; | ||
| 59 | #ifdef CONFIG_X86_32 | ||
| 60 | if (reg == APIC_LDR) | ||
| 61 | return SET_APIC_LOGICAL_ID(1UL << smp_processor_id()); | ||
| 62 | #endif | ||
| 63 | if (reg != APIC_ID) | ||
| 64 | return 0; | ||
| 65 | |||
| 66 | ret = HYPERVISOR_dom0_op(&op); | ||
| 67 | if (ret) | ||
| 68 | return 0; | ||
| 69 | |||
| 70 | return op.u.pcpu_info.apic_id << 24; | ||
| 71 | } | ||
| 72 | |||
| 73 | static void xen_apic_write(u32 reg, u32 val) | ||
| 74 | { | ||
| 75 | /* Warn to see if there's any stray references */ | ||
| 76 | WARN_ON(1); | ||
| 77 | } | ||
| 78 | |||
| 79 | static u64 xen_apic_icr_read(void) | ||
| 80 | { | ||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | |||
| 84 | static void xen_apic_icr_write(u32 low, u32 id) | ||
| 85 | { | ||
| 86 | /* Warn to see if there's any stray references */ | ||
| 87 | WARN_ON(1); | ||
| 88 | } | ||
| 89 | |||
| 90 | static u32 xen_safe_apic_wait_icr_idle(void) | ||
| 91 | { | ||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | static int xen_apic_probe_pv(void) | ||
| 96 | { | ||
| 97 | if (xen_pv_domain()) | ||
| 98 | return 1; | ||
| 99 | |||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | static int xen_madt_oem_check(char *oem_id, char *oem_table_id) | ||
| 104 | { | ||
| 105 | return xen_pv_domain(); | ||
| 106 | } | ||
| 107 | |||
| 108 | static int xen_id_always_valid(int apicid) | ||
| 109 | { | ||
| 110 | return 1; | ||
| 111 | } | ||
| 112 | |||
| 113 | static int xen_id_always_registered(void) | ||
| 114 | { | ||
| 115 | return 1; | ||
| 116 | } | ||
| 117 | |||
| 118 | static int xen_phys_pkg_id(int initial_apic_id, int index_msb) | ||
| 119 | { | ||
| 120 | return initial_apic_id >> index_msb; | ||
| 121 | } | ||
| 122 | |||
| 123 | #ifdef CONFIG_X86_32 | ||
| 124 | static int xen_x86_32_early_logical_apicid(int cpu) | ||
| 125 | { | ||
| 126 | /* Match with APIC_LDR read. Otherwise setup_local_APIC complains. */ | ||
| 127 | return 1 << cpu; | ||
| 128 | } | ||
| 129 | #endif | ||
| 130 | |||
| 131 | static void xen_noop(void) | ||
| 132 | { | ||
| 133 | } | ||
| 134 | |||
| 135 | static void xen_silent_inquire(int apicid) | ||
| 136 | { | ||
| 137 | } | ||
| 138 | |||
| 139 | static struct apic xen_pv_apic = { | ||
| 140 | .name = "Xen PV", | ||
| 141 | .probe = xen_apic_probe_pv, | ||
| 142 | .acpi_madt_oem_check = xen_madt_oem_check, | ||
| 143 | .apic_id_valid = xen_id_always_valid, | ||
| 144 | .apic_id_registered = xen_id_always_registered, | ||
| 145 | |||
| 146 | /* .irq_delivery_mode - used in native_compose_msi_msg only */ | ||
| 147 | /* .irq_dest_mode - used in native_compose_msi_msg only */ | ||
| 148 | |||
| 149 | .target_cpus = default_target_cpus, | ||
| 150 | .disable_esr = 0, | ||
| 151 | /* .dest_logical - default_send_IPI_ use it but we use our own. */ | ||
| 152 | .check_apicid_used = default_check_apicid_used, /* Used on 32-bit */ | ||
| 153 | |||
| 154 | .vector_allocation_domain = flat_vector_allocation_domain, | ||
| 155 | .init_apic_ldr = xen_noop, /* setup_local_APIC calls it */ | ||
| 156 | |||
| 157 | .ioapic_phys_id_map = default_ioapic_phys_id_map, /* Used on 32-bit */ | ||
| 158 | .setup_apic_routing = NULL, | ||
| 159 | .cpu_present_to_apicid = default_cpu_present_to_apicid, | ||
| 160 | .apicid_to_cpu_present = physid_set_mask_of_physid, /* Used on 32-bit */ | ||
| 161 | .check_phys_apicid_present = default_check_phys_apicid_present, /* smp_sanity_check needs it */ | ||
| 162 | .phys_pkg_id = xen_phys_pkg_id, /* detect_ht */ | ||
| 163 | |||
| 164 | .get_apic_id = xen_get_apic_id, | ||
| 165 | .set_apic_id = xen_set_apic_id, /* Can be NULL on 32-bit. */ | ||
| 166 | .apic_id_mask = 0xFF << 24, /* Used by verify_local_APIC. Match with what xen_get_apic_id does. */ | ||
| 167 | |||
| 168 | .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, | ||
| 169 | |||
| 170 | #ifdef CONFIG_SMP | ||
| 171 | .send_IPI_mask = xen_send_IPI_mask, | ||
| 172 | .send_IPI_mask_allbutself = xen_send_IPI_mask_allbutself, | ||
| 173 | .send_IPI_allbutself = xen_send_IPI_allbutself, | ||
| 174 | .send_IPI_all = xen_send_IPI_all, | ||
| 175 | .send_IPI_self = xen_send_IPI_self, | ||
| 176 | #endif | ||
| 177 | /* .wait_for_init_deassert- used by AP bootup - smp_callin which we don't use */ | ||
| 178 | .inquire_remote_apic = xen_silent_inquire, | ||
| 179 | |||
| 180 | .read = xen_apic_read, | ||
| 181 | .write = xen_apic_write, | ||
| 182 | .eoi_write = xen_apic_write, | ||
| 183 | |||
| 184 | .icr_read = xen_apic_icr_read, | ||
| 185 | .icr_write = xen_apic_icr_write, | ||
| 186 | .wait_icr_idle = xen_noop, | ||
| 187 | .safe_wait_icr_idle = xen_safe_apic_wait_icr_idle, | ||
| 188 | |||
| 189 | #ifdef CONFIG_X86_32 | ||
| 190 | /* generic_processor_info and setup_local_APIC. */ | ||
| 191 | .x86_32_early_logical_apicid = xen_x86_32_early_logical_apicid, | ||
| 192 | #endif | ||
| 193 | }; | ||
| 194 | |||
| 195 | static void __init xen_apic_check(void) | ||
| 196 | { | ||
| 197 | if (apic == &xen_pv_apic) | ||
| 198 | return; | ||
| 199 | |||
| 200 | pr_info("Switched APIC routing from %s to %s.\n", apic->name, | ||
| 201 | xen_pv_apic.name); | ||
| 202 | apic = &xen_pv_apic; | ||
| 203 | } | ||
| 31 | void __init xen_init_apic(void) | 204 | void __init xen_init_apic(void) |
| 32 | { | 205 | { |
| 33 | x86_io_apic_ops.read = xen_io_apic_read; | 206 | x86_io_apic_ops.read = xen_io_apic_read; |
| 207 | /* On PV guests the APIC CPUID bit is disabled so none of the | ||
| 208 | * routines end up executing. */ | ||
| 209 | if (!xen_initial_domain()) | ||
| 210 | apic = &xen_pv_apic; | ||
| 211 | |||
| 212 | x86_platform.apic_post_init = xen_apic_check; | ||
| 34 | } | 213 | } |
| 214 | apic_driver(xen_pv_apic); | ||
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 5240f563076d..b9a227284149 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
| @@ -927,92 +927,6 @@ static void xen_io_delay(void) | |||
| 927 | { | 927 | { |
| 928 | } | 928 | } |
| 929 | 929 | ||
| 930 | #ifdef CONFIG_X86_LOCAL_APIC | ||
| 931 | static unsigned long xen_set_apic_id(unsigned int x) | ||
| 932 | { | ||
| 933 | WARN_ON(1); | ||
| 934 | return x; | ||
| 935 | } | ||
| 936 | static unsigned int xen_get_apic_id(unsigned long x) | ||
| 937 | { | ||
| 938 | return ((x)>>24) & 0xFFu; | ||
| 939 | } | ||
| 940 | static u32 xen_apic_read(u32 reg) | ||
| 941 | { | ||
| 942 | struct xen_platform_op op = { | ||
| 943 | .cmd = XENPF_get_cpuinfo, | ||
| 944 | .interface_version = XENPF_INTERFACE_VERSION, | ||
| 945 | .u.pcpu_info.xen_cpuid = 0, | ||
| 946 | }; | ||
| 947 | int ret = 0; | ||
| 948 | |||
| 949 | /* Shouldn't need this as APIC is turned off for PV, and we only | ||
| 950 | * get called on the bootup processor. But just in case. */ | ||
| 951 | if (!xen_initial_domain() || smp_processor_id()) | ||
| 952 | return 0; | ||
| 953 | |||
| 954 | if (reg == APIC_LVR) | ||
| 955 | return 0x10; | ||
| 956 | |||
| 957 | if (reg != APIC_ID) | ||
| 958 | return 0; | ||
| 959 | |||
| 960 | ret = HYPERVISOR_dom0_op(&op); | ||
| 961 | if (ret) | ||
| 962 | return 0; | ||
| 963 | |||
| 964 | return op.u.pcpu_info.apic_id << 24; | ||
| 965 | } | ||
| 966 | |||
| 967 | static void xen_apic_write(u32 reg, u32 val) | ||
| 968 | { | ||
| 969 | /* Warn to see if there's any stray references */ | ||
| 970 | WARN_ON(1); | ||
| 971 | } | ||
| 972 | |||
| 973 | static u64 xen_apic_icr_read(void) | ||
| 974 | { | ||
| 975 | return 0; | ||
| 976 | } | ||
| 977 | |||
| 978 | static void xen_apic_icr_write(u32 low, u32 id) | ||
| 979 | { | ||
| 980 | /* Warn to see if there's any stray references */ | ||
| 981 | WARN_ON(1); | ||
| 982 | } | ||
| 983 | |||
| 984 | static void xen_apic_wait_icr_idle(void) | ||
| 985 | { | ||
| 986 | return; | ||
| 987 | } | ||
| 988 | |||
| 989 | static u32 xen_safe_apic_wait_icr_idle(void) | ||
| 990 | { | ||
| 991 | return 0; | ||
| 992 | } | ||
| 993 | |||
| 994 | static void set_xen_basic_apic_ops(void) | ||
| 995 | { | ||
| 996 | apic->read = xen_apic_read; | ||
| 997 | apic->write = xen_apic_write; | ||
| 998 | apic->icr_read = xen_apic_icr_read; | ||
| 999 | apic->icr_write = xen_apic_icr_write; | ||
| 1000 | apic->wait_icr_idle = xen_apic_wait_icr_idle; | ||
| 1001 | apic->safe_wait_icr_idle = xen_safe_apic_wait_icr_idle; | ||
| 1002 | apic->set_apic_id = xen_set_apic_id; | ||
| 1003 | apic->get_apic_id = xen_get_apic_id; | ||
| 1004 | |||
| 1005 | #ifdef CONFIG_SMP | ||
| 1006 | apic->send_IPI_allbutself = xen_send_IPI_allbutself; | ||
| 1007 | apic->send_IPI_mask_allbutself = xen_send_IPI_mask_allbutself; | ||
| 1008 | apic->send_IPI_mask = xen_send_IPI_mask; | ||
| 1009 | apic->send_IPI_all = xen_send_IPI_all; | ||
| 1010 | apic->send_IPI_self = xen_send_IPI_self; | ||
| 1011 | #endif | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | #endif | ||
| 1015 | |||
| 1016 | static void xen_clts(void) | 930 | static void xen_clts(void) |
| 1017 | { | 931 | { |
| 1018 | struct multicall_space mcs; | 932 | struct multicall_space mcs; |
| @@ -1618,7 +1532,7 @@ asmlinkage __visible void __init xen_start_kernel(void) | |||
| 1618 | /* | 1532 | /* |
| 1619 | * set up the basic apic ops. | 1533 | * set up the basic apic ops. |
| 1620 | */ | 1534 | */ |
| 1621 | set_xen_basic_apic_ops(); | 1535 | xen_init_apic(); |
| 1622 | #endif | 1536 | #endif |
| 1623 | 1537 | ||
| 1624 | if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) { | 1538 | if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) { |
| @@ -1731,8 +1645,6 @@ asmlinkage __visible void __init xen_start_kernel(void) | |||
| 1731 | if (HYPERVISOR_dom0_op(&op) == 0) | 1645 | if (HYPERVISOR_dom0_op(&op) == 0) |
| 1732 | boot_params.kbd_status = op.u.firmware_info.u.kbd_shift_flags; | 1646 | boot_params.kbd_status = op.u.firmware_info.u.kbd_shift_flags; |
| 1733 | 1647 | ||
| 1734 | xen_init_apic(); | ||
| 1735 | |||
| 1736 | /* Make sure ACS will be enabled */ | 1648 | /* Make sure ACS will be enabled */ |
| 1737 | pci_request_acs(); | 1649 | pci_request_acs(); |
| 1738 | 1650 | ||
