Commit dc9a8338 authored by Charles Jacobsen's avatar Charles Jacobsen Committed by Vikram Narayanan

pmfs: mount: Add mechanism to disable interrupts inside LCD.

We need a way to temporarily prevent external interrupts from
causing an LCD exit.
parent 30b2f271
......@@ -54,6 +54,19 @@ struct lcd_arch_vmcs *lcd_arch_alloc_vmcs(int cpu);
* Free @vmcs page(s).
*/
void lcd_arch_free_vmcs(struct lcd_arch_vmcs *vmcs);
/**
* Configure LCD so that external interrupts do not cause an
* unconditional exit.
*/
void lcd_arch_irq_disable(struct lcd_arch *lcd_arch);
/**
* Configure LCD so that external interrupts *do* cause an
* unconditional exit.
*
* NOTE: Unlike local_irq_enable, this function *always*
* "re-enables" interrupts.
*/
void lcd_arch_irq_enable(struct lcd_arch *lcd_arch);
/* Some internal data used in create */
extern struct kmem_cache *lcd_arch_cache;
......
......@@ -250,5 +250,14 @@ static inline void lcd_syscall_dump_stack(void)
lcd_syscall_no_args(LCD_SYSCALL_DUMP_STACK);
}
static inline void lcd_syscall_irq_disable(void)
{
lcd_syscall_no_args(LCD_SYSCALL_IRQ_DISABLE);
}
static inline void lcd_syscall_irq_enable(void)
{
lcd_syscall_no_args(LCD_SYSCALL_IRQ_ENABLE);
}
#endif /* ASM_LCD_DOMAINS_LIBLCD_H */
......@@ -1036,3 +1036,28 @@ int lcd_arch_set_gva_root(struct lcd_arch *lcd_arch, gpa_t a)
vmx_put_cpu(lcd_arch);
return 0;
}
void lcd_arch_irq_disable(struct lcd_arch *lcd_arch)
{
/*
* Clear pin based external interrupt bit. NMIs will still
* cause an exit.
*/
vmx_get_cpu(lcd_arch);
vmcs_write32(PIN_BASED_VM_EXEC_CONTROL,
lcd_global_vmcs_config.pin_based_exec_controls &
~PIN_BASED_EXT_INTR_MASK);
vmx_put_cpu(lcd_arch);
}
void lcd_arch_irq_enable(struct lcd_arch *lcd_arch)
{
/*
* Set pin based external interrupt bit.
*/
vmx_get_cpu(lcd_arch);
vmcs_write32(PIN_BASED_VM_EXEC_CONTROL,
lcd_global_vmcs_config.pin_based_exec_controls &
PIN_BASED_EXT_INTR_MASK);
vmx_put_cpu(lcd_arch);
}
/*
* irq.h
*
* Enable and disable IRQs.
*
* Motivation: You want to configure the LCD so that
* external interrupts do not cause a VM exit. Note that
* if you invoke a hypercall that causes a VM exit, the
* microkernel may choose to enable interrupts, and may
* get preempted at that point.
*/
#ifdef LIBLCD_IRQ_H
#define LIBLCD_IRQ_H
/**
* lcd_irq_disable
*
* For isolated code, disables interrupts and prevents interrupts
* from causing a VM exit. Note that NMIs will still trigger an
* exit.
*
* This is a no-op for non-isolated code. You should use the
* regular local_irq_disable.
*/
void lcd_irq_disable(void);
/**
* lcd_irq_enable
*
* For isolated code, unconditionally re-enables interrupts. Interrupts
* will cause a VM exit now.
*
* Again, this is a no-op for non-isolated code.
*/
void lcd_irq_enable(void);
#endif /* LIBLCD_IRQ_H */
......@@ -28,6 +28,8 @@ enum lcd_syscall {
LCD_SYSCALL_MMAP,
LCD_SYSCALL_MUNMAP,
LCD_SYSCALL_DUMP_STACK,
LCD_SYSCALL_IRQ_ENABLE,
LCD_SYSCALL_IRQ_DISABLE,
};
#endif /* LCD_DOMAINS_SYSCALL_H */
/*
* irq.c
*/
#include <liblcd/irq.h>
void lcd_irq_disable(void)
{
return; /* no op */
}
void lcd_irq_enable(void)
{
return; /* no op */
}
/* EXPORTS -------------------------------------------------- */
EXPORT_SYMBOL(lcd_irq_disable);
EXPORT_SYMBOL(lcd_irq_enable);
/*
* irq.c
*/
#include <lcd_config/pre_hook.h>
#include <asm/lcd_domains/liblcd.h>
#include <liblcd/irq.h>
#include <lcd_config/post_hook.h>
void lcd_irq_disable(void)
{
/* Disable interrupts inside the VM */
__asm__ ("cli");
/* Configure LCD so that external interrupts do not cause vm exit */
lcd_syscall_irq_disable();
}
void lcd_irq_enable(void)
{
/* Disable interrupts inside the VM */
__asm__ ("sti");
/* Configure LCD so that external interrupts *do* cause a vm exit */
lcd_syscall_irq_enable();
}
......@@ -290,6 +290,16 @@ static int handle_syscall_exit(struct lcd *lcd, int *lcd_ret)
return 1; /* signal LCD has exited */
}
static int handle_syscall_irq_disable(struct lcd *lcd)
{
lcd_arch_irq_disable(lcd->lcd_arch);
}
static int handle_syscall_irq_enable(struct lcd *lcd)
{
lcd_arch_irq_enable(lcd->lcd_arch);
}
static int handle_syscall(struct lcd *lcd, int *lcd_ret)
{
int syscall_id;
......@@ -361,6 +371,12 @@ static int handle_syscall(struct lcd *lcd, int *lcd_ret)
case LCD_SYSCALL_DUMP_STACK:
ret = handle_syscall_dump_stack(lcd);
break;
case LCD_SYSCALL_IRQ_DISABLE:
ret = handle_syscall_irq_disable(lcd);
break;
case LCD_SYSCALL_IRQ_ENABLE:
ret = handle_syscall_irq_enable(lcd);
break;
default:
LCD_ERR("unimplemented syscall %d", syscall_id);
ret = -ENOSYS;
......@@ -374,7 +390,7 @@ static int handle_syscall(struct lcd *lcd, int *lcd_ret)
}
/* RUN LOOP -------------------------------------------------- */
int icount = 0;
static int run_once(struct lcd *lcd, int *lcd_ret)
{
int ret;
......@@ -396,6 +412,7 @@ static int run_once(struct lcd *lcd, int *lcd_ret)
* Continue
*/
ret = 0;
icount++;
goto out;
case LCD_ARCH_STATUS_EPT_FAULT:
LCD_ERR("ept fault");
......@@ -475,6 +492,7 @@ static int main_for_lcd(struct lcd *lcd)
lcd_arch_dump_lcd(lcd->lcd_arch);
return ret;
} else if (ret == 1) {
LCD_MSG("icount is %d", icount);
/* lcd exited */
return lcd_ret;
} else {
......
......@@ -24,6 +24,7 @@ lib-y += $(addprefix liblcd/lcd-domains/, \
sync_ipc.o \
ioremap.o \
trace.o \
irq.o \
)
lib-y += $(addprefix liblcd/lib/, \
......
......@@ -48,6 +48,7 @@ lcd_domains-y += $(addprefix kliblcd/, \
module_load.o \
sync_ipc.o \
trace.o \
irq.o \
)
# code shared by kliblcd and isolated liblcd
......
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