libcap.h 11.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
/* 
 * libcap primary header file and interface.
 *
 * Author: Charles Jacobsen <charlesj@cs.utah.edu>
 * Copyright: University of Utah
 *
 * This is the non-isolated code interface to the microkernel. The
 * implementation is in virt/lcd-domains/kliblcd.c.
 *
 * An LCD that runs in non-isolated code is called a klcd.
 */
#ifndef __LIBCAP_H__
#define __LIBCAP_H__

#include "libcap_types.h"

struct cnode;
struct cspace;

struct cap_type_ops {
	char *name;
	int (*delete)(struct cspace *cspace, struct cnode *cnode, void *object);
	int (*revoke)(struct cspace *cspace, struct cnode *cnode, void *object);
};

/*
 * Add some macros to generate built-in capability object type.  Not
 * ideal to put this here, but don't want to expose internal headers,
 * and have to give per-platform a chance to change them.
 */
#define CAP_BUILD_CORE_TYPES(PT)				\
	typedef enum cap_type {					\
		CAP_TYPE_ERR = -1,				\
		CAP_TYPE_NONE = 0,				\
		CAP_TYPE_INVALID,				\
		CAP_TYPE_FREE,					\
		CAP_TYPE_CNODE,					\
		PT,						\
		CAP_TYPE_FIRST_NONBUILTIN			\
	} cap_type_t
#define CAP_BUILD_CORE_TYPES_NOBUILTIN()			\
	typedef enum cap_type {					\
		CAP_TYPE_NONE = 0,				\
		CAP_TYPE_INVALID,				\
		CAP_TYPE_FREE,					\
		CAP_TYPE_CNODE,					\
		CAP_TYPE_FIRST_NONBUILTIN			\
	} cap_type_t

#ifdef __KERNEL__
#include "libcap_kernel.h"
#else
#include "libcap_user.h"
#endif

#ifndef CAP_TYPE_MAX
#define CAP_TYPE_MAX 256
#endif

60 61
#define CAP_BUG() __cap_bug()

62
/**
63
 * For now, put debug macros in the user-accessible part; convenient.
64
 */
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
extern int cap_debug_level;

#define CAP_ERR __cap_err
#define CAP_WARN __cap_warn
#define CAP_MSG __cap_msg

#define CAP_DEBUG_ERR  1
#define CAP_DEBUG_WARN 2
#define CAP_DEBUG_MSG  3

#define CAP_DEBUG(lvl, msg, ...) {					\
	if (lvl <= cap_debug_level)					\
	    __cap_debug(msg,## __VA_ARGS__);				\
	}

/* CPTRs -------------------------------------------------- */

82 83 84
#include "libcap_internal.h" /* temporary hack */


85
/**
86 87 88 89 90
 * __cptr -- Construct a cptr from an unsigned long
 * @cptr: the unsigned long to use
 *
 * This is a low-level function. You need to know how to pack
 * the bits into the unsigned long.
91
 */
92 93 94 95
static inline cptr_t __cptr(unsigned long cptr)
{
	return (cptr_t) {cptr};
}
96
/**
97 98 99 100 101
 * cptr_val -- Extract the unsigned long (bits) in the cptr
 * @c: the ctpr to extract
 *
 * This can be useful if you want to pass a cptr in a register,
 * as a scalar.
102
 */
103 104 105 106
static inline unsigned long cptr_val(cptr_t c)
{
	return c.cptr;
}
107
/**
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
 * cap_cptr_slot -- Returns the slot index into the final cnode table
 * @c: the cptr
 *
 * Once you have arrived at the correct cnode table in the cspace
 * radix tree, this is the index into that table to get the
 * capability that @c refers to.
 */
static inline unsigned long cap_cptr_slot(cptr_t c)
{
	/*
	 * Mask off low bits
	 */
	return cptr_val(c) & ((1 << (CAP_CSPACE_CNODE_TABLE_BITS - 1)) - 1);
}
/**
 * cap_cptr_fanout -- Gives fanout index for going *from* @lvl to @lvl + 1
 * @c: the cptr
 * @lvl: the level in the cspace radix tree, where 0 <= lvl < CAP_CSPACE_DEPTH
 *
 * Each node in the cspace radix tree is a cnode table. Each cnode
 * table is split in half: the first half are capability slots, and
 * the other half are pointers to further nodes in the tree. If a
 * cptr refers to a slot in a deeper level in the tree, you need to
 * follow these pointers. The fanout index tells you which pointers
 * to follow at each level.
 */
static inline unsigned long cap_cptr_fanout(cptr_t c, int lvl)
{
	unsigned long i;

	if (lvl >= CAP_CSPACE_DEPTH - 1)
		CAP_BUG();

	i = cptr_val(c);
	/*
	 * Shift and mask off bits at correct section
	 */
	i >>= ((lvl + 1) * (CAP_CSPACE_CNODE_TABLE_BITS - 1));
	i &= ((1 << (CAP_CSPACE_CNODE_TABLE_BITS - 1)) - 1);

	return i;
}
/**
 * cap_cptr_level -- The zero-indexed level in the cspace radix tree
 * @c: the cptr
 *
 * Returns the level of the slot which @c refers to. 0 means the root 
 * cnode table.
 */
static inline unsigned long cap_cptr_level(cptr_t c)
{
	unsigned long i;

	i = cptr_val(c);
	/*
	 * Shift and mask
	 */
	i >>= (CAP_CSPACE_DEPTH * (CAP_CSPACE_CNODE_TABLE_BITS - 1));
	i &= ((1 << CAP_CSPACE_DEPTH_BITS) - 1);

	return i;
}
/**
 * cap_cptr_set_level -- Sets the level for @c
 * @c: the cptr
 * @lvl: the level in the cspace radix tree, 0 <= lvl < CAP_CSPACE_DEPTH
 */
static inline void cap_cptr_set_level(cptr_t *c, int lvl)
{
	/* Shift and OR to store lvl */
	c->cptr |= (lvl << 
		(CAP_CSPACE_DEPTH * (CAP_CSPACE_CNODE_TABLE_BITS - 1)));
}
/**
 * cptr_is_null -- Returns non-zero if cptr is the special null cptr
 * @c: cptr to test
 */
static inline int cptr_is_null(cptr_t c)
{
	return cptr_val(c) == cptr_val(CAP_CPTR_NULL);
}

/* CPTR CACHEs -------------------------------------------------- */

192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
#if (CAP_CSPACE_DEPTH == 4)

struct cptr_cache {
	/* lock */
	cap_mutex_t lock;
	/* level 0 bitmap */
	unsigned long bmap0[CAP_BITS_TO_LONGS(CAP_CSPACE_SLOTS_IN_LEVEL(0))];
	/* level 1 bitmap */
	unsigned long bmap1[CAP_BITS_TO_LONGS(CAP_CSPACE_SLOTS_IN_LEVEL(1))];
	/* level 2 bitmap */
	unsigned long bmap2[CAP_BITS_TO_LONGS(CAP_CSPACE_SLOTS_IN_LEVEL(2))];
	/* level 3 bitmap */
	unsigned long bmap3[CAP_BITS_TO_LONGS(CAP_CSPACE_SLOTS_IN_LEVEL(3))];
};

#else
#error "You need to adjust the cptr cache def."
#endif

211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
/**
 * cptr_init -- Initalize the cptr cache subsystem
 */
int cptr_init(void);
/**
 * cptr_fini -- Tear down the cptr cache subsystem.
 */
void cptr_fini(void);
/**
 * cptr_cache_alloc -- Allocate a cptr cache data structure (not initialized)
 * @out: out param, pointer to newly alloc'd cache
 *
 * You should call cptr_cache_free when done with the cache. Returns
 * non-zero on error.
 */
int cptr_cache_alloc(struct cptr_cache **out);
/**
 * cptr_cache_free -- Free a cptr cache alloc'd via cptr_cache_alloc
 * @cache: the cptr cache to free
 */
void cptr_cache_free(struct cptr_cache *cache);
/**
 * cptr_cache_init -- Initialize the data in a cptr cache
 * @cache: the cptr cache to initialize
 *
 * Zeros out things, and sets some initial values. You *must* call this
 * function before using the cptr cache.
 */
int cptr_cache_init(struct cptr_cache *cache);
/**
 * cptr_cache_destroy -- Destroys internals of cptr cache
 * @cache: cache to destroy
 *
 * For now, this is a no-op. You *must* call this before freeing the
 * cache. (Yes, for now it is a no-op, but perhaps it won't be in the
 * future.)
 */
void cptr_cache_destroy(struct cptr_cache *cache);
/**
 * cptr_alloc -- Allocate a new cptr from the cache
 * @cache: the cptr cache to allocate from
 * @free_cptr: out param, points to the allocated cptr
 *
 * Returns non-zero if there are no more slots left.
255 256 257
 */
int cptr_alloc(struct cptr_cache *cptr_cache, cptr_t *free_cptr);
/**
258 259 260 261 262
 * cptr_free -- Return a cptr to the cache
 * @cache: the cptr cache to return the cptr to
 * @c: the cptr to return
 *
 * Fails silently if the cptr is free already.
263 264
 */
void cptr_free(struct cptr_cache *cptr_cache, cptr_t c);
265

266 267 268

/* CSPACES -------------------------------------------------- */

269 270 271 272 273 274 275 276 277 278
/**
 * Initializes caches, etc. in capability subsystem. Called when microkernel
 * intializes.
 */
int cap_init(void);
/**
 * Tears down caches, etc. in capability subsystem. Called when microkernel
 * is exiting.
 */
void cap_fini(void);
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296

/**
 * cap_cspace_slots_in_level -- Return total number of slots in cspace at lvl
 * @lvl: the level to query
 *
 * Returns the total number of *capability* slots in all of the
 * cnode tables at a given @lvl of the cspace radix tree.
 */
