add a proper tombstoned flag.
[AROS.git] / arch / all-pc / kernel / apic.c
blob1812a842c8f240d3d25f548a680ca468683a1108
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <exec/memory.h>
7 #include <proto/exec.h>
9 #include "kernel_base.h"
10 #include "kernel_debug.h"
11 #include "kernel_intern.h"
12 #include "apic.h"
14 #define D(x)
16 /* Initialize APIC by probing */
17 struct APICData *core_APIC_Probe(void)
19 struct APICData *data;
20 APTR ssp;
22 #ifdef __i386__
23 /* Only i386 needs detection. On x86-64 APIC is always present. */
24 ULONG arg = 1;
25 ULONG res;
27 asm volatile("cpuid":"+a"(arg),"=d"(res)::"%ebx", "%ecx");
29 if (!(res & (1 << 9)))
30 return NULL;
32 D(bug("[APIC] Detected by CPUID instruction\n"));
33 #endif
35 /* Assuming uniprocessor IBM PC compatible */
36 data = AllocMem(sizeof(struct APICData) + sizeof(struct CPUData), MEMF_CLEAR);
37 if (!data)
38 return NULL;
40 D(bug("[APIC] APIC Data @ 0x%p\n", data));
42 if ((ssp = SuperState()) != NULL)
44 data->lapicBase = core_APIC_GetBase();
46 D(bug("[APIC] APIC Base = 0x%p\n", data->lapicBase));
48 data->apic_count = 1;
49 data->flags = APF_8259;
50 data->cores[0].cpu_LocalID = core_APIC_GetID(data->lapicBase);
52 UserState(ssp);
54 D(bug("[APIC] ID #%d\n", data->cores[0].cpu_LocalID));
56 data->cores[0].cpu_GDT = __KernBootPrivate->BOOTGDT;
57 data->cores[0].cpu_TLS = __KernBootPrivate->BOOTTLS;
58 data->cores[0].cpu_IDT = __KernBootPrivate->BOOTIDT;
59 data->cores[0].cpu_MMU = &__KernBootPrivate->MMU;
61 /* Just initialize to default state */
62 core_APIC_Init(data, 0);
64 else
66 FreeMem(data, sizeof(struct APICData) + sizeof(struct CPUData));
67 data = NULL;
69 return data;
72 apicid_t core_APIC_GetNumberFromLocal(struct APICData *data, apicid_t apicLocalID)
74 apicid_t __APICNo;
76 D(bug("[APIC] %s()\n", __func__));
78 if (!data)
80 /* No APIC data -> uniprocessor system */
81 if (apicLocalID > 0)
82 return -1;
83 else
84 return 0;
87 for (__APICNo = 0; __APICNo < data->apic_count; __APICNo++)
89 if (data->cores[__APICNo].cpu_LocalID == apicLocalID)
90 return __APICNo;
93 return -1;
96 apicid_t core_APIC_GetNumber(struct APICData *data)
98 apicid_t __APICLogicalID;
100 D(bug("[APIC] %s()\n", __func__));
102 if (!data)
104 D(bug("[APIC] %s: BSP or uniprocessor\n", __func__));
105 /* No APIC data -> uniprocessor system */
106 return 0;
109 __APICLogicalID = core_APIC_GetID(data->lapicBase);
111 D(bug("[APIC] %s: APIC ID %03u\n", __func__, __APICLogicalID));
113 return core_APIC_GetNumberFromLocal(data, __APICLogicalID);
116 void core_APIC_GetMask(struct APICData *data, apicid_t cpuNo, cpumask_t *mask)
118 ULONG *apicMask;
119 int idlong, idbit;
121 D(bug("[APIC] %s()\n", __func__));
123 if ((IPTR)mask != TASKAFFINITY_ANY)
125 idlong = cpuNo / 32;
126 idbit = cpuNo - (idlong * 32);
128 D(bug("[APIC] %s: %d -> %d:%d\n", __func__, cpuNo, idlong, idbit));
129 D(bug("[APIC] %s: mask @ 0x%p\n", __func__, mask));
131 if ((apicMask = (ULONG *)mask) != NULL)
132 apicMask[idlong] = (1 << idbit);
135 return;
138 BOOL core_APIC_CPUInMask(apicid_t cpuNo, cpumask_t *mask)
140 ULONG *apicMask;
141 int idlong, idbit;
143 D(bug("[APIC] %s()\n", __func__));
145 if (mask == NULL)
147 if (cpuNo == 0)
148 return TRUE;
149 return FALSE;
152 if ((IPTR)mask == TASKAFFINITY_ANY)
154 // TODO: make sure it is a valid cpu number in the range of available cpus.
155 return TRUE;
158 idlong = cpuNo / 32;
159 idbit = cpuNo - (idlong * 32);
161 D(bug("[APIC] %s: %d -> %d:%d\n", __func__, cpuNo, idlong, idbit));
162 D(bug("[APIC] %s: mask @ 0x%p\n", __func__, mask));
164 if (((apicMask = (ULONG *)mask) != NULL) && (apicMask[idlong] & (1 << idbit)))
165 return TRUE;
167 return FALSE;