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