saving current changes

This commit is contained in:
2026-02-17 15:30:40 +00:00
parent 6f114cd188
commit 762b3b4cbb
15 changed files with 6147 additions and 95 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,164 @@
#include "riscv_test.h"
#if __riscv_xlen == 64
# define STORE sd
# define LOAD ld
# define REGBYTES 8
#else
# define STORE sw
# define LOAD lw
# define REGBYTES 4
#endif
#define STACK_TOP (_end + RISCV_PGSIZE * 4)
.section ".text.init","ax",@progbits
.globl _start
.align 2
_start:
j handle_reset
/* NMI vector */
.align 2
nmi_vector:
j wtf
.align 2
trap_vector:
j wtf
handle_reset:
li x1, 0
li x2, 0
li x3, 0
li x4, 0
li x5, 0
li x6, 0
li x7, 0
li x8, 0
li x9, 0
li x10, 0
li x11, 0
li x12, 0
li x13, 0
li x14, 0
li x15, 0
li x16, 0
li x17, 0
li x18, 0
li x19, 0
li x20, 0
li x21, 0
li x22, 0
li x23, 0
li x24, 0
li x25, 0
li x26, 0
li x27, 0
li x28, 0
li x29, 0
li x30, 0
li x31, 0
INIT_RNMI
la t0, trap_vector
csrw mtvec, t0
la sp, STACK_TOP - SIZEOF_TRAPFRAME_T
csrr t0, mhartid
slli t0, t0, 12
add sp, sp, t0
csrw mscratch, sp
call extra_boot
la a0, userstart
j vm_boot
.globl pop_tf
pop_tf:
LOAD t0,33*REGBYTES(a0)
csrw sepc,t0
LOAD x1,1*REGBYTES(a0)
LOAD x2,2*REGBYTES(a0)
LOAD x3,3*REGBYTES(a0)
LOAD x4,4*REGBYTES(a0)
LOAD x5,5*REGBYTES(a0)
LOAD x6,6*REGBYTES(a0)
LOAD x7,7*REGBYTES(a0)
LOAD x8,8*REGBYTES(a0)
LOAD x9,9*REGBYTES(a0)
LOAD x11,11*REGBYTES(a0)
LOAD x12,12*REGBYTES(a0)
LOAD x13,13*REGBYTES(a0)
LOAD x14,14*REGBYTES(a0)
LOAD x15,15*REGBYTES(a0)
LOAD x16,16*REGBYTES(a0)
LOAD x17,17*REGBYTES(a0)
LOAD x18,18*REGBYTES(a0)
LOAD x19,19*REGBYTES(a0)
LOAD x20,20*REGBYTES(a0)
LOAD x21,21*REGBYTES(a0)
LOAD x22,22*REGBYTES(a0)
LOAD x23,23*REGBYTES(a0)
LOAD x24,24*REGBYTES(a0)
LOAD x25,25*REGBYTES(a0)
LOAD x26,26*REGBYTES(a0)
LOAD x27,27*REGBYTES(a0)
LOAD x28,28*REGBYTES(a0)
LOAD x29,29*REGBYTES(a0)
LOAD x30,30*REGBYTES(a0)
LOAD x31,31*REGBYTES(a0)
LOAD a0,10*REGBYTES(a0)
sret
.global trap_entry
.align 2
trap_entry:
csrrw sp, sscratch, sp
# save gprs
STORE x1,1*REGBYTES(sp)
STORE x3,3*REGBYTES(sp)
STORE x4,4*REGBYTES(sp)
STORE x5,5*REGBYTES(sp)
STORE x6,6*REGBYTES(sp)
STORE x7,7*REGBYTES(sp)
STORE x8,8*REGBYTES(sp)
STORE x9,9*REGBYTES(sp)
STORE x10,10*REGBYTES(sp)
STORE x11,11*REGBYTES(sp)
STORE x12,12*REGBYTES(sp)
STORE x13,13*REGBYTES(sp)
STORE x14,14*REGBYTES(sp)
STORE x15,15*REGBYTES(sp)
STORE x16,16*REGBYTES(sp)
STORE x17,17*REGBYTES(sp)
STORE x18,18*REGBYTES(sp)
STORE x19,19*REGBYTES(sp)
STORE x20,20*REGBYTES(sp)
STORE x21,21*REGBYTES(sp)
STORE x22,22*REGBYTES(sp)
STORE x23,23*REGBYTES(sp)
STORE x24,24*REGBYTES(sp)
STORE x25,25*REGBYTES(sp)
STORE x26,26*REGBYTES(sp)
STORE x27,27*REGBYTES(sp)
STORE x28,28*REGBYTES(sp)
STORE x29,29*REGBYTES(sp)
STORE x30,30*REGBYTES(sp)
STORE x31,31*REGBYTES(sp)
csrrw t0,sscratch,sp
STORE t0,2*REGBYTES(sp)
# get sr, epc, badvaddr, cause
csrr t0,sstatus
STORE t0,32*REGBYTES(sp)
csrr t0,sepc
STORE t0,33*REGBYTES(sp)
csrr t0,stval
STORE t0,34*REGBYTES(sp)
csrr t0,scause
STORE t0,35*REGBYTES(sp)
move a0, sp
j handle_trap

