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.
|
# preferentially in alphabetical order.
|
||||||
VISOR_SOURCES_x86_64 := \
|
VISOR_SOURCES_x86_64 := \
|
||||||
src/vintel.c \
|
src/vintel.c \
|
||||||
|
src/proc.c \
|
||||||
# end of x86_64 specific sources list
|
# end of x86_64 specific sources list
|
||||||
|
|
||||||
# Architecture-agnostic kernel sources.
|
# Architecture-agnostic kernel sources.
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,18 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#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))
|
__attribute__ ((packed))
|
||||||
struct GDTR {
|
struct GDTR {
|
||||||
uint16_t limit;
|
uint16_t limit;
|
||||||
|
|
@ -17,4 +29,17 @@ storegdt(void)
|
||||||
return gdtr;
|
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
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,17 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#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))
|
__attribute__ ((packed))
|
||||||
struct IDTR {
|
struct IDTR {
|
||||||
uint16_t limit;
|
uint16_t limit;
|
||||||
|
|
@ -17,4 +28,16 @@ storeidt(void)
|
||||||
return idtr;
|
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
|
#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 <efilib.h>
|
||||||
|
|
||||||
#include "virt.h"
|
#include "virt.h"
|
||||||
|
#include "bootstrap.h"
|
||||||
|
#include "procvisor.h"
|
||||||
|
|
||||||
struct virt_vtable *virt = &virt_vtable_intel;
|
struct virt_vtable *virt = &virt_vtable_intel;
|
||||||
|
|
||||||
static char virt_err[100];
|
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
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable)
|
efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable)
|
||||||
{
|
{
|
||||||
InitializeLib(imageHandle, 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");
|
AsciiPrint("* Checking for VT-x Support\n");
|
||||||
if (!virt->has_support(virt_err, sizeof virt_err)) {
|
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");
|
Print(L"Extended VMX Error\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME Allocate the correct amount of space!
|
||||||
Print(L"Allocating VMCS Page\n");
|
Print(L"Allocating VMCS Page\n");
|
||||||
uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiRuntimeServicesData, 1, &vmcs_region);
|
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