Skip to content

Commit a2c759e

Browse files
committed
Add misalignment test suite
Force a variable and a function placed at a misaligned address to trigger the all three misaligned traps. The test suite only tested the misalignment of instruction fetch and lw/sw instruction. The corresponding trap handler is called successfully to handle the trap.
1 parent e8c8ee9 commit a2c759e

File tree

6 files changed

+213
-37
lines changed

6 files changed

+213
-37
lines changed

src/emulate.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,10 @@ static uint32_t *csr_get_ptr(riscv_t *rv, uint32_t csr)
218218
return (uint32_t *) (&rv->csr_misa);
219219

220220
/* Machine Trap Handling */
221+
case CSR_MEDELEG: /* Machine Exception Delegation Register */
222+
return (uint32_t *) (&rv->csr_medeleg);
223+
case CSR_MIDELEG: /* Machine Interrupt Delegation Register */
224+
return (uint32_t *) (&rv->csr_mideleg);
221225
case CSR_MSCRATCH: /* Machine Scratch Register */
222226
return (uint32_t *) (&rv->csr_mscratch);
223227
case CSR_MEPC: /* Machine Exception Program Counter */

src/riscv_private.h

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
/* CSRs */
2626
enum {
2727
/* floating point */
28-
CSR_FFLAGS = 0x001, /* Floating-point accrued exceptions */
29-
CSR_FRM = 0x002, /* Floating-point dynamic rounding mode */
30-
CSR_FCSR = 0x003, /* Floating-point control and status register */
28+
CSR_FFLAGS = 0x001, /* Floating-point accrued exceptions */
29+
CSR_FRM = 0x002, /* Floating-point dynamic rounding mode */
30+
CSR_FCSR = 0x003, /* Floating-point control and status register */
3131

3232
/* Supervisor trap setup */
3333
CSR_SSTATUS = 0x100, /* Supervisor status register */
@@ -36,20 +36,20 @@ enum {
3636
CSR_SCOUNTEREN = 0x106, /* Supervisor counter enable */
3737

3838
/* Supervisor trap handling */
39-
CSR_SSCRATCH = 0x140, /* Supervisor register for machine trap handlers */
40-
CSR_SEPC = 0x141, /* Supervisor exception program counter */
41-
CSR_SCAUSE = 0x142, /* Supervisor trap cause */
42-
CSR_STVAL = 0x143, /* Supervisor bad address or instruction */
43-
CSR_SIP = 0x144, /* Supervisor interrupt pending */
39+
CSR_SSCRATCH = 0x140, /* Supervisor register for machine trap handlers */
40+
CSR_SEPC = 0x141, /* Supervisor exception program counter */
41+
CSR_SCAUSE = 0x142, /* Supervisor trap cause */
42+
CSR_STVAL = 0x143, /* Supervisor bad address or instruction */
43+
CSR_SIP = 0x144, /* Supervisor interrupt pending */
4444

4545
/* Supervisor protection and translation */
46-
CSR_SATP = 0x180, /* Supervisor address translation and protection */
46+
CSR_SATP = 0x180, /* Supervisor address translation and protection */
4747

4848
/* Machine information registers */
49-
CSR_MVENDORID = 0xF11, /* Vendor ID */
50-
CSR_MARCHID = 0xF12, /* Architecture ID */
51-
CSR_MIMPID = 0xF13, /* Implementation ID */
52-
CSR_MHARTID = 0xF14, /* Hardware thread ID */
49+
CSR_MVENDORID = 0xF11, /* Vendor ID */
50+
CSR_MARCHID = 0xF12, /* Architecture ID */
51+
CSR_MIMPID = 0xF13, /* Implementation ID */
52+
CSR_MHARTID = 0xF14, /* Hardware thread ID */
5353

5454
/* Machine trap setup */
5555
CSR_MSTATUS = 0x300, /* Machine status register */
@@ -61,15 +61,15 @@ enum {
6161
CSR_MCOUNTEREN = 0x306, /* Machine counter enable */
6262

6363
/* machine trap handling */
64-
CSR_MSCRATCH = 0x340, /* Scratch register for machine trap handlers */
65-
CSR_MEPC = 0x341, /* Machine exception program counter */
66-
CSR_MCAUSE = 0x342, /* Machine trap cause */
67-
CSR_MTVAL = 0x343, /* Machine bad address or instruction */
68-
CSR_MIP = 0x344, /* Machine interrupt pending */
64+
CSR_MSCRATCH = 0x340, /* Scratch register for machine trap handlers */
65+
CSR_MEPC = 0x341, /* Machine exception program counter */
66+
CSR_MCAUSE = 0x342, /* Machine trap cause */
67+
CSR_MTVAL = 0x343, /* Machine bad address or instruction */
68+
CSR_MIP = 0x344, /* Machine interrupt pending */
6969

7070
/* low words */
71-
CSR_CYCLE = 0xC00, /* Cycle counter for RDCYCLE instruction */
72-
CSR_TIME = 0xC01, /* Timer for RDTIME instruction */
71+
CSR_CYCLE = 0xC00, /* Cycle counter for RDCYCLE instruction */
72+
CSR_TIME = 0xC01, /* Timer for RDTIME instruction */
7373
CSR_INSTRET = 0xC02,
7474

7575
/* high words */
@@ -142,22 +142,22 @@ struct riscv_internal {
142142
#endif
143143

144144
/* csr registers */
145-
uint64_t csr_cycle; /* Machine cycle counter */
146-
uint32_t csr_time[2]; /* Performance counter */
147-
uint32_t csr_mstatus; /* Machine status register */
148-
uint32_t csr_mtvec; /* Machine trap-handler base address */
149-
uint32_t csr_misa; /* ISA and extensions */
150-
uint32_t csr_mtval; /* Machine bad address or instruction */
151-
uint32_t csr_mcause; /* Machine trap cause */
152-
uint32_t csr_mscratch; /* Scratch register for machine trap handler */
153-
uint32_t csr_mepc; /* Machine exception program counter */
154-
uint32_t csr_mip; /* Machine interrupt pending */
155-
uint32_t csr_mie; /* Machine interrupt enable */
156-
uint32_t csr_mideleg; /* Machine interrupt delegation register */
157-
uint32_t csr_medeleg; /* Machine exception delegation register */
158-
uint32_t csr_mvendorid; /* vendor ID */
159-
uint32_t csr_marchid; /* Architecture ID */
160-
uint32_t csr_mimpid; /* Implementation ID */
145+
uint64_t csr_cycle; /* Machine cycle counter */
146+
uint32_t csr_time[2]; /* Performance counter */
147+
uint32_t csr_mstatus; /* Machine status register */
148+
uint32_t csr_mtvec; /* Machine trap-handler base address */
149+
uint32_t csr_misa; /* ISA and extensions */
150+
uint32_t csr_mtval; /* Machine bad address or instruction */
151+
uint32_t csr_mcause; /* Machine trap cause */
152+
uint32_t csr_mscratch; /* Scratch register for machine trap handler */
153+
uint32_t csr_mepc; /* Machine exception program counter */
154+
uint32_t csr_mip; /* Machine interrupt pending */
155+
uint32_t csr_mie; /* Machine interrupt enable */
156+
uint32_t csr_mideleg; /* Machine interrupt delegation register */
157+
uint32_t csr_medeleg; /* Machine exception delegation register */
158+
uint32_t csr_mvendorid; /* vendor ID */
159+
uint32_t csr_marchid; /* Architecture ID */
160+
uint32_t csr_mimpid; /* Implementation ID */
161161
uint32_t csr_mbadaddr;
162162

163163
uint32_t csr_sstatus; /* supervisor status register */
@@ -171,7 +171,7 @@ struct riscv_internal {
171171
uint32_t csr_stval; /* supervisor trap value register */
172172
uint32_t csr_satp; /* supervisor address translation and protection */
173173

174-
uint32_t priv_mode; /* U-mode or S-mode or M-mode */
174+
uint32_t priv_mode; /* U-mode or S-mode or M-mode */
175175

176176
bool compressed; /**< current instruction is compressed or not */
177177
#if !RV32_HAS(JIT)

tests/system/alignment/Makefile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
PREFIX ?= riscv32-unknown-elf-
2+
ARCH = -march=rv32izicsr
3+
LINKER_SCRIPT = linker.ld
4+
5+
DEBUG_CFLAGS = -g
6+
CFLAGS = -c
7+
LDFLAGS = -T
8+
EXEC = misalign.elf
9+
10+
CC = $(PREFIX)gcc
11+
AS = $(PREFIX)as
12+
LD = $(PREFIX)ld
13+
OBJDUMP = $(PREFIX)objdump
14+
15+
deps = main.o misalign.o
16+
17+
all:
18+
$(CC) $(DEBUG_CLAGS) $(CFLAGS) main.c
19+
$(AS) $(DEBUG_CLAGS) $(ARCH) misalign.S -o misalign.o
20+
$(LD) $(LDFLAGS) $(LINKER_SCRIPT) -o $(EXEC) $(deps)
21+
22+
dump:
23+
$(OBJDUMP) -Ds $(EXEC) | less
24+
25+
clean:
26+
rm $(EXEC) $(deps)

tests/system/alignment/linker.ld

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
OUTPUT_ARCH( "riscv" )
2+
3+
ENTRY(_start)
4+
5+
SECTIONS
6+
{
7+
. = 0x10000;
8+
.text : { *(.text) }
9+
. = 0x8000003;
10+
.misdata : { *(.misdata) }
11+
. = 0x10000007;
12+
.mistext : { *(.mistext) }
13+
.data : { *(.data) }
14+
.bss : { *(.bss) }
15+
}

tests/system/alignment/main.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#define write_csr(reg, val) ({ asm volatile("csrw " #reg ", %0" ::"rK"(val)); })
2+
3+
#define CAUSE_MISALIGNED_INSN_FETCH (1U << 0x0)
4+
#define CAUSE_MISALIGNED_LOAD (1U << 0x4)
5+
#define CAUSE_MISALIGNED_STORE (1U << 0x6)
6+
7+
#define printstr(ptr, length) \
8+
do { \
9+
asm volatile( \
10+
"add a7, x0, 0x40;" \
11+
"add a0, x0, 0x1;" /* stdout */ \
12+
"add a1, x0, %0;" \
13+
"mv a2, %1;" /* length character */ \
14+
"ecall;" \
15+
: \
16+
: "r"(ptr), "r"(length) \
17+
: "a0", "a1", "a2", "a7"); \
18+
} while (0)
19+
20+
#define TEST_OUTPUT(msg, length) printstr(msg, length)
21+
22+
#define TEST_LOGGER(msg) \
23+
{ \
24+
char _msg[] = msg; \
25+
TEST_OUTPUT(_msg, sizeof(_msg)); \
26+
}
27+
28+
extern int *misalign_data;
29+
30+
extern void misalign_func();
31+
32+
extern void misalign_trap_handler();
33+
34+
int main()
35+
{
36+
/* init s-mode trap handler */
37+
write_csr(stvec, misalign_trap_handler);
38+
write_csr(medeleg, CAUSE_MISALIGNED_INSN_FETCH | CAUSE_MISALIGNED_LOAD |
39+
CAUSE_MISALIGNED_STORE);
40+
41+
/* misalign load */
42+
const int x = *misalign_data;
43+
/* execute the registered trap handler is considered a pass (use gdb to
44+
* track) */
45+
TEST_LOGGER("MISALIGNED LOAD TEST PASSED!\n");
46+
47+
/* misalign store */
48+
char *ptr = (char *) misalign_data;
49+
*(int *) (ptr + 3) = x + 3;
50+
/* execute the registered trap handler is considered a pass (use gdb to
51+
* track) */
52+
TEST_LOGGER("MISALIGNED STORE TEST PASSED!\n");
53+
54+
/* misalign instuction fetch */
55+
misalign_func();
56+
/* execute the registered trap handler is considered a pass (use gdb to
57+
* track) */
58+
TEST_LOGGER("MISALIGNED INSTRUCTION FETCH TEST PASSED!\n");
59+
60+
return 0;
61+
}

tests/system/alignment/misalign.S

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
CAUSE_MISALIGNED_INSN_FETCH = 0x0
2+
CAUSE_MISALIGNED_LOAD = 0x4
3+
CAUSE_MISALIGNED_STORE = 0x6
4+
5+
.section .misdata, "aw", @progbits
6+
.global misalign_data
7+
.type misalign_data, @object
8+
misalign_data:
9+
.word = 0xBAAAAAAD
10+
. = 0x8000003 # force misaligned address
11+
12+
.section .mistext, "ax", @progbits
13+
.global misalign_func
14+
.type misalign_func, @function
15+
misalign_func:
16+
. = 0x10000007 # force misaligned address
17+
addi t0, t0, 1
18+
19+
.section .text
20+
.global _start
21+
_start:
22+
call main
23+
j exit
24+
25+
# Assume three traps are delegated to supervisor,
26+
# so handle them using supervisor CSR
27+
.global misalign_trap_handler
28+
misalign_trap_handler:
29+
csrr t0, scause
30+
31+
# Check for misaligned instruction fetch
32+
li t1, CAUSE_MISALIGNED_INSN_FETCH
33+
beq t0, t1, misaligned_insn_fetch_handler
34+
35+
# Check for misaligned load
36+
li t1, CAUSE_MISALIGNED_LOAD
37+
beq t0, t1, misaligned_load_handler
38+
39+
# Check for misaligned store
40+
li t1, CAUSE_MISALIGNED_STORE
41+
beq t0, t1, misaligned_store_handler
42+
43+
# If none of the above, exit failed
44+
fail:
45+
li a0, 1
46+
j exit
47+
48+
exit:
49+
li a7, 93
50+
ecall
51+
52+
misaligned_insn_fetch_handler:
53+
# simply jump back to caller since no really handling it
54+
# since the rest of instruction are also misaligned
55+
jalr zero, ra, 0
56+
57+
misaligned_load_handler:
58+
# Handle load misalignment: skip load
59+
csrr t0, sepc
60+
addi t0, t0, 4
61+
csrw sepc, t0
62+
sret
63+
64+
misaligned_store_handler:
65+
# Handle store misalignment: skip store
66+
csrr t0, sepc
67+
addi t0, t0, 4
68+
csrw sepc, t0
69+
sret
70+

0 commit comments

Comments
 (0)