View File

@@ -0,0 +1,16 @@
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
SECTIONS
{
. = 0x80000000;
.text.init : { *(.text.init) }
. = ALIGN(0x1000);
.tohost : { *(.tohost) }
. = ALIGN(0x1000);
.text : { *(.text) }
. = ALIGN(0x1000);
.data : { *(.data) }
.bss : { *(.bss) }
_end = .;
}

View File

@@ -0,0 +1,98 @@
// See LICENSE for license details.
#ifndef _ENV_VIRTUAL_SINGLE_CORE_H
#define _ENV_VIRTUAL_SINGLE_CORE_H
#include "../p/riscv_test.h"
//-----------------------------------------------------------------------
// Begin Macro
//-----------------------------------------------------------------------
#undef RVTEST_FP_ENABLE
#define RVTEST_FP_ENABLE fssr x0
#undef RVTEST_VECTOR_ENABLE
#define RVTEST_VECTOR_ENABLE \
csrwi fcsr, 0; \
csrwi vcsr, 0;
#undef RVTEST_ZVE32X_ENABLE
#define RVTEST_ZVE32X_ENABLE \
csrwi vcsr, 0;
#undef RVTEST_CODE_BEGIN
#define RVTEST_CODE_BEGIN \
.text; \
.global extra_boot; \
extra_boot: \
EXTRA_INIT \
ret; \
.global trap_filter; \
trap_filter: \
FILTER_TRAP \
li a0, 0; \
ret; \
.global pf_filter; \
pf_filter: \
FILTER_PAGE_FAULT \
li a0, 0; \
ret; \
.global userstart; \
userstart: \
init
//-----------------------------------------------------------------------
// Pass/Fail Macro
//-----------------------------------------------------------------------
#undef RVTEST_PASS
#define RVTEST_PASS li a0, 1; scall
#undef RVTEST_FAIL
#define RVTEST_FAIL sll a0, TESTNUM, 1; 1:beqz a0, 1b; or a0, a0, 1; scall;
//-----------------------------------------------------------------------
// Data Section Macro
//-----------------------------------------------------------------------
#undef RVTEST_DATA_END
#define RVTEST_DATA_END
//-----------------------------------------------------------------------
// Supervisor mode definitions and macros
//-----------------------------------------------------------------------
#ifndef LFSR_BITS
#define LFSR_BITS 6
#endif
#define MAX_TEST_PAGES ((1 << LFSR_BITS)-1) // this must be the period of the LFSR below
#define LFSR_NEXT(x) (((((x)^((x)>>1)) & 1) << (LFSR_BITS-1)) | ((x) >> 1))
#define PGSHIFT 12
#define PGSIZE (1UL << PGSHIFT)
#define SIZEOF_TRAPFRAME_T ((__riscv_xlen / 8) * 36)
#ifndef __ASSEMBLER__
typedef unsigned long pte_t;
#define LEVELS (sizeof(pte_t) == sizeof(uint64_t) ? 3 : 2)
#define PTIDXBITS (PGSHIFT - (sizeof(pte_t) == 8 ? 3 : 2))
#define VPN_BITS (PTIDXBITS * LEVELS)
#define VA_BITS (VPN_BITS + PGSHIFT)
#define PTES_PER_PT (1UL << RISCV_PGLEVEL_BITS)
#define MEGAPAGE_SIZE (PTES_PER_PT * PGSIZE)
typedef struct
{
long gpr[32];
long sr;
long epc;
long badvaddr;
long cause;
} trapframe_t;
#endif
#endif

View File

