plan9fox/sys/src/9/pc64/squidboy.c
cinap_lenrek 7bb1a9a185 pc64: map kernel text readonly and everything else no-execute
the idea is to catch bugs and make kernel exploitation
harder by mapping the kernel text section readonly
and everything else no-execute.

l.s maps the KZERO address space using 2MB pages so
to get the 4K granularity for the text section we use
the new ptesplit() function to split that mapping up.

we need to set EFER no-execute enable bit early
in apbootstrap so secondary application processors
will understand the NX bit in our shared kernel page
tables. also APBOOTSTRAP needs to be kept executable.

rebootjump() needs to mark REBOOTADDR page executable.
2019-08-29 07:35:22 +02:00

109 lines
2.2 KiB
C

#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "mp.h"
extern void _stts(void);
static void
squidboy(Apic* apic)
{
machinit();
mmuinit();
cpuidentify();
cpuidprint();
syncclock();
active.machs[m->machno] = 1;
apic->online = 1;
lapicinit(apic);
lapiconline();
timersinit();
_stts();
schedinit();
}
void
mpstartap(Apic* apic)
{
uintptr *apbootp, *pml4, *pdp0;
Segdesc *gdt;
Mach *mach;
uchar *p;
int i;
/*
* Initialise the AP page-tables and Mach structure.
* Xspanalloc will panic if an allocation can't be made.
*/
p = xspanalloc(2*PTSZ + BY2PG + MACHSIZE, BY2PG, 0);
pml4 = (uintptr*)p;
p += PTSZ;
pdp0 = (uintptr*)p;
p += PTSZ;
gdt = (Segdesc*)p;
p += BY2PG;
mach = (Mach*)p;
memset(pml4, 0, PTSZ);
memset(pdp0, 0, PTSZ);
memset(gdt, 0, BY2PG);
memset(mach, 0, MACHSIZE);
mach->machno = apic->machno;
mach->pml4 = pml4;
mach->gdt = gdt; /* filled by mmuinit */
MACHP(mach->machno) = mach;
/*
* map KZERO (note that we share the KZERO (and VMAP)
* PDP between processors.
*/
pml4[PTLX(KZERO, 3)] = MACHP(0)->pml4[PTLX(KZERO, 3)];
pml4[PTLX(VMAP, 3)] = MACHP(0)->pml4[PTLX(VMAP, 3)];
/* double map */
pml4[0] = PADDR(pdp0) | PTEWRITE|PTEVALID;
pdp0[0] = *mmuwalk(pml4, KZERO, 2, 0);
/*
* Tell the AP where its kernel vector and pdb are.
* The offsets are known in the AP bootstrap code.
*/
apbootp = (uintptr*)(APBOOTSTRAP+0x08);
apbootp[0] = (uintptr)squidboy; /* assembler jumps here eventually */
apbootp[1] = (uintptr)PADDR(pml4);
apbootp[2] = (uintptr)apic;
apbootp[3] = (uintptr)mach;
apbootp[4] |= (uintptr)m->havenx<<11; /* EFER */
/*
* Universal Startup Algorithm.
*/
p = KADDR(0x467); /* warm-reset vector */
*p++ = PADDR(APBOOTSTRAP);
*p++ = PADDR(APBOOTSTRAP)>>8;
i = (PADDR(APBOOTSTRAP) & ~0xFFFF)/16;
/* code assumes i==0 */
if(i != 0)
print("mp: bad APBOOTSTRAP\n");
*p++ = i;
*p = i>>8;
coherence();
nvramwrite(0x0F, 0x0A); /* shutdown code: warm reset upon init ipi */
lapicstartap(apic, PADDR(APBOOTSTRAP));
for(i = 0; i < 100000; i++){
if(arch->fastclock == tscticks)
cycles(&m->tscticks); /* for ap's syncclock(); */
if(apic->online)
break;
delay(1);
}
nvramwrite(0x0F, 0x00);
}