Commit d71afeb4 authored by Charlie Jacobsen's avatar Charlie Jacobsen Committed by Vikram Narayanan

Finished the majority of the arch-indep code changes needed.

Refactored lcd's into lcd and lcd_thread. Still need to test/update
tests.
parent 22f4bcd9
......@@ -246,12 +246,13 @@ struct lcd_arch_thread {
* : Free / Unmapped :
* : :
* | |
* LCD_ARCH_TOP----------> +---------------------------+ 0x0000 0000 0000 1000
* | Reserved |
* LCD_ARCH_TOP,---------> +---------------------------+ 0x0000 0000 0000 1000
* LCD_ARCH_BOTTOM | Reserved |
* | (not mapped, catch NULLs) | (4 KBs)
* +---------------------------+ 0x0000 0000 0000 0000
*/
#define LCD_ARCH_TOP (1 << 12)
#define LCD_ARCH_BOTTOM (1 << 12)
#define LCD_ARCH_TOP LCD_ARCH_BOTTOM
#define LCD_ARCH_FS_BASE __gpa(0UL)
#define LCD_ARCH_FS_LIMIT 0xFFFFFFFF
......@@ -302,6 +303,9 @@ struct lcd_arch *lcd_arch_create(void);
/**
* Tears down arch-dep part of LCD. All lcd_arch_threads should be
* removed and torn down before calling this.
*
* IMPORTANT: When the ept is torn down, any host memory that is still mapped
* will be freed. This is for convenience. But beware.
*/
void lcd_arch_destroy(struct lcd_arch *lcd_arch);
/**
......@@ -393,6 +397,10 @@ int lcd_arch_ept_map_range(struct lcd_arch *lcd, gpa_t ga_start,
* Simple routine combining ept walk and unset.
*/
int lcd_arch_ept_unmap(struct lcd_arch *lcd, gpa_t a);
/**
* Like unmpa, but returns old hpa in hpa_out.
*/
int lcd_arch_ept_unmap2(struct lcd_arch *lcd, gpa_t a, hpa_t *hpa_out);
/**
* Unmaps
*
......
......@@ -29,6 +29,8 @@
/* DEBUGGING -------------------------------------------------- */
#define LCD_ARCH_DEBUG 0
#define LCD_ARCH_ERR(msg...) __lcd_arch_err(__FILE__, __LINE__, msg)
static inline void __lcd_arch_err(char *file, int lineno, char *fmt, ...)
{
......@@ -1168,6 +1170,29 @@ int lcd_arch_ept_unmap(struct lcd_arch *lcd, gpa_t a)
return 0;
}
int lcd_arch_ept_unmap2(struct lcd_arch *lcd, gpa_t a, hpa_t *hpa_out)
{
int ret;
lcd_arch_epte_t *ept_entry;
/*
* Walk ept
*/
ret = lcd_arch_ept_walk(lcd, a, 0, &ept_entry);
if (ret)
return ret;
/*
* Extract hpa
*/
*hpa_out = lcd_arch_ept_hpa(ept_entry);
/*
* Unset
*/
lcd_arch_ept_unset(ept_entry);
return 0;
}
int lcd_arch_ept_unmap_range(struct lcd_arch *lcd, gpa_t ga_start,
unsigned long npages)
{
......@@ -1226,6 +1251,9 @@ int lcd_arch_ept_gpa_to_hpa(struct lcd_arch *lcd, gpa_t ga, hpa_t *ha_out)
* 1 = pdpt
* 2 = page dir
* 3 = page table
*
* IMPORTANT: Any host page frames that are still mapped are freed! Beware -
* this can lead to awful bugs.
*/
static void vmx_free_ept_dir_level(lcd_arch_epte_t *dir, int level)
{
......@@ -1235,14 +1263,11 @@ static void vmx_free_ept_dir_level(lcd_arch_epte_t *dir, int level)
/*
* Base case of recursion
*
* Just make sure none of the pte's are present, to
* ensure there are no memory leaks.
* Free the host page frame
*/
for (idx = 0; idx < LCD_ARCH_PTRS_PER_EPTE; idx++) {
if (vmx_epte_present(dir[idx])) {
LCD_ARCH_ERR("potential memory leak at hva %lx (hpa %lx, pt idx %d)\n",
hva_val(vmx_epte_hva(dir[idx])),
hpa_val(vmx_epte_hpa(dir[idx])));
if (vmx_epte_present(dir[idx]))
free_page(hva_val(vmx_epte_hva(dir[idx])));
}
} else {
/*
......
......@@ -33,17 +33,23 @@ enum lcd_thread_status {
struct lcd;
struct lcd_thread {
/*
* My corresponding kthread
*/
struct task_struct *kthread;
/*
* The containing lcd
*/
struct lcd *lcd;
/*
* List of threads in containing lcd
* List of threads in containing lcd. Protected by lock in containing
* lcd.
*/
struct list_head lcd_threads;
/*
* Thread control block, accessible by lcd_thread while running inside
* lcd. Contains message registers, etc.
* lcd (mapped in the bottom of its stack). Contains message
* registers, etc.
*/
struct lcd_utcb *utcb;
/*
......@@ -61,45 +67,42 @@ struct lcd_thread {
* =================
*
* The layout below reflects the guest physical *and* virtual memory
* layout. Guest virtual paging memory is filled on on demand
* during lcd initialization (so parts may not be backed by host physical
* memory), and stacks/utcb's are also filled in on demand as threads are
* created and added to the lcd. The lcd starts with one lcd_thread, so
* Stack 0 / utcb 0 will be mapped after the lcd is initialized.
* layout. This means guest physical and virtual addresses have identical
* values. (See the arch-dependent code header for the arch-dependent
* part of the address space.)
*
* Guest physical addresses are mapped one-to-one to the same guest
* virtual addresses.
* Stack/utcb pages: Except for the first thread, these are set up on demand.
* The microkernel will set up and map the first thread's stack/utcb in the
* stack 0 / utcb 0 page. For subsequent threads, the LCD requests that a
* thread be created and provides the guest physical and virtual addresses for
* its stack/utcb page; the microkernel will allocate a host physical page
* and map it in the guest physical/virtual address space of the LCD. This
* makes the microkernel logic simpler and puts the tricky/vulnerable
* guest address space allocation logic inside the LCD.
*
* The module is mapped to the same guest physical / guest virtual
* address space as the host, to avoid relocating symbols.
*
* The LCD is free to modify its guest virtual -> guest physical mappings after
* it starts. The guest virtual paging memory is for the microkernel's
* initial set up of the guest virtual address space (mapping the arch
* dependent chunks, the module, and the stack for the first thread).
*
* +---------------------------+
* module mapped | |
* somewhere in : :
* here -------> : :
* at a higher | |
* at a higher | FREE SPACE |
* address | |
* | |
* +---------------------------+
* | Stack 1023 |
* : : (4 KBs)
* | utcb 1023 |
* +---------------------------+
* | ... |
* : :
* | ... |
* +---------------------------+
* | Stack 1 |
* : : (4 KBs)
* | utcb 1 |
* +---------------------------+
* | Stack 0 |
* : : (4 KBs)
* | utcb 0 |
* +---------------------------+
* | Guest Virtual | (4 MBs)
* | Paging Memory |
* LCD_ARCH_FREE---> +---------------------------+
* LCD_ARCH_TOP----> +---------------------------+
* | |
* : Reserved Arch Memory :
* | |
......@@ -114,50 +117,63 @@ struct lcd {
*/
char name[MODULE_NAME_LEN];
/*
* Guest virtual paging:
* The module mapped in the lcd
*/
struct module *module;
/*
* List of contained lcd_threads
*/
struct {
struct list_head list;
struct mutex lock;
} lcd_threads;
/*
* Guest virtual paging
*
* This is only needed while we're setting up the LCD. The LCD will
* be responsible for managing its guest virtual address space after
* it starts up (hence no lock, for now ...).
*
* We use a simple counter for allocating guest virtual memory used for
* page tables for the lcd's guest virtual address space, to ensure
* we don't go past 4 MBs. (See the address space diagram above.)
*
* root is the host virtual address that points to the root of
* the lcd's guest virtual paging hierarchy.
*
* We use a simple bitmap for allocating memory used for page tables
* for the lcd's guest virtual address space. This is only needed when
* the lcd is being set up - mapping the arch bits, module code, the
* first lcd_thread's tcb, etc.
*/
pgd_t *root;
DECLARE_BITMAP(gv_paging_bmap, (LCD_PAGING_MEM_SIZE >> PAGE_SIZE));
struct {
pgd_t *root;
gpa_t root_gpa;
int counter;
} gv_paging;
/*
* The first thread to enter the lcd and run the module's init. Pass
* this to lcd_thread_start to start running it in the lcd.
*/
struct lcd_thread *init_thread;
};
/**
* -- Loads module_name into host kernel. (Note: The module loading code
* expects underscores, _, rather than hyphens. If the module's name
* in the file system is some-module.ko, use the name some_module.)
* -- Spawns a kernel thread that will host the lcd.
* -- The kernel thread will create the lcd and map the module into
* the lcd. The kernel thread will then wait with the lcd's status
* set to LCD_THREAD_SUSPENDED.
* -- Call lcd_run_as_module to start running the lcd.
* -- Returns NULL if we fail to create the kernel thread, or if the
* kernel thread failed to initialize the lcd, etc.
* -- Sets up the address space with the module mapped inside it in the lcd
* -- Sets up an initial thread for running inside the lcd (stored in
* the struct lcd's init_thread)
*
* Call lcd_destroy_as_module after a successful return from
* lcd_create_as_module to stop the kthread and remove the module
* from the host kernel.
*/
struct task_struct * lcd_create_as_module(char *module_name);
/**
* Wakes up kthread to start running lcd. Call this after a successful
* return from lcd_create_as_module. Call lcd_destroy_as_module when
* the kthread/lcd are no longer needed.
*/
int lcd_run_as_module(struct task_struct *t);
/**
* Stops the kernel thread (which in turn, destroys the lcd) and removes
* the module from the host kernel.
* Call lcd_thread_start on the lcd's init thread to start executing the
* module's init inside the lcd.
*
* Call lcd_destroy after killing the lcd's init thread to tear down the
* lcd and remove the module from the host.
*
* Note: The kthread checks if it should stop each time the lcd exits in
* the main run loop.
* lcd_thread_kill will block until the underlying kernel thread exits (the
* kthread checks whether it should stop each time the lcd thread exits from
* the lcd -- due to an interrupt, etc.).
*/
void lcd_destroy_as_module(struct task_struct *t, char *module_name);
int lcd_create(char *module_name, struct lcd **out);
void lcd_destroy(struct lcd *lcd);
int lcd_thread_start(struct lcd_thread *t);
int lcd_thread_kill(struct lcd_thread *t);
#endif /* LCD_DOMAINS_LCD_DOMAINS_H */
......@@ -1467,8 +1467,8 @@ struct task_struct {
atomic_t usage;
unsigned int flags; /* per process flags, defined below */
unsigned int ptrace;
#ifdef CONFIG_LCD_CSPACE
struct lcd *lcd;
#ifdef CONFIG_HAVE_LCD
struct lcd_thread *lcd_thread;
#endif
#ifdef CONFIG_SMP
struct llist_node wake_entry;
......
......@@ -14,17 +14,6 @@
/* FIXME: this must be reserved in miscdevice.h */
#define LCD_MINOR 234
struct lcd_pv_kernel_config {
char *file_name;
unsigned int file_name_length;
__u64 length;
} __attribute__((packed));
struct lcd_blob_info {
unsigned char *blob;
unsigned int blob_order;
} __attribute__((packed));
struct lcd_init_module_args {
/* syscall arguments to init_module */
void *module_image;
......@@ -32,8 +21,6 @@ struct lcd_init_module_args {
const char *param_values;
} __attribute__((packed));
#define LCD_LOAD_PV_KERNEL _IOR(LCD_MINOR, 0x01, struct lcd_pv_kernel_config)
#define LCD_RUN_BLOB _IOR(LCD_MINOR, 0x02, struct lcd_blob_info)
#define LCD_INIT_MODULE _IOR(LCD_MINOR, 0x03, struct lcd_init_module_args)
#define LCD_INIT_MODULE _IOR(LCD_MINOR, 0x01, struct lcd_init_module_args)
#endif /* LCD_DOMAINS_H */
This diff is collapsed.
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