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+ }
0 commit comments