revert between 56095 -> 55830 in arch
[AROS.git] / arch / all-pc / kernel / acpi_apic.c
bloba16048de18e92eafe77ee12756ccbd29fc5edf33
1 /*
2 Copyright © 1995-2018, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/asmcall.h>
7 #include <proto/acpica.h>
8 #include <proto/exec.h>
10 #include <inttypes.h>
11 #include <string.h>
13 #include "kernel_base.h"
14 #include "kernel_debug.h"
15 #include "kernel_intern.h"
17 #include "acpi.h"
18 #include "apic.h"
19 #include "apic_ia32.h"
21 #define D(x)
23 #define ACPI_MODPRIO_APIC 100
25 #if (__WORDSIZE==64)
26 extern struct KernBootPrivate *__KernBootPrivate;
27 #endif
29 /************************************************************************************************
30 ACPI APIC RELATED FUNCTIONS
31 ************************************************************************************************/
33 const char *ACPI_TABLE_MADT_STR __attribute__((weak)) = "APIC";
35 void acpi_APIC_AllocPrivate(struct PlatformData *pdata)
37 if (!pdata->kb_APIC)
39 pdata->kb_APIC = AllocMem(sizeof(struct APICData) + pdata->kb_ACPI->acpi_apicCnt * sizeof(struct CPUData), MEMF_CLEAR);
40 pdata->kb_APIC->apic_count = 1; /* Only one CPU is running right now */
42 D(bug("[Kernel:ACPI-APIC] Local APIC Private @ 0x%p, for %u APIC's\n", pdata->kb_APIC, pdata->kb_ACPI->acpi_apicCnt));
46 void acpi_APIC_HandleCPUWakeSC(struct ExceptionContext *regs)
48 struct APICCPUWake_Data *apicWake =
49 #if (__WORDSIZE==64)
50 (struct APICCPUWake_Data *)regs->rbx;
51 #else
52 (struct APICCPUWake_Data *)regs->ebx;
53 #endif
55 D(bug("[Kernel:ACPI-APIC] %s: Handle Wake CPU SysCall\n", __func__));
56 D(bug("[Kernel:ACPI-APIC] %s: Wake data @ 0x%p\n", __func__, apicWake));
57 D(bug("[Kernel:ACPI-APIC] %s: Attempting to wake APIC ID %03u (base @ 0x%p)\n", __func__, apicWake->cpuw_apicid, apicWake->cpuw_apicbase));
59 #if (__WORDSIZE==64)
60 regs->rax =
61 #else
62 regs->eax =
63 #endif
64 core_APIC_Wake(apicWake->cpuw_apicstartrip, apicWake->cpuw_apicid, apicWake->cpuw_apicbase);
66 core_LeaveInterrupt(regs);
69 struct syscallx86_Handler acpi_APIC_SCCPUWakeHandler =
72 .ln_Name = (APTR)SC_X86CPUWAKE
74 (APTR)acpi_APIC_HandleCPUWakeSC
77 /* Process the 'Local APIC Address Override' MADT Table */
78 AROS_UFH3(static IPTR, ACPI_hook_Table_LAPIC_Addr_Ovr_Parse,
79 AROS_UFHA(struct Hook *, table_hook, A0),
80 AROS_UFHA(ACPI_MADT_LOCAL_APIC_OVERRIDE *, lapic_addr_ovr, A2),
81 AROS_UFHA(struct ACPI_TABLESCAN_DATA *, tsdata, A1))
83 AROS_USERFUNC_INIT
85 struct PlatformData *pdata = tsdata->acpits_UserData;
87 D(bug("[Kernel:ACPI-APIC] ## %s()\n", __func__));
89 if (!pdata->kb_APIC)
91 ACPI_TABLE_MADT *madtTable = (ACPI_TABLE_MADT *)tsdata->acpits_Table;
93 acpi_APIC_AllocPrivate(pdata);
94 pdata->kb_ACPI->acpi_madt = madtTable; /* Cache ACPI data for secondary cores */
95 pdata->kb_APIC->flags = ((madtTable->Flags & ACPI_MADT_PCAT_COMPAT) == ACPI_MADT_MULTIPLE_APIC) ? APF_8259 : 0;
98 pdata->kb_APIC->lapicBase = lapic_addr_ovr->Address;
100 D(bug("[Kernel:ACPI-APIC] %s: Local APIC address Override to 0x%p\n", __func__, pdata->kb_APIC->lapicBase));
102 return TRUE;
104 AROS_USERFUNC_EXIT
107 /* Process the 'Local APIC Non-Maskable Interrupt' MADT Table */
108 AROS_UFH3(IPTR, ACPI_hook_Table_LAPIC_NMI_Parse,
109 AROS_UFHA(struct Hook *, table_hook, A0),
110 AROS_UFHA(ACPI_MADT_LOCAL_APIC_NMI *, lapic_nmi, A2),
111 AROS_UFHA(struct PlatformData *, pdata, A1))
113 AROS_USERFUNC_INIT
115 IPTR cpu_num = (IPTR)table_hook->h_Data;
117 D(bug("[Kernel:ACPI-APIC] ## %s()\n", __func__));
119 if ((lapic_nmi->ProcessorId == pdata->kb_APIC->cores[cpu_num].cpu_PrivateID) || (lapic_nmi->ProcessorId == 0xff))
121 UWORD reg;
122 ULONG val = LVT_MT_NMI; /* This is the default (edge-triggered, active low) */
124 D(bug("[Kernel:ACPI-APIC.%03u] %s: NMI LINT%u\n", cpu_num, __func__, lapic_nmi->Lint));
126 switch (lapic_nmi->Lint)
128 case 0:
129 reg = APIC_LINT0_VEC;
130 break;
132 case 1:
133 reg = APIC_LINT1_VEC;
134 break;
136 default:
137 /* Invalid LINT# value */
138 return FALSE;
141 if ((lapic_nmi->IntiFlags & ACPI_MADT_POLARITY_MASK) == ACPI_MADT_POLARITY_ACTIVE_LOW)
143 D(bug("[Kernel:ACPI-APIC.%03u] %s: NMI active low\n", cpu_num, __func__));
144 val |= LVT_ACTIVE_LOW;
147 if ((lapic_nmi->IntiFlags & ACPI_MADT_TRIGGER_MASK) == ACPI_MADT_TRIGGER_LEVEL)
149 D(bug("[Kernel:ACPI-APIC.%03u] %s: NMI level-triggered\n", cpu_num, __func__));
150 val |= LVT_TGM_LEVEL;
153 APIC_REG(pdata->kb_APIC->lapicBase, reg) = val;
154 return TRUE;
157 return FALSE;
159 AROS_USERFUNC_EXIT
163 * Initialize APIC on a CPU core with specified number.
164 * This routine is run by all cores.
166 void acpi_APIC_InitCPU(struct PlatformData *pdata, IPTR cpuNum)
168 D(bug("[Kernel:ACPI-APIC] %s(%03u)\n", __func__, cpuNum));
170 /* Initialize APIC to the default configuration */
171 core_APIC_Init(pdata->kb_APIC, cpuNum);
173 if (pdata->kb_ACPI->acpi_madt)
175 struct Hook hook;
177 D(bug("[Kernel:ACPI-APIC] %s: Parsing NMI ..\n", __func__));
179 /* Set up NMI for ourselves */
180 hook.h_Entry = (APTR)ACPI_hook_Table_LAPIC_NMI_Parse;
181 hook.h_Data = (APTR)cpuNum;
182 acpi_ScanTableEntries(pdata->kb_ACPI->acpi_madt, sizeof(ACPI_TABLE_MADT), ACPI_MADT_TYPE_LOCAL_APIC_NMI, &hook, pdata);
187 * Process the 'Local APIC' MADT Table.
188 * This function collects APIC IDs.
190 AROS_UFH3(static IPTR, ACPI_hook_Table_LAPIC_Parse,
191 AROS_UFHA(struct Hook *, table_hook, A0),
192 AROS_UFHA(ACPI_MADT_LOCAL_APIC *, processor, A2),
193 AROS_UFHA(struct ACPI_TABLESCAN_DATA *, tsdata, A1))
195 AROS_USERFUNC_INIT
197 struct PlatformData *pdata = tsdata->acpits_UserData;
199 D(bug("[Kernel:ACPI-APIC] ## %s()\n", __func__));
201 if (!pdata->kb_APIC)
203 ACPI_TABLE_MADT *madtTable = (ACPI_TABLE_MADT *)tsdata->acpits_Table;
205 acpi_APIC_AllocPrivate(pdata);
206 pdata->kb_APIC->lapicBase = madtTable->Address;
207 pdata->kb_ACPI->acpi_madt = madtTable; /* Cache ACPI data for secondary cores */
208 pdata->kb_APIC->flags = ((madtTable->Flags & ACPI_MADT_PCAT_COMPAT) == ACPI_MADT_MULTIPLE_APIC) ? APF_8259 : 0;
210 bug("[Kernel:ACPI-APIC] Local APIC address 0x%p; Flags 0x%04X\n", pdata->kb_APIC->lapicBase, pdata->kb_APIC->flags);
211 D(bug("[Kernel:ACPI-APIC] MADT @ 0x%p\n", pdata->kb_ACPI->acpi_madt));
213 /* Remember ID of the bootstrap APIC, this is CPU #1 */
214 pdata->kb_APIC->cores[0].cpu_LocalID = core_APIC_GetID(pdata->kb_APIC->lapicBase);
215 D(bug("[Kernel:ACPI-APIC] BSP ID: 0x%02X\n", pdata->kb_APIC->cores[0].cpu_LocalID));
218 if ((pdata->kb_APIC) && (processor->LapicFlags & ACPI_MADT_ENABLED))
220 if (pdata->kb_APIC->cores[0].cpu_LocalID == processor->Id)
222 /* This is the BSP, slot 0 is always reserved for it. */
223 bug("[Kernel:ACPI-APIC] Registering Core #1 [ID=%03u] as BSP\n", processor->Id);
225 pdata->kb_APIC->cores[0].cpu_PrivateID = processor->ProcessorId;
227 pdata->kb_APIC->cores[0].cpu_GDT = __KernBootPrivate->BOOTGDT;
228 pdata->kb_APIC->cores[0].cpu_TLS = __KernBootPrivate->BOOTTLS;
229 pdata->kb_APIC->cores[0].cpu_IDT = __KernBootPrivate->BOOTIDT;
230 pdata->kb_APIC->cores[0].cpu_MMU = &__KernBootPrivate->MMU;
232 /* Initialize LAPIC for ourselves (CPU #0) */
233 acpi_APIC_InitCPU(pdata, 0);
235 else
237 /* Add one more AP */
238 bug("[Kernel:ACPI-APIC] Registering Core #%u [ID=%03u:%03u]\n", pdata->kb_APIC->apic_count + 1, processor->Id, processor->ProcessorId);
240 pdata->kb_APIC->cores[pdata->kb_APIC->apic_count].cpu_LocalID = processor->Id;
241 pdata->kb_APIC->cores[pdata->kb_APIC->apic_count].cpu_PrivateID = processor->ProcessorId;
243 /* register the SysCall Handler for our Wake requests .. */
244 krnAddSysCallHandler(pdata, &acpi_APIC_SCCPUWakeHandler, TRUE, FALSE);
246 pdata->kb_APIC->apic_count++;
249 return TRUE;
252 return FALSE;
254 AROS_USERFUNC_EXIT
258 * Process the 'Local APIC' MADT Table.
259 * This function counts the available APICs.
261 AROS_UFH3(static IPTR, ACPI_hook_Table_LAPIC_Count,
262 AROS_UFHA(struct Hook *, table_hook, A0),
263 AROS_UFHA(ACPI_MADT_LOCAL_APIC *, processor, A2),
264 AROS_UFHA(struct ACPI_TABLESCAN_DATA *, tsdata, A1))
266 AROS_USERFUNC_INIT
268 struct PlatformData *pdata = tsdata->acpits_UserData;
269 struct ACPI_TABLE_HOOK *scanHook;
271 D(bug("[Kernel:ACPI-APIC] ## %s()\n", __func__));
273 if (pdata->kb_ACPI->acpi_apicCnt == 0)
276 * The local APIC base address is obtained from the MADT (32-bit value) and
277 * (optionally) overridden by a LAPIC_ADDR_OVR entry (64-bit value).
279 scanHook = (struct ACPI_TABLE_HOOK *)AllocMem(sizeof(struct ACPI_TABLE_HOOK), MEMF_CLEAR);
280 if (scanHook)
282 scanHook->acpith_Node.ln_Name = (char *)ACPI_TABLE_MADT_STR;
283 scanHook->acpith_Node.ln_Pri = ACPI_MODPRIO_APIC - 10; /* Queue 10 priority levels after the module parser */
284 scanHook->acpith_Hook.h_Entry = (APTR)ACPI_hook_Table_LAPIC_Addr_Ovr_Parse;
285 scanHook->acpith_HeaderLen = sizeof(ACPI_TABLE_MADT);
286 scanHook->acpith_EntryType = ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE;
287 scanHook->acpith_UserData = pdata;
288 Enqueue(&pdata->kb_ACPI->acpi_tablehooks, &scanHook->acpith_Node);
291 scanHook = (struct ACPI_TABLE_HOOK *)AllocMem(sizeof(struct ACPI_TABLE_HOOK), MEMF_CLEAR);
292 if (scanHook)
294 scanHook->acpith_Node.ln_Name = (char *)ACPI_TABLE_MADT_STR;
295 scanHook->acpith_Node.ln_Pri = ACPI_MODPRIO_APIC - 20; /* Queue 20 priority levels after the module parser */
296 scanHook->acpith_Hook.h_Entry = (APTR)ACPI_hook_Table_LAPIC_Parse;
297 scanHook->acpith_HeaderLen = sizeof(ACPI_TABLE_MADT);
298 scanHook->acpith_EntryType = ACPI_MADT_TYPE_LOCAL_APIC;
299 scanHook->acpith_UserData = pdata;
300 Enqueue(&pdata->kb_ACPI->acpi_tablehooks, &scanHook->acpith_Node);
303 pdata->kb_ACPI->acpi_apicCnt++;
305 return TRUE;
307 AROS_USERFUNC_EXIT
310 void ACPI_APIC_SUPPORT(struct PlatformData *pdata)
312 struct ACPI_TABLE_HOOK *scanHook;
314 scanHook = (struct ACPI_TABLE_HOOK *)AllocMem(sizeof(struct ACPI_TABLE_HOOK), MEMF_CLEAR);
315 if (scanHook)
317 D(bug("[Kernel:ACPI-APIC] Registering APIC Table Parser...\n"));
318 D(bug("[Kernel:ACPI-APIC] %s: Table Hook @ 0x%p\n", __func__, scanHook));
319 scanHook->acpith_Node.ln_Name = (char *)ACPI_TABLE_MADT_STR;
320 scanHook->acpith_Node.ln_Pri = ACPI_MODPRIO_APIC;
321 scanHook->acpith_Hook.h_Entry = (APTR)ACPI_hook_Table_LAPIC_Count;
322 scanHook->acpith_HeaderLen = sizeof(ACPI_TABLE_MADT);
323 scanHook->acpith_EntryType = ACPI_MADT_TYPE_LOCAL_APIC;
324 scanHook->acpith_UserData = pdata;
325 Enqueue(&pdata->kb_ACPI->acpi_tablehooks, &scanHook->acpith_Node);
327 D(bug("[Kernel:ACPI-APIC] Registering done\n"));
330 DECLARESET(KERNEL__ACPISUPPORT)
331 ADD2SET(ACPI_APIC_SUPPORT, KERNEL__ACPISUPPORT, 0)