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/xapic.h> 15#include <arch/kernel/x2apic.h> 16 17#ifdef CONFIG_XAPIC 18#ifdef CONFIG_USE_LOGICAL_IDS 19/* using flat cluster mode we only support 8 cores */ 20compile_assert(number_of_cores_invalid_for_logical_ids, CONFIG_MAX_NUM_NODES <= 8) 21 22BOOT_CODE static void 23init_xapic_ldr(void) 24{ 25 uint32_t ldr; 26 27 apic_write_reg(APIC_DEST_FORMAT, XAPIC_DFR_FLAT); 28 ldr = apic_read_reg(APIC_LOGICAL_DEST) & MASK(XAPIC_LDR_SHIFT); 29 ldr |= (BIT(getCurrentCPUIndex()) << XAPIC_LDR_SHIFT); 30 apic_write_reg(APIC_LOGICAL_DEST, ldr); 31} 32#endif /* CONFIG_USE_LOGICAL_IDS */ 33 34BOOT_CODE bool_t 35apic_enable(void) 36{ 37 apic_base_msr_t apic_base_msr; 38 apic_base_msr.words[0] = x86_rdmsr_low(IA32_APIC_BASE_MSR); 39 40 if (!apic_base_msr_get_enabled(apic_base_msr)) { 41 printf("APIC: Enabled bit not set\n"); 42 return false; 43 } 44 45 if (x2apic_is_enabled()) { 46 printf("x2APIC enabled in BIOS but kernel does not support that\n"); 47 return false; 48 } 49 50#ifdef CONFIG_USE_LOGICAL_IDS 51 init_xapic_ldr(); 52#endif /* CONFIG_USE_LOGICAL_IDS */ 53 54 return true; 55} 56 57bool_t apic_is_interrupt_pending(void) 58{ 59 word_t i; 60 61 /* read 256-bit register: each 32-bit word is 16 byte aligned */ 62 assert(int_irq_min % 32 == 0); 63 for (i = int_irq_min; i <= int_irq_max; i += 32) { 64 if (apic_read_reg(APIC_IRR_BASE + i / 2) != 0) { 65 return true; 66 } 67 } 68 return false; 69} 70 71BOOT_CODE void 72apic_send_init_ipi(cpu_id_t cpu_id) 73{ 74 apic_write_icr( 75 apic_icr2_new( 76 cpu_id /* dest */ 77 ).words[0], 78 apic_icr1_new( 79 0, /* dest_shorthand */ 80 1, /* trigger_mode */ 81 1, /* level */ 82 0, /* delivery_status */ 83 0, /* dest_mode */ 84 5, /* delivery_mode */ 85 0 /* vector */ 86 ).words[0] 87 ); 88 apic_write_icr( 89 apic_icr2_new( 90 cpu_id /* dest */ 91 ).words[0], 92 apic_icr1_new( 93 0, /* dest_shorthand */ 94 1, /* trigger_mode */ 95 0, /* level */ 96 0, /* delivery_status */ 97 0, /* dest_mode */ 98 5, /* delivery_mode */ 99 0 /* vector */ 100 ).words[0] 101 ); 102} 103 104BOOT_CODE void 105apic_send_startup_ipi(cpu_id_t cpu_id, paddr_t startup_addr) 106{ 107 /* check if 4K aligned */ 108 assert(IS_ALIGNED(startup_addr, PAGE_BITS)); 109 /* check if startup_addr < 640K */ 110 assert(startup_addr < 0xa0000); 111 startup_addr >>= PAGE_BITS; 112 113 apic_write_icr( 114 apic_icr2_new( 115 cpu_id /* dest */ 116 ).words[0], 117 apic_icr1_new( 118 0, /* dest_shorthand */ 119 0, /* trigger_mode */ 120 0, /* level */ 121 0, /* delivery_status */ 122 0, /* dest_mode */ 123 6, /* delivery_mode */ 124 startup_addr /* vector */ 125 ).words[0] 126 ); 127} 128 129void apic_send_ipi_core(irq_t vector, cpu_id_t cpu_id) 130{ 131 apic_icr1_t icr1; 132 /* wait till we can send an IPI */ 133 do { 134 icr1.words[0] = apic_read_reg(APIC_ICR1); 135 } while (apic_icr1_get_delivery_status(icr1)); 136 137 apic_write_icr( 138 apic_icr2_new( 139 cpu_id /* dest */ 140 ).words[0], 141 apic_icr1_new( 142 0, /* dest_shorthand */ 143 0, /* trigger_mode */ 144 0, /* level */ 145 0, /* delivery_status */ 146 0, /* dest_mode */ 147 0, /* delivery_mode */ 148 vector /* vector */ 149 ).words[0] 150 ); 151} 152 153void apic_send_ipi_cluster(irq_t vector, word_t mda) 154{ 155 apic_icr1_t icr1; 156 /* wait till we can send an IPI */ 157 do { 158 icr1.words[0] = apic_read_reg(APIC_ICR1); 159 } while (apic_icr1_get_delivery_status(icr1)); 160 161 apic_write_icr( 162 apic_icr2_new( 163 mda /* message destination address */ 164 ).words[0], 165 apic_icr1_new( 166 0, /* dest_shorthand */ 167 0, /* trigger_mode */ 168 0, /* level */ 169 0, /* delivery_status */ 170 1, /* dest_mode */ 171 0, /* delivery_mode */ 172 vector /* vector */ 173 ).words[0] 174 ); 175} 176#endif /* CONFIG_XAPIC */ 177