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

Commit 2b30532

Browse files
committed
Add benchmark for page swapping
1 parent 02581be commit 2b30532

File tree

7 files changed

+276
-85
lines changed

7 files changed

+276
-85
lines changed

bench/Makefile

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ BENCH_FLAGS := -DUSE_FREEMEM -DUSE_PAGING -DUSE_PAGE_HASH -DUSE_PAGE_CRYPTO -D__
44

55
.PHONY: benches clean
66

7-
benches: hmac crypto
7+
benches: hmac crypto page_swap
88

9-
MODULES := hmac.o sha256.o aes.o bench/bencher.o bench/crypto.o bench/hmac.o
9+
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
1010
OBJ_PREFIX := objs/
1111

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

24+
PAGE_SWAP_MODULES := sha256.o aes.o hmac.o freemem.o page_swap.o bench/bencher.o bench/page_swap.o
25+
page_swap: $(addprefix $(OBJ_PREFIX),$(PAGE_SWAP_MODULES))
26+
$(CC) $(CFLAGS) $(BENCH_FLAGS) $^ $(LDFLAGS) -o $@
27+
2428
clean:
25-
rm -rf hmac crypto objs/
29+
rm -rf hmac crypto page_swap objs/

bench/page_swap.c

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
#define _GNU_SOURCE
2+
3+
#include "../page_swap.h"
4+
5+
#include <assert.h>
6+
#include <stdlib.h>
7+
#include <string.h>
8+
#include <sys/mman.h>
9+
#include <time.h>
10+
11+
#include "../freemem.h"
12+
#include "../paging.h"
13+
#include "../vm_defs.h"
14+
#include "bencher.h"
15+
16+
void
17+
sbi_exit_enclave(uintptr_t code) {
18+
exit(code);
19+
}
20+
21+
size_t
22+
rt_util_getrandom(void* vaddr, size_t buflen) {
23+
uint8_t* charbuf = (uint8_t*)vaddr;
24+
for (size_t i = 0; i < buflen; i++) charbuf[i] = rand();
25+
return buflen;
26+
}
27+
28+
uintptr_t
29+
sbi_random() {
30+
uintptr_t out;
31+
rt_util_getrandom(&out, sizeof out);
32+
return out;
33+
}
34+
35+
bool
36+
paging_epm_inbounds(uintptr_t addr) {
37+
(void)addr;
38+
return true;
39+
}
40+
41+
static void* backing_region;
42+
#define BACKING_REGION_SIZE (2 * 1024 * 1024)
43+
44+
bool
45+
paging_backpage_inbounds(uintptr_t addr) {
46+
return (addr >= (uintptr_t)backing_region) &&
47+
(addr < (uintptr_t)backing_region + BACKING_REGION_SIZE);
48+
}
49+
50+
uintptr_t
51+
paging_backing_region() {
52+
if (!backing_region) {
53+
backing_region = mmap(
54+
NULL, BACKING_REGION_SIZE, PROT_READ | PROT_WRITE,
55+
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
56+
assert(backing_region != MAP_FAILED);
57+
}
58+
return (uintptr_t)backing_region;
59+
}
60+
uintptr_t
61+
paging_backing_region_size() {
62+
return BACKING_REGION_SIZE;
63+
}
64+
65+
uintptr_t
66+
__va(uintptr_t pa) {
67+
return pa;
68+
}
69+
70+
uintptr_t
71+
paging_evict_and_free_one(uintptr_t swap_va) {
72+
(void)swap_va;
73+
assert(false);
74+
}
75+
76+
bool
77+
spa_page_inbounds(uintptr_t page_addr) {
78+
(void)page_addr;
79+
return true;
80+
}
81+
82+
#define VM_REGION_SIZE (2 * 1024 * 1024)
83+
#define VM_REGION_PAGES (VM_REGION_SIZE / RISCV_PAGE_SIZE)
84+
#define SWAPPABLE_PAGES 128
85+
#define RAND_BOOK_SIZE 4096
86+
87+
typedef struct {
88+
void* vm_region;
89+
uint64_t swapped_out[SWAPPABLE_PAGES / 64];
90+
uintptr_t swappable_pages_front[SWAPPABLE_PAGES];
91+
uintptr_t swappable_pages_back[SWAPPABLE_PAGES];
92+
93+
int rand_book[RAND_BOOK_SIZE];
94+
size_t rand_book_idx;
95+
} bench_ctx_t;
96+
97+
static int
98+
bench_ctx__init(bench_ctx_t* ctx) {
99+
ctx->vm_region = mmap(
100+
NULL, VM_REGION_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
101+
-1, 0);
102+
if (ctx->vm_region == MAP_FAILED) return -1;
103+
104+
for (size_t i = 0; i < RAND_BOOK_SIZE; i++) ctx->rand_book[i] = rand();
105+
return 0;
106+
}
107+
108+
static int
109+
bench_ctx__destroy(bench_ctx_t* ctx) {
110+
return munmap(ctx->vm_region, VM_REGION_SIZE);
111+
}
112+
113+
static int
114+
bench_ctx__rand(bench_ctx_t* ctx) {
115+
int out = ctx->rand_book[ctx->rand_book_idx];
116+
ctx->rand_book_idx = (ctx->rand_book_idx + 1) % RAND_BOOK_SIZE;
117+
return out;
118+
}
119+
120+
static int
121+
page_swap__init(void* _ctx) {
122+
bench_ctx_t* ctx = (bench_ctx_t*)_ctx;
123+
124+
spa_init((uintptr_t)ctx->vm_region, VM_REGION_SIZE);
125+
pswap_init();
126+
memset(ctx->swapped_out, 0, sizeof ctx->swapped_out);
127+
128+
for (size_t i = 0; i < SWAPPABLE_PAGES; i++) {
129+
ctx->swappable_pages_front[i] = spa_get();
130+
ctx->swappable_pages_back[i] = paging_alloc_backing_page();
131+
rt_util_getrandom((void*)ctx->swappable_pages_front[i], RISCV_PAGE_SIZE);
132+
}
133+
134+
ctx->rand_book_idx = rand() % RAND_BOOK_SIZE;
135+
return 0;
136+
}
137+
138+
static int
139+
page_swap__destroy(void* _ctx) {
140+
(void)_ctx;
141+
return 0;
142+
}
143+
144+
static int
145+
page_swap(void* _ctx) {
146+
bench_ctx_t* ctx = (bench_ctx_t*)_ctx;
147+
148+
// Choose a page (excluding the first page, which is used by the SPA)
149+
size_t which_page = bench_ctx__rand(ctx) % SWAPPABLE_PAGES;
150+
uintptr_t front_page = ctx->swappable_pages_front[which_page];
151+
uintptr_t back_page = ctx->swappable_pages_back[which_page];
152+
uintptr_t swap_page;
153+
154+
if (ctx->swapped_out[which_page / 64] & (1ull << (which_page % 64))) {
155+
// Have already swapped this page out
156+
swap_page = back_page;
157+
} else {
158+
swap_page = 0;
159+
ctx->swapped_out[which_page / 64] |= (1ull << (which_page % 64));
160+
}
161+
162+
return page_swap_epm(back_page, front_page, swap_page);
163+
}
164+
165+
int
166+
main(int argc, char** argv) {
167+
srand(time(NULL));
168+
bench_ctx_t ctx = {};
169+
int err = bench_ctx__init(&ctx);
170+
assert(!err);
171+
172+
struct bench benches[] = {
173+
{.name = "page swap",
174+
.init = page_swap__init,
175+
.deinit = page_swap__destroy,
176+
.iter = page_swap},
177+
};
178+
struct bench_opts opts = bench_argp(argc, argv);
179+
run_benches(&opts, benches, sizeof(benches) / sizeof(struct bench), &ctx);
180+
181+
err = bench_ctx__destroy(&ctx);
182+
assert(!err);
183+
}

freemem.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#ifdef USE_FREEMEM
22
#include "string.h"
33
#include "common.h"
4-
#include "vm.h"
54
#include "freemem.h"
65
#include "paging.h"
76

@@ -16,8 +15,17 @@
1615
* spa_free_pages will only hold the head and the tail pages so that
1716
* SPA can allocate/free a page in constant time. */
1817

18+
uintptr_t freemem_va_start;
19+
size_t freemem_size;
20+
1921
static struct pg_list spa_free_pages;
2022

23+
__attribute__((weak)) bool
24+
spa_page_inbounds(uintptr_t page_addr) {
25+
return page_addr >= EYRIE_LOAD_START &&
26+
page_addr < (freemem_va_start + freemem_size);
27+
}
28+
2129
/* get a free page from the simple page allocator */
2230
uintptr_t
2331
__spa_get(bool zero)
@@ -48,7 +56,7 @@ __spa_get(bool zero)
4856
spa_free_pages.head = next;
4957
spa_free_pages.count--;
5058

51-
assert(free_page > EYRIE_LOAD_START && free_page < (freemem_va_start + freemem_size));
59+
assert(spa_page_inbounds(free_page));
5260

5361
if (zero)
5462
memset((void*)free_page, 0, RISCV_PAGE_SIZE);
@@ -66,7 +74,7 @@ spa_put(uintptr_t page_addr)
6674
uintptr_t prev;
6775

6876
assert(IS_ALIGNED(page_addr, RISCV_PAGE_BITS));
69-
assert(page_addr >= EYRIE_LOAD_START && page_addr < (freemem_va_start + freemem_size));
77+
assert(spa_page_inbounds(page_addr));
7078

7179
if (!LIST_EMPTY(spa_free_pages)) {
7280
prev = spa_free_pages.tail;

freemem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
#ifndef __FREEMEM_H__
44
#define __FREEMEM_H__
55

6+
#include <stddef.h>
7+
#include <stdint.h>
8+
69
#define NEXT_PAGE(page) *((uintptr_t*)page)
710
#define LIST_EMPTY(list) ((list).count == 0 || (list).head == 0)
811
#define LIST_INIT(list) { (list).count = 0; (list).head = 0; (list).tail = 0; }
@@ -19,5 +22,8 @@ uintptr_t spa_get(void);
1922
uintptr_t spa_get_zero(void);
2023
void spa_put(uintptr_t page);
2124
unsigned int spa_available();
25+
26+
extern uintptr_t freemem_va_start;
27+
extern size_t freemem_size;
2228
#endif
2329
#endif

0 commit comments

Comments
 (0)