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