1*9ef1f84bSDavid du Colombier #include "u.h"
2*9ef1f84bSDavid du Colombier #include "../port/lib.h"
3*9ef1f84bSDavid du Colombier #include "mem.h"
4*9ef1f84bSDavid du Colombier #include "dat.h"
5*9ef1f84bSDavid du Colombier #include "fns.h"
6*9ef1f84bSDavid du Colombier
7*9ef1f84bSDavid du Colombier #include "apic.h"
8*9ef1f84bSDavid du Colombier #include "sipi.h"
9*9ef1f84bSDavid du Colombier
10*9ef1f84bSDavid du Colombier #define SIPIHANDLER (KZERO+0x3000)
11*9ef1f84bSDavid du Colombier
12*9ef1f84bSDavid du Colombier /*
13*9ef1f84bSDavid du Colombier * Parameters are passed to the bootstrap code via a vector
14*9ef1f84bSDavid du Colombier * in low memory indexed by the APIC number of the processor.
15*9ef1f84bSDavid du Colombier * The layout, size, and location have to be kept in sync
16*9ef1f84bSDavid du Colombier * with the handler code in l64sipi.s.
17*9ef1f84bSDavid du Colombier */
18*9ef1f84bSDavid du Colombier typedef struct Sipi Sipi;
19*9ef1f84bSDavid du Colombier struct Sipi {
20*9ef1f84bSDavid du Colombier u32int pml4;
21*9ef1f84bSDavid du Colombier u32int _4_;
22*9ef1f84bSDavid du Colombier uintptr stack;
23*9ef1f84bSDavid du Colombier Mach* mach;
24*9ef1f84bSDavid du Colombier uintptr pc;
25*9ef1f84bSDavid du Colombier };
26*9ef1f84bSDavid du Colombier
27*9ef1f84bSDavid du Colombier void
sipi(void)28*9ef1f84bSDavid du Colombier sipi(void)
29*9ef1f84bSDavid du Colombier {
30*9ef1f84bSDavid du Colombier Apic *apic;
31*9ef1f84bSDavid du Colombier Mach *mach;
32*9ef1f84bSDavid du Colombier Sipi *sipi;
33*9ef1f84bSDavid du Colombier int apicno, i;
34*9ef1f84bSDavid du Colombier u8int *sipiptr;
35*9ef1f84bSDavid du Colombier uintmem sipipa;
36*9ef1f84bSDavid du Colombier u8int *alloc, *p;
37*9ef1f84bSDavid du Colombier extern void squidboy(int);
38*9ef1f84bSDavid du Colombier
39*9ef1f84bSDavid du Colombier /*
40*9ef1f84bSDavid du Colombier * Move the startup code into place,
41*9ef1f84bSDavid du Colombier * must be aligned properly.
42*9ef1f84bSDavid du Colombier */
43*9ef1f84bSDavid du Colombier sipipa = mmuphysaddr(SIPIHANDLER);
44*9ef1f84bSDavid du Colombier if((sipipa & (4*KiB - 1)) || sipipa > (1*MiB - 2*4*KiB))
45*9ef1f84bSDavid du Colombier return;
46*9ef1f84bSDavid du Colombier sipiptr = UINT2PTR(SIPIHANDLER);
47*9ef1f84bSDavid du Colombier memmove(sipiptr, sipihandler, sizeof(sipihandler));
48*9ef1f84bSDavid du Colombier memset(sipiptr+4*KiB, 0, sizeof(Sipi)*Napic);
49*9ef1f84bSDavid du Colombier
50*9ef1f84bSDavid du Colombier /*
51*9ef1f84bSDavid du Colombier * Notes:
52*9ef1f84bSDavid du Colombier * The Universal Startup Algorithm described in the MP Spec. 1.4.
53*9ef1f84bSDavid du Colombier * The data needed per-processor is the sum of the stack, page
54*9ef1f84bSDavid du Colombier * table pages, vsvm page and the Mach page. The layout is similar
55*9ef1f84bSDavid du Colombier * to that described in data.h for the bootstrap processor, but
56*9ef1f84bSDavid du Colombier * with any unused space elided.
57*9ef1f84bSDavid du Colombier */
58*9ef1f84bSDavid du Colombier for(apicno = 0; apicno < Napic; apicno++){
59*9ef1f84bSDavid du Colombier apic = &xapic[apicno];
60*9ef1f84bSDavid du Colombier if(!apic->useable || apic->addr || apic->machno == 0)
61*9ef1f84bSDavid du Colombier continue;
62*9ef1f84bSDavid du Colombier sipi = &((Sipi*)(sipiptr+4*KiB))[apicno];
63*9ef1f84bSDavid du Colombier
64*9ef1f84bSDavid du Colombier /*
65*9ef1f84bSDavid du Colombier * NOTE: for now, share the page tables with the
66*9ef1f84bSDavid du Colombier * bootstrap processor, until this code is worked out,
67*9ef1f84bSDavid du Colombier * so only the Mach and stack portions are used below.
68*9ef1f84bSDavid du Colombier */
69*9ef1f84bSDavid du Colombier alloc = mallocalign(MACHSTKSZ+4*PTSZ+4*KiB+MACHSZ, 4096, 0, 0);
70*9ef1f84bSDavid du Colombier if(alloc == nil)
71*9ef1f84bSDavid du Colombier continue;
72*9ef1f84bSDavid du Colombier memset(alloc, 0, MACHSTKSZ+4*PTSZ+4*KiB+MACHSZ);
73*9ef1f84bSDavid du Colombier p = alloc+MACHSTKSZ;
74*9ef1f84bSDavid du Colombier
75*9ef1f84bSDavid du Colombier sipi->pml4 = cr3get();
76*9ef1f84bSDavid du Colombier sipi->stack = PTR2UINT(p);
77*9ef1f84bSDavid du Colombier
78*9ef1f84bSDavid du Colombier p += 4*PTSZ+4*KiB;
79*9ef1f84bSDavid du Colombier
80*9ef1f84bSDavid du Colombier /*
81*9ef1f84bSDavid du Colombier * Committed. If the AP startup fails, can't safely
82*9ef1f84bSDavid du Colombier * release the resources, who knows what mischief
83*9ef1f84bSDavid du Colombier * the AP is up to. Perhaps should try to put it
84*9ef1f84bSDavid du Colombier * back into the INIT state?
85*9ef1f84bSDavid du Colombier */
86*9ef1f84bSDavid du Colombier mach = (Mach*)p;
87*9ef1f84bSDavid du Colombier sipi->mach = mach;
88*9ef1f84bSDavid du Colombier mach->machno = apic->machno; /* NOT one-to-one... */
89*9ef1f84bSDavid du Colombier mach->splpc = PTR2UINT(squidboy);
90*9ef1f84bSDavid du Colombier sipi->pc = mach->splpc;
91*9ef1f84bSDavid du Colombier mach->apicno = apicno;
92*9ef1f84bSDavid du Colombier mach->stack = PTR2UINT(alloc);
93*9ef1f84bSDavid du Colombier mach->vsvm = alloc+MACHSTKSZ+4*PTSZ;
94*9ef1f84bSDavid du Colombier mach->pml4 = m->pml4;
95*9ef1f84bSDavid du Colombier
96*9ef1f84bSDavid du Colombier p = KADDR(0x467);
97*9ef1f84bSDavid du Colombier *p++ = sipipa;
98*9ef1f84bSDavid du Colombier *p++ = sipipa>>8;
99*9ef1f84bSDavid du Colombier *p++ = 0;
100*9ef1f84bSDavid du Colombier *p = 0;
101*9ef1f84bSDavid du Colombier
102*9ef1f84bSDavid du Colombier nvramwrite(0x0f, 0x0a);
103*9ef1f84bSDavid du Colombier apicsipi(apicno, sipipa);
104*9ef1f84bSDavid du Colombier
105*9ef1f84bSDavid du Colombier for(i = 0; i < 1000; i++){
106*9ef1f84bSDavid du Colombier if(mach->splpc == 0)
107*9ef1f84bSDavid du Colombier break;
108*9ef1f84bSDavid du Colombier millidelay(5);
109*9ef1f84bSDavid du Colombier }
110*9ef1f84bSDavid du Colombier nvramwrite(0x0f, 0x00);
111*9ef1f84bSDavid du Colombier
112*9ef1f84bSDavid du Colombier DBG("apicno%d: machno %d mach %#p (%#p) %dMHz\n",
113*9ef1f84bSDavid du Colombier apicno, mach->machno,
114*9ef1f84bSDavid du Colombier mach, sys->machptr[mach->machno],
115*9ef1f84bSDavid du Colombier mach->cpumhz);
116*9ef1f84bSDavid du Colombier }
117*9ef1f84bSDavid du Colombier }
118