Copyright clean-up (part 1):
[AROS.git] / arch / i386-pc / kernel / smp.c
blob20092deec75568c4f8bec76eee16f15866b0ab25
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/atomic.h>
7 #include <asm/io.h>
8 #include <exec/execbase.h>
9 #include <exec/memory.h>
10 #include <proto/exec.h>
12 #include "kernel_base.h"
13 #include "kernel_debug.h"
14 #include "kernel_intern.h"
15 #include "kernel_syscall.h"
16 #include "apic.h"
17 #include "smpbootstrap.h"
19 #define D(x) x
20 #define DWAKE(x)
22 extern const void *_binary_smpbootstrap_start;
23 extern const void *_binary_smpbootstrap_size;
25 static void smp_Entry(volatile UBYTE *apicready)
28 * This is the entry point for secondary cores.
29 * KernelBase is already set up by the primary CPU, so we can use it.
31 IPTR _APICBase;
32 UWORD _APICID;
33 UBYTE _APICNO;
35 /* Find out ourselves */
36 _APICBase = core_APIC_GetBase();
37 _APICID = core_APIC_GetID(_APICBase);
38 _APICNO = core_APIC_GetNumber(KernelBase->kb_PlatformData->kb_APIC);
40 D(bug("[SMP] smp_Entry[0x%02X]: APIC base @ 0x%p\n", _APICID, _APICBase));
41 D(bug("[SMP] smp_Entry[0x%02X]: Ready lock 0x%p\n", _APICID, apicready));
43 bug("[SMP] APIC #%u of %u Going IDLE (Halting)...\n", _APICNO + 1, KernelBase->kb_PlatformData->kb_APIC->count);
45 /* Signal the bootstrap core that we are running */
46 *apicready = 1;
49 * Unfortunately at the moment we have nothing more to do.
50 * The rest of AROS is not SMP-capable. :-(
52 while (1) asm volatile("hlt");
55 int smp_Setup(void)
57 struct PlatformData *pdata = KernelBase->kb_PlatformData;
58 /* Low memory header is in the tail of memory list - see kernel_startup.c */
59 struct MemHeader *lowmem = (struct MemHeader *)SysBase->MemList.lh_TailPred;
60 APTR smpboot;
61 struct SMPBootstrap *bs;
64 * Allocate space for SMP bootstrap code in low memory. Its address must be page-aligned.
65 * Every CPU starts up in real mode (DAMN CRAP!!!)
67 smpboot = Allocate(lowmem, (unsigned long)&_binary_smpbootstrap_size + PAGE_SIZE - 1);
68 if (!smpboot)
70 D(bug("[SMP] Failed to allocate space for SMP bootstrap\n"));
71 return 0;
74 /* Install SMP bootstrap code */
75 bs = (APTR)AROS_ROUNDUP2((IPTR)smpboot, PAGE_SIZE);
76 CopyMem(&_binary_smpbootstrap_start, bs, (unsigned long)&_binary_smpbootstrap_size);
77 pdata->kb_APIC_TrampolineBase = bs;
79 D(bug("[SMP] Copied APIC bootstrap code to 0x%p\n", bs));
81 bs->IP = smp_Entry;
82 return 1;
86 * Here we wake up our secondary cores.
88 int smp_Wake(void)
90 struct PlatformData *pdata = KernelBase->kb_PlatformData;
91 struct SMPBootstrap *bs = pdata->kb_APIC_TrampolineBase;
92 struct APICData *apic = pdata->kb_APIC;
93 APTR _APICStackBase;
94 IPTR wakeresult;
95 UBYTE i;
96 volatile UBYTE apicready;
98 D(bug("[SMP] Ready spinlock at 0x%p\n", &apicready));
100 /* Core number 0 is our bootstrap core, so we start from No 1 */
101 for (i = 1; i < apic->count; i++)
103 UBYTE apic_id = apic->cores[i].lapicID;
105 D(bug("[SMP] Launching APIC #%u (ID 0x%02X)\n", i + 1, apic_id));
107 /* First we need to allocate a stack for our CPU. */
108 _APICStackBase = AllocMem(STACK_SIZE, MEMF_CLEAR);
109 D(bug("[SMP] Allocated STACK for APIC ID 0x%02X @ 0x%p\n", apic_id, _APICStackBase));
110 if (!_APICStackBase)
111 return 0;
113 /* Give the stack to the CPU */
114 bs->Arg1 = (IPTR)&apicready;
115 bs->SP = _APICStackBase + STACK_SIZE;
117 /* Initialize 'ready' flag to zero before launching the core */
118 apicready = 0;
120 /* Start IPI sequence */
121 wakeresult = core_APIC_Wake(bs, apic_id, apic->lapicBase);
122 /* wakeresult != 0 means error */
123 if (!wakeresult)
126 * Before we proceed we need to make sure that the core has picked up
127 * its stack and we can reload bootstrap argument area with another one.
128 * We use a very simple spinlock in order to perform this waiting.
129 * Previously we have set apicready to 0. When the core starts up,
130 * it writes 1 there.
132 DWAKE(bug("[SMP] Waiting for APIC #%u to initialise .. ", i + 1));
133 while (!apicready);
135 D(bug("[SMP] APIC #%u started up\n", i + 1));
137 D(else bug("[SMP] APIC wake() failed, status 0x%p\n", wakeresult));
140 D(bug("[SMP] Done\n"));
142 return 1;