Per-processor GDT & IDT
This commit is contained in:
parent
3704e95c64
commit
4965c38de9
10 changed files with 174 additions and 1 deletions
1
Makefile
1
Makefile
|
|
@ -9,6 +9,7 @@ CFLAGS += -ggdb
|
|||
# preferentially in alphabetical order.
|
||||
VISOR_SOURCES_x86_64 := \
|
||||
src/vintel.c \
|
||||
src/proc.c \
|
||||
# end of x86_64 specific sources list
|
||||
|
||||
# Architecture-agnostic kernel sources.
|
||||
|
|
|
|||
|
|
@ -3,6 +3,18 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
__attribute__ ((packed))
|
||||
struct segdescr {
|
||||
uint16_t limit0;
|
||||
uint16_t base0;
|
||||
uint8_t base1;
|
||||
uint8_t access;
|
||||
uint8_t flags;
|
||||
uint16_t base2;
|
||||
uint32_t base3;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
__attribute__ ((packed))
|
||||
struct GDTR {
|
||||
uint16_t limit;
|
||||
|
|
@ -17,4 +29,17 @@ storegdt(void)
|
|||
return gdtr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
setsegdescr(struct segdescr *descr, uint64_t base, uint32_t limit, uint8_t access, uint8_t flags)
|
||||
{
|
||||
descr->limit0 = limit;
|
||||
descr->base0 = base;
|
||||
descr->base1 = base >> 16;
|
||||
descr->access = access;
|
||||
descr->flags = flags | (limit >> 16);
|
||||
descr->base2 = base >> 24;
|
||||
descr->base3 = base >> 32;
|
||||
descr->reserved = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,6 +3,17 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
__attribute__ ((packed))
|
||||
struct intdescr {
|
||||
uint16_t offset0;
|
||||
uint16_t seg;
|
||||
uint8_t ist;
|
||||
uint8_t access;
|
||||
uint16_t offset1;
|
||||
uint32_t offset2;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
__attribute__ ((packed))
|
||||
struct IDTR {
|
||||
uint16_t limit;
|
||||
|
|
@ -17,4 +28,16 @@ storeidt(void)
|
|||
return idtr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
setintdescr(struct intdescr *descr, uint64_t offset, uint16_t seg, uint8_t ist, uint8_t access)
|
||||
{
|
||||
descr->offset0 = offset;
|
||||
descr->seg = seg;
|
||||
descr->ist = ist;
|
||||
descr->access = access;
|
||||
descr->offset1 = offset >> 16;
|
||||
descr->offset2 = offset >> 32;
|
||||
descr->reserved = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
3
run.sh
Executable file
3
run.sh
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
OVMF_BLOB=/usr/share/OVMF/x64/OVMF.fd
|
||||
uefi-run -d -b "$OVMF_BLOB" build/visor -- -enable-kvm -cpu host "$@"
|
||||
3
src/bootstrap.h
Normal file
3
src/bootstrap.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#include <stddef.h>
|
||||
|
||||
void *bs_alloc(size_t size);
|
||||
15
src/efi.c
15
src/efi.c
|
|
@ -4,18 +4,31 @@
|
|||
#include <efilib.h>
|
||||
|
||||
#include "virt.h"
|
||||
#include "bootstrap.h"
|
||||
#include "procvisor.h"
|
||||
|
||||
struct virt_vtable *virt = &virt_vtable_intel;
|
||||
|
||||
static char virt_err[100];
|
||||
|
||||
void *
|
||||
bs_alloc(size_t size)
|
||||
{
|
||||
size_t npages = (size + (4096 - 1)) / 4096;
|
||||
void *ptr;
|
||||
uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiRuntimeServicesData, npages, &ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
EFIAPI
|
||||
EFI_STATUS
|
||||
efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable)
|
||||
{
|
||||
InitializeLib(imageHandle, systemTable);
|
||||
|
||||
Print(L"Hello, World!\n");
|
||||
AsciiPrint("* Setting up processor structures\n");
|
||||
struct procvisor *pv = proc_setup();
|
||||
(void)pv;
|
||||
|
||||
AsciiPrint("* Checking for VT-x Support\n");
|
||||
if (!virt->has_support(virt_err, sizeof virt_err)) {
|
||||
|
|
|
|||
62
src/proc.c
Normal file
62
src/proc.c
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
#include <x86/idt.h>
|
||||
#include <x86/gdt.h>
|
||||
#include "procvisor.h"
|
||||
#include "bootstrap.h"
|
||||
|
||||
#define GDT_SIZE ( 3 * sizeof (struct segdescr))
|
||||
#define IDT_SIZE (256 * sizeof (struct intdescr))
|
||||
|
||||
struct procvisor *procvisors[256];
|
||||
|
||||
static void
|
||||
proc_fill_host_gdt(struct GDTR gdtr)
|
||||
{
|
||||
struct segdescr *descrs = (void *)gdtr.base;
|
||||
setsegdescr(&descrs[0], 0, 0, 0, 0); // null
|
||||
setsegdescr(&descrs[1], 0, 0xffffff, 0x9B, 0xA0); // code
|
||||
setsegdescr(&descrs[2], 0, 0xffffff, 0x93, 0xC0); // data
|
||||
}
|
||||
|
||||
static void
|
||||
proc_fill_host_idt(struct IDTR idtr)
|
||||
{
|
||||
struct intdescr *descrs = (void *)idtr.base;
|
||||
for (int i = 0; i < 256; i++) {
|
||||
setintdescr(&descrs[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 GDT
|
||||
top -= GDT_SIZE;
|
||||
pv->host_gdtr.base = (uintptr_t)top;
|
||||
pv->host_gdtr.limit = GDT_SIZE - 1;
|
||||
|
||||
// Carve out IDT
|
||||
top -= IDT_SIZE;
|
||||
pv->host_idtr.base = (uintptr_t)top;
|
||||
pv->host_idtr.limit = IDT_SIZE - 1;
|
||||
|
||||
// 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);
|
||||
proc_fill_host_idt(pv->host_idtr);
|
||||
|
||||
// Register procvisor & return
|
||||
unsigned procid = myprocid();
|
||||
procvisors[procid] = pv;
|
||||
return pv;
|
||||
}
|
||||
37
src/procvisor.h
Normal file
37
src/procvisor.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include <stddef.h>
|
||||
#include <cpuid.h>
|
||||
#include <x86/gdt.h>
|
||||
#include <x86/idt.h>
|
||||
|
||||
#define PROC_REGION_SIZE (512 * 4096)
|
||||
|
||||
/* Per-processor visor state and structures */
|
||||
struct procvisor {
|
||||
void *host_stack;
|
||||
struct GDTR host_gdtr;
|
||||
struct IDTR host_idtr;
|
||||
//void *host_cr3;
|
||||
//void *vmctl;
|
||||
};
|
||||
|
||||
extern struct procvisor *procvisors[256];
|
||||
|
||||
/* Get our own LAPIC ID -- the slow way ... */
|
||||
static inline unsigned
|
||||
myprocid(void)
|
||||
{
|
||||
unsigned info[4];
|
||||
__get_cpuid(0x1, &info[0], &info[1], &info[2], &info[3]);
|
||||
unsigned procid = info[1] >> 24;
|
||||
return procid;
|
||||
}
|
||||
|
||||
static inline struct procvisor *
|
||||
myprocvisor(void)
|
||||
{
|
||||
unsigned procid = myprocid();
|
||||
if (procid >= 256) return NULL;
|
||||
return procvisors[procid];
|
||||
}
|
||||
|
||||
struct procvisor *proc_setup(void);
|
||||
|
|
@ -211,6 +211,7 @@ vintel_enable(void)
|
|||
Print(L"Extended VMX Error\n");
|
||||
}
|
||||
|
||||
// FIXME Allocate the correct amount of space!
|
||||
Print(L"Allocating VMCS Page\n");
|
||||
uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiRuntimeServicesData, 1, &vmcs_region);
|
||||
|
||||
|
|
|
|||
5
src/vsegment.h
Normal file
5
src/vsegment.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
struct vsegment {
|
||||
uint64_t gpa;
|
||||
uint64_t ha;
|
||||
uint64_t count;
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue