2 Copyright © 1995-2018, The AROS Development Team. All rights reserved.
6 #include <aros/asmcall.h>
7 #include <proto/acpica.h>
8 #include <proto/exec.h>
13 #include "kernel_base.h"
14 #include "kernel_debug.h"
15 #include "kernel_intern.h"
19 #include "apic_ia32.h"
23 #define ACPI_MODPRIO_APIC 100
26 extern struct KernBootPrivate
*__KernBootPrivate
;
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
)
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
=
50 (struct APICCPUWake_Data
*)regs
->rbx
;
52 (struct APICCPUWake_Data
*)regs
->ebx
;
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
));
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
))
85 struct PlatformData
*pdata
= tsdata
->acpits_UserData
;
87 D(bug("[Kernel:ACPI-APIC] ## %s()\n", __func__
));
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
));
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
))
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))
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
)
129 reg
= APIC_LINT0_VEC
;
133 reg
= APIC_LINT1_VEC
;
137 /* Invalid LINT# value */
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
;
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
)
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
))
197 struct PlatformData
*pdata
= tsdata
->acpits_UserData
;
199 D(bug("[Kernel:ACPI-APIC] ## %s()\n", __func__
));
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);
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
++;
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
))
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
);
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
);
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
++;
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
);
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)