Skip to content
This repository was archived by the owner on Nov 29, 2023. It is now read-only.

Commit

Permalink
Add benchmark for entire page swap operation
Browse files Browse the repository at this point in the history
  • Loading branch information
archshift committed Dec 2, 2020
1 parent dc309d0 commit 5f3cc9c
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 12 deletions.
10 changes: 7 additions & 3 deletions bench/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ BENCH_FLAGS := -DUSE_FREEMEM -DUSE_PAGING -DUSE_PAGE_HASH -DUSE_PAGE_CRYPTO -D__

.PHONY: benches clean

benches: hmac crypto
benches: hmac crypto page_swap

MODULES := hmac.o sha256.o aes.o bench/bencher.o bench/crypto.o bench/hmac.o
MODULES := hmac.o sha256.o aes.o page_swap.o freemem.o bench/bencher.o bench/crypto.o bench/hmac.o bench/page_swap.o
OBJ_PREFIX := objs/

$(addprefix $(OBJ_PREFIX),$(MODULES)) :: $(OBJ_PREFIX)%.o : ../%.c
Expand All @@ -21,5 +21,9 @@ CRYPTO_MODULES := sha256.o aes.o bench/bencher.o bench/crypto.o
crypto: $(addprefix $(OBJ_PREFIX),$(CRYPTO_MODULES))
$(CC) $(CFLAGS) $(BENCH_FLAGS) $^ $(LDFLAGS) -o $@

PAGE_SWAP_MODULES := sha256.o aes.o hmac.o freemem.o page_swap.o bench/bencher.o bench/page_swap.o
page_swap: $(addprefix $(OBJ_PREFIX),$(PAGE_SWAP_MODULES))
$(CC) $(CFLAGS) $(BENCH_FLAGS) $^ $(LDFLAGS) -o $@

clean:
rm -rf hmac crypto objs/
rm -rf hmac crypto page_swap objs/
183 changes: 183 additions & 0 deletions bench/page_swap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
#define _GNU_SOURCE

#include "../page_swap.h"

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <time.h>

#include "../freemem.h"
#include "../paging.h"
#include "../vm_defs.h"
#include "bencher.h"

void
sbi_exit_enclave(uintptr_t code) {
exit(code);
}

size_t
rt_util_getrandom(void* vaddr, size_t buflen) {
uint8_t* charbuf = (uint8_t*)vaddr;
for (size_t i = 0; i < buflen; i++) charbuf[i] = rand();
return buflen;
}

uintptr_t
sbi_random() {
uintptr_t out;
rt_util_getrandom(&out, sizeof out);
return out;
}

bool
paging_epm_inbounds(uintptr_t addr) {
(void)addr;
return true;
}

static void* backing_region;
#define BACKING_REGION_SIZE (2 * 1024 * 1024)

bool
paging_backpage_inbounds(uintptr_t addr) {
return (addr >= (uintptr_t)backing_region) &&
(addr < (uintptr_t)backing_region + BACKING_REGION_SIZE);
}

uintptr_t
paging_backing_region() {
if (!backing_region) {
backing_region = mmap(
NULL, BACKING_REGION_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
assert(backing_region != MAP_FAILED);
}
return (uintptr_t)backing_region;
}
uintptr_t
paging_backing_region_size() {
return BACKING_REGION_SIZE;
}

uintptr_t
__va(uintptr_t pa) {
return pa;
}

uintptr_t
paging_evict_and_free_one(uintptr_t swap_va) {
(void)swap_va;
assert(false);
}

bool
spa_page_inbounds(uintptr_t page_addr) {
(void)page_addr;
return true;
}

#define VM_REGION_SIZE (2 * 1024 * 1024)
#define VM_REGION_PAGES (VM_REGION_SIZE / RISCV_PAGE_SIZE)
#define SWAPPABLE_PAGES 128
#define RAND_BOOK_SIZE 4096

typedef struct {
void* vm_region;
uint64_t swapped_out[SWAPPABLE_PAGES / 64];
uintptr_t swappable_pages_front[SWAPPABLE_PAGES];
uintptr_t swappable_pages_back[SWAPPABLE_PAGES];

int rand_book[RAND_BOOK_SIZE];
size_t rand_book_idx;
} bench_ctx_t;

static int
bench_ctx__init(bench_ctx_t* ctx) {
ctx->vm_region = mmap(
NULL, VM_REGION_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
if (ctx->vm_region == MAP_FAILED) return -1;

for (size_t i = 0; i < RAND_BOOK_SIZE; i++) ctx->rand_book[i] = rand();
return 0;
}

static int
bench_ctx__destroy(bench_ctx_t* ctx) {
return munmap(ctx->vm_region, VM_REGION_SIZE);
}

static int
bench_ctx__rand(bench_ctx_t* ctx) {
int out = ctx->rand_book[ctx->rand_book_idx];
ctx->rand_book_idx = (ctx->rand_book_idx + 1) % RAND_BOOK_SIZE;
return out;
}

static int
page_swap__init(void* _ctx) {
bench_ctx_t* ctx = (bench_ctx_t*)_ctx;

spa_init((uintptr_t)ctx->vm_region, VM_REGION_SIZE);
pswap_init();
memset(ctx->swapped_out, 0, sizeof ctx->swapped_out);

for (size_t i = 0; i < SWAPPABLE_PAGES; i++) {
ctx->swappable_pages_front[i] = spa_get();
ctx->swappable_pages_back[i] = paging_alloc_backing_page();
rt_util_getrandom((void*)ctx->swappable_pages_front[i], RISCV_PAGE_SIZE);
}

ctx->rand_book_idx = rand() % RAND_BOOK_SIZE;
return 0;
}

static int
page_swap__destroy(void* _ctx) {
(void)_ctx;
return 0;
}

static int
page_swap(void* _ctx) {
bench_ctx_t* ctx = (bench_ctx_t*)_ctx;

// Choose a page (excluding the first page, which is used by the SPA)
size_t which_page = bench_ctx__rand(ctx) % SWAPPABLE_PAGES;
uintptr_t front_page = ctx->swappable_pages_front[which_page];
uintptr_t back_page = ctx->swappable_pages_back[which_page];
uintptr_t swap_page;

if (ctx->swapped_out[which_page / 64] & (1ull << (which_page % 64))) {
// Have already swapped this page out
swap_page = back_page;
} else {
swap_page = 0;
ctx->swapped_out[which_page / 64] |= (1ull << (which_page % 64));
}

return page_swap_epm(back_page, front_page, swap_page);
}

int
main(int argc, char** argv) {
srand(time(NULL));
bench_ctx_t ctx = {};
int err = bench_ctx__init(&ctx);
assert(!err);

struct bench benches[] = {
{.name = "page swap",
.init = page_swap__init,
.deinit = page_swap__destroy,
.iter = page_swap},
};
struct bench_opts opts = bench_argp(argc, argv);
run_benches(&opts, benches, sizeof(benches) / sizeof(struct bench), &ctx);

err = bench_ctx__destroy(&ctx);
assert(!err);
}
20 changes: 15 additions & 5 deletions freemem.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#ifdef USE_FREEMEM
#include "string.h"
#include "common.h"
#include "vm.h"
#include "freemem.h"

#include "common.h"
#include "paging.h"
#include "string.h"
#include "vm_defs.h"

/* This file implements a simple page allocator (SPA)
* which stores the pages based on a linked list.
Expand All @@ -16,8 +17,17 @@
* spa_free_pages will only hold the head and the tail pages so that
* SPA can allocate/free a page in constant time. */

uintptr_t freemem_va_start;
size_t freemem_size;

static struct pg_list spa_free_pages;

__attribute__((weak)) bool
spa_page_inbounds(uintptr_t page_addr) {
return page_addr >= EYRIE_LOAD_START &&
page_addr < (freemem_va_start + freemem_size);
}

/* get a free page from the simple page allocator */
uintptr_t
__spa_get(bool zero)
Expand Down Expand Up @@ -48,7 +58,7 @@ __spa_get(bool zero)
spa_free_pages.head = next;
spa_free_pages.count--;

assert(free_page > EYRIE_LOAD_START && free_page < (freemem_va_start + freemem_size));
assert(spa_page_inbounds(free_page));

if (zero)
memset((void*)free_page, 0, RISCV_PAGE_SIZE);
Expand All @@ -66,7 +76,7 @@ spa_put(uintptr_t page_addr)
uintptr_t prev;

assert(IS_ALIGNED(page_addr, RISCV_PAGE_BITS));
assert(page_addr >= EYRIE_LOAD_START && page_addr < (freemem_va_start + freemem_size));
assert(spa_page_inbounds(page_addr));

if (!LIST_EMPTY(spa_free_pages)) {
prev = spa_free_pages.tail;
Expand Down
6 changes: 6 additions & 0 deletions freemem.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#ifndef __FREEMEM_H__
#define __FREEMEM_H__

#include <stddef.h>
#include <stdint.h>

#define NEXT_PAGE(page) *((uintptr_t*)page)
#define LIST_EMPTY(list) ((list).count == 0 || (list).head == 0)
#define LIST_INIT(list) { (list).count = 0; (list).head = 0; (list).tail = 0; }
Expand All @@ -19,5 +22,8 @@ uintptr_t spa_get(void);
uintptr_t spa_get_zero(void);
void spa_put(uintptr_t page);
unsigned int spa_available();

extern uintptr_t freemem_va_start;
extern size_t freemem_size;
#endif
#endif
4 changes: 0 additions & 4 deletions vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,6 @@ pte load_l3_page_table[BIT(RISCV_PT_INDEX_BITS)] __attribute__((aligned(RISCV_PA

/* Program break */
uintptr_t program_break;

/* freemem */
uintptr_t freemem_va_start;
size_t freemem_size;
#endif // USE_FREEMEM

/* shared buffer */
Expand Down

0 comments on commit 5f3cc9c

Please sign in to comment.