@@ -0,0 +1,295 @@
// See LICENSE for license details.
#ifndef _ENV_PHYSICAL_SINGLE_CORE_H
#define _ENV_PHYSICAL_SINGLE_CORE_H
#include "../encoding.h"
//-----------------------------------------------------------------------
// Begin Macro
//-----------------------------------------------------------------------
#define RVTEST_RV64U \
.macro init; \
.endm
#define RVTEST_RV64UF \
.macro init; \
RVTEST_FP_ENABLE; \
.endm
#define RVTEST_RV64UV \
.macro init; \
RVTEST_VECTOR_ENABLE; \
.endm
#define RVTEST_RV64UVX \
.macro init; \
RVTEST_ZVE32X_ENABLE; \
.endm
#define RVTEST_RV32U \
.macro init; \
.endm
#define RVTEST_RV32UF \
.macro init; \
RVTEST_FP_ENABLE; \
.endm
#define RVTEST_RV32UV \
.macro init; \
RVTEST_VECTOR_ENABLE; \
.endm
#define RVTEST_RV32UVX \
.macro init; \
RVTEST_ZVE32X_ENABLE; \
.endm
#define RVTEST_RV64M \
.macro init; \
RVTEST_ENABLE_MACHINE; \
.endm
#define RVTEST_RV64S \
.macro init; \
RVTEST_ENABLE_SUPERVISOR; \
.endm
#define RVTEST_RV32M \
.macro init; \
RVTEST_ENABLE_MACHINE; \
.endm
#define RVTEST_RV32S \
.macro init; \
RVTEST_ENABLE_SUPERVISOR; \
.endm
#if __riscv_xlen == 64
# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bgez a0, 1f; RVTEST_PASS; 1:
#else
# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bltz a0, 1f; RVTEST_PASS; 1:
#endif
#define INIT_XREG \
li x1, 0; \
li x2, 0; \
li x3, 0; \
li x4, 0; \
li x5, 0; \
li x6, 0; \
li x7, 0; \
li x8, 0; \
li x9, 0; \
li x10, 0; \
li x11, 0; \
li x12, 0; \
li x13, 0; \
li x14, 0; \
li x15, 0; \
li x16, 0; \
li x17, 0; \
li x18, 0; \
li x19, 0; \
li x20, 0; \
li x21, 0; \
li x22, 0; \
li x23, 0; \
li x24, 0; \
li x25, 0; \
li x26, 0; \
li x27, 0; \
li x28, 0; \
li x29, 0; \
li x30, 0; \
li x31, 0;
#define INIT_PMP \
la t0, 1f; \
csrw mtvec, t0; \
/* Set up a PMP to permit all accesses */ \
li t0, (1 << (31 + (__riscv_xlen / 64) * (53 - 31))) - 1; \
csrw pmpaddr0, t0; \
li t0, PMP_NAPOT | PMP_R | PMP_W | PMP_X; \
csrw pmpcfg0, t0; \
.align 2; \
1:
#define INIT_RNMI \
la t0, 1f; \
csrw mtvec, t0; \
csrwi CSR_MNSTATUS, MNSTATUS_NMIE; \
.align 2; \
1:
#define INIT_SATP \
la t0, 1f; \
csrw mtvec, t0; \
csrwi satp, 0; \
.align 2; \
1:
#define DELEGATE_NO_TRAPS \
csrwi mie, 0; \
la t0, 1f; \
csrw mtvec, t0; \
csrwi medeleg, 0; \
csrwi mideleg, 0; \
.align 2; \
1:
#define RVTEST_ENABLE_SUPERVISOR \
li a0, MSTATUS_MPP & (MSTATUS_MPP >> 1); \
csrs mstatus, a0; \
li a0, SIP_SSIP | SIP_STIP; \
csrs mideleg, a0; \
#define RVTEST_ENABLE_MACHINE \
li a0, MSTATUS_MPP; \
csrs mstatus, a0; \
#define RVTEST_FP_ENABLE \
li a0, MSTATUS_FS & (MSTATUS_FS >> 1); \
csrs mstatus, a0; \
csrwi fcsr, 0
#define RVTEST_VECTOR_ENABLE \
li a0, (MSTATUS_VS & (MSTATUS_VS >> 1)) | \
(MSTATUS_FS & (MSTATUS_FS >> 1)); \
csrs mstatus, a0; \
csrwi fcsr, 0; \
csrwi vcsr, 0;
#define RVTEST_ZVE32X_ENABLE \
li a0, (MSTATUS_VS & (MSTATUS_VS >> 1)); \
csrs mstatus, a0; \
csrwi vcsr, 0;
#define RISCV_MULTICORE_DISABLE \
csrr a0, mhartid; \
1: bnez a0, 1b
#define EXTRA_TVEC_USER
#define EXTRA_TVEC_MACHINE
#define EXTRA_INIT
#define EXTRA_INIT_TIMER
#define FILTER_TRAP
#define FILTER_PAGE_FAULT
#define INTERRUPT_HANDLER j other_exception /* No interrupts should occur */
#define RVTEST_CODE_BEGIN \
.section .text.init; \
.align 6; \
.weak stvec_handler; \
.weak mtvec_handler; \
.globl _start; \
_start: \
/* reset vector */ \
j reset_vector; \
.align 2; \
trap_vector: \
/* test whether the test came from pass/fail */ \
csrr t5, mcause; \
li t6, CAUSE_USER_ECALL; \
beq t5, t6, write_tohost; \
li t6, CAUSE_SUPERVISOR_ECALL; \
beq t5, t6, write_tohost; \
li t6, CAUSE_MACHINE_ECALL; \
beq t5, t6, write_tohost; \
/* if an mtvec_handler is defined, jump to it */ \
la t5, mtvec_handler; \
beqz t5, 1f; \
jr t5; \
/* was it an interrupt or an exception? */ \
1: csrr t5, mcause; \
bgez t5, handle_exception; \
INTERRUPT_HANDLER; \
handle_exception: \
/* we don't know how to handle whatever the exception was */ \
other_exception: \
/* some unhandlable exception occurred */ \
1: ori TESTNUM, TESTNUM, 1337; \
write_tohost: \
sw TESTNUM, tohost, t5; \
sw zero, tohost + 4, t5; \
j write_tohost; \
reset_vector: \
INIT_XREG; \
RISCV_MULTICORE_DISABLE; \
INIT_RNMI; \
INIT_SATP; \
INIT_PMP; \
DELEGATE_NO_TRAPS; \
li TESTNUM, 0; \
la t0, trap_vector; \
csrw mtvec, t0; \
CHECK_XLEN; \
/* if an stvec_handler is defined, delegate exceptions to it */ \
la t0, stvec_handler; \
beqz t0, 1f; \
csrw stvec, t0; \
li t0, (1 << CAUSE_LOAD_PAGE_FAULT) | \
(1 << CAUSE_STORE_PAGE_FAULT) | \
(1 << CAUSE_FETCH_PAGE_FAULT) | \
(1 << CAUSE_MISALIGNED_FETCH) | \
(1 << CAUSE_USER_ECALL) | \
(1 << CAUSE_BREAKPOINT); \
csrw medeleg, t0; \
1: csrwi mstatus, 0; \
init; \
EXTRA_INIT; \
EXTRA_INIT_TIMER; \
la t0, 1f; \
csrw mepc, t0; \
csrr a0, mhartid; \
mret; \
1:
//-----------------------------------------------------------------------
// End Macro
//-----------------------------------------------------------------------
#define RVTEST_CODE_END \
unimp
//-----------------------------------------------------------------------
// Pass/Fail Macro
//-----------------------------------------------------------------------
#define RVTEST_PASS \
fence; \
li TESTNUM, 1; \
li a7, 93; \
li a0, 0; \
ecall
#define TESTNUM gp
#define RVTEST_FAIL \
fence; \
1: beqz TESTNUM, 1b; \
sll TESTNUM, TESTNUM, 1; \
or TESTNUM, TESTNUM, 1; \
li a7, 93; \
addi a0, TESTNUM, 0; \
ecall
//-----------------------------------------------------------------------
// Data Section Macro
//-----------------------------------------------------------------------
#define EXTRA_DATA
#define RVTEST_DATA_BEGIN \
EXTRA_DATA \
.pushsection .tohost,"aw",@progbits; \
.align 6; .global tohost; tohost: .dword 0; .size tohost, 8; \
.align 6; .global fromhost; fromhost: .dword 0; .size fromhost, 8;\
.popsection; \
.align 4; .global begin_signature; begin_signature:
#define RVTEST_DATA_END .align 4; .global end_signature; end_signature:
#endif

