Commit 070e2688 authored by Charlie Jacobsen's avatar Charlie Jacobsen Committed by Vikram Narayanan

Set up simple lcd run (no loop) and some handling (untested).

lcd_arch_run:
-- disables kernel preemption while lcd is running
-- simple switch on vmx exit conditions

vmx_handle_exception_nmi
-- for nmi's and exceptions generated by lcd

vmx_handle_hard_exception
-- for `hardware exceptions': page faults, traps,
   machine checks
parent 1ba7bf47
......@@ -48,6 +48,15 @@ struct lcd_arch_ept {
};
struct lcd_arch {
/*
* Public Data
*/
u64 page_fault_addr;
/*
* Private Data
*/
int cpu;
int launched;
int vpid;
......@@ -101,5 +110,19 @@ struct lcd_arch *lcd_arch_create(void);
* some cpu, it will become inactive.)
*/
void lcd_arch_destroy(struct lcd_arch *vcpu);
/**
* Runs the LCD on the calling cpu. (If the LCD is active on
* a different cpu, it will become inactive there.) Kernel
* preemption is disabled while the LCD is launched, but
* external interrupts are not disabled and will be handled.
*/
int lcd_arch_run(struct lcd_arch *vcpu);
/**
* Status codes for running LCDs.
*/
enum lcd_arch_status {
LCD_ARCH_STATUS_PF = 0
};
#endif /* LCD_DOMAINS_ARCH_H */
......@@ -12,6 +12,7 @@
#include <asm/virtext.h>
#include <asm/vmx.h>
#include <uapi/asm/vmx.h>
#include <asm/desc.h>
#include <asm/lcd-domains-arch.h>
......@@ -1533,7 +1534,7 @@ fail_vcpu:
return NULL;
}
static void lcd_arch_destroy(struct lcd_arch *vcpu)
void lcd_arch_destroy(struct lcd_arch *vcpu)
{
/*
* Premption Disabled
......@@ -1568,7 +1569,82 @@ static void lcd_arch_destroy(struct lcd_arch *vcpu)
kfree(vcpu);
}
/* VMX RUN LOOP -------------------------------------------------- */
/* VMX EXIT HANDLING -------------------------------------------------- */
static void vmx_handle_vmcall(struct lcd_arch *vcpu)
{
}
static void vmx_handle_external_int(struct lcd_arch *vcpu)
{
}
static int vmx_handle_hard_exception(struct lcd_arch *vcpu)
{
int vector;
/*
* Intel SDM V3 24.9.2, 27.2.2
*/
vector = vcpu->exit_intr_info & INTR_INFO_VECTOR_MASK;
switch (vector) {
case 14:
/*
* Guest virtual page fault
*
* Set page fault address, and return status code.
*/
vcpu->page_fault_addr = vcpu->exit_qualification;
return LCD_ARCH_STATUS_PF;
default:
printk(KERN_ERR "lcd vmx: unhandled hw exception:\n");
printk(KERN_ERR " vector: %x, info: %x\n",
vector, vcpu->exit_intr_info);
return -EIO;
}
}
/**
* Processes software / hardware exceptions and nmi's generated
* while lcd was running.
*/
static int vmx_handle_exception_nmi(struct lcd_arch *vcpu)
{
int type;
type = vcpu->exit_intr_info & INTR_INFO_INTR_TYPE_MASK;
switch (type) {
case INTR_TYPE_HARD_EXCEPTION:
/*
* Page fault, trap, machine check, ...
*/
return vmx_handle_hard_exception(vcpu);
default:
/*
* NMI, div by zero, overflow, ...
*/
printk(KERN_ERR "lcd vmx: unhandled exception or nmi:\n");
printk(KERN_ERR " interrupt info: %x\n",
vcpu->exit_intr_info);
return -EIO;
}
}
static void vmx_handle_ept(struct lcd_arch *vcpu)
{
}
static void vmx_handle_control_reg(struct lcd_arch *vcpu)
{
}
/* VMX RUN -------------------------------------------------- */
/**
* Low-level vmx launch / resume to enter non-root mode on cpu with
......@@ -1730,6 +1806,52 @@ static int __noclone vmx_enter(struct lcd_arch *vcpu)
return vcpu->exit_reason;
}
int lcd_arch_run(struct lcd_arch *vcpu)
{
int ret;
/*
* Load the lcd and invalidate any cached mappings.
*
* *preemption disabled*
*/
vmx_get_cpu(vcpu);
/*
* Enter lcd
*/
ret = vmx_enter(vcpu);
/*
* Handle exit reason
*
* Intel SDM V3 Appendix C
*/
switch (ret) {
case EXIT_REASON_EXCEPTION_NMI:
vmx_handle_exception_nmi(vcpu);
break;
case EXIT_REASON_EXTERNAL_INTERRUPT:
vmx_handle_external_int(vcpu);
break;
case EXIT_REASON_VMCALL:
vmx_handle_vmcall(vcpu);
break;
case EXIT_REASON_EPT_VIOLATION:
vmx_handle_ept(vcpu);
break;
case EXIT_REASON_CR_ACCESS:
vmx_handle_control_reg(vcpu);
break;
}
/*
* Preemption enabled
*/
vmx_put_cpu(vcpu);
}
/* EXPORTS -------------------------------------------------- */
EXPORT_SYMBOL(lcd_arch_init);
......
......@@ -2266,107 +2266,107 @@ static int vmx_handle_nmi_exception(struct lcd *vcpu)
return -EIO;
}
int lcd_run(struct lcd *lcd) {
int done = 0;
int ret = 0;
int countdown = 1000;
cycles_t begin, end;
begin = get_cycles();
g_prepare_time = begin - g_prepare_start;
while (1) {
vmx_get_cpu(lcd);
local_irq_disable();
/*if (need_resched()) {
local_irq_enable();
vmx_put_cpu(lcd);
cond_resched();
continue;
}*/
// In case we run from insmod.
if (signal_pending(current)) {
int signr;
siginfo_t info;
uint32_t x;
local_irq_enable();
vmx_put_cpu(lcd);
spin_lock_irq(&current->sighand->siglock);
signr = dequeue_signal(current, &current->blocked,
&info);
spin_unlock_irq(&current->sighand->siglock);
if (!signr)
continue;
if (signr == SIGKILL) {
printk(KERN_INFO "vmx: got sigkill, dying");
lcd->ret_code = ((ENOSYS) << 8);
break;
}
x = signr; // + base?
x |= INTR_INFO_VALID_MASK;
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, x);
continue;
}
/* int lcd_run(struct lcd *lcd) { */
/* int done = 0; */
/* int ret = 0; */
/* int countdown = 1000; */
/* cycles_t begin, end; */
/* begin = get_cycles(); */
/* g_prepare_time = begin - g_prepare_start; */
/* while (1) { */
/* vmx_get_cpu(lcd); */
/* local_irq_disable(); */
/* /\*if (need_resched()) { */
/* local_irq_enable(); */
/* vmx_put_cpu(lcd); */
/* cond_resched(); */
/* continue; */
/* }*\/ */
/* // In case we run from insmod. */
/* if (signal_pending(current)) { */
/* int signr; */
/* siginfo_t info; */
/* uint32_t x; */
/* local_irq_enable(); */
/* vmx_put_cpu(lcd); */
/* spin_lock_irq(&current->sighand->siglock); */
/* signr = dequeue_signal(current, &current->blocked, */
/* &info); */
/* spin_unlock_irq(&current->sighand->siglock); */
/* if (!signr) */
/* continue; */
/* if (signr == SIGKILL) { */
/* printk(KERN_INFO "vmx: got sigkill, dying"); */
/* lcd->ret_code = ((ENOSYS) << 8); */
/* break; */
/* } */
/* x = signr; // + base? */
/* x |= INTR_INFO_VALID_MASK; */
/* vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, x); */
/* continue; */
/* } */
/* local_irq_enable(); */
/* /\* local_irq_enable(); *\/ */
ret = vmx_run_vcpu(lcd);
if (ret == EXIT_REASON_VMCALL ||
ret == EXIT_REASON_CPUID) {
vmx_step_instruction();
}
/* ret = vmx_run_vcpu(lcd); */
/* if (ret == EXIT_REASON_VMCALL || */
/* ret == EXIT_REASON_CPUID) { */
/* vmx_step_instruction(); */
/* } */
if (ret == EXIT_REASON_EXTERNAL_INTERRUPT) {
vmx_handle_external_interrupt(lcd);
/* --countdown; */
}
/* if (ret == EXIT_REASON_EXTERNAL_INTERRUPT) { */
/* vmx_handle_external_interrupt(lcd); */
/* /\* --countdown; *\/ */
/* } */
vmx_put_cpu(lcd);
/* vmx_put_cpu(lcd); */
if (ret == EXIT_REASON_VMCALL) {
vmx_handle_vmcall(lcd);
}
else if (ret == EXIT_REASON_EPT_VIOLATION) {
done = vmx_handle_ept_violation(lcd);
}
else if (ret == EXIT_REASON_EXCEPTION_NMI) {
if (vmx_handle_nmi_exception(lcd))
done = 1;
} else if (ret != EXIT_REASON_EXTERNAL_INTERRUPT) {
printk(KERN_INFO "unhandled exit: reason %d: %s, "
"exit qualification %llx\n",
ret, lcd_exit_reason(ret), lcd->exit_qualification);
vmx_dump_cpu(lcd);
done = 1;
}
/* if (ret == EXIT_REASON_VMCALL) { */
/* vmx_handle_vmcall(lcd); */
/* } */
/* else if (ret == EXIT_REASON_EPT_VIOLATION) { */
/* done = vmx_handle_ept_violation(lcd); */
/* } */
/* else if (ret == EXIT_REASON_EXCEPTION_NMI) { */
/* if (vmx_handle_nmi_exception(lcd)) */
/* done = 1; */
/* } else if (ret != EXIT_REASON_EXTERNAL_INTERRUPT) { */
/* printk(KERN_INFO "unhandled exit: reason %d: %s, " */
/* "exit qualification %llx\n", */
/* ret, lcd_exit_reason(ret), lcd->exit_qualification); */
/* vmx_dump_cpu(lcd); */
/* done = 1; */
/* } */
--countdown;
if (countdown <=0 || done || lcd->shutdown) {
end = get_cycles();
printk("Cycles: %llu, counter %d\n", end-begin, countdown);
printk(KERN_INFO "unhandled exit: reason %d: %s, "
"exit qualification %llx, intr_info %x\n",
ret, lcd_exit_reason(ret), lcd->exit_qualification,
lcd->exit_intr_info);
/* vmx_dump_cpu(lcd); */
break;
}
}
/* --countdown; */
/* if (countdown <=0 || done || lcd->shutdown) { */
/* end = get_cycles(); */
/* printk("Cycles: %llu, counter %d\n", end-begin, countdown); */
/* printk(KERN_INFO "unhandled exit: reason %d: %s, " */
/* "exit qualification %llx, intr_info %x\n", */
/* ret, lcd_exit_reason(ret), lcd->exit_qualification, */
/* lcd->exit_intr_info); */
/* /\* vmx_dump_cpu(lcd); *\/ */
/* break; */
/* } */
/* } */
if (irqs_disabled())
local_irq_enable();
/* if (irqs_disabled()) */
/* local_irq_enable(); */
return 0;
}
EXPORT_SYMBOL(lcd_run);
/* return 0; */
/* } */
/* EXPORT_SYMBOL(lcd_run); */
/* int setup_vmlinux(struct lcd *lcd, char *file) { */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment