From 78112c32ee5cea7fd5a899f17f4d9363d999bdb2 Mon Sep 17 00:00:00 2001 From: Yen-Fu Chen Date: Tue, 11 Apr 2023 21:02:37 +0800 Subject: [PATCH 1/2] Improve memory read/write After analyzing the data collected during the execution of the Dhrystone benchmark, it was discovered that the primary performance bottleneck lies in memory read/write operations. To address this issue, modifications were made to the implementation of memory read/write operations, eliminating unnecessary checks and replacing slow operations with more efficient ones. Additionally, a simple memory pool was integrated. It is now possible for the user to enable misaligned memory access by launching with option "--misalign". The enhancements made to the memory I/O resulted in a significant improvement, as observed through performance results obtained by running Dhrystone. | Test | 66200d0 | improvement |Speedup| |------------+--------------+-----------------+-------| | Dhrystone | 815 DMIPS | 1245 DMIPS | +52.7%| Close #122 --- Makefile | 1 + src/emulate.c | 136 +++++++++++----------------------------- src/io.c | 76 +++++++++++------------ src/io.h | 7 +++ src/main.c | 12 +++- src/mpool.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++ src/mpool.h | 43 +++++++++++++ src/riscv.h | 3 + src/syscall.c | 8 +-- src/syscall_sdl.c | 2 +- 10 files changed, 297 insertions(+), 145 deletions(-) create mode 100644 src/mpool.c create mode 100644 src/mpool.h diff --git a/Makefile b/Makefile index 317a7df11..3bdb1192c 100644 --- a/Makefile +++ b/Makefile @@ -94,6 +94,7 @@ OBJS := \ riscv.o \ elf.o \ cache.o \ + mpool.o \ $(OBJS_EXT) \ main.o diff --git a/src/emulate.c b/src/emulate.c index b267fff67..caad4640e 100644 --- a/src/emulate.c +++ b/src/emulate.c @@ -90,6 +90,22 @@ static void rv_exception_default_handler(riscv_t *rv) RV_EXCEPTION_LIST #undef _ +/* wrap load/store and insn misaligned handler + * @mask_or_pc: mask for load/store and pc for insn misaligned handler. + * @type: type of misaligned handler + * @compress: compressed instruction or not + * @IO: whether the misaligned handler is for load/store or insn. + */ +#define RV_EXC_MISALIGN_HANDLER(mask_or_pc, type, compress, IO) \ + IIF(IO) \ + (if (!rv->io.allow_misalign && unlikely(addr & (mask_or_pc))), \ + if (unlikely(insn_is_misaligned(rv->PC)))) \ + { \ + rv->compressed = compress; \ + rv_except_##type##_misaligned(rv, IIF(IO)(addr, mask_or_pc)); \ + return false; \ + } + /* Get current time in microsecnds and update csr_time register */ static inline void update_time(riscv_t *rv) { @@ -310,11 +326,7 @@ RVOP(jal, { if (ir->rd) rv->X[ir->rd] = pc + ir->insn_len; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISALIGN_HANDLER(pc, insn, false, 0); return true; }) @@ -333,11 +345,7 @@ RVOP(jalr, { if (ir->rd) rv->X[ir->rd] = pc + ir->insn_len; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISALIGN_HANDLER(pc, insn, false, 0); return true; }) @@ -352,11 +360,7 @@ RVOP(beq, { } rv->PC += ir->imm; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISALIGN_HANDLER(pc, insn, false, 0); if (ir->branch_taken) return ir->branch_taken->impl(rv, ir->branch_taken); return true; @@ -373,11 +377,7 @@ RVOP(bne, { } rv->PC += ir->imm; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISALIGN_HANDLER(pc, insn, false, 0); if (ir->branch_taken) return ir->branch_taken->impl(rv, ir->branch_taken); return true; @@ -394,11 +394,7 @@ RVOP(blt, { } rv->PC += ir->imm; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISALIGN_HANDLER(pc, insn, false, 0); if (ir->branch_taken) return ir->branch_taken->impl(rv, ir->branch_taken); return true; @@ -415,11 +411,7 @@ RVOP(bge, { } rv->PC += ir->imm; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISALIGN_HANDLER(pc, insn, false, 0); if (ir->branch_taken) return ir->branch_taken->impl(rv, ir->branch_taken); return true; @@ -436,11 +428,7 @@ RVOP(bltu, { } rv->PC += ir->imm; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISALIGN_HANDLER(pc, insn, false, 0); if (ir->branch_taken) return ir->branch_taken->impl(rv, ir->branch_taken); return true; @@ -457,11 +445,7 @@ RVOP(bgeu, { } rv->PC += ir->imm; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISALIGN_HANDLER(pc, insn, false, 0); if (ir->branch_taken) return ir->branch_taken->impl(rv, ir->branch_taken); return true; @@ -476,22 +460,14 @@ RVOP(lb, { /* LH: Load Halfword */ RVOP(lh, { const uint32_t addr = rv->X[ir->rs1] + ir->imm; - if (unlikely(addr & 1)) { - rv->compressed = false; - rv_except_load_misaligned(rv, addr); - return false; - } + RV_EXC_MISALIGN_HANDLER(1, load, false, 1); rv->X[ir->rd] = sign_extend_h(rv->io.mem_read_s(rv, addr)); }) /* LW: Load Word */ RVOP(lw, { const uint32_t addr = rv->X[ir->rs1] + ir->imm; - if (unlikely(addr & 3)) { - rv->compressed = false; - rv_except_load_misaligned(rv, addr); - return false; - } + RV_EXC_MISALIGN_HANDLER(3, load, false, 1); rv->X[ir->rd] = rv->io.mem_read_w(rv, addr); }) @@ -501,11 +477,7 @@ RVOP(lbu, { rv->X[ir->rd] = rv->io.mem_read_b(rv, rv->X[ir->rs1] + ir->imm); }) /* LHU: Load Halfword Unsigned */ RVOP(lhu, { const uint32_t addr = rv->X[ir->rs1] + ir->imm; - if (unlikely(addr & 1)) { - rv->compressed = false; - rv_except_load_misaligned(rv, addr); - return false; - } + RV_EXC_MISALIGN_HANDLER(1, load, false, 1); rv->X[ir->rd] = rv->io.mem_read_s(rv, addr); }) @@ -515,22 +487,14 @@ RVOP(sb, { rv->io.mem_write_b(rv, rv->X[ir->rs1] + ir->imm, rv->X[ir->rs2]); }) /* SH: Store Halfword */ RVOP(sh, { const uint32_t addr = rv->X[ir->rs1] + ir->imm; - if (unlikely(addr & 1)) { - rv->compressed = false; - rv_except_store_misaligned(rv, addr); - return false; - } + RV_EXC_MISALIGN_HANDLER(1, store, false, 1); rv->io.mem_write_s(rv, addr, rv->X[ir->rs2]); }) /* SW: Store Word */ RVOP(sw, { const uint32_t addr = rv->X[ir->rs1] + ir->imm; - if (unlikely(addr & 3)) { - rv->compressed = false; - rv_except_store_misaligned(rv, addr); - return false; - } + RV_EXC_MISALIGN_HANDLER(3, store, false, 1); rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]); }) @@ -1088,11 +1052,7 @@ RVOP(caddi4spn, { rv->X[ir->rd] = rv->X[2] + (uint16_t) ir->imm; }) */ RVOP(clw, { const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm; - if (unlikely(addr & 3)) { - rv->compressed = true; - rv_except_load_misaligned(rv, addr); - return false; - } + RV_EXC_MISALIGN_HANDLER(3, load, true, 1); rv->X[ir->rd] = rv->io.mem_read_w(rv, addr); }) @@ -1103,11 +1063,7 @@ RVOP(clw, { */ RVOP(csw, { const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm; - if (unlikely(addr & 3)) { - rv->compressed = true; - rv_except_store_misaligned(rv, addr); - return false; - } + RV_EXC_MISALIGN_HANDLER(3, store, true, 1); rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]); }) @@ -1126,11 +1082,7 @@ RVOP(caddi, { rv->X[ir->rd] += (int16_t) ir->imm; }) RVOP(cjal, { rv->X[1] = rv->PC + ir->insn_len; rv->PC += ir->imm; - if (unlikely(rv->PC & 0x1)) { - rv->compressed = true; - rv_except_insn_misaligned(rv, rv->PC); - return false; - } + RV_EXC_MISALIGN_HANDLER(rv->PC, insn, true, 0); return true; }) @@ -1198,11 +1150,7 @@ RVOP(cand, { rv->X[ir->rd] = rv->X[ir->rs1] & rv->X[ir->rs2]; }) */ RVOP(cj, { rv->PC += ir->imm; - if (unlikely(rv->PC & 0x1)) { - rv->compressed = true; - rv_except_insn_misaligned(rv, rv->PC); - return false; - } + RV_EXC_MISALIGN_HANDLER(rv->PC, insn, true, 0); return true; }) @@ -1249,11 +1197,7 @@ RVOP(cslli, { rv->X[ir->rd] <<= (uint8_t) ir->imm; }) /* C.LWSP */ RVOP(clwsp, { const uint32_t addr = rv->X[rv_reg_sp] + ir->imm; - if (unlikely(addr & 3)) { - rv->compressed = true; - rv_except_load_misaligned(rv, addr); - return false; - } + RV_EXC_MISALIGN_HANDLER(3, load, true, 1); rv->X[ir->rd] = rv->io.mem_read_w(rv, addr); }) @@ -1279,11 +1223,7 @@ RVOP(cjalr, { const int32_t jump_to = rv->X[ir->rs1]; rv->X[rv_reg_ra] = rv->PC + ir->insn_len; rv->PC = jump_to; - if (unlikely(rv->PC & 0x1)) { - rv->compressed = true; - rv_except_insn_misaligned(rv, rv->PC); - return false; - } + RV_EXC_MISALIGN_HANDLER(rv->PC, insn, true, 0); return true; }) @@ -1299,11 +1239,7 @@ RVOP(cadd, { rv->X[ir->rd] = rv->X[ir->rs1] + rv->X[ir->rs2]; }) /* C.SWSP */ RVOP(cswsp, { const uint32_t addr = rv->X[2] + ir->imm; - if (unlikely(addr & 3)) { - rv->compressed = true; - rv_except_store_misaligned(rv, addr); - return false; - } + RV_EXC_MISALIGN_HANDLER(3, store, true, 1); rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]); }) #endif diff --git a/src/io.c b/src/io.c index 732c2f5b2..938d00915 100644 --- a/src/io.c +++ b/src/io.c @@ -9,14 +9,19 @@ #include #include "io.h" +#include "mpool.h" static const uint32_t mask_lo = 0xffff; static const uint32_t mask_hi = ~(0xffff); +static struct mpool *mp; + memory_t *memory_new() { - memory_t *m = malloc(sizeof(memory_t)); - memset(m->chunks, 0, sizeof(m->chunks)); + memory_t *m = calloc(1, sizeof(memory_t)); + /* Initialize the mpool size to sizeof(chunk_t) << 2, and it will extend + * automatically if needed */ + mp = mpool_create(sizeof(chunk_t) << 2, sizeof(chunk_t)); return m; } @@ -24,12 +29,7 @@ void memory_delete(memory_t *m) { if (!m) return; - - for (uint32_t i = 0; i < (sizeof(m->chunks) / sizeof(chunk_t *)); i++) { - chunk_t *c = m->chunks[i]; - if (c) - free(c); - } + mpool_destory(mp); free(m); } @@ -85,54 +85,53 @@ uint32_t memory_ifetch(memory_t *m, uint32_t addr) uint32_t memory_read_w(memory_t *m, uint32_t addr) { const uint32_t addr_lo = addr & mask_lo; - if (addr_lo <= 0xfffc) { /* test if this is within one chunk */ - chunk_t *c; - if ((c = m->chunks[addr >> 16])) - return *(const uint32_t *) (c->data + addr_lo); - return 0U; - } - uint32_t dst = 0; - memory_read(m, (uint8_t *) &dst, addr, 4); - return dst; + chunk_t *c = m->chunks[addr >> 16]; + return *(const uint32_t *) (c->data + addr_lo); } uint16_t memory_read_s(memory_t *m, uint32_t addr) { const uint32_t addr_lo = addr & mask_lo; - if (addr_lo <= 0xfffe) { /* test if this is within one chunk */ - chunk_t *c; - if ((c = m->chunks[addr >> 16])) - return *(const uint16_t *) (c->data + addr_lo); - return 0U; - } - uint16_t dst = 0; - memory_read(m, (uint8_t *) &dst, addr, 2); - return dst; + chunk_t *c = m->chunks[addr >> 16]; + return *(const uint16_t *) (c->data + addr_lo); } uint8_t memory_read_b(memory_t *m, uint32_t addr) { - chunk_t *c; - if ((c = m->chunks[addr >> 16])) - return *(c->data + (addr & 0xffff)); - return 0U; + chunk_t *c = m->chunks[addr >> 16]; + return c->data[addr & mask_lo]; } void memory_write(memory_t *m, uint32_t addr, const uint8_t *src, uint32_t size) { for (uint32_t i = 0; i < size; ++i) { - uint32_t p = addr + i; - uint32_t x = p >> 16; - chunk_t *c = m->chunks[x]; + const uint32_t addr_lo = (addr + i) & mask_lo, + addr_hi = (addr + i) >> 16; + chunk_t *c = m->chunks[addr_hi]; if (!c) { - c = malloc(sizeof(chunk_t)); - memset(c->data, 0, sizeof(c->data)); - m->chunks[x] = c; + c = mpool_calloc(mp); + m->chunks[addr_hi] = c; } - c->data[p & 0xffff] = src[i]; + c->data[addr_lo] = src[i]; } } +#define MEM_WRITE_IMPL(size, type) \ + void memory_write_##size(memory_t *m, uint32_t addr, const uint8_t *src) \ + { \ + const uint32_t addr_lo = addr & mask_lo, addr_hi = addr >> 16; \ + chunk_t *c = m->chunks[addr_hi]; \ + if (unlikely(!c)) { \ + c = mpool_calloc(mp); \ + m->chunks[addr_hi] = c; \ + } \ + *(type *) (c->data + addr_lo) = *(const type *) src; \ + } + +MEM_WRITE_IMPL(w, uint32_t); +MEM_WRITE_IMPL(s, uint16_t); +MEM_WRITE_IMPL(b, uint8_t); + void memory_fill(memory_t *m, uint32_t addr, uint32_t size, uint8_t val) { for (uint32_t i = 0; i < size; ++i) { @@ -140,8 +139,7 @@ void memory_fill(memory_t *m, uint32_t addr, uint32_t size, uint8_t val) uint32_t x = p >> 16; chunk_t *c = m->chunks[x]; if (!c) { - c = malloc(sizeof(chunk_t)); - memset(c->data, 0, sizeof(c->data)); + c = mpool_calloc(mp); m->chunks[x] = c; } c->data[p & 0xffff] = val; diff --git a/src/io.h b/src/io.h index 1793ce0dc..79f2dc495 100644 --- a/src/io.h +++ b/src/io.h @@ -43,4 +43,11 @@ void memory_write(memory_t *m, uint32_t addr, const uint8_t *src, uint32_t size); + +void memory_write_w(memory_t *m, uint32_t addr, const uint8_t *src); + +void memory_write_s(memory_t *m, uint32_t addr, const uint8_t *src); + +void memory_write_b(memory_t *m, uint32_t addr, const uint8_t *src); + void memory_fill(memory_t *m, uint32_t addr, uint32_t size, uint8_t val); diff --git a/src/main.c b/src/main.c index 4c6d7e488..6a615498c 100644 --- a/src/main.c +++ b/src/main.c @@ -25,6 +25,9 @@ static char *signature_out_file; /* target executable */ static const char *opt_prog_name = "a.out"; +/* enable misaligned memory access */ +static bool opt_misaligned = false; + #define MEMIO(op) on_mem_##op #define IO_HANDLER_IMPL(type, op, RW) \ static IIF(RW)( \ @@ -34,7 +37,7 @@ static const char *opt_prog_name = "a.out"; { \ state_t *s = rv_userdata(rv); \ IIF(RW) \ - (memory_write(s->mem, addr, (uint8_t *) &data, sizeof(data)), \ + (memory_##op(s->mem, addr, (uint8_t *) &data), \ return memory_##op(s->mem, addr)); \ } @@ -123,6 +126,12 @@ static bool parse_args(int argc, char **args) signature_out_file = args[++i]; continue; } + + if (!strcmp(arg, "--misalign")) { + opt_misaligned = true; + continue; + } + /* otherwise, error */ fprintf(stderr, "Unknown argument '%s'\n", arg); return false; @@ -192,6 +201,7 @@ int main(int argc, char **args) /* system */ .on_ecall = ecall_handler, .on_ebreak = ebreak_handler, + .allow_misalign = opt_misaligned, }; state_t *state = state_new(); diff --git a/src/mpool.c b/src/mpool.c new file mode 100644 index 000000000..9589a5c3c --- /dev/null +++ b/src/mpool.c @@ -0,0 +1,154 @@ +/* + * rv32emu is freely redistributable under the MIT License. See the file + * "LICENSE" for information on usage and redistribution of this file. + */ +#include +#include +#if !defined(_WIN32) +#define USE_MMAP 1 +#include +#include +#endif + +#include "mpool.h" + +typedef struct memchunk { + struct memchunk *next; +} memchunk_t; + +typedef struct area { + char *mapped; + struct area *next; +} area_t; + +typedef struct mpool { + size_t chunk_count; + size_t page_count; + size_t chunk_size; + struct memchunk *free_chunk_head; + area_t area; +} mpool_t; + +static void *mem_arena(size_t sz) +{ +#if defined(USE_MMAP) + void *p = + mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + if (p == MAP_FAILED) + return NULL; +#else + void *p = malloc(sz); + if (!p) + return NULL; +#endif + return p; +} + +mpool_t *mpool_create(size_t pool_size, size_t chunk_size) +{ + mpool_t *new_mp = malloc(sizeof(mpool_t)); + if (!new_mp) + return NULL; + + new_mp->area.next = NULL; + size_t pgsz = getpagesize(); + if (pool_size < chunk_size + sizeof(memchunk_t)) + pool_size += sizeof(memchunk_t); + size_t page_count = (pool_size + pgsz - 1) / pgsz; + char *p = mem_arena(page_count * pgsz); + if (!p) { + free(new_mp); + return NULL; + } + + new_mp->area.mapped = p; + new_mp->page_count = page_count; + new_mp->chunk_count = pool_size / (sizeof(memchunk_t) + chunk_size); + new_mp->chunk_size = chunk_size; + new_mp->free_chunk_head = (memchunk_t *) p; + memchunk_t *cur = new_mp->free_chunk_head; + for (size_t i = 0; i < new_mp->chunk_count - 1; i++) { + cur->next = + (memchunk_t *) ((char *) cur + (sizeof(memchunk_t) + chunk_size)); + cur = cur->next; + } + cur->next = NULL; + return new_mp; +} + +static void *mpool_extend(mpool_t *mp) +{ + size_t pool_size = mp->page_count * getpagesize(); + char *p = mem_arena(pool_size); + if (!p) + return NULL; + area_t *new_area = malloc(sizeof(area_t)); + new_area->mapped = p; + new_area->next = NULL; + size_t chunk_count = pool_size / (sizeof(memchunk_t) + mp->chunk_size); + mp->free_chunk_head = (memchunk_t *) p; + memchunk_t *cur = mp->free_chunk_head; + for (size_t i = 0; i < chunk_count - 1; i++) { + cur->next = (memchunk_t *) ((char *) cur + + (sizeof(memchunk_t) + mp->chunk_size)); + cur = cur->next; + } + mp->chunk_count += chunk_count; + /* insert new mapped */ + area_t *cur_area = &mp->area; + while (cur_area->next) { + cur_area = cur_area->next; + } + cur_area->next = new_area; + return p; +} + +void *mpool_alloc(mpool_t *mp) +{ + if (!mp->chunk_count && !(mpool_extend(mp))) + return NULL; + char *ptr = (char *) mp->free_chunk_head + sizeof(memchunk_t); + mp->free_chunk_head = mp->free_chunk_head->next; + mp->chunk_count--; + return ptr; +} + +void *mpool_calloc(mpool_t *mp) +{ + if (!mp->chunk_count && !(mpool_extend(mp))) + return NULL; + char *ptr = (char *) mp->free_chunk_head + sizeof(memchunk_t); + mp->free_chunk_head = mp->free_chunk_head->next; + mp->chunk_count--; + memset(ptr, 0, mp->chunk_size); + return ptr; +} + +void mpool_free(mpool_t *mp, void *target) +{ + memchunk_t *ptr = (memchunk_t *) ((char *) target - sizeof(memchunk_t)); + ptr->next = mp->free_chunk_head; + mp->free_chunk_head = ptr; + mp->chunk_count++; +} + +void mpool_destory(mpool_t *mp) +{ +#if defined(USE_MMAP) + size_t mem_size = mp->page_count * getpagesize(); + area_t *cur = &mp->area, *tmp = NULL; + while (cur) { + tmp = cur; + cur = cur->next; + munmap(tmp->mapped, mem_size); + } +#else + area_t *cur = &mp->area, *tmp = NULL; + while (cur) { + tmp = cur; + cur = cur->next; + free(tmp->mapped); + } +#endif + free(mp); +} \ No newline at end of file diff --git a/src/mpool.h b/src/mpool.h new file mode 100644 index 000000000..8f8b2a157 --- /dev/null +++ b/src/mpool.h @@ -0,0 +1,43 @@ +/* + * rv32emu is freely redistributable under the MIT License. See the file + * "LICENSE" for information on usage and redistribution of this file. + */ +#pragma once + +#include + +struct mpool; + +/** + * mpool_create - create a new memory pool + * @pool_size: the size of memory pool + * @chunk_size: the size of memory chunk, pool would be divided into several + * chunks + */ +struct mpool *mpool_create(size_t pool_size, size_t chunk_size); + +/** + * mpool_alloc - allocate a memory chunk from target memory pool + * @mp: a pointer points to the target memory pool + */ +void *mpool_alloc(struct mpool *mp); + +/** + * mpool_calloc - allocate a memory chunk from target memory pool + * @mp: a pointer points to the target memory pool + */ +void *mpool_calloc(struct mpool *mp); + +/** + * mpool_calloc - allocate a memory chunk from target memory pool and set it to + * zero + * @mp: a pointer points to target memory pool + * @target: a pointer points to the target memory chunk + */ +void mpool_free(struct mpool *mp, void *target); + +/** + * mpool_destory - destory a memory pool + * @mp: a pointer points to the target memory pool + */ +void mpool_destory(struct mpool *mp); \ No newline at end of file diff --git a/src/riscv.h b/src/riscv.h index cb96847d8..271bdc242 100644 --- a/src/riscv.h +++ b/src/riscv.h @@ -107,6 +107,9 @@ typedef struct { /* system */ riscv_on_ecall on_ecall; riscv_on_ebreak on_ebreak; + + /* enable misaligned memory access */ + bool allow_misalign; } riscv_io_t; /* create a RISC-V emulator */ diff --git a/src/syscall.c b/src/syscall.c index 166f2899f..bdcd7a139 100644 --- a/src/syscall.c +++ b/src/syscall.c @@ -142,8 +142,8 @@ static void syscall_gettimeofday(riscv_t *rv) if (tv) { struct timeval tv_s; rv_gettimeofday(&tv_s); - memory_write(s->mem, tv + 0, (const uint8_t *) &tv_s.tv_sec, 4); - memory_write(s->mem, tv + 8, (const uint8_t *) &tv_s.tv_usec, 4); + memory_write_w(s->mem, tv + 0, (const uint8_t *) &tv_s.tv_sec); + memory_write_w(s->mem, tv + 8, (const uint8_t *) &tv_s.tv_usec); } if (tz) { @@ -176,8 +176,8 @@ static void syscall_clock_gettime(riscv_t *rv) if (tp) { struct timespec tp_s; rv_clock_gettime(&tp_s); - memory_write(s->mem, tp + 0, (const uint8_t *) &tp_s.tv_sec, 4); - memory_write(s->mem, tp + 8, (const uint8_t *) &tp_s.tv_nsec, 4); + memory_write_w(s->mem, tp + 0, (const uint8_t *) &tp_s.tv_sec); + memory_write_w(s->mem, tp + 8, (const uint8_t *) &tp_s.tv_nsec); } /* success */ diff --git a/src/syscall_sdl.c b/src/syscall_sdl.c index 1fe1648d5..95fdc79a3 100644 --- a/src/syscall_sdl.c +++ b/src/syscall_sdl.c @@ -110,7 +110,7 @@ static void event_push(riscv_t *rv, event_t event) uint32_t count; memory_read(s->mem, (void *) &count, event_count, sizeof(uint32_t)); count += 1; - memory_write(s->mem, event_count, (void *) &count, sizeof(uint32_t)); + memory_write_w(s->mem, event_count, (void *) &count); } static inline uint32_t round_pow2(uint32_t x) From 0771e4ebb5ffe0c81eb8c4dbdba86ab8f2902361 Mon Sep 17 00:00:00 2001 From: Yen-Fu Chen Date: Tue, 11 Apr 2023 22:04:22 +0800 Subject: [PATCH 2/2] Add misaligned memory access test item --- .github/workflows/main.yml | 1 + Makefile | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 059835f62..53671a1c9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,6 +17,7 @@ jobs: run: | make check make tests + make misalign - name: diverse configurations run: | make distclean ENABLE_EXT_C=0 check diff --git a/Makefile b/Makefile index 3bdb1192c..7763169f8 100644 --- a/Makefile +++ b/Makefile @@ -133,6 +133,15 @@ check: $(BIN) fi; \ ) +EXPECTED_aes = Dec 15 2022 16:35:12 Test results AES-128 ECB encryption: PASSED! AES-128 ECB decryption: PASSED! AES-128 CBC encryption: PASSED! AES-128 CBC decryption: PASSED! AES-128 CFB encryption: PASSED! AES-128 CFB decryption: PASSED! AES-128 OFB encryption: PASSED! AES-128 OFB decryption: PASSED! AES-128 CTR encryption: PASSED! AES-128 CTR decryption: PASSED! AES-128 XTS encryption: PASSED! AES-128 XTS decryption: PASSED! AES-128 validate CMAC : PASSED! AES-128 Poly-1305 mac : PASSED! AES-128 GCM encryption: PASSED! AES-128 GCM decryption: PASSED! AES-128 CCM encryption: PASSED! AES-128 CCM decryption: PASSED! AES-128 OCB encryption: PASSED! AES-128 OCB decryption: PASSED! AES-128 SIV encryption: PASSED! AES-128 SIV decryption: PASSED! AES-128 GCMSIV encrypt: PASSED! AES-128 GCMSIV decrypt: PASSED! AES-128 EAX encryption: PASSED! AES-128 EAX decryption: PASSED! AES-128 key wrapping : PASSED! AES-128 key unwrapping: PASSED! AES-128 FF1 encryption: PASSED! AES-128 FPE decryption: PASSED! +-> Let's do some extra tests AES-128 OCB encryption: PASSED! AES-128 OCB decryption: PASSED! AES-128 GCMSIV encrypt: PASSED! AES-128 GCMSIV decrypt: PASSED! AES-128 GCMSIV encrypt: PASSED! AES-128 GCMSIV decrypt: PASSED! AES-128 SIV encryption: PASSED! AES-128 SIV decryption: PASSED! AES-128 SIV encryption: PASSED! AES-128 SIV decryption: PASSED! AES-128 EAX encryption: PASSED! AES-128 EAX decryption: PASSED! AES-128 EAX encryption: PASSED! AES-128 EAX decryption: PASSED! AES-128 Poly-1305 mac : PASSED! inferior exit code 0 +misalign: $(BIN) + $(Q)$(PRINTF) "Running aes.elf ... "; +ifeq ($(shell $(BIN) --misalign $(OUT)/aes.elf | uniq), $(EXPECTED_aes)) + $(Q)$(call notice, [OK]); +else + $(Q)$(PRINTF) "Failed.\n"; +endif + include mk/external.mk # Non-trivial demonstration programs