View File

@@ -0,0 +1,114 @@
#include <string.h>
#include <stdint.h>
#include <ctype.h>
void* memcpy(void* dest, const void* src, size_t len)
{
if ((((uintptr_t)dest | (uintptr_t)src | len) & (sizeof(uintptr_t)-1)) == 0) {
const uintptr_t* s = src;
uintptr_t *d = dest;
while (d < (uintptr_t*)(dest + len))
*d++ = *s++;
} else {
const char* s = src;
char *d = dest;
while (d < (char*)(dest + len))
*d++ = *s++;
}
return dest;
}
void* memset(void* dest, int byte, size_t len)
{
if ((((uintptr_t)dest | len) & (sizeof(uintptr_t)-1)) == 0) {
uintptr_t word = byte & 0xFF;
word |= word << 8;
word |= word << 16;
word |= word << 16 << 16;
uintptr_t *d = dest;
while (d < (uintptr_t*)(dest + len))
*d++ = word;
} else {
char *d = dest;
while (d < (char*)(dest + len))
*d++ = byte;
}
return dest;
}
size_t strlen(const char *s)
{
const char *p = s;
while (*p)
p++;
return p - s;
}
int strcmp(const char* s1, const char* s2)
{
unsigned char c1, c2;
do {
c1 = *s1++;
c2 = *s2++;
} while (c1 != 0 && c1 == c2);
return c1 - c2;
}
int memcmp(const void* s1, const void* s2, size_t n)
{
if ((((uintptr_t)s1 | (uintptr_t)s2) & (sizeof(uintptr_t)-1)) == 0) {
const uintptr_t* u1 = s1;
const uintptr_t* u2 = s2;
const uintptr_t* end = u1 + (n / sizeof(uintptr_t));
while (u1 < end) {
if (*u1 != *u2)
break;
u1++;
u2++;
}
n -= (const void*)u1 - s1;
s1 = u1;
s2 = u2;
}
while (n--) {
unsigned char c1 = *(const unsigned char*)s1++;
unsigned char c2 = *(const unsigned char*)s2++;
if (c1 != c2)
return c1 - c2;
}
return 0;
}
char* strcpy(char* dest, const char* src)
{
char* d = dest;
while ((*d++ = *src++))
;
return dest;
}
long atol(const char* str)
{
long res = 0;
int sign = 0;
while (*str == ' ')
str++;
if (*str == '-' || *str == '+') {
sign = *str == '-';
str++;
}
while (*str) {
res *= 10;
res += *str++ - '0';
}
return sign ? -res : res;
}

