Page table management - retrotruestory/M1DEV GitHub Wiki
Here's how to optimize page table management using Magic-1's specialized instructions:
.cseg
.global _write_page_entry
.global _read_page_entry
.global _map_page
.global _unmap_page
// Write a page table entry (PTE)
// void write_page_entry(uint16_t pte, void* addr, int is_code)
_write_page_entry:
enter 8
push b
push c
ld.16 a,12(sp) ; Load PTE value
ld.16 b,14(sp) ; Load virtual address
ld.16 c,16(sp) ; Load is_code flag
cmp.16 c,#0 ; Check if code or data page
br.eq .data_page
wcpte a,(b) ; Write code page table entry
br .done
.data_page:
wdpte a,(b) ; Write data page table entry
.done: pop c
pop b
leave
ret
// Map a physical page to virtual address
// void map_page(uint16_t phys_page, void* virt_addr, int is_code, int is_writable)
_map_page:
enter 8
push b
push c
ld.16 a,12(sp) ; Load physical page number
ld.16 b,14(sp) ; Load virtual address
ld.16 c,16(sp) ; Load is_code flag
; Build PTE: Present(1) + Writable(param) + RAM(1) + Page(11 bits)
or.16 a,#0x8000 ; Set present bit
ld.16 c,18(sp) ; Load writable flag
cmp.16 c,#0
br.eq .readonly
or.16 a,#0x4000 ; Set writable bit
.readonly:
or.16 a,#0x2000 ; Set RAM bit
; Write PTE
push c
ld.16 c,18(sp) ; Reload is_code flag
wcpte a,(b) ; Write to page table
pop c
pop c
pop b
leave
ret
Create a C interface:
#ifndef PAGE_MGMT_H
#define PAGE_MGMT_H
#include <stdint.h>
// Page table entry flags
#define PTE_PRESENT 0x8000
#define PTE_WRITABLE 0x4000
#define PTE_RAM 0x2000
#define PTE_MASK 0x07FF // 11 bits for page number
// Function declarations
void write_page_entry(uint16_t pte, void* addr, int is_code);
void map_page(uint16_t phys_page, void* virt_addr, int is_code, int is_writable);
// Helper macros
#define PAGE_SIZE 2048
#define PAGES_PER_PROC 32
#define CODE_PAGE 1
#define DATA_PAGE 0
#endif
Example usage:
#include <stdio.h>
#include "page_mgmt.h"
void setup_process_memory(int pid) {
uint16_t code_base = pid * PAGES_PER_PROC;
uint16_t data_base = code_base + PAGES_PER_PROC;
// Map code pages (read-only)
for(int i = 0; i < PAGES_PER_PROC; i++) {
void* virt_addr = (void*)(i * PAGE_SIZE);
map_page(code_base + i, virt_addr, CODE_PAGE, 0);
}
// Map data pages (read-write)
for(int i = 0; i < PAGES_PER_PROC; i++) {
void* virt_addr = (void*)((i + PAGES_PER_PROC) * PAGE_SIZE);
map_page(data_base + i, virt_addr, DATA_PAGE, 1);
}
}
Update Makefile:
CC = clcc
AS = m1_as
CFLAGS = -O2
OBJECTS = page_mgmt.o test_paging.o
test_paging: $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $(OBJECTS)
%.o: %.s
$(AS) -o $@ $<
%.o: %.c
$(CC) $(CFLAGS) -c $<
clean:
rm -f test_paging *.o
Key features:
- Direct use of
wcpte
/wdpte
instructions for page table management - Hardware-assisted page table updates
- Support for both code and data pages
- Page protection flags (present, writable, RAM)
- Process memory isolation
This implementation is particularly useful for:
- Process memory management
- Virtual memory setup
- Memory protection
- Process isolation
- Page table manipulation in kernel mode