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