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 */
14 compile_assert(number_of_cores_invalid_for_logical_ids, CONFIG_MAX_NUM_NODES <= 8)
15 
16 BOOT_CODE static void
init_xapic_ldr(void)17 init_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 
apic_enable(void)28 BOOT_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 
apic_is_interrupt_pending(void)50 bool_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 
apic_send_init_ipi(cpu_id_t cpu_id)64 BOOT_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 
apic_send_startup_ipi(cpu_id_t cpu_id,paddr_t startup_addr)96 BOOT_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 
apic_send_ipi_core(irq_t vector,cpu_id_t cpu_id)120 void 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 
apic_send_ipi_cluster(irq_t vector,word_t mda)144 void 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