Commit 730fd7d4 authored by Charlie Jacobsen's avatar Charlie Jacobsen Committed by Vikram Narayanan

Adds 'data store' to non-isolated kliblcd.

Kind of boring, but important. Now poised for doing some non-isolated
glue code.

Kind of bummer we have essentially three copies of the cspace-related
code - one in liblcd (isolated data store), one in kliblcd, and one in
the microkernel (real cspaces). Hopefully we can coalesce and reduce
the redundancy at some point.

The data store code for kliblcd is in virt/lcd-domains/kliblcd/dstore.c.
The interface is in include/lcd-domains/kliblcd.h.

Moved dstore into kliblcd. No build yet.

Small typo in cap doc.

Debug something else.

Updated dstore to do get/put.

Fixes build. liblcd tests pass.
parent 4f442454
......@@ -272,7 +272,7 @@ final cnode table:
bits = 11 = 3; so we follow the 3rd table slot to arrive
at the cnode table in level 3
We now use the cap lot index bits = 01 = 1 to look up the capability.
We now use the cap slot index bits = 01 = 1 to look up the capability.
Another example: if the cptr is
......@@ -283,7 +283,7 @@ Starting in the root cnode table,
[1] we see that the level = 01 = 1 > 0, so we look at the first pair of
fanout bits = 01 = 1; we follow the pointer in the 1st table slot
to level
to level 1
[2] we now see that the level of the cptr = the level we are at, 1, so
we now use the slot bits to look up the slot in the table (11 = 3).
......
......@@ -402,6 +402,79 @@ static inline void __lcd_free_cptr(struct cptr_cache *cache, cptr_t c)
return __klcd_free_cptr(cache, c);
}
/* DATA STORE -------------------------------------------------- */
/*
* Adapted from cptrs / capabilities.
*/
struct dstore;
struct dstore_node;
typedef struct { unsigned long dptr; } dptr_t;
/**
* These tags are reserved.
*/
#define LCD_DSTORE_TAG_NULL 0
#define LCD_DSTORE_TAG_DSTORE_NODE 1
/**
* Initializes caches, etc. in data store subsystem. Should be called when
* LCD boots, but after the slab allocator is initialized.
*/
int lcd_dstore_init(void);
/**
* Tears down caches, etc. in data store subsystem. Should be called before
* LCD exits (not critical right now).
*/
void lcd_dstore_exit(void);
/**
* Sets up a data store.
*/
int lcd_dstore_init_dstore(struct dstore **out);
/**
* Inserts object into data store. The caller can associate
* an arbitrary integer tag with the object so that it can do basic
* type checking. Tags 0 and 1 are reserved.
*
* Returns dptr where object is stored in out.
*/
int lcd_dstore_insert(struct dstore *dstore, void *object, int tag,
dptr_t *out);
/**
* Removes object from data store. Unlike capabilities, does not free object
* or do anything else; the caller is responsible for tracking that.
*
* Silently fails if no object is stored at d, or if d is invalid.
*/
void lcd_dstore_delete(struct dstore *dstore, dptr_t d);
/**
* Tears down data store.
*/
void lcd_dstore_destroy(struct dstore *dstore);
/**
* Look up object in dstore at d. Ensure it has tag. Returns dstore node
* containing object in out.
*
* ** THIS LOCKS THE DSTORE NODE. CALL A MATCHING lcd_dstore_put TO RELEASE **
*
* This can be used to synchronize multiple threads that are trying to
* look up the object and modify it.
*
* Returns non-zero if object not found, or if object found but has wrong
* tag.
*/
int lcd_dstore_get(struct dstore *dstore, dptr_t d, int tag,
struct dstore_node **out);
/**
* Extracts object from dstore node.
*/
void *lcd_dstore_node_object(struct dstore_node *n);
/**
* Release the lock on the dstore object stored at d.
*/
void lcd_dstore_put(struct dstore_node *n);
/* EXTRAS -------------------------------------------------- */
......
......@@ -288,140 +288,19 @@ static inline struct lcd_boot_info * lcd_get_boot_info(void)
* this multithreaded in the future.
*/
typedef struct { unsigned long dptr; } dptr_t;
static inline dptr_t __dptr(unsigned long dptr)
{
return (dptr_t){ dptr };
}
static inline unsigned long dptr_val(dptr_t d)
{
return d.dptr;
}
#define LCD_DPTR_NULL (__dptr(0))
static inline int dptr_is_null(dptr_t d)
{
return dptr_val(d) == dptr_val(LCD_DPTR_NULL);
}
#define LCD_DPTR_DEPTH_BITS 2 /* max depth of 3, zero indexed */
#define LCD_DPTR_FANOUT_BITS 2 /* each level fans out by a factor of 4 */
#define LCD_DPTR_SLOT_BITS 2 /* each node contains 4 slots */
#define LCD_DSTORE_NODE_TABLE_NUM_SLOTS ((1 << LCD_DPTR_SLOT_BITS) + \
(1 << LCD_DPTR_FANOUT_BITS))
#define LCD_DPTR_LEVEL_SHIFT (((1 << LCD_DPTR_DEPTH_BITS) - 1) * \
LCD_DPTR_FANOUT_BITS + LCD_DPTR_SLOT_BITS)
static inline unsigned long lcd_dptr_slot(dptr_t d)
{
/*
* Mask off low bits
*/
return dptr_val(d) & ((1 << LCD_DPTR_SLOT_BITS) - 1);
}
/*
* Gives fanout index for going *from* lvl to lvl + 1, where
* 0 <= lvl < 2^LCD_DPTR_DEPTH_BITS - 1 (i.e., we can't go anywhere
* if lvl = 2^LCD_DPTR_DEPTH_BITS - 1, because we are at the deepest
* level).
*/
static inline unsigned long lcd_dptr_fanout(dptr_t d, int lvl)
{
unsigned long i;
i = dptr_val(d);
/*
* Shift and mask off bits at correct section
*/
i >>= (lvl * LCD_DPTR_FANOUT_BITS + LCD_DPTR_SLOT_BITS);
i &= ((1 << LCD_DPTR_FANOUT_BITS) - 1);
return i;
}
/*
* Gives depth/level of cptr, zero indexed (0 means the root cnode table)
*/
static inline unsigned long lcd_dptr_level(dptr_t d)
{
unsigned long i;
i = dptr_val(d);
/*
* Shift and mask
*/
i >>= LCD_DPTR_LEVEL_SHIFT;
i &= ((1 << LCD_DPTR_DEPTH_BITS) - 1);
return i;
}
/*
* DPTR CACHE
*/
struct dptr_cache {
unsigned long *bmaps[1 << LCD_DPTR_DEPTH_BITS];
};
/*
* Data store
* Adapted from cptrs / capabilities.
*/
enum allocation_state {
ALLOCATION_INVALID,
ALLOCATION_VALID,
ALLOCATION_MARKED_FOR_DELETE,
ALLOCATION_REMOVED,
};
struct dstore;
struct dstore_node;
/*
* (The dstore derivation tree, the analogue of the cdt, may be pointless
* right now since we don't allow grant, etc. with data stores. But maybe
* in the future ...)
*/
struct ddt_root_node {
struct mutex lock;
struct dstore_node *root_node;
enum allocation_state state;
};
typedef struct { unsigned long dptr; } dptr_t;
/**
* These tags are reserved.
*/
#define LCD_DSTORE_TAG_NULL 0
#define LCD_DSTORE_TAG_DSTORE_NODE 1
struct dstore;
struct dstore_node {
struct mutex lock;
/*
* dstore node data
*/
void *object;
int tag;
struct dstore *dstore;
/*
* ddt data
*/
struct ddt_root_node *ddt_root;
struct list_head children;
struct list_head siblings;
};
struct dstore_node_table {
struct dstore_node dstore_node[LCD_DSTORE_NODE_TABLE_NUM_SLOTS];
uint8_t table_level;
struct list_head table_list;
};
struct dstore {
struct mutex lock;
enum allocation_state state;
struct dstore_node_table *root_table;
struct kmem_cache *dstore_node_table_cache;
struct dptr_cache *dptr_cache;
struct list_head table_list;
};
/**
* Initializes caches, etc. in data store subsystem. Should be called when
* LCD boots, but after the slab allocator is initialized.
......@@ -433,7 +312,7 @@ int lcd_dstore_init(void);
*/
void lcd_dstore_exit(void);
/**
* Sets up data store.
* Sets up a data store.
*/
int lcd_dstore_init_dstore(struct dstore **out);
/**
......@@ -457,9 +336,28 @@ void lcd_dstore_delete(struct dstore *dstore, dptr_t d);
*/
void lcd_dstore_destroy(struct dstore *dstore);
/**
* Look up object in dstore at d. Ensure it has tag.
* Look up object in dstore at d. Ensure it has tag. Returns dstore node
* containing object in out.
*
* ** THIS LOCKS THE DSTORE NODE. CALL A MATCHING lcd_dstore_put TO RELEASE **
*
* This can be used to synchronize multiple threads that are trying to
* look up the object and modify it.
*
* Returns non-zero if object not found, or if object found but has wrong
* tag.
*/
int lcd_dstore_get(struct dstore *dstore, dptr_t d, int tag,
struct dstore_node **out);
/**
* Extracts object from dstore node.
*/
int lcd_dstore_lookup(struct dstore *dstore, dptr_t d, int tag, void **out);
void *lcd_dstore_node_object(struct dstore_node *n);
/**
* Release the lock on the dstore object stored at d.
*/
void lcd_dstore_put(struct dstore_node *n);
/* TESTING -------------------------------------------------- */
......
......@@ -16,6 +16,143 @@
#include <lcd-domains/liblcd-hacks.h>
/* CONFIGURATION ---------------------------------------- */
/* These control the shape of the data store - its depth, width
* of tables, etc.
*/
#define LCD_DPTR_DEPTH_BITS 2 /* max depth of 3, zero indexed */
#define LCD_DPTR_FANOUT_BITS 2 /* each level fans out by a factor of 4 */
#define LCD_DPTR_SLOT_BITS 2 /* each node contains 4 slots */
#define LCD_DSTORE_NODE_TABLE_NUM_SLOTS ((1 << LCD_DPTR_SLOT_BITS) + \
(1 << LCD_DPTR_FANOUT_BITS))
#define LCD_DPTR_LEVEL_SHIFT (((1 << LCD_DPTR_DEPTH_BITS) - 1) * \
LCD_DPTR_FANOUT_BITS + LCD_DPTR_SLOT_BITS)
/* DPTR DEFS -------------------------------------------------- */
static inline dptr_t __dptr(unsigned long dptr)
{
return (dptr_t){ dptr };
}
static inline unsigned long dptr_val(dptr_t d)
{
return d.dptr;
}
#define LCD_DPTR_NULL (__dptr(0))
static inline int dptr_is_null(dptr_t d)
{
return dptr_val(d) == dptr_val(LCD_DPTR_NULL);
}
static inline unsigned long lcd_dptr_slot(dptr_t d)
{
/*
* Mask off low bits
*/
return dptr_val(d) & ((1 << LCD_DPTR_SLOT_BITS) - 1);
}
/*
* Gives fanout index for going *from* lvl to lvl + 1, where
* 0 <= lvl < 2^LCD_DPTR_DEPTH_BITS - 1 (i.e., we can't go anywhere
* if lvl = 2^LCD_DPTR_DEPTH_BITS - 1, because we are at the deepest
* level).
*/
static inline unsigned long lcd_dptr_fanout(dptr_t d, int lvl)
{
unsigned long i;
i = dptr_val(d);
/*
* Shift and mask off bits at correct section
*/
i >>= (lvl * LCD_DPTR_FANOUT_BITS + LCD_DPTR_SLOT_BITS);
i &= ((1 << LCD_DPTR_FANOUT_BITS) - 1);
return i;
}
/*
* Gives depth/level of cptr, zero indexed (0 means the root cnode table)
*/
static inline unsigned long lcd_dptr_level(dptr_t d)
{
unsigned long i;
i = dptr_val(d);
/*
* Shift and mask
*/
i >>= LCD_DPTR_LEVEL_SHIFT;
i &= ((1 << LCD_DPTR_DEPTH_BITS) - 1);
return i;
}
/*
* DPTR CACHE
*/
struct dptr_cache {
unsigned long *bmaps[1 << LCD_DPTR_DEPTH_BITS];
};
/* DATA STORE DEFS ---------------------------------------- */
enum allocation_state {
ALLOCATION_INVALID,
ALLOCATION_VALID,
ALLOCATION_MARKED_FOR_DELETE,
ALLOCATION_REMOVED,
};
/*
* (The dstore derivation tree, the analogue of the cdt, may be pointless
* right now since we don't allow grant, etc. with data stores. But maybe
* in the future ...)
*/
struct dstore_node;
struct ddt_root_node {
struct mutex lock;
struct dstore_node *root_node;
enum allocation_state state;
};
struct dstore;
struct dstore_node {
struct mutex lock;
/*
* dstore node data
*/
void *object;
int tag;
struct dstore *dstore;
/*
* ddt data
*/
struct ddt_root_node *ddt_root;
struct list_head children;
struct list_head siblings;
};
struct dstore_node_table {
struct dstore_node dstore_node[LCD_DSTORE_NODE_TABLE_NUM_SLOTS];
uint8_t table_level;
struct list_head table_list;
};
struct dstore {
struct mutex lock;
enum allocation_state state;
struct dstore_node_table *root_table;
struct kmem_cache *dstore_node_table_cache;
struct dptr_cache *dptr_cache;
struct list_head table_list;
};
/* DDT CACHE -------------------------------------------------- */
struct ddt_cache_t {
......@@ -585,7 +722,13 @@ fail1:
return ret;
}
int lcd_dstore_lookup(struct dstore *dstore, dptr_t d, int tag, void **out)
void *lcd_dstore_node_object(struct dstore_node *n)
{
return n->object;
}
int lcd_dstore_get(struct dstore *dstore, dptr_t d, int tag,
struct dstore_node **out)
{
struct dstore_node *dstore_node;
int ret;
......@@ -606,11 +749,16 @@ int lcd_dstore_lookup(struct dstore *dstore, dptr_t d, int tag, void **out)
return -EINVAL;
}
*out = dstore_node->object;
*out = dstore_node;
return 0;
}
void lcd_dstore_put(struct dstore_node *n)
{
mutex_unlock(&n->lock);
}
/**
* Does actual removal from ddt. Returns non-zero if dstore node is the last
* one in the ddt.
......@@ -931,8 +1079,6 @@ fail1:
/* INIT / EXIT -------------------------------------------------- */
static int dstore_tests(void);
int lcd_dstore_init(void)
{
/*
......@@ -945,12 +1091,6 @@ int lcd_dstore_init(void)
return -ENOMEM;
}
/*
* Run tests
*/
if (dstore_tests())
return -1;
return 0;
}
......@@ -958,10 +1098,3 @@ void lcd_dstore_exit(void)
{
kmem_cache_destroy(ddt_cache.ddt_root_cache);
}
/* TESTS -------------------------------------------------- */
static int dstore_tests(void)
{
return 0;
}
......@@ -152,6 +152,7 @@ fail1:
static int dstore_test(void)
{
struct dstore *d1, *d2;
struct dstore_node *n;
int ret;
int i, j;
int objs_d1[10];
......@@ -195,7 +196,8 @@ static int dstore_test(void)
* Look up and check
*/
for (i = 0; i < 10; i++) {
ret = lcd_dstore_lookup(d1, dptrs_d1[i], 3, &obj);
ret = lcd_dstore_get(d1, dptrs_d1[i], 3, &n);
obj = lcd_dstore_node_object(n);
if (ret) {
LIBLCD_ERR("lookup object i = %d in d1", i);
goto fail5;
......@@ -208,9 +210,11 @@ static int dstore_test(void)
LIBLCD_ERR("wrong value at i = %d in d1", i);
goto fail5;
}
lcd_dstore_put(n);
}
for (j = 0; j < 10; j++) {
ret = lcd_dstore_lookup(d2, dptrs_d2[j], 7, &obj);
ret = lcd_dstore_get(d2, dptrs_d2[j], 7, &n);
obj = lcd_dstore_node_object(n);
if (ret) {
LIBLCD_ERR("lookup object j = %d in d2", j);
goto fail6;
......@@ -223,6 +227,7 @@ static int dstore_test(void)
LIBLCD_ERR("wrong value at j = %d in d2", j);
goto fail6;
}
lcd_dstore_put(n);
}
/*
* Tear it all down
......
......@@ -17,7 +17,8 @@ lcd-domains-y += ../../arch/$(ARCH)/lcd-domains/main.o
lcd-domains-y += kliblcd/init.o kliblcd/mem.o \
kliblcd/ipc.o kliblcd/enterexit.o \
kliblcd/create.o kliblcd/cap.o \
kliblcd/cptr_cache.o
kliblcd/cptr_cache.o \
kliblcd/dstore.o
# Unit tests module
obj-$(CONFIG_LCD_DOMAINS_TESTS) += tests/
......
......@@ -363,6 +363,7 @@ int __lcd_cap_grant_cheat(struct lcd *caller, cptr_t lcd, cptr_t src,
int __lcd_cap_page_grant_map_cheat(struct lcd *caller, cptr_t lcd,
cptr_t page, cptr_t dest, gpa_t gpa);
/* IPC -------------------------------------------------- */
int __lcd_ipc_init(void);
......@@ -401,4 +402,6 @@ void __lcd_destroy(struct lcd *owned_lcd);
void __lcd_destroy__(struct lcd *owned_lcd);
#endif /* LCD_DOMAINS_INTERNAL_H */
This diff is collapsed.
/**
* init.c
*
* Nothing much here. These are invoked by the microkernel when it boots,
* These are invoked by the microkernel when it boots,
* so that individual parts can initialize.
*
* Authors:
* Charlie Jacobsen <charlesj@cs.utah.edu>
*/
#include <lcd-domains/kliblcd.h>
int __kliblcd_init(void)
{
/* Do nothing for now */
/* Initialize data store code */
lcd_dstore_init();
return 0;
}
void __kliblcd_exit(void)
{
/* Tear down data store code */
lcd_dstore_exit();
return;
}
......@@ -5,6 +5,6 @@ obj-$(CONFIG_LCD_DOMAINS_TESTS) += lcd-tests.o
lcd-tests-y += runner.o cap-tests.o cptr-tests.o \
ipc-tests.o enterexit-tests.o \
mem-tests.o
mem-tests.o dstore-tests.o
# arch-dependent tests
lcd-tests-y += $(LCD_ARCH_PATH)/arch-tests.o
/**
* Regression tests for the (kliblcd version of) the data store.
*/
#include <lcd-domains/kliblcd.h>
#include <lcd-domains/tests-util.h>
#include "../internal.h"
static int test01(void)
{
int ret;
struct dstore *d;
ret = lcd_enter();
if (ret) {
LCD_ERR("enter klcd");
goto fail1;
}
/*
* Create and then destroy empty data store.
*/
ret = lcd_dstore_init_dstore(&d);
if (ret) {
LCD_ERR("create dstore");
goto fail2;
}
lcd_dstore_destroy(d);
ret = 0;
goto out;
out:
fail2:
lcd_exit(0);
fail1:
return ret;
}
void dstore_tests(void)
{
int n = 0;
int total = 1;
RUN_TEST(test01, n);
if (n < total) {
LCD_MSG("%d of %d dstore tests failed",
(total - n), total);
} else {
LCD_MSG("all dstore tests passed!");
}
}
......@@ -11,6 +11,7 @@ void mem_tests(void);
void cptr_tests(void);
void enterexit_tests(void);
void arch_tests(void);
void dstore_tests(void);
static int __init runner_init(void)
{
......@@ -20,6 +21,7 @@ static int __init runner_init(void)
cptr_tests();
enterexit_tests();
arch_tests();
dstore_tests();
return 0;
}
......
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