static inline int cap_cspace_slots_in_level(int lvl)
{
	int out = CAP_CSPACE_CNODE_TABLE_SIZE/2;
	if (lvl < 0 || lvl >= CAP_CSPACE_DEPTH)
		CAP_BUG();
	for ( ; lvl > 0; lvl-- )
		out *= CAP_CSPACE_CNODE_TABLE_SIZE/2;
	return out;
}

297 298 299 300 301 302 303 304
/**
 * Register a new capability object type.  If you pass type == 0, the
 * system will select the next available identifier and return it.  You
 * should use the returned value as your object identifier.  If you
 * attempt to use a type that is already in use, this returns
 * -EADDRINUSE.  If there are no types remaining or you exceed
 * CAP_TYPE_MAX, this returns -ENOMEM .
 */
305
cap_type_t cap_register_type(cap_type_t type, const struct cap_type_ops *ops);
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
/**
 * Revoke all derived capabilities.
 *
 * Does not delete the caller's capability.
 *
 * This may change the state of the lcd's whose capabilities are revoked (see
 * comment lcd_cap_delete).
 */
int cap_revoke(struct cspace *cspace, cptr_t c);
/**
 * Delete the capability in slot from this cspace.
 *
 * This may change the state of the caller. (For example, if the caller is
 * a regular lcd, and if the capability is to a page, the page will be unmapped
 * from the caller's address space.)
 *
 * If this is the last capability to the object, the object will be destroyed,
 * unless it is a kernel page. See klcd_add_page and klcd_rm_page.
 */
void cap_delete(struct cspace *cspace, cptr_t c);

327
/**
328
 * Allocates a new cspace. If no memory could be allocated, returns NULL.
329 330 331 332
 */
struct cspace * cap_alloc_cspace(void);

/**
333
 * Frees a cspace allocated with `cap_alloc_cspace`.
334 335 336
 */
void cap_free_cspace(struct cspace *cspace);

337 338 339 340
/**
 * Sets up cspace - initializes lock, root cnode table, etc.
 */
int cap_init_cspace(struct cspace *cspace);
341 342 343 344 345 346 347 348
/**
 * Set the "owner" field of the given cspace
 */
void cap_cspace_setowner(struct cspace *cspace, void * owner);
/**
 * Get the "owner" field of the given cspace
 */
void* cap_cspace_getowner(struct cspace *cspace);
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
/**
 * Inserts object data into cspace at cnode pointed at by c.
 */
int cap_insert(struct cspace *cspace, cptr_t c, void *object, cap_type_t type);
/**
 * Deletes object data from cspace at cnode pointed at by c.
 *
 * Updates the state of the microkernel to reflect rights change (e.g., if
 * a cnode for a page is deleted, and the page is mapped, the page will be
 * unmapped).
 *
 * If this is the last cnode that refers to the object, the object is
 * destroyed.
 */
void cap_delete(struct cspace *cspace, cptr_t c);
/**
 * Copies cnode data in src cnode at c_src to dest cnode at c_dst. The dest
 * cnode will be a child of the src cnode in the cdt containing src cnode.
 */
int cap_grant(struct cspace *cspacesrc, cptr_t c_src,
	      struct cspace *cspacedst, cptr_t c_dst);
/**
 * Equivalent to calling lcd_cap_delete on all of the cnode's children. 
 *
 * ** Does not delete the cnode itself. **
 */
int cap_revoke(struct cspace *cspace, cptr_t c);
/**
 * Equivalent to calling lcd_cap_delete on all cnodes in cspace. Frees up
 * all cnode tables, etc.
 */
void cap_destroy_cspace(struct cspace *cspace);
/**
382
 * Looks up cnode at cap in cspace.
383
 *
384
 * ** Frees the cnode lock itself without relying on user.
385 386 387 388
 *
 * ** Interrupts and preemption *are not* disabled. **
 *    (so we can easily get out of deadlocks while debugging)
 */
389
int cap_cnode_verify(struct cspace *cspace, cptr_t cap);
390 391 392 393 394
/**
 * Return the cptr that points to this cnode.
 */
cptr_t cap_cnode_cptr(struct cnode *cnode);

395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
/**
 * Return the cnode that this cptr points to in the given cspace. Acquires
 * a lock to the cnode. Returns zero on success. Make sure to call
 * cap_cnode_put after every cap_cnode_get.
 */
int cap_cnode_get(struct cspace *cspace, cptr_t cptr, struct cnode **cnode);

/**
 * Unlock the cnode. Call this on every cnode you've called
 * cap_cnode_get on.
 */
void cap_cnode_put(struct cnode *cnode);

/**
 * Get the object stored at this cnode.
 */
void* cap_cnode_object(struct cnode *cnode);

Josh Kunz's avatar
Josh Kunz committed
413 414 415 416 417
/**
 * Get the type of this cnode
 */
cap_type_t cap_cnode_type(struct cnode *cnode);

418 419 420 421 422
/**
 * Get the cspace this cnode is in.
 */
struct cspace * cap_cnode_cspace(struct cnode *cnode);

423 424

#endif /* __LIBCAP_H__ */