Skip to content

Commit 14bd2cf

Browse files
committed
exe: implements memory copy operation mcopy
1 parent 953a66d commit 14bd2cf

2 files changed

Lines changed: 107 additions & 1 deletion

File tree

examples/mcopy.rsm

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// This demonstrates and tests copying of memory with mcopy
2+
3+
fun main() {
4+
// allocate stack memory (SP since exe1 doesn't support stkmem)
5+
const STKSIZE = 0x3000
6+
SP = SP - STKSIZE
7+
8+
// addresses with different page offsets
9+
R3 = 0x1200 // size
10+
R1 = SP - R3 // dst
11+
R2 = R1 - R3 // src
12+
mcopy R1 R2 R3
13+
14+
// addresses with matching page offsets (page aligned)
15+
// R5 is a mask that filters the page address of an address
16+
R5 = 0xfffffffffffff000 // (~0 ^ (PAGE_SIZE - 1))
17+
R3 = 0x1500 // size
18+
R1 = SP - R3 // dst
19+
R1 = R1 & R5 // align_floor(dst, PAGE_SIZE)
20+
R4 = R3 * 2 // size *= 2 for align_floor(src, PAGE_SIZE)
21+
R2 = R1 - R4 // src
22+
R2 = R2 & R5 // align_floor(src, PAGE_SIZE)
23+
mcopy R1 R2 R3
24+
25+
// addresses with matching page offsets (not page aligned)
26+
R1 = R1 + 3
27+
R2 = R2 + 3
28+
R3 = R3 - 3
29+
mcopy R1 R2 R3
30+
31+
SP = SP + STKSIZE
32+
}

src/sched_exec.c

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,82 @@ enum execerr_t {
184184
TYPE, m_vm_cache((t)->m, VM_PERM_RW), &(t)->m->s->vm_map, vaddr__, value__); \
185185
}
186186

187+
#define HADDR_OFFS_MASK ((uintptr)( (uintptr)PAGE_SIZE - (uintptr)1 ))
188+
#define HADDR_PAGE_MASK ((uintptr)( ~(uintptr)0 ^ ((uintptr)PAGE_SIZE - (uintptr)1) ))
189+
187190
static void mcopy(EXEC_PARAMS, u64 dstaddr, u64 srcaddr, u64 size) {
188-
panic("NOT IMPLEMENTED"); // TODO virtual memory
191+
// mcopy copies at page boundaries to reduce vm_translate operations.
192+
//
193+
// Example: addresses at different page offsets: (worst case scenario)
194+
// mcopy(0x5d00, 0x1200, 9000)
195+
//
196+
// 0x1200 ─────src───── 0x3528 0x5d00 ─────dst───── 0x8028
197+
// ┌─┴──────┬────────┬────┴───┬────────┬──────┴─┬────────┬────────┬─┴──────┐
198+
// │ 0x1000 │ 0x2000 │ 0x3000 │ 0x4000 │ 0x5000 │ 0x6000 │ 0x7000 │ 0x8000 │
199+
// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
200+
//
201+
// copy 768 B 0x1200-0x1500 ⟶ 0x5d00-0x6000 (nearest page boundary: 0x6000)
202+
// copy 2816 B 0x1500-0x2000 ⟶ 0x6000-0x6b00 (nearest page boundary: 0x2000)
203+
// copy 1280 B 0x2000-0x2500 ⟶ 0x6b00-0x7000 (nearest page boundary: 0x7000)
204+
// copy 2816 B 0x2500-0x3000 ⟶ 0x7000-0x7b00 (nearest page boundary: 0x3000)
205+
// copy 1280 B 0x3000-0x3500 ⟶ 0x7b00-0x8000 (nearest page boundary: 0x8000)
206+
// copy 40 B 0x3500-0x3528 ⟶ 0x8000-0x8028 (tail)
207+
//
208+
// Example: addresses at matching page offsets:
209+
// mcopy(0x5200, 0x1200, 9000)
210+
//
211+
// 0x1200 ─────src───── 0x3528 0x5200 ─────dst───── 0x7528
212+
// ┌─┴──────┬────────┬────┴───┬────────┬─┴──────┬────────┬────┴───┐
213+
// │ 0x1000 │ 0x2000 │ 0x3000 │ 0x4000 │ 0x5000 │ 0x6000 │ 0x7000 │
214+
// └────────┴────────┴────────┴────────┴────────┴────────┴────────┘
215+
//
216+
// copy 3584 B 0x1200-0x2000 ⟶ 0x5200-0x6000
217+
// copy 4096 B 0x2000-0x3000 ⟶ 0x6000-0x7000
218+
// copy 1320 B 0x3000-0x3528 ⟶ 0x7000-0x7528
219+
//
220+
vm_map_t* map = &(t)->m->s->vm_map;
221+
vm_cache_t* cache = m_vm_cache((t)->m, VM_PERM_RW);
222+
223+
tracemem("%012llx <- %012llx (%llu B)", dstaddr, srcaddr, size);
224+
225+
// check for overlapping address ranges
226+
#if RSM_SAFE
227+
if (vm_ranges_overlap(dstaddr, size, srcaddr, size)) {
228+
panic(
229+
"overlapping address ranges:\n dst %012llx…%012llx\n src %012llx…%012llx",
230+
dstaddr, dstaddr+size, srcaddr, srcaddr+size);
231+
}
232+
#endif
233+
234+
void* src = (void*)vm_translate(cache, map, srcaddr, 1, VM_OP_LOAD_1);
235+
void* dst = (void*)vm_translate(cache, map, dstaddr, 1, VM_OP_STORE_1);
236+
//tracemem("[haddr] dst %p, src %p, size %llu", dst, src, size);
237+
238+
for (;;) {
239+
uintptr src_nextpage = ((uintptr)src + PAGE_SIZE) & HADDR_PAGE_MASK;
240+
uintptr dst_nextpage = ((uintptr)dst + PAGE_SIZE) & HADDR_PAGE_MASK;
241+
242+
usize src_nbyte = (usize)(src_nextpage - (uintptr)src);
243+
usize dst_nbyte = (usize)(dst_nextpage - (uintptr)dst);
244+
usize nbyte = MIN(src_nbyte, dst_nbyte);
245+
if ((u64)nbyte > size)
246+
nbyte = (usize)size;
247+
248+
dlog("copy %4zu B %p-%p -> %p-%p", nbyte, src, src+nbyte, dst, dst+nbyte);
249+
memcpy(dst, src, nbyte);
250+
251+
if (size == (u64)nbyte)
252+
break;
253+
254+
assert_no_sub_overflow(size, (u64)nbyte);
255+
size -= (u64)nbyte;
256+
257+
srcaddr += (u64)nbyte;
258+
dstaddr += (u64)nbyte;
259+
260+
src = (void*)vm_translate(cache, map, srcaddr, 1, VM_OP_LOAD_1);
261+
dst = (void*)vm_translate(cache, map, dstaddr, 1, VM_OP_STORE_1);
262+
}
189263
}
190264

191265
static i64 mcmp(EXEC_PARAMS, u64 xaddr, u64 yaddr, u64 size) {

0 commit comments

Comments
 (0)