Commit 6b12bac4 authored by Charlie Jacobsen's avatar Charlie Jacobsen Committed by Vikram Narayanan
Browse files

Adds example to test async runtime.

The example fails right now. Michael and I will debug.

Async (THC) runtime init/exit integrated into
LCD boot/shutdown. This is working properly.

This commit also fixes a serious bug in the page allocator,
and fixes some kmalloc configuration.

As I will note on the wiki, the maximum allowed alloc size
for kmalloc is 32 pages (128 KBs). This was chosen so that
the async runtime will work (lazy stacks are about 17 pages).
There is a limit on the max size because of how I allocate
groups of pages (I use an array allocated on the stack inside
the page allocator at some point, and this array can't be
too big). In the future, we may improve on this.
parent 742eca0d
......@@ -4,7 +4,10 @@
#
export LCD_DOMAINS_INCLUDE=$(PWD)/include
export LCD_DOMAINS_CFLAGS=-Werror -I$(LCD_DOMAINS_INCLUDE)
export LCD_DOMAINS_CFLAGS=-Werror \
-I$(LCD_DOMAINS_INCLUDE) \
-DLCD_DOMAINS \
-DCONFIG_LAZY_THC
# Don't print "Entering directory..." etc.
MAKEFLAGS += --no-print-directory
......@@ -12,10 +15,10 @@ MAKEFLAGS += --no-print-directory
all: liblcd the_rest
the_rest: liblcd
$(MAKE) -C .. M=$(PWD)
$(MAKE) -C .. M=$(PWD) -j8
liblcd:
$(MAKE) -C .. M=$(PWD)/liblcd
$(MAKE) -C .. M=$(PWD)/liblcd -j8
clean: module_init_tools_clean
$(MAKE) -C .. M=$(PWD) clean
......
......@@ -55,6 +55,7 @@
#undef CONFIG_SMP
#undef CONFIG_KALLSYMS
#undef CONFIG_SWAP
#undef CONFIG_TRANSPARENT_HUGEPAGE
#ifndef CONFIG_SLAB
#define CONFIG_SLAB
......@@ -65,6 +66,9 @@
#undef CONFIG_NODES_SHIFT /* force max numnodes to 1 */
#undef CONFIG_FORCE_MAX_ZONEORDER
#define CONFIG_FORCE_MAX_ZONEORDER 6
/*
* Set include guards to force using our includes.
*/
......
......@@ -125,6 +125,11 @@ int lcd_enter(void);
*/
void __noreturn lcd_exit(int retval);
/**
* Exit from lcd. Doesn't try to tear down anything. Just does
* exit syscall immediately.
*/
void __noreturn lcd_abort(void);
/* LOW LEVEL PAGE ALLOC -------------------------------------------------- */
......
......@@ -107,10 +107,6 @@ void thc_done(void);
awe_t _awe; \
extern void * CONT_RET_FN_NAME(_C) (void); \
\
_awe.status = LAZY_AWE; \
_awe.lazy_stack = NULL; \
_awe.pts = NULL; \
\
/* Define nested function containing the body */ \
noinline auto void _thc_nested_async(FORCE_ARGS_STACK awe_t *awe) __asm__(NESTED_FN_STRING(_C)); \
noinline void _thc_nested_async(FORCE_ARGS_STACK awe_t *awe) { \
......@@ -127,6 +123,10 @@ void thc_done(void);
/* Otherwise, return */ \
RETURN_CONT(CONT_RET_FN_STRING(_C)); \
} \
_awe.status = LAZY_AWE; \
_awe.lazy_stack = NULL; \
_awe.pts = NULL; \
\
SCHEDULE_CONT(&_awe, _thc_nested_async); \
__asm__ volatile ( \
" .globl " CONT_RET_FN_STRING(_C) "\n\t" \
......
......@@ -359,8 +359,8 @@ extern int _end_text_nx;
#define SCHEDULE_CONT(_AWE_PTR, NESTED_FUNC) \
({ \
KILL_CALLEE_SAVES(); \
uint64_t savedRAX; \
KILL_CALLEE_SAVES(); \
__asm__ __volatile__( \
"movq %%rbx, %0\n\t" \
"movq %1, %%rbx\n\t" \
......
......@@ -352,24 +352,24 @@ static inline hpa_t hva2hpa(hva_t hva)
* somewhere in : (mostly free) :
* here --------> | |
* | |
* +---------------------------+ 0x0000 0000 0150 4000
* +---------------------------+ 0x0000 0000 0150 8000
* | |
* | Heap |
* : (16 MBs) :
* | |
* +---------------------------+ 0x0000 0000 0050 4000
* +---------------------------+ 0x0000 0000 0050 8000
* | Stack |
* | (4 KBs) |
* +---------------------------+ 0x0000 0000 0050 3000
* | (8 KBs) |
* +---------------------------+ 0x0000 0000 0050 6000
* | Guard page |
* | (not mapped) |
* | (4 KBs) |
* +---------------------------+ 0x0000 0000 0050 2000
* +---------------------------+ 0x0000 0000 0050 5000
* | UTCB |
* | (4 KBs) |
* +---------------------------+ 0x0000 0000 0050 1000
* +---------------------------+ 0x0000 0000 0050 4000
* | Boot info |
* | (4 KBs) |
* | (16 KBs) |
* +---------------------------+ 0x0000 0000 0050 0000
* | Guest Virtual Page Tables |
* | (4 MBs max) |
......@@ -380,7 +380,7 @@ static inline hpa_t hva2hpa(hva_t hva)
*/
#define LCD_BOOT_PAGES_ORDER 2
#define LCD_STACK_PAGES_ORDER 0
#define LCD_STACK_PAGES_ORDER 1
/* guest physical addresses */
#define LCD_GV_PAGING_MEM_GPA __gpa(1 << 20) /* low 1 MB is empty */
......
......@@ -1574,7 +1574,7 @@ int klcd_create_module_lcd(cptr_t *slot_out, char *mdir, char *mname,
* Configure lcd
*/
ret = lcd_config(*slot_out, (*mi)->init,
gva_add(LCD_STACK_GVA, LCD_STACK_SIZE - 1), /* stack */
gva_add(LCD_STACK_GVA, LCD_STACK_SIZE), /* stack */
LCD_GV_PAGING_MEM_GPA,
LCD_UTCB_GPA);
if (ret) {
......
......@@ -5,9 +5,6 @@
# I hack KBUILD_CFLAGS so we don't have to do this in every kbuild file.
KBUILD_CFLAGS := $(KBUILD_CFLAGS) $(LCD_DOMAINS_CFLAGS)
# for async code conditional compilation
ccflags-y := -DLCD_DOMAINS
lib-y += $(addprefix lcd/, cap.o \
enterexit.o \
ipc.o \
......
......@@ -52,13 +52,15 @@
#define DEBUGPRINTF debug_printf
#elif LCD_DOMAINS
#define DEBUGPRINTF printk
#undef KERN_ERR
#define KERN_ERR ""
#else
#define DEBUGPRINTF printf
#endif
//#define DEBUG_STATS(XX)
#define DEBUG_STATS(XX) do{ XX; } while (0)
#define DEBUG_STATS_PREFIX " stats: "
#define DEBUG_STATS_PREFIX " stats: "
//#define VERBOSE_DEBUG
......@@ -162,8 +164,13 @@ static struct thc_latch debug_latch = {0};
static void thc_print_pts_stats(PTState_t *t, int clear)
{
thc_latch_acquire(&debug_latch);
DEBUG_STATS(DEBUGPRINTF(DEBUG_STATS_PREFIX "----------------------------------------\n"));
#ifdef LCD_DOMAINS
printk(KERN_ERR "---------------\n");
printk(KERN_ERR " THC STATS \n");
printk(KERN_ERR "---------------\n");
#else
DEBUG_STATS(DEBUGPRINTF(DEBUG_STATS_PREFIX "------------------------------\n"));
#endif
DEBUG_STATS(DEBUGPRINTF(DEBUG_STATS_PREFIX " %c stacks %8d %8d\n",
(t->stacksAllocated == t->stacksDeallocated) ? ' ' : '*',
t->stacksAllocated, t->stacksDeallocated));
......@@ -521,6 +528,7 @@ static void thc_dispatch(PTState_t *pts) {
static void thc_start_rts(void) {
InitPTS();
printk("Initialized PTS!");
assert(PTS() && (!PTS()->doneInit) && "Already initialized RTS");
DEBUG_INIT(DEBUGPRINTF(DEBUG_INIT_PREFIX "> Starting\n"));
thc_init_dispatch_loop();
......@@ -611,7 +619,7 @@ static void init_lazy_awe (void ** lazy_awe_fp) {
awe_t *awe = THC_LAZY_FRAME_AWE(lazy_awe_fp);
#ifdef LCD_DOMAINS
printk(KERN_ERR "\nthe value of the lazy frame awe is: %x\n", (int)awe);
printk(KERN_ERR "\nthe value of the lazy frame awe is: 0x%p\n", awe);
#endif
DEBUG_AWE(DEBUGPRINTF(DEBUG_AWE_PREFIX " found lazy awe %p @ frameptr %p",
......@@ -640,9 +648,9 @@ static void init_lazy_awe (void ** lazy_awe_fp) {
// they are found.
static void check_for_lazy_awe (void * ebp) {
DEBUG_AWE(DEBUGPRINTF(DEBUG_AWE_PREFIX "> CheckForLazyAWE (ebp=%p)\n", ebp));
void **frame_ptr = (void **) ebp;
void *ret_addr = THC_LAZY_FRAME_RET(frame_ptr);
DEBUG_AWE(DEBUGPRINTF(DEBUG_AWE_PREFIX "> CheckForLazyAWE (ebp=%p)\n", ebp));
while (frame_ptr != NULL && ret_addr != NULL) {
if (ret_addr == &_thc_lazy_awe_marker) {
#ifdef LCD_DOMAINS
......@@ -1347,8 +1355,17 @@ static void *thc_alloc_new_stack_0(void)
void *res = kmalloc(STACK_COMMIT_BYTES + STACK_GUARD_BYTES, GFP_KERNEL);
if (!res) {
LIBLCD_ERR("lcd async stack allocation failed");
return NULL;
/*
* The rest of the async code isn't prepared to
* handle a failed malloc (boo), so we die inside
* here. (We could certainly patch up the code in the
* future.)
*/
lcd_abort();
}
printk("kmalloc'd stack");
/* Note that sizeof(void) = 1 not 8. */
res += STACK_GUARD_BYTES + STACK_COMMIT_BYTES;
return res;
......
#include <lcd-domains/liblcd-config.h>
#include <lcd-domains/liblcd.h>
#include <lcd-domains/thc.h>
#include <lcd-domains/liblcd-hacks.h>
int lcd_enter(void)
......@@ -47,6 +47,14 @@ int lcd_enter(void)
goto fail;
}
LIBLCD_MSG("data store subystem ready");
/*
* Set up async runtime
*/
thc_init();
lcd_printk("===============");
lcd_printk(" LCD BOOTED ");
lcd_printk("===============");
return 0;
......@@ -56,11 +64,26 @@ fail:
void __noreturn lcd_exit(int retval)
{
lcd_printk("=================");
lcd_printk("LCD SHUTTING DOWN");
lcd_printk("=================");
/*
* For now, don't tear anything down, just exit.
* For now, just tear down async so we can make sure
* it all worked.
*/
thc_done();
LIBLCD_MSG("exiting");
lcd_set_r0(retval);
for(;;)
LCD_DO_SYSCALL(LCD_SYSCALL_EXIT); /* doesn't return */
}
void __noreturn lcd_abort(void)
{
LIBLCD_MSG("aborting");
lcd_set_r0(-EIO);
for(;;)
LCD_DO_SYSCALL(LCD_SYSCALL_EXIT); /* doesn't return */
}
......@@ -18,8 +18,11 @@
#define LCD_FREE_MEM_SIZE (16 << 20)
#define LCD_FREE_MEM_BMAP_SIZE (LCD_FREE_MEM_SIZE >> PAGE_SHIFT)
/* Controls the biggest chunk of pages we can alloc - 2^3 = 8 */
#define LCD_FREE_MEM_MAX_ORDER 3
/* Controls the biggest chunk of pages we can alloc. This is ultimately
* configured in liblcd-config.h under CONFIG_FORCE_MAX_ZONEORDER.
* NOTE: This needs to be small enough so that the stack frame for
* allocating pages isn't too big. */
#define LCD_FREE_MEM_MAX_ORDER MAX_ORDER
static DECLARE_BITMAP(paging_mem_bmap, LCD_GV_PAGING_MEM_BMAP_SIZE);
static cptr_t paging_mem_page2cptr[LCD_GV_PAGING_MEM_BMAP_SIZE];
......@@ -788,6 +791,14 @@ int lcd_alloc_pages(unsigned order, gva_t *base_out)
cptr_t pages[1 << LCD_FREE_MEM_MAX_ORDER];
int ret;
unsigned i, j;
/*
* Check that order isn't too big
*/
if (order > LCD_FREE_MEM_MAX_ORDER) {
lcd_printk("lcd_alloc_pages: order %d is too big",
order);
return -ENOMEM;
}
/*
* Get pages from microkernel
*/
......@@ -964,6 +975,7 @@ static void init_page_alloc_data(void)
idx = gpa_val(boot_mem_pi_start[i].page_gpa);
idx -= gpa_val(LCD_BOOT_PAGES_GPA);
idx >>= PAGE_SHIFT;
BUG_ON(idx >= (1 << LCD_BOOT_PAGES_ORDER));
boot_cptrs[idx] = boot_mem_pi_start[i].my_cptr;
}
/*
......@@ -973,6 +985,7 @@ static void init_page_alloc_data(void)
idx = gpa_val(stack_mem_pi_start[i].page_gpa);
idx -= gpa_val(LCD_STACK_GPA);
idx >>= PAGE_SHIFT;
BUG_ON(idx >= (1 << LCD_STACK_PAGES_ORDER));
stack_cptrs[idx] = stack_mem_pi_start[i].my_cptr;
}
/*
......@@ -984,6 +997,7 @@ static void init_page_alloc_data(void)
idx = gpa_val(paging_mem_pi_start[i].page_gpa);
idx -= gpa_val(LCD_GV_PAGING_MEM_BASE);
idx >>= PAGE_SHIFT;
BUG_ON(idx >= LCD_GV_PAGING_MEM_BMAP_SIZE);
set_bit(idx, paging_mem_bmap);
paging_mem_page2cptr[idx] = paging_mem_pi_start[i].my_cptr;
}
......@@ -994,6 +1008,7 @@ static void init_page_alloc_data(void)
idx = gpa_val(free_mem_pi_start[i].page_gpa);
idx -= gpa_val(LCD_FREE_MEM_BASE);
idx >>= PAGE_SHIFT;
BUG_ON(idx >= LCD_FREE_MEM_BMAP_SIZE);
set_bit(idx, free_mem_bmap);
free_mem_page2cptr[idx] = free_mem_pi_start[i].my_cptr;
}
......
......@@ -149,6 +149,34 @@ fail1:
return ret;
}
static int kmalloc_big_test(void)
{
void *x;
/* Alloc 24 pages */
x = kmalloc(24 << PAGE_SHIFT, GFP_KERNEL);
if (!x) {
LIBLCD_ERR("kmalloc failed");
return -1;
}
kfree(x);
return 0;
}
static int kmalloc_bigbig_test(void)
{
void *x;
/* This alloc should fail. */
x = kmalloc(KMALLOC_MAX_SIZE + 1, GFP_KERNEL);
if (x) {
LIBLCD_ERR("kmalloc should have failed");
kfree(x);
return -1;
}
return 0;
}
static int dstore_test(void)
{
struct dstore *d1, *d2;
......@@ -268,6 +296,18 @@ int lcd_run_tests(void)
return ret;
}
LIBLCD_MSG("kmalloc test passed!");
ret = kmalloc_big_test();
if (ret) {
LIBLCD_ERR("kmalloc big test failed");
return ret;
}
LIBLCD_MSG("kmalloc big test passed!");
ret = kmalloc_bigbig_test();
if (ret) {
LIBLCD_ERR("kmalloc bigbig test failed");
return ret;
}
LIBLCD_MSG("kmalloc bigbig test passed!");
ret = dstore_test();
if (ret) {
LIBLCD_ERR("dstore test failed");
......
......@@ -19,3 +19,5 @@ obj-m += create-klcd/
obj-m += glue-example/
obj-m += pmfs/
obj-m += async/
# Main targets
obj-m += lcd_test_mod_async_boot.o
lcd_test_mod_async_boot-y += boot.o
obj-m += lcd_test_mod_async_lcd.o
lcd_test_mod_async_lcd-y += lcd.o
lcd_test_mod_async_lcd-y += $(LIBLCD)
/**
* boot.c - non-isolated kernel module, does setup
*
*/
#include <lcd-domains/kliblcd.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int boot_main(void)
{
int ret;
cptr_t lcd;
struct lcd_info *mi;
/*
* Enter lcd mode
*/
ret = lcd_enter();
if (ret) {
LIBLCD_ERR("lcd enter failed");
goto fail1;
}
/*
* Create lcd
*/
ret = lcd_create_module_lcd(&lcd,
LCD_DIR("async"),
"lcd_test_mod_async_lcd",
LCD_CPTR_NULL, &mi);
if (ret) {
LIBLCD_ERR("failed to create lcd");
goto fail2;
}
/*
* Set up boot info
*/
ret = lcd_dump_boot_info(mi);
if (ret) {
LIBLCD_ERR("dump boot info");
goto fail3;
}
/*
* Run lcd
*/
ret = lcd_run(lcd);
if (ret) {
LIBLCD_ERR("failed to start lcd");
goto fail4;
}
/*
* Hang out for a few seconds for lcd to exit
*/
msleep(3000);
/*
* Tear everything down
*/
ret = 0;
goto out;
out:
fail4:
fail3:
/*
* This call is necessary because we need to tear down the module
* on the host (otherwise, an lcd_cap_delete would be sufficient
*/
lcd_destroy_module_lcd(lcd, mi, LCD_CPTR_NULL);
fail2:
lcd_exit(0);
fail1:
return ret;
}
static void boot_exit(void)
{
/* nothing to do */
}
module_init(boot_main);
module_exit(boot_exit);
/**
* lcd.c - code for lcd in ipc test
*/
#include <lcd-domains/liblcd-config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <lcd-domains/liblcd.h>
#include <lcd-domains/thc.h>
#include <lcd-domains/liblcd-hacks.h>
static void f1(void)
{
LIBLCD_MSG("called f1, yielding...");
THCYield();
LIBLCD_MSG("back in f1 from yield");
}
static void f2(void)
{
LIBLCD_MSG("called f2, yielding...");
THCYield();
LIBLCD_MSG("back in f2 from yield");
}
static void do_stuff(void)
{
DO_FINISH(
ASYNC(
f1();
);
ASYNC(
f2();
);
);
LIBLCD_MSG("out of do-finish");
}
static int __noreturn __init async_lcd_init(void)
{
int r = 0;
r = lcd_enter();
if (r)
goto out;
do_stuff();
goto out;
out:
lcd_exit(r);
}
static void async_lcd_exit(void)
{
return;
}
module_init(async_lcd_init);
module_exit(async_lcd_exit);
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