.option norvc .option norelax # ================================================== # Text section # ================================================== .section .text .globl _start .globl vm_boot _start: vm_boot: # -------------------------------------------------- # Only hart 0 runs # -------------------------------------------------- csrr a0, mhartid bnez a0, hang # -------------------------------------------------- # Build page tables # -------------------------------------------------- # # Page table setup (Sv39) — binary + hex example # # Purpose: # Build a VALID page table entry (PTE) in the root page table # that points to the next-level page table (l1_pt). # # Assume: # l1_pt physical address = # binary: 00000000 10000000 01000000 00110000 00000000 # hex: 0x0000000080403000 # (page aligned, lower 12 bits = 0) # # Step-by-step instruction meaning: # # la t0, l1_pt # Load physical address of l1_pt. # # t0 = # binary: 00000000 10000000 01000000 00110000 00000000 # hex: 0x0000000080403000 # # srli t0, t0, 12 # Drop 12-bit page offset → extract Physical Page Number (PPN). # # t0 (PPN) = # binary: 00000000 00000000 10000000 01000000 0011 # hex: 0x0000000000080403 # # slli t0, t0, 10 # Shift PPN into PTE bit positions [63:10]. # Bits [9:0] are flags. # # t0 = # binary: 00000000 00000000 10000000 01000000 0011 0000000000 # hex: 0x0000000020100C00 # # ori t0, t0, 1 # Set bit 0 (V = Valid). # # t0 (final PTE) = # binary: 00000000 00000000 10000000 01000000 0011 0000000001 # hex: 0x0000000020100C01 # # Memory effect: # # root_pt[0] = # bit index: # 63 10 9 0 # +----------------------------------+----------+ # | PPN = 0x0000000000080403 | V = 1 | # +----------------------------------+----------+ # # binary: 00000000 00000000 10000000 01000000 0011 0000000001 # hex: 0x0000000020100C01 # # Result: # Root page table entry 0 is VALID and points to l1_pt. # The MMU uses this entry to continue the Sv39 page-table walk. # # root_pt[0] -> l1_pt la t0, l1_pt srli t0, t0, 12 # PPN slli t0, t0, 10 # PTE format ori t0, t0, 0x1 # V la t1, root_pt sd t0, 0(t1) # l1_pt[0] -> l0_pt la t0, l0_pt srli t0, t0, 12 slli t0, t0, 10 ori t0, t0, 0x1 # V la t1, l1_pt sd t0, 0(t1) # l0_pt[0] -> identity mapping (RWX) li t0, (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<6) # V R W X A la t1, l0_pt sd t0, 0(t1) # -------------------------------------------------- # Enable Sv39 paging # -------------------------------------------------- # Enable virtual memory (Sv39) — SATP setup diagram (binary) # # Assume: # root_pt physical address = # 00000000 10000000 01000000 00010000 00000000 # (4 KB aligned, lower 12 bits = 0) # # Instruction flow: # # la t0, root_pt # t0 = # 00000000 10000000 01000000 00010000 00000000 # # srli t0, t0, 12 ; extract PPN # t0 (PPN) = # 00000000 00000000 10000000 01000000 0001 # # li t1, (8 << 60) ; MODE = Sv39 # t1 = # 1000 0000000000000000000000000000000000000000000000000000 # ^^^^ # MODE[63:60] = 1000 (Sv39) # # or t0, t0, t1 # satp value = # 1000 0000000000000000000000000000000010000000010000000001 # |<-- MODE -->|<----------- ASID ---------->|<---- PPN ---->| # # csrw satp, t0 # satp register loaded: # # 63 60 59 44 43 0 # +------+----------------------------------+----------------+ # |1000 |0000000000000000 |0000000010000000010000000001| # +------+----------------------------------+----------------+ # MODE=Sv39 ASID=0 root_pt PPN # # sfence.vma zero, zero # Flush all TLB entries so new page tables are used # # Meaning: # - Virtual memory enabled in Sv39 mode # - Root page table base = root_pt # - ASID = 0 # - MMU now performs 3-level page table walks # la t0, root_pt srli t0, t0, 12 li t1, (8 << 60) # MODE=Sv39 or t0, t0, t1 csrw satp, t0 sfence.vma zero, zero # -------------------------------------------------- # Write data to memory (safe area) # -------------------------------------------------- la t2, test_buf li t3, 0x1122334455667788 sd t3, 0(t2) # -------------------------------------------------- # Read data back # -------------------------------------------------- ld t4, 0(t2) # Optional check (simple) bne t3, t4, hang # -------------------------------------------------- # Signal success # -------------------------------------------------- la t0, tohost li t1, 1 sd t1, 0(t0) hang: wfi j hang # ================================================== # Required test symbol # ================================================== .globl exit exit: j exit # ================================================== # Data section # ================================================== .section .data .align 3 .globl tohost .globl fromhost tohost: .dword 0 fromhost: .dword 0 # -------------------------------------------------- # Test buffer (safe data memory) # -------------------------------------------------- .align 3 test_buf: .zero 16 # -------------------------------------------------- # Page tables (must be 4 KiB each) # -------------------------------------------------- .align 12 root_pt: .zero 4096 .align 12 l1_pt: .zero 4096 .align 12 l0_pt: .zero 4096