visor/visor/proc.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;
}