Commit d4684e77 authored by Jack Lange's avatar Jack Lange

import vos code

parent 4d6eb816
/*
* Copyright (c) 2016, Jack Lange <jacklange@cs.pitt.edu>
* All rights reserved.
*
* This is free software. You are permitted to use,
* redistribute, and modify it as specified in the file "PETLAB_LICENSE".
*/
#include "segments.h"
#include "vmm_lowlevel.h"
static void
vos_print_segment(char * name,
struct vos_segment * seg)
{
vos_lnx_printk("\t%s: Sel=%x, base=%p, limit=%x long_mode=%d, db=%d, type=%x )\n",
name,
seg->selector,
(void *)(uintptr_t)seg->base,
seg->limit,
seg->long_mode,
seg->db,
seg->type);
vos_lnx_printk("\t\tSys=%d, dpl=%x, P=%d, avail=%d, gran.=%d, unusable=%d\n",
seg->system,
seg->dpl,
seg->present,
seg->avail,
seg->granularity,
seg->unusable);
}
void
vos_print_segments(struct vos_segments * segs)
{
struct vos_segment * seg_ptr = (struct vos_segment *)segs;
char * seg_names[] = {"CS", "DS" , "ES", "FS", "GS", "SS" , "LDTR", "GDTR", "IDTR", "TR", NULL};
int i = 0;
vos_lnx_printk("Segments\n");
for (i = 0; seg_names[i] != NULL; i++) {
vos_print_segment(seg_names[i], &seg_ptr[i]);
}
}
static int
parse_seg_desc(struct x86_segment * seg,
struct vos_segment * vos_seg)
{
uintptr_t base = seg->base_lo + (seg->base_hi << 24);
uintptr_t limit = seg->limit_lo + (seg->limit_hi << 16);
vos_seg->base = base;
vos_seg->limit = limit;
vos_seg->type = seg->type;
vos_seg->system = seg->system;
vos_seg->dpl = seg->dpl;
vos_seg->present = seg->present;
vos_seg->avail = seg->avail;
vos_seg->long_mode = seg->long_mode;
vos_seg->db = seg->db;
vos_seg->granularity = seg->granularity;
if (vos_seg->present == 0) {
vos_lnx_printk("Marking Segment unusable\n");
vos_seg->unusable = 1;
}
return 0;
}
static int
parse_ext_seg_desc(struct x86_ext_segment * seg,
struct vos_segment * vos_seg)
{
u64 base = 0;
uintptr_t limit = seg->limit_lo | (seg->limit_hi << 16);
base = seg->base_hi;
base <<= 24;
base |= seg->base_lo;
vos_seg->base = base;
vos_seg->limit = limit;
vos_seg->type = seg->type;
vos_seg->system = seg->system;
vos_seg->dpl = seg->dpl;
vos_seg->present = seg->present;
vos_seg->avail = seg->avail;
vos_seg->long_mode = seg->long_mode;
vos_seg->db = seg->db;
vos_seg->granularity = seg->granularity;
if (vos_seg->present == 0) {
vos_lnx_printk("Marking Segment unusable\n");
vos_seg->unusable = 1;
}
return 0;
}
int
vos_get_host_segments(struct vos_segments * segs)
{
uintptr_t selector_val = 0;
struct x86_seg_selector * selector = (struct x86_seg_selector *)&selector_val;
struct x86_segment * gdt_arr = NULL;
struct x86_segment * ldt_arr = NULL;
struct {
u16 limit;
uintptr_t base;
} __attribute__((packed)) tmp_seg;
memset(segs, 0, sizeof(struct vos_segments));
vos_lnx_printk("Host Segments\n");
/* GDTR */
__asm__ __volatile__("sgdt (%0);"
:
: "q"(&tmp_seg)
: "memory"
);
segs->gdtr.base = tmp_seg.base;
segs->gdtr.limit = tmp_seg.limit;
gdt_arr = (struct x86_segment *)(segs->gdtr.base);
vos_lnx_printk("GDTR: [base=%p] [limit=%d]\n", (void *)segs->gdtr.base, segs->gdtr.limit);
/* IDTR */
__asm__ __volatile__("sidt (%0);"
:
: "q"(&tmp_seg)
: "memory"
);
segs->idtr.base = tmp_seg.base;
segs->idtr.limit = tmp_seg.limit;
vos_lnx_printk("IDTR: [base=%p] [limit=%d]\n", (void *)segs->idtr.base, segs->idtr.limit);
/* LDTR */
__asm__ __volatile__("sldt (%0);"
:
: "q"(&selector_val)
: "memory"
);
if (selector_val != 0) {
segs->ldtr.selector = selector_val;
parse_ext_seg_desc((struct x86_ext_segment *)&gdt_arr[selector->index], &(segs->ldtr));
ldt_arr = (struct x86_segment *)(segs->ldtr.base);
} else {
segs->ldtr.unusable = 1;
}
vos_lnx_printk("LDTR: [base=%p]\n", (void *)segs->ldtr.base);
/* TR */
__asm__ __volatile__("str (%0);"
:
: "q"(&selector_val)
: "memory"
);
if (selector_val != 0) {
segs->tr.selector = selector_val;
if (selector->tbl_index == 1) {
parse_ext_seg_desc((struct x86_ext_segment *)&ldt_arr[selector->index], &(segs->tr));
} else {
parse_ext_seg_desc((struct x86_ext_segment *)&gdt_arr[selector->index], &(segs->tr));
}
} else {
segs->tr.unusable = 1;
}
vos_lnx_printk("TR: [selector=%d] [base=%p]\n", (u32)selector_val, (void *)segs->tr.base);
/* CS */
__asm__ __volatile__ ("movq %%cs, %0; "
: "=q"(selector_val)
: );
if (selector_val != 0) {
segs->cs.selector = selector_val;
if (selector->tbl_index == 1) {
parse_seg_desc(&ldt_arr[selector->index], &(segs->cs));
} else {
parse_seg_desc(&gdt_arr[selector->index], &(segs->cs));
}
} else {
segs->cs.unusable = 1;
}
vos_lnx_printk("CS: [selector=%d] [base=%p]\n", (u32)selector_val, (void *)segs->cs.base);
/* SS */
__asm__ __volatile__ ( "movq %%ss, %0; "
: "=q"(selector_val)
: );
if (selector_val != 0) {
segs->ss.selector = selector_val;
if (selector->tbl_index == 1) {
parse_seg_desc(&ldt_arr[selector->index], &(segs->ss));
} else {
parse_seg_desc(&gdt_arr[selector->index], &(segs->ss));
}
} else {
segs->ss.unusable = 1;
}
vos_lnx_printk("SS: [selector=%d] [base=%p]\n", (u32)selector_val, (void *)segs->ss.base);
/* DS */
__asm__ __volatile__ ( "movq %%ds, %0; "
: "=q"(selector_val)
: );
if (selector_val != 0) {
segs->ds.selector = selector_val;
if (selector->tbl_index == 1) {
parse_seg_desc(&ldt_arr[selector->index], &(segs->ds));
} else {
parse_seg_desc(&gdt_arr[selector->index], &(segs->ds));
}
} else {
segs->ds.unusable = 1;
}
vos_lnx_printk("DS: [selector=%d] [base=%p]\n", (u32)selector_val, (void *)segs->ds.base);
/* ES */
__asm__ __volatile__ ( "movq %%es, %0; "
: "=q"(selector_val)
: );
if (selector_val != 0) {
segs->es.selector = selector_val;
if (selector->tbl_index == 1) {
parse_seg_desc(&ldt_arr[selector->index], &(segs->es));
} else {
parse_seg_desc(&gdt_arr[selector->index], &(segs->es));
}
} else {
segs->es.unusable = 1;
}
vos_lnx_printk("ES: [selector=%d] [base=%p]\n", (u32)selector_val, (void *)segs->es.base);
/* FS */
__asm__ __volatile__ ( "movq %%fs, %0; "
: "=q"(selector_val)
: );
if (selector_val != 0) {
segs->fs.selector = selector_val;
if (selector->tbl_index == 1) {
parse_seg_desc(&ldt_arr[selector->index], &(segs->fs));
} else {
parse_seg_desc(&gdt_arr[selector->index], &(segs->fs));
}
} else {
segs->fs.unusable = 1;
}
vos_lnx_printk("FS: [selector=%d] [base=%p]\n", (u32)selector_val, (void *)segs->fs.base);
/* GS */
__asm__ __volatile__ ( "movq %%gs, %0; "
: "=q"(selector_val)
: );
if (selector_val != 0) {
segs->gs.selector = selector_val;
if (selector->tbl_index == 1) {
parse_seg_desc(&ldt_arr[selector->index], &(segs->gs));
} else {
parse_seg_desc(&gdt_arr[selector->index], &(segs->gs));
}
} else {
segs->gs.unusable = 1;
}
vos_lnx_printk("GS: [selector=%d] [base=%p]\n", (u32)selector_val, (void *)segs->gs.base);
vos_print_segments(segs);
return 0;
}
/*
* Copyright (c) 2016, Jack Lange <jacklange@cs.pitt.edu>
* All rights reserved.
*
* This is free software. You are permitted to use,
* redistribute, and modify it as specified in the file "PETLAB_LICENSE".
*/
#ifndef __SEGMENTS_H__
#define __SEGMENTS_H__
#include "vos.h"
struct vos_segment {
u16 selector;
u32 limit;
u64 base;
u32 type : 4;
u32 system : 1;
u32 dpl : 2;
u32 present : 1;
u32 avail : 1;
u32 long_mode : 1;
u32 db : 1;
u32 granularity : 1;
u32 unusable : 1;
} __attribute__((packed));
struct vos_segments {
union {
struct vos_segment seg_arr[10];
struct {
struct vos_segment cs;
struct vos_segment ds;
struct vos_segment es;
struct vos_segment fs;
struct vos_segment gs;
struct vos_segment ss;
struct vos_segment ldtr;
struct vos_segment gdtr;
struct vos_segment idtr;
struct vos_segment tr;
} __attribute__((packed));
} __attribute__((packed));
} __attribute__((packed));
int vos_get_host_segments(struct vos_segments * segs);
void vos_print_segments(struct vos_segments * segs);
#endif
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2016, Jack Lange <jacklange@cs.pitt.edu>
* All rights reserved.
*
* This is free software. You are permitted to use,
* redistribute, and modify it as specified in the file "PETLAB_LICENSE".
*/
#include "vos.h"
#ifndef __VMM_LOWLEVEL_H__
#define __VMM_LOWLEVEL_H__
#define CPUID_FEATURE_IDS 0x00000001
#define CPUID_EXT_FEATURE_IDS 0x80000001
#define IA32_PAT_MSR 0x00000277
#define SYSENTER_CS_MSR 0x00000174
#define SYSENTER_ESP_MSR 0x00000175
#define SYSENTER_EIP_MSR 0x00000176
#define EFER_MSR 0xc0000080
#define IA32_STAR_MSR 0xc0000081
#define IA32_LSTAR_MSR 0xc0000082
#define IA32_CSTAR_MSR 0xc0000083
#define IA32_FMASK_MSR 0xc0000084
#define FS_BASE_MSR 0xc0000100
#define GS_BASE_MSR 0xc0000101
#define IA32_KERN_GS_BASE_MSR 0xc0000102
#define IA32_DEBUG_CTL_MSR 0xc00001d9
#define IA32_X2APIC_APICID 0x00000802
#define IA32_X2APIC_VERSION 0x00000803
#define IA32_X2APIC_TPR 0x00000808
#define IA32_X2APIC_PPR 0x0000080A
#define IA32_X2APIC_EOI 0x0000080B
#define IA32_X2APIC_LDR 0x0000080D
#define IA32_X2APIC_SIVR 0x0000080F
#define IA32_X2APIC_ISR0 0x00000810
#define IA32_X2APIC_ISR1 0x00000811
#define IA32_X2APIC_ISR2 0x00000812
#define IA32_X2APIC_ISR3 0x00000813
#define IA32_X2APIC_ISR4 0x00000814
#define IA32_X2APIC_ISR5 0x00000815
#define IA32_X2APIC_ISR6 0x00000816
#define IA32_X2APIC_ISR7 0x00000817
#define IA32_X2APIC_TMR0 0x00000818
#define IA32_X2APIC_TMR1 0x00000819
#define IA32_X2APIC_TMR2 0x0000081A
#define IA32_X2APIC_TMR3 0x0000081B
#define IA32_X2APIC_TMR4 0x0000081C
#define IA32_X2APIC_TMR5 0x0000081D
#define IA32_X2APIC_TMR6 0x0000081E
#define IA32_X2APIC_TMR7 0x0000081F
#define IA32_X2APIC_IRR0 0x00000820
#define IA32_X2APIC_IRR1 0x00000821
#define IA32_X2APIC_IRR2 0x00000822
#define IA32_X2APIC_IRR3 0x00000823
#define IA32_X2APIC_IRR4 0x00000824
#define IA32_X2APIC_IRR5 0x00000825
#define IA32_X2APIC_IRR6 0x00000826
#define IA32_X2APIC_IRR7 0x00000827
#define IA32_X2APIC_ESR 0x00000828
#define IA32_X2APIC_LVT_CMCI 0x0000082F
#define IA32_X2APIC_ICR 0x00000830
#define IA32_X2APIC_LVT_TIMER 0x00000832
#define IA32_X2APIC_LVT_THERMAL 0x00000833
#define IA32_X2APIC_LVT_PMI 0x00000834
#define IA32_X2APIC_LVT_LINT0 0x00000835
#define IA32_X2APIC_LVT_ERROR 0x00000837
#define IA32_X2APIC_INIT_COUNT 0x00000838
#define IA32_X2APIC_CUR_COUNT 0x00000839
#define IA32_X2APIC_DIV_CONF 0x0000083E
#define IA32_X2APIC_SELF_IPI 0x0000083F
struct x86_msr {
union {
u64 value;
struct {
u32 lo;
u32 hi;
} __attribute__((packed));
} __attribute__((packed));
} __attribute__((packed));
struct x86_seg_selector {
union {
u16 value;
struct {
u8 rpl : 2;
u8 tbl_index : 1;
u16 index : 13;
} __attribute__((packed));
} __attribute__((packed));
} __attribute__((packed));
struct x86_segment {
u16 limit_lo;
u32 base_lo : 24;
u32 type : 4;
u32 system : 1;
u32 dpl : 2;
u32 present : 1;
u32 limit_hi : 4;
u32 avail : 1;
u32 long_mode : 1;
u32 db : 1;
u32 granularity : 1;
u32 base_hi : 8;
} __attribute__((packed));
/**
* Long-Mode Gate Descriptor (16-bytes)
*/
struct x86_ext_segment {
u16 limit_lo;
u64 base_lo : 24;
u32 type : 4;
u32 system : 1;
u32 dpl : 2;
u32 present : 1;
u32 limit_hi : 4;
u32 avail : 1;
u32 long_mode : 1;
u32 db : 1;
u32 granularity : 1;
u64 base_hi : 40;
u32 rsvd ;
} __attribute__((packed));
struct x86_tss_desc {
u16 limit1;
u16 base1;
u32 base2 : 8;
/* In IA32, type follows the form 10B1b, where B is the busy flag */
u32 type : 4;
u32 zero1 : 1;
u32 dpl : 2;
u32 present : 1;
u32 limit2 : 4;
u32 available : 1;
u32 zero2 : 1;
u32 zero3 : 1;
u32 granularity : 1;
u32 base3 : 8;
u32 base4;
u32 rsvd1 : 8;
u32 zero4 : 5;
u32 rsvd2 : 19;
} __attribute__((packed));
struct x86_intr_gate {
u16 offset_low; /**< [15-0] of target code segment offset */
u16 segment; /**< Target code segment selector */
u32 ist : 3; /**< Interrupt-Stack-Table index into TSS */
u32 zero0 : 5; /**< Must be zero */
u32 type : 5; /**< Gate descriptor type */
u32 dpl : 2; /**< Privilege level */
u32 p : 1; /**< Present bit... in use? */
u8 offset_middle; /**< [31-24] of target code segment offset */
u32 offset_high; /**< [63-32] of target code segment offset */
u32 zero1; /**< Must be zero */
} __attribute__((packed));
static void __inline__
vos_cpuid(u32 target,
u32 * eax,
u32 * ebx,
u32 * ecx,
u32 * edx)
{
__asm__ __volatile__ (
"cpuid\n\t"
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
: "0" (target), "2" (*ecx)
);
return;
}
static void __inline__
vos_set_msr(u32 msr,
u32 high_byte,
u32 low_byte)
{
__asm__ __volatile__ (
"wrmsr"
:
: "c" (msr), "d" (high_byte), "a" (low_byte)
);
}
static void __inline__
vos_get_msr(u32 msr,
u32 * high_byte,
u32 * low_byte)
{
__asm__ __volatile__ (
"rdmsr"
: "=d" (*high_byte), "=a" (*low_byte)
: "c" (msr)
);
}
static void __inline__
vos_enable_ints( void )
{
__asm__ __volatile__ ("sti");
}
static void __inline__
vos_disable_ints( void )
{
__asm__ __volatile__ ("cli");
}
static uintptr_t __inline__
vos_irq_save( void )
{
uintptr_t state;
__asm__ __volatile__ ("pushfq \n\t"
"popq %0 \n\t"
"cli \n\t"
:"=g" (state)
:
:"memory"
);
return state;
}
static void __inline__
vos_irq_restore(uintptr_t state)
{
__asm__ __volatile__("pushq %0 \n\t"
"popfq \n\t"
:
:"g" (state)
:"memory", "cc"
);
}
#endif
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2016, Jack Lange <jacklange@cs.pitt.edu>
* All rights reserved.
*
* This is free software. You are permitted to use,
* redistribute, and modify it as specified in the file "PETLAB_LICENSE".
*/
#ifndef __VMX_H__
#define __VMX_H__
#include "vos.h"
#include "vmcs.h"
struct vos_core;
struct vos_vmm;
struct vos_vm;
#define VMX_SUCCESS 0
#define VMX_FAIL_INVALID 1
#define VMX_FAIL_VALID 2
#define VMM_ERROR 3
struct vmx_pin_ctrls {
union {
u32 value;
struct {
u32 ext_int_exit : 1;
u32 rsvd1 : 2;
u32 nmi_exit : 1;
u32 rsvd2 : 1;
u32 virt_nmi : 1;
u32 active_preempt_timer : 1;
u32 rsvd3 : 25;
} __attribute__((packed));
} __attribute__((packed));
} __attribute__((packed));
struct vmx_pri_proc_ctrls {
union {
u32 value;
struct {
u32 rsvd1 : 2;
u32 int_wndw_exit : 1;
u32 tsc_offset : 1;
u32 rsvd2 : 3;
u32 hlt_exit : 1;
u32 rsvd3 : 1;
u32 invlpg_exit : 1;
u32 mwait_exit : 1;
u32 rdpmc_exit : 1;
u32 rdtsc_exit : 1;
u32 rsvd4 : 2;
u32 cr3_ld_exit : 1;
u32 cr3_str_exit : 1;
u32 rsvd5 : 2;
u32 cr8_ld_exit : 1;
u32 cr8_str_exit : 1;
u32 tpr_shdw : 1;
u32 nmi_wndw_exit : 1;
u32 mov_dr_exit : 1;
u32 uncon_io_exit : 1;
u32 use_io_bitmap : 1;
u32 rsvd6 : 1;
u32 monitor_trap : 1;
u32 use_msr_bitmap : 1;
u32 monitor_exit : 1;
u32 pause_exit : 1;
u32 sec_ctrls : 1;