67 lines
1.6 KiB
C
67 lines
1.6 KiB
C
#include <x86/idt.h>
|
|
#include <x86/gdt.h>
|
|
#include "procvisor.h"
|
|
#include "bootstrap.h"
|
|
|
|
#define GDT_SIZE ( 5 * sizeof (struct segdescr))
|
|
#define IDT_SIZE (256 * sizeof (struct intdescr))
|
|
#define TSS_SIZE (sizeof (struct TSS))
|
|
|
|
struct procvisor *procvisors[256];
|
|
|
|
static void
|
|
proc_fill_host_gdt(struct GDTR gdtr, struct TSS *tss)
|
|
{
|
|
setsegdescr(&gdtr.base[0], 0, 0, 0, 0); // null
|
|
setsegdescr(&gdtr.base[1], 0, 0xffffff, 0x9B, 0xA0); // code
|
|
setsegdescr(&gdtr.base[2], 0, 0xffffff, 0x93, 0xC0); // data
|
|
setsegdescr(&gdtr.base[3], (uintptr_t)tss, TSS_SIZE - 1, 0x89, 0x00); // TSS
|
|
*(uint64_t *)(&gdtr.base[4]) = (uintptr_t)tss >> 32;// TSS (continued)
|
|
}
|
|
|
|
static void
|
|
proc_fill_host_idt(struct IDTR idtr)
|
|
{
|
|
for (int i = 0; i < 256; i++) {
|
|
setintdescr(&idtr.base[i], 0, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
struct procvisor *
|
|
proc_setup(void)
|
|
{
|
|
// Allocate 2M region for per-processor stuff
|
|
char *region = bs_alloc(PROC_REGION_SIZE);
|
|
char *top = region + PROC_REGION_SIZE;
|
|
|
|
// Carve out struct procvisor
|
|
top -= sizeof (struct procvisor);
|
|
struct procvisor *pv = (void *)top;
|
|
|
|
// Carve out IDT
|
|
top -= IDT_SIZE;
|
|
pv->host_idtr.base = (void *)top;
|
|
pv->host_idtr.limit = IDT_SIZE - 1;
|
|
|
|
// Carve out GDT
|
|
top -= GDT_SIZE;
|
|
pv->host_gdtr.base = (void *)top;
|
|
pv->host_gdtr.limit = GDT_SIZE - 1;
|
|
|
|
// Carve out TSS
|
|
top -= TSS_SIZE;
|
|
pv->host_tss = (void *)top;
|
|
|
|
// Leave the rest as stack
|
|
top -= ((uintptr_t)top & 0xf); // align on 16-byte boundary
|
|
pv->host_stack = top;
|
|
|
|
// Fill out GDT & IDT structures
|
|
proc_fill_host_gdt(pv->host_gdtr, pv->host_tss);
|
|
proc_fill_host_idt(pv->host_idtr);
|
|
|
|
// Register procvisor & return
|
|
unsigned procid = myprocid();
|
|
procvisors[procid] = pv;
|
|
return pv;
|
|
}
|