View File

@@ -0,0 +1,300 @@
// See LICENSE for license details.
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "riscv_test.h"
#define SYS_write 64
# define SATP_MODE_CHOICE SATP_MODE_SV39
void trap_entry();
void pop_tf(trapframe_t*);
extern volatile uint64_t tohost;
extern volatile uint64_t fromhost;
static void do_tohost(uint64_t tohost_value)
{
while (tohost)
fromhost = 0;
tohost = tohost_value;
}
#define pa2kva(pa) ((void*)(pa) - DRAM_BASE - MEGAPAGE_SIZE)
#define uva2kva(pa) ((void*)(pa) - MEGAPAGE_SIZE)
#define flush_page(addr) asm volatile ("sfence.vma %0" : : "r" (addr) : "memory")
static uint64_t lfsr63(uint64_t x)
{
uint64_t bit = (x ^ (x >> 1)) & 1;
return (x >> 1) | (bit << 62);
}
static void cputchar(int x)
{
#if __riscv_xlen == 32
// HTIF devices are not supported on RV32, so proxy a write system call
volatile uint64_t syscall_struct[8];
volatile int buff = x;
syscall_struct[0] = SYS_write;
syscall_struct[1] = 1;
syscall_struct[2] = (uintptr_t)&buff;
syscall_struct[3] = 1;
do_tohost((uintptr_t)&syscall_struct);
// Wait for response as struct has to be read by HTIF
while(!fromhost);
#else
do_tohost(0x0101000000000000 | (unsigned char)x);
#endif
}
static void cputstring(const char* s)
{
while (*s)
cputchar(*s++);
}
static void terminate(int code)
{
do_tohost(code);
while (1);
}
void wtf()
{
terminate(841);
}
#define stringify1(x) #x
#define stringify(x) stringify1(x)
#define assert(x) do { \
if (x) break; \
cputstring("Assertion failed: " stringify(x) "\n"); \
terminate(3); \
} while(0)
#define l1pt pt[0]
#define user_l2pt pt[1]
# define NPT 4
# define kernel_l2pt pt[2]
# define user_llpt pt[3]
pte_t pt[NPT][PTES_PER_PT] __attribute__((aligned(PGSIZE)));
typedef struct { pte_t addr; void* next; } freelist_t;
freelist_t user_mapping[MAX_TEST_PAGES];
freelist_t freelist_nodes[MAX_TEST_PAGES];
freelist_t *freelist_head, *freelist_tail;
void printhex(uint64_t x)
{
char str[17];
for (int i = 0; i < 16; i++)
{
str[15-i] = (x & 0xF) + ((x & 0xF) < 10 ? '0' : 'a'-10);
x >>= 4;
}
str[16] = 0;
cputstring(str);
}
static void evict(unsigned long addr)
{
assert(addr >= PGSIZE && addr < MAX_TEST_PAGES * PGSIZE);
addr = addr/PGSIZE*PGSIZE;
freelist_t* node = &user_mapping[addr/PGSIZE];
if (node->addr)
{
// check accessed and dirty bits
assert(user_llpt[addr/PGSIZE] & PTE_A);
uintptr_t sstatus = set_csr(sstatus, SSTATUS_SUM);
if (memcmp((void*)addr, uva2kva(addr), PGSIZE)) {
assert(user_llpt[addr/PGSIZE] & PTE_D);
memcpy(uva2kva(addr), (void*)addr, PGSIZE);
}
write_csr(sstatus, sstatus);
user_mapping[addr/PGSIZE].addr = 0;
if (freelist_tail == 0)
freelist_head = freelist_tail = node;
else
{
freelist_tail->next = node;
freelist_tail = node;
}
}
}
extern int pf_filter(uintptr_t addr, uintptr_t *pte, int *copy);
extern int trap_filter(trapframe_t *tf);
void handle_fault(uintptr_t addr, uintptr_t cause)
{
uintptr_t filter_encodings = 0;
int copy_page = 1;
assert(addr >= PGSIZE && addr < MAX_TEST_PAGES * PGSIZE);
addr = addr/PGSIZE*PGSIZE;
if (user_llpt[addr/PGSIZE]) {
if (!(user_llpt[addr/PGSIZE] & PTE_A)) {
user_llpt[addr/PGSIZE] |= PTE_A;
} else {
assert(!(user_llpt[addr/PGSIZE] & PTE_D) && cause == CAUSE_STORE_PAGE_FAULT);
user_llpt[addr/PGSIZE] |= PTE_D;
}
flush_page(addr);
return;
}
freelist_t* node = freelist_head;
assert(node);
freelist_head = node->next;
if (freelist_head == freelist_tail)
freelist_tail = 0;
uintptr_t new_pte = (node->addr >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V | PTE_U | PTE_R | PTE_W | PTE_X;
if (pf_filter(addr, &filter_encodings, &copy_page)) {
new_pte = (node->addr >> PGSHIFT << PTE_PPN_SHIFT) | filter_encodings;
}
user_llpt[addr/PGSIZE] = new_pte | PTE_A | PTE_D;
flush_page(addr);
assert(user_mapping[addr/PGSIZE].addr == 0);
user_mapping[addr/PGSIZE] = *node;
uintptr_t sstatus = set_csr(sstatus, SSTATUS_SUM);
memcpy((void*)addr, uva2kva(addr), PGSIZE);
write_csr(sstatus, sstatus);
user_llpt[addr/PGSIZE] = new_pte;
flush_page(addr);
asm volatile ("fence.i");
}
void handle_trap(trapframe_t* tf)
{
if (trap_filter(tf)) {
pop_tf(tf);
}
if (tf->cause == CAUSE_USER_ECALL)
{
int n = tf->gpr[10];
for (long i = 1; i < MAX_TEST_PAGES; i++)
evict(i*PGSIZE);
terminate(n);
}
else if (tf->cause == CAUSE_ILLEGAL_INSTRUCTION)
{
assert(tf->epc % 4 == 0);
int* fssr;
asm ("jal %0, 1f; fssr x0; 1:" : "=r"(fssr));
if (*(int*)tf->epc == *fssr)
terminate(1); // FP test on non-FP hardware. "succeed."
else
assert(!"illegal instruction");
tf->epc += 4;
}
else if (tf->cause == CAUSE_FETCH_PAGE_FAULT || tf->cause == CAUSE_LOAD_PAGE_FAULT || tf->cause == CAUSE_STORE_PAGE_FAULT)
handle_fault(tf->badvaddr, tf->cause);
else
assert(!"unexpected exception");
pop_tf(tf);
}
static void coherence_torture()
{
// cause coherence misses without affecting program semantics
uint64_t random = ENTROPY;
while (1) {
uintptr_t paddr = DRAM_BASE + ((random % (2 * (MAX_TEST_PAGES + 1) * PGSIZE)) & -4);
#ifdef __riscv_atomic
if (random & 1) // perform a no-op write
asm volatile ("amoadd.w zero, zero, (%0)" :: "r"(paddr));
else // perform a read
#endif
asm volatile ("lw zero, (%0)" :: "r"(paddr));
random = lfsr63(random);
}
}
void vm_boot(uintptr_t test_addr)
{
uint64_t random = ENTROPY;
if (read_csr(mhartid) > 0)
coherence_torture();
_Static_assert(SIZEOF_TRAPFRAME_T == sizeof(trapframe_t), "???");
#if (MAX_TEST_PAGES > PTES_PER_PT) || (DRAM_BASE % MEGAPAGE_SIZE) != 0
# error
#endif
// map user to lowermost megapage
l1pt[0] = ((pte_t)user_l2pt >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V;
// map kernel to uppermost megapage
l1pt[PTES_PER_PT-1] = ((pte_t)kernel_l2pt >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V;
kernel_l2pt[PTES_PER_PT-1] = (DRAM_BASE/RISCV_PGSIZE << PTE_PPN_SHIFT) | PTE_V | PTE_R | PTE_W | PTE_X | PTE_A | PTE_D;
user_l2pt[0] = ((pte_t)user_llpt >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V;
uintptr_t vm_choice = SATP_MODE_CHOICE;
uintptr_t satp_value = ((uintptr_t)l1pt >> PGSHIFT)
| (vm_choice * (SATP_MODE & ~(SATP_MODE<<1)));
write_csr(satp, satp_value);
if (read_csr(satp) != satp_value)
assert(!"unsupported satp mode");
flush_page(DRAM_BASE);
// Set up PMPs if present, ignoring illegal instruction trap if not.
uintptr_t pmpc = PMP_NAPOT | PMP_R | PMP_W | PMP_X;
uintptr_t pmpa = ((uintptr_t)1 << (__riscv_xlen == 32 ? 31 : 53)) - 1;
asm volatile ("la t0, 1f\n\t"
"csrrw t0, mtvec, t0\n\t"
"csrw pmpaddr0, %1\n\t"
"csrw pmpcfg0, %0\n\t"
".align 2\n\t"
"1: csrw mtvec, t0"
: : "r" (pmpc), "r" (pmpa) : "t0");
// set up supervisor trap handling
write_csr(stvec, pa2kva(trap_entry));
write_csr(sscratch, pa2kva(read_csr(mscratch)));
write_csr(medeleg,
(1 << CAUSE_USER_ECALL) |
(1 << CAUSE_FETCH_PAGE_FAULT) |
(1 << CAUSE_LOAD_PAGE_FAULT) |
(1 << CAUSE_STORE_PAGE_FAULT));
// FPU on; accelerator on; vector unit on
write_csr(mstatus, MSTATUS_FS | MSTATUS_XS | MSTATUS_VS);
write_csr(mie, 0);
random = 1 + (random % MAX_TEST_PAGES);
freelist_head = pa2kva((void*)&freelist_nodes[0]);
freelist_tail = pa2kva(&freelist_nodes[MAX_TEST_PAGES-1]);
for (long i = 0; i < MAX_TEST_PAGES; i++)
{
freelist_nodes[i].addr = DRAM_BASE + (MAX_TEST_PAGES + random)*PGSIZE;
freelist_nodes[i].next = pa2kva(&freelist_nodes[i+1]);
random = LFSR_NEXT(random);
}
freelist_nodes[MAX_TEST_PAGES-1].next = 0;
trapframe_t tf;
memset(&tf, 0, sizeof(tf));
tf.epc = test_addr - DRAM_BASE;
pop_tf(&tf);
}

37
Tests/isa/Cheri.S Normal file
View File

@@ -0,0 +1,37 @@
.section .bss
.align 6 # 64-byte alignment helps bounds encoding
buffer:
.space 64
.section .text
.globl _start
_start:
# ------------------------------------------------------------
# 1. Create capability to buffer using DDC (c0)
# ------------------------------------------------------------
la t0, buffer
cincoffset c1, c0, t0 # c1 -> buffer capability
# ------------------------------------------------------------
# 2. Set bounds to first 16 bytes
# ------------------------------------------------------------
li t1, 16
csetbounds c2, c1, t1 # c2 = bounded capability
# ------------------------------------------------------------
# 3. Store value 0x42 into buffer[0] using capability
# ------------------------------------------------------------
li t2, 0x42
csb t2, 0(c2) # capability store byte
# ------------------------------------------------------------
# 4. Load the value back from buffer[0]
# ------------------------------------------------------------
clbu t3, 0(c2) # t3 should now contain 0x42
# ------------------------------------------------------------
# 5. Infinite loop (bare-metal halt)
# ------------------------------------------------------------
1:
j 1b

Binary file not shown.

View File

@@ -2,164 +2,176 @@
.option norelax
# ==================================================
# Text section
# Constants
# ==================================================
.equ PTE_V, 0x001
.equ PTE_R, 0x002
.equ PTE_W, 0x004
.equ PTE_X, 0x008
.equ PTE_A, 0x040
.equ PTE_D, 0x080
.equ SATP_MODE_SV39, (8 << 60)
# ==================================================
# Text
# ==================================================
.section .text
.globl _start
.globl vm_boot
_start:
vm_boot:
# Only hart 0 runs
csrr a0, mhartid
bnez a0, hang
# only hart 0
csrr a0, mhartid
bnez a0, hang
# install trap vector (required)
la t0, trap_vector
csrw stvec, t0
# --------------------------------------------------
# Page tables (Sv39, identity map)
# Build page tables (Sv39 identity map 1 GiB)
# --------------------------------------------------
la t0, l1_pt
srli t0, t0, 12
slli t0, t0, 10
ori t0, t0, 1
la t1, root_pt
sd t0, 0(t1)
la t0, l0_pt
srli t0, t0, 12
slli t0, t0, 10
ori t0, t0, 1
la t1, l1_pt
sd t0, 0(t1)
# root_pt[0] -> l1_pt
la t0, l1_pt
srli t0, t0, 12
slli t0, t0, 10
ori t0, t0, PTE_V
la t1, root_pt
sd t0, 0(t1)
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)
# l1_pt[0] -> l0_pt
la t0, l0_pt
srli t0, t0, 12
slli t0, t0, 10
ori t0, t0, PTE_V
la t1, l1_pt
sd t0, 0(t1)
# l0_pt[0] = 1GiB RWX identity leaf
li t0, (PTE_V|PTE_R|PTE_W|PTE_X|PTE_A|PTE_D)
la t1, l0_pt
sd t0, 0(t1)
# --------------------------------------------------
# Enable Sv39
la t0, root_pt
srli t0, t0, 12
li t1, (8 << 60)
or t0, t0, t1
csrw satp, t0
sfence.vma zero, zero
# --------------------------------------------------
la t0, root_pt
srli t0, t0, 12
li t1, SATP_MODE_SV39
or t0, t0, t1
csrw satp, t0
# sfence.vma zero, zero
# --------------------------------------------------
# Init allocator (explicit, no .bss)
# Init allocator
# --------------------------------------------------
la t0, heap_base
la t1, heap_ptr
sd t0, 0(t1)
la t0, heap_base
la t1, heap_ptr
sd t0, 0(t1)
la t0, free_list
sd zero, 0(t0)
la t0, free_list
sd zero, 0(t0)
# --------------------------------------------------
# Allocate free reuse test
# --------------------------------------------------
li a0, 16
jal ra, alloc
mv s1, a0
li a0, 16
call alloc
mv s1, a0
li t0, 0x1122334455667788
sd t0, 0(s1)
li t0, 0x1122334455667788
sd t0, 0(s1)
mv a0, s1
jal ra, free
mv a0, s1
call free
li a0, 16
jal ra, alloc
mv s2, a0
li a0, 16
call alloc
mv s2, a0
ld t1, 0(s2)
li t0, 0x1122334455667788
bne t1, t0, hang
ld t1, 0(s2)
li t0, 0x1122334455667788
bne t1, t0, hang
# success
la t0, tohost
li t1, 1
sd t1, 0(t0)
la t0, tohost
li t1, 1
sd t1, 0(t0)
hang:
wfi
j hang
# ==================================================
# Minimal trap handler (required)
# ==================================================
.align 2
trap_vector:
csrr t0, scause
j hang
# ==================================================
# alloc(size)
# a0 = size
# returns a0 = ptr
# ==================================================
.globl alloc
alloc:
la t0, free_list
ld t1, 0(t0)
beqz t1, alloc_bump
la t0, free_list
ld t1, 0(t0)
beqz t1, alloc_bump
# pop free list
ld t2, 0(t1)
sd t2, 0(t0)
addi a0, t1, 8
ld t2, 0(t1)
sd t2, 0(t0)
addi a0, t1, 8
ret
alloc_bump:
la t0, heap_ptr
ld t1, 0(t0)
addi t2, a0, 8
add t3, t1, t2
la t4, heap_end
bgtu t3, t4, hang
sd t3, 0(t0)
addi a0, t1, 8
la t0, heap_ptr
ld t1, 0(t0)
addi t2, a0, 8
add t3, t1, t2
la t4, heap_end
bgtu t3, t4, hang
sd t3, 0(t0)
addi a0, t1, 8
ret
# ==================================================
# free(ptr)
# a0 = user pointer
# ==================================================
.globl free
free:
addi t0, a0, -8
la t1, free_list
ld t2, 0(t1)
sd t2, 0(t0)
sd t0, 0(t1)
addi t0, a0, -8
la t1, free_list
ld t2, 0(t1)
sd t2, 0(t0)
sd t0, 0(t1)
ret
# ==================================================
# Exit symbol
# ==================================================
.globl exit
exit:
j exit
# ==================================================
# Data section (NO .bss)
# Data (NO .bss)
# ==================================================
.section .data
.align 3
# Host interface
.globl tohost
.globl fromhost
tohost: .dword 0
fromhost: .dword 0
tohost: .dword 0
fromhost: .dword 0
# Allocator state (explicitly initialized)
.globl heap_ptr
.globl free_list
heap_ptr: .dword 0
free_list: .dword 0
heap_ptr: .dword 0
free_list: .dword 0
# Heap
.align 12
heap_base:
.zero 4096
heap_end:
# Page tables
.align 12
root_pt: .zero 4096
.align 12
l1_pt: .zero 4096
.align 12
l0_pt: .zero 4096
l0_pt: .zero 4096

BIN
Tests/isa/string Normal file

Binary file not shown.

View File

@@ -109,7 +109,7 @@ benchmarks:
# ================================================================
# Generate Bluespec CHERI tag controller source file
CAPSIZE = 128
CAPSIZE = 128
TAGS_STRUCT = 0 64
TAGS_ALIGN = 32
.PHONY: tagsparams

View File

@@ -1003,6 +1003,7 @@ function DecodeResult decode(Instruction inst, Bool cap_mode);
regs.src1 = Valid(tagged Gpr rs1);
regs.src2 = Valid(tagged Gpr rs2);
dInst.capFunc = CapModify (SetBounds (SetBoundsRounding));
// TODOD Add the delta function under this
end
f7_cap_CSetBoundsExact: begin
legalInst = True;

View File

@@ -310,7 +310,7 @@ typedef enum {
} ModifyOffsetFunc deriving(Bits, Eq, FShow);
typedef enum {
SetBoundsExact, SetBoundsRounding, CRRL, CRAM
SetBoundsExact, SetBoundsRounding, CRRL, CRAM, SetDelta
} SetBoundsFunc deriving(Bits, Eq, FShow);
typedef enum {
@@ -336,6 +336,8 @@ typedef enum {
typedef union tagged {
ModifyOffsetFunc ModifyOffset;
SetBoundsFunc SetBounds;
// TODOD: Delta add type here
// SetDeltaFunc SetDelta;
SpecialRWFunc SpecialRW;
AddrSource SetAddr;
void Seal;
@@ -1068,7 +1070,7 @@ function Fmt showInst(Instruction inst);
return ret;
endfunction
function x addPc(x cap, Bit#(12) inc) provisos (Add#(f, 12, c), CHERICap::CHERICap#(x, a, b, c, d, e)) = setAddrUnsafe(cap, getAddr(cap) + signExtend(inc));
function x addPc(x cap, Bit#(12) inc) provisos (Add#(f, 12, c), CHERICap::CHERICap#(x, a, b, c, d, e, f)) = setAddrUnsafe(cap, getAddr(cap) + signExtend(inc));
`ifdef PERFORMANCE_MONITORING
typedef 8 Report_Width;