1/* 2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#include <config.h> 8#include <arch/kernel/x2apic.h> 9 10BOOT_CODE bool_t x2apic_is_enabled(void) 11{ 12 apic_base_msr_t apic_base_msr; 13 apic_base_msr.words[0] = x86_rdmsr_low(IA32_APIC_BASE_MSR); 14 15 if ((x86_cpuid_ecx(1, 0) & BIT(21)) && 16 apic_base_msr_get_enabled(apic_base_msr) && 17 apic_base_msr_get_x2apic(apic_base_msr)) { 18 return true; 19 } 20 return false; 21} 22 23#ifdef CONFIG_X2APIC 24BOOT_CODE bool_t apic_enable(void) 25{ 26 apic_base_msr_t apic_base_msr; 27 apic_base_msr.words[0] = x86_rdmsr_low(IA32_APIC_BASE_MSR); 28 29 if (!apic_base_msr_get_enabled(apic_base_msr)) { 30 printf("APIC: Enabled bit not set\n"); 31 return false; 32 } 33 34 if (x86_cpuid_ecx(1, 0) & BIT(21)) { 35 apic_base_msr = apic_base_msr_set_x2apic(apic_base_msr, 1); 36 x86_wrmsr(IA32_APIC_BASE_MSR, apic_base_msr.words[0]); 37 } else { 38 printf("APIC: x2APIC is not supported on this machine\n"); 39 return false; 40 } 41 42 return true; 43} 44 45bool_t apic_is_interrupt_pending(void) 46{ 47 word_t i; 48 49 assert(int_irq_min % 32 == 0); 50 for (i = int_irq_min; i <= int_irq_max; i += 32) { 51 if (apic_read_reg(APIC_IRR_BASE + ((i / 32) - 1)) != 0) { 52 return true; 53 } 54 } 55 return false; 56} 57 58BOOT_CODE void apic_send_init_ipi(cpu_id_t cpu_id) 59{ 60 apic_write_icr( 61 x2apic_icr2_new( 62 cpu_id /* dest */ 63 ).words[0], 64 x2apic_icr1_new( 65 0, /* dest_shorthand */ 66 1, /* trigger_mode */ 67 1, /* level */ 68 0, /* dest_mode */ 69 5, /* delivery_mode */ 70 0 /* vector */ 71 ).words[0] 72 ); 73 apic_write_icr( 74 apic_icr2_new( 75 cpu_id /* dest */ 76 ).words[0], 77 x2apic_icr1_new( 78 0, /* dest_shorthand */ 79 1, /* trigger_mode */ 80 0, /* level */ 81 0, /* dest_mode */ 82 5, /* delivery_mode */ 83 0 /* vector */ 84 ).words[0] 85 ); 86} 87 88BOOT_CODE void apic_send_startup_ipi(cpu_id_t cpu_id, paddr_t startup_addr) 89{ 90 /* check if 4K aligned */ 91 assert(IS_ALIGNED(startup_addr, PAGE_BITS)); 92 /* check if startup_addr < 640K */ 93 assert(startup_addr < 0xa0000); 94 startup_addr >>= PAGE_BITS; 95 96 apic_write_icr( 97 x2apic_icr2_new( 98 cpu_id /* dest */ 99 ).words[0], 100 x2apic_icr1_new( 101 0, /* dest_shorthand */ 102 0, /* trigger_mode */ 103 0, /* level */ 104 0, /* dest_mode */ 105 6, /* delivery_mode */ 106 startup_addr /* vector */ 107 ).words[0] 108 ); 109} 110 111void apic_send_ipi_core(irq_t vector, cpu_id_t cpu_id) 112{ 113 apic_write_icr( 114 x2apic_icr2_new( 115 cpu_id /* dest */ 116 ).words[0], 117 x2apic_icr1_new( 118 0, /* dest_shorthand */ 119 0, /* trigger_mode */ 120 0, /* level */ 121 0, /* dest_mode */ 122 0, /* delivery_mode */ 123 vector /* vector */ 124 ).words[0] 125 ); 126} 127 128void apic_send_ipi_cluster(irq_t vector, word_t mda) 129{ 130 apic_write_icr( 131 x2apic_icr2_new( 132 mda /* message destination address */ 133 ).words[0], 134 x2apic_icr1_new( 135 0, /* dest_shorthand */ 136 0, /* trigger_mode */ 137 0, /* level */ 138 1, /* dest_mode */ 139 0, /* delivery_mode */ 140 vector /* vector */ 141 ).words[0] 142 ); 143} 144#endif /* CONFIG_X2APIC */ 145