13af1e415SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 23af1e415SThomas Gleixner #define pr_fmt(fmt) "APIC: " fmt 33af1e415SThomas Gleixner 43af1e415SThomas Gleixner #include <asm/apic.h> 53af1e415SThomas Gleixner 63af1e415SThomas Gleixner #include "local.h" 73af1e415SThomas Gleixner 8*3b7c27e6SThomas Gleixner /* 9*3b7c27e6SThomas Gleixner * Use DEFINE_STATIC_CALL_NULL() to avoid having to provide stub functions 10*3b7c27e6SThomas Gleixner * for each callback. The callbacks are setup during boot and all except 11*3b7c27e6SThomas Gleixner * wait_icr_idle() must be initialized before usage. The IPI wrappers 12*3b7c27e6SThomas Gleixner * use static_call() and not static_call_cond() to catch any fails. 13*3b7c27e6SThomas Gleixner */ 14*3b7c27e6SThomas Gleixner #define DEFINE_APIC_CALL(__cb) \ 15*3b7c27e6SThomas Gleixner DEFINE_STATIC_CALL_NULL(apic_call_##__cb, *apic->__cb) 16*3b7c27e6SThomas Gleixner 17*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(eoi); 18*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(native_eoi); 19*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(icr_read); 20*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(icr_write); 21*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(read); 22*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(send_IPI); 23*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(send_IPI_mask); 24*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(send_IPI_mask_allbutself); 25*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(send_IPI_allbutself); 26*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(send_IPI_all); 27*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(send_IPI_self); 28*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(wait_icr_idle); 29*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(wakeup_secondary_cpu); 30*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(wakeup_secondary_cpu_64); 31*3b7c27e6SThomas Gleixner DEFINE_APIC_CALL(write); 32*3b7c27e6SThomas Gleixner 33*3b7c27e6SThomas Gleixner EXPORT_STATIC_CALL_TRAMP_GPL(apic_call_send_IPI_mask); 34*3b7c27e6SThomas Gleixner EXPORT_STATIC_CALL_TRAMP_GPL(apic_call_send_IPI_self); 35*3b7c27e6SThomas Gleixner 36bef4f379SThomas Gleixner /* The container for function call overrides */ 37bef4f379SThomas Gleixner struct apic_override __x86_apic_override __initdata; 38bef4f379SThomas Gleixner 39bef4f379SThomas Gleixner #define apply_override(__cb) \ 40bef4f379SThomas Gleixner if (__x86_apic_override.__cb) \ 41bef4f379SThomas Gleixner apic->__cb = __x86_apic_override.__cb 42bef4f379SThomas Gleixner restore_override_callbacks(void)43bef4f379SThomas Gleixnerstatic __init void restore_override_callbacks(void) 44bef4f379SThomas Gleixner { 45bef4f379SThomas Gleixner apply_override(eoi); 46bef4f379SThomas Gleixner apply_override(native_eoi); 47bef4f379SThomas Gleixner apply_override(write); 48bef4f379SThomas Gleixner apply_override(read); 49bef4f379SThomas Gleixner apply_override(send_IPI); 50bef4f379SThomas Gleixner apply_override(send_IPI_mask); 51bef4f379SThomas Gleixner apply_override(send_IPI_mask_allbutself); 52bef4f379SThomas Gleixner apply_override(send_IPI_allbutself); 53bef4f379SThomas Gleixner apply_override(send_IPI_all); 54bef4f379SThomas Gleixner apply_override(send_IPI_self); 55bef4f379SThomas Gleixner apply_override(icr_read); 56bef4f379SThomas Gleixner apply_override(icr_write); 57bef4f379SThomas Gleixner apply_override(wakeup_secondary_cpu); 58bef4f379SThomas Gleixner apply_override(wakeup_secondary_cpu_64); 59bef4f379SThomas Gleixner } 60bef4f379SThomas Gleixner 61*3b7c27e6SThomas Gleixner #define update_call(__cb) \ 62*3b7c27e6SThomas Gleixner static_call_update(apic_call_##__cb, *apic->__cb) 63*3b7c27e6SThomas Gleixner update_static_calls(void)64*3b7c27e6SThomas Gleixnerstatic __init void update_static_calls(void) 65*3b7c27e6SThomas Gleixner { 66*3b7c27e6SThomas Gleixner update_call(eoi); 67*3b7c27e6SThomas Gleixner update_call(native_eoi); 68*3b7c27e6SThomas Gleixner update_call(write); 69*3b7c27e6SThomas Gleixner update_call(read); 70*3b7c27e6SThomas Gleixner update_call(send_IPI); 71*3b7c27e6SThomas Gleixner update_call(send_IPI_mask); 72*3b7c27e6SThomas Gleixner update_call(send_IPI_mask_allbutself); 73*3b7c27e6SThomas Gleixner update_call(send_IPI_allbutself); 74*3b7c27e6SThomas Gleixner update_call(send_IPI_all); 75*3b7c27e6SThomas Gleixner update_call(send_IPI_self); 76*3b7c27e6SThomas Gleixner update_call(icr_read); 77*3b7c27e6SThomas Gleixner update_call(icr_write); 78*3b7c27e6SThomas Gleixner update_call(wait_icr_idle); 79*3b7c27e6SThomas Gleixner update_call(wakeup_secondary_cpu); 80*3b7c27e6SThomas Gleixner update_call(wakeup_secondary_cpu_64); 81*3b7c27e6SThomas Gleixner } 82*3b7c27e6SThomas Gleixner apic_setup_apic_calls(void)83bef4f379SThomas Gleixnervoid __init apic_setup_apic_calls(void) 84bef4f379SThomas Gleixner { 85bef4f379SThomas Gleixner /* Ensure that the default APIC has native_eoi populated */ 86bef4f379SThomas Gleixner apic->native_eoi = apic->eoi; 87*3b7c27e6SThomas Gleixner update_static_calls(); 88*3b7c27e6SThomas Gleixner pr_info("Static calls initialized\n"); 89bef4f379SThomas Gleixner } 90bef4f379SThomas Gleixner apic_install_driver(struct apic * driver)913af1e415SThomas Gleixnervoid __init apic_install_driver(struct apic *driver) 923af1e415SThomas Gleixner { 933af1e415SThomas Gleixner if (apic == driver) 943af1e415SThomas Gleixner return; 953af1e415SThomas Gleixner 963af1e415SThomas Gleixner apic = driver; 973af1e415SThomas Gleixner 983af1e415SThomas Gleixner if (IS_ENABLED(CONFIG_X86_X2APIC) && apic->x2apic_set_max_apicid) 993af1e415SThomas Gleixner apic->max_apic_id = x2apic_max_apicid; 1003af1e415SThomas Gleixner 101bef4f379SThomas Gleixner /* Copy the original eoi() callback as KVM/HyperV might overwrite it */ 102bef4f379SThomas Gleixner if (!apic->native_eoi) 103bef4f379SThomas Gleixner apic->native_eoi = apic->eoi; 104bef4f379SThomas Gleixner 105bef4f379SThomas Gleixner /* Apply any already installed callback overrides */ 106bef4f379SThomas Gleixner restore_override_callbacks(); 107*3b7c27e6SThomas Gleixner update_static_calls(); 108bef4f379SThomas Gleixner 1093af1e415SThomas Gleixner pr_info("Switched APIC routing to: %s\n", driver->name); 1103af1e415SThomas Gleixner } 111