Skip to content

Commit

Permalink
feat(mmio): add memory map reg support
Browse files Browse the repository at this point in the history
  • Loading branch information
cz4e committed Nov 20, 2024
1 parent b9507fb commit a080180
Show file tree
Hide file tree
Showing 14 changed files with 142 additions and 18 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ CFLAGS += -D__ISA__=$(ISA)

ifdef CONFIG_ENABLE_CONFIG_MMIO_SPACE
CFLAGS += -D__MMIO_SPECE_RANGE__=$(call remove_quote,$(CONFIG_MMIO_SPACE_RANGE))
CFLAGS += -D__L1DCACHECTL_SPACE_RANGE__=$(call remove_quote,$(CONFIG_L1DCACHECTL_SPACE_RANGE))
CFLAGS += -D__L3CACHECTL_SPACE_RANGE__=$(call remove_quote,$(CONFIG_L3CACHECTL_SPACE_RANGE))
endif

# CFLAGS += -g
Expand Down
2 changes: 2 additions & 0 deletions configs/riscv64-dual-xs-ref_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ CONFIG_USE_MMAP=y
# CONFIG_MEM_RANDOM is not set
CONFIG_ENABLE_CONFIG_MMIO_SPACE=y
CONFIG_MMIO_SPACE_RANGE="0x0, 0x7FFFFFFF"
CONFIG_L1DCACHECTL_SPACE_RANGE="0x38022000,0x3802207F"
CONFIG_L3CACHECTL_SPACE_RANGE="0x39000000,0x39000FFF"
# end of Memory Configuration

CONFIG_DEVICE=y
Expand Down
2 changes: 2 additions & 0 deletions configs/riscv64-xs-cpt_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ CONFIG_USE_MMAP=y
CONFIG_MEM_COMPRESS=y
CONFIG_ENABLE_CONFIG_MMIO_SPACE=y
CONFIG_MMIO_SPACE_RANGE="0x0, 0x7FFFFFFF"
CONFIG_L1DCACHECTL_SPACE_RANGE="0x38022000,0x3802207F"
CONFIG_L3CACHECTL_SPACE_RANGE="0x39000000,0x39000FFF"
# end of Memory Configuration

CONFIG_DEVICE=y
Expand Down
2 changes: 2 additions & 0 deletions configs/riscv64-xs-diff-spike_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ CONFIG_USE_MMAP=y
CONFIG_MEM_COMPRESS=y
CONFIG_ENABLE_CONFIG_MMIO_SPACE=y
CONFIG_MMIO_SPACE_RANGE="0x0, 0x7FFFFFFF"
CONFIG_L1DCACHECTL_SPACE_RANGE="0x38022000,0x3802207F"
CONFIG_L3CACHECTL_SPACE_RANGE="0x39000000,0x39000FFF"
# end of Memory Configuration

CONFIG_DEVICE=y
Expand Down
2 changes: 2 additions & 0 deletions configs/riscv64-xs-ref_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ CONFIG_USE_MMAP=y
# CONFIG_MEM_RANDOM is not set
CONFIG_ENABLE_CONFIG_MMIO_SPACE=y
CONFIG_MMIO_SPACE_RANGE="0x0, 0x7FFFFFFF"
CONFIG_L1DCACHECTL_SPACE_RANGE="0x38022000,0x3802207F"
CONFIG_L3CACHECTL_SPACE_RANGE="0x39000000,0x39000FFF"
# end of Memory Configuration

CONFIG_DEVICE=y
Expand Down
2 changes: 2 additions & 0 deletions configs/riscv64-xs_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ CONFIG_USE_MMAP=y
# CONFIG_MEM_COMPRESS is not set
CONFIG_ENABLE_CONFIG_MMIO_SPACE=y
CONFIG_MMIO_SPACE_RANGE="0x0, 0x7FFFFFFF"
CONFIG_L1DCACHECTL_SPACE_RANGE="0x38022000,0x3802207F"
CONFIG_L3CACHECTL_SPACE_RANGE="0x39000000,0x39000FFF"
# end of Memory Configuration

CONFIG_DEVICE=y
Expand Down
3 changes: 3 additions & 0 deletions include/device/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ void add_pio_map(const char *name, ioaddr_t addr,
void add_mmio_map(const char *name, paddr_t addr,
void *space, uint32_t len, io_callback_t callback);

void add_mmreg_map(const char *name, paddr_t addr,
void *space, uint32_t len, io_callback_t callback);

word_t map_read(paddr_t addr, int len, IOMap *map);
void map_write(paddr_t addr, int len, word_t data, IOMap *map);

Expand Down
4 changes: 4 additions & 0 deletions include/device/mmio.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
#include <common.h>

bool mmio_is_real_device(paddr_t addr);
bool mmio_is_real_mmreg(paddr_t addr);
word_t mmio_read(paddr_t addr, int len);
void mmio_write(paddr_t addr, int len, word_t data);

void init_l1dcachectl();
void init_l3cachectl();

#endif
45 changes: 33 additions & 12 deletions src/device/io/mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@

#include <device/map.h>

#define NR_MAP 16
#define NR_MMIO_MAP 16
#define NR_MMREG_MAP 32

static IOMap maps[NR_MAP] = {};
static int nr_map = 0;
static IOMap mmio_maps[NR_MMIO_MAP] = {};
static int nr_mmio_map = 0;

static IOMap mmreg_maps[NR_MMREG_MAP] = {};
static int nr_mmreg_map = 0;

#ifdef CONFIG_ENABLE_CONFIG_MMIO_SPACE

Expand All @@ -29,7 +33,7 @@ static_assert(MMIO_SPEC_NUM % 2 == 0, "The address space of mmio needs to be spe

#endif // CONFIG_ENABLE_CONFIG_MMIO_SPACE

static inline IOMap* fetch_mmio_map(paddr_t addr) {
static inline IOMap* fetch_mm_map(IOMap* maps, int nr_map, paddr_t addr) {
int mapid = find_mapid_by_addr(maps, nr_map, addr);
return (mapid == -1 ? NULL : &maps[mapid]);
}
Expand All @@ -44,37 +48,54 @@ bool is_in_mmio(paddr_t addr) {
}
return false;
#else
int mapid = find_mapid_by_addr(maps, nr_map, addr);
int mapid = find_mapid_by_addr(mmio_maps, nr_mmio_map, addr);
return (mapid == -1 ? false : true);
#endif // CONFIG_ENABLE_CONFIG_MMIO_SPACE

}

/* device interface */
void add_mmio_map(const char *name, paddr_t addr, void *space, uint32_t len, io_callback_t callback) {
assert(nr_map < NR_MAP);
maps[nr_map] = (IOMap){ .name = name, .low = addr, .high = addr + len - 1,
assert(nr_mmio_map < NR_MMIO_MAP);
mmio_maps[nr_mmio_map] = (IOMap){ .name = name, .low = addr, .high = addr + len - 1,
.space = space, .callback = callback };
// Log("Add mmio map '%s' at [" FMT_PADDR ", " FMT_PADDR "]",
// maps[nr_map].name, maps[nr_map].low, maps[nr_map].high);
// fflush(stdout);

nr_map ++;
nr_mmio_map ++;
}

void add_mmreg_map(const char *name, paddr_t addr, void *space, uint32_t len, io_callback_t callback) {
assert(nr_mmreg_map < NR_MMREG_MAP);
printf("add memory map reg: 0x%lx\n", addr);
mmreg_maps[nr_mmreg_map] = (IOMap){ .name = name, .low = addr, .high = addr + len - 1,
.space = space, .callback = callback };
nr_mmreg_map ++;
}

bool mmio_is_real_device(paddr_t addr) {
IOMap *map = fetch_mmio_map(addr);
IOMap *map = fetch_mm_map(mmio_maps, nr_mmio_map, addr);
return map != NULL && addr <= map->high && addr >= map->low;
}

bool mmio_is_real_mmreg(paddr_t addr) {
IOMap *map = fetch_mm_map(mmreg_maps, nr_mmreg_map, addr);
return map != NULL && addr <= map->high && addr >= map->low;
}


/* bus interface */
__attribute__((noinline))
word_t mmio_read(paddr_t addr, int len) {
return map_read(addr, len, fetch_mmio_map(addr));
IOMap* maps = mmio_is_real_device(addr) ? mmio_maps : mmreg_maps;
int nr_maps = mmio_is_real_device(addr) ? nr_mmio_map : nr_mmreg_map;
return map_read(addr, len, fetch_mm_map(maps, nr_maps, addr));
}

__attribute__((noinline))
void mmio_write(paddr_t addr, int len, word_t data) {
map_write(addr, len, data, fetch_mmio_map(addr));
}
IOMap* maps = mmio_is_real_device(addr) ? mmio_maps : mmreg_maps;
int nr_maps = mmio_is_real_device(addr) ? nr_mmio_map : nr_mmreg_map;
map_write(addr, len, data, fetch_mm_map(maps, nr_maps, addr));
}
68 changes: 68 additions & 0 deletions src/device/io/mmreg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/***************************************************************************************
* Copyright (c) 2014-2021 Zihao Yu, Nanjing University
*
* NEMU is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/
#include <common.h>
#include <device/map.h>

#ifdef CONFIG_ENABLE_CONFIG_MMIO_SPACE

// L1 DCache Ctl
static const uint64_t l1dcachectl_space_bound[] = {__L1DCACHECTL_SPACE_RANGE__};
#define L1DCACHECTL_SPEC_NUM (sizeof(l1dcachectl_space_bound) / sizeof(uint64_t))
#define L1DCACHECTL_SPEC_PAIR_NUM (L1DCACHECTL_SPEC_NUM / 2)
static_assert(L1DCACHECTL_SPEC_NUM % 2 == 0, "The address space of l1dcachectl needs to be spaceified in pairs.");

static void l1dcachectl_io_handler(uint32_t offset, int len, bool is_write) {
// nothing to return here
return ;
}

void init_l1dcachectl() {
uint32_t space_size = l1dcachectl_space_bound[1] - l1dcachectl_space_bound[0] + 1;
uint32_t *base_addr = (uint32_t *)new_space(space_size);

add_mmreg_map(
"L1DCacheCtl",
l1dcachectl_space_bound[0],
base_addr,
space_size,
l1dcachectl_io_handler
);
}

// L3 Cache Ctl
static const uint64_t l3cachectl_space_bound[] = {__L3CACHECTL_SPACE_RANGE__};
#define L3CACHECTL_SPEC_NUM (sizeof(l3cachectl_space_bound) / sizeof(uint64_t))
#define L3CACHECTL_SPEC_PAIR_NUM (L3CACHECTL_SPEC_NUM / 2)
static_assert(L3CACHECTL_SPEC_NUM % 2 == 0, "The address space of l3cachectl needs to be spaceified in pairs.");

static void l3cachectl_io_handler(uint32_t offset, int len, bool is_write) {
// nothing to return here
return ;
}

void init_l3cachectl() {
uint32_t space_size = l3cachectl_space_bound[1] - l3cachectl_space_bound[0] + 1;
uint32_t *base_addr = (uint32_t *)new_space(space_size);

add_mmreg_map(
"L3CacheCtl",
l3cachectl_space_bound[0],
base_addr,
space_size,
l3cachectl_io_handler
);
}

#endif // CONFIG_ENABLE_CONFIG_MMIO_SPACE
8 changes: 7 additions & 1 deletion src/isa/riscv64/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

#include <isa.h>
#include <memory/paddr.h>
#include <utils.h>
#include <device/map.h>
#include <memory/sparseram.h>
#include "local-include/csr.h"

Expand All @@ -37,6 +39,8 @@ void init_trigger();
void init_clint();
#endif
void init_device();
void init_l1dcachectl();
void init_l3cachectl();

#define CSR_ZERO_INIT(name, addr) name->val = 0;

Expand Down Expand Up @@ -180,7 +184,7 @@ void init_isa() {
minstret->val = 0;

#ifdef CONFIG_RV_CSR_MCOUNTINHIBIT
mcountinhibit->val = 0;
mcountinhibit->val = 0;
#endif // CONFIG_RV_CSR_MCOUNTINHIBIT

// All hpm counters are read-only zero in NEMU
Expand Down Expand Up @@ -229,6 +233,8 @@ void init_isa() {

if (!is_second_call) {
IFDEF(CONFIG_SHARE, init_device());
init_l1dcachectl();
init_l3cachectl();
}

#ifndef CONFIG_SHARE
Expand Down
10 changes: 10 additions & 0 deletions src/memory/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,14 @@ config MMIO_SPACE_RANGE
This will specify the MMIO address space area as [0x0, 0x7FFFFFFF] and [0x100000000, 0x100001000].
Specifying the MMIO address space is not the same as specifying the peripherals, this is just to ensure PMA for RISC-V.

config L1DCACHECTL_SPACE_RANGE
string "L1 DCache controller address space range"
default "0x38022000, 0x3802207F"
depends on ENABLE_CONFIG_MMIO_SPACE

config L3CACHECTL_SPACE_RANGE
string "L3Cache controller address space range"
default "0x39000000, 0x39000FFF"
depends on ENABLE_CONFIG_MMIO_SPACE

endmenu #MEMORY
8 changes: 4 additions & 4 deletions src/memory/paddr.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ word_t paddr_read(paddr_t addr, int len, int type, int trap_type, int mode, vadd
// check if the address is misaligned
isa_mmio_misalign_data_addr_check(addr, vaddr, len, MEM_TYPE_READ, cross_page_load);
#ifdef CONFIG_ENABLE_CONFIG_MMIO_SPACE
if (!mmio_is_real_device(addr)) {
if (!mmio_is_real_device(addr) && !mmio_is_real_mmreg(addr)) {
raise_read_access_fault(trap_type, vaddr);
return 0;
}
Expand All @@ -270,7 +270,7 @@ word_t paddr_read(paddr_t addr, int len, int type, int trap_type, int mode, vadd
// check if the address is misaligned
isa_mmio_misalign_data_addr_check(addr, vaddr, len, MEM_TYPE_READ, cross_page_load);
#ifdef CONFIG_ENABLE_CONFIG_MMIO_SPACE
if (!mmio_is_real_device(addr)) {
if (!mmio_is_real_device(addr) && !mmio_is_real_mmreg(addr)) {
raise_read_access_fault(trap_type, vaddr);
return 0;
}
Expand Down Expand Up @@ -367,7 +367,7 @@ void paddr_write(paddr_t addr, int len, word_t data, int mode, vaddr_t vaddr) {
// check if the address is misaligned
isa_mmio_misalign_data_addr_check(addr, vaddr, len, MEM_TYPE_WRITE, cross_page_store);
#ifdef CONFIG_ENABLE_CONFIG_MMIO_SPACE
if (!mmio_is_real_device(addr)) {
if (!mmio_is_real_device(addr) && !mmio_is_real_mmreg(addr)) {
raise_access_fault(EX_SAF, vaddr);
return;
}
Expand All @@ -391,7 +391,7 @@ void paddr_write(paddr_t addr, int len, word_t data, int mode, vaddr_t vaddr) {
// check if the address is misaligned
isa_mmio_misalign_data_addr_check(addr, vaddr, len, MEM_TYPE_WRITE, cross_page_store);
#ifdef CONFIG_ENABLE_CONFIG_MMIO_SPACE
if (!mmio_is_real_device(addr)) {
if (!mmio_is_real_device(addr) && !mmio_is_real_mmreg(addr)) {
raise_access_fault(EX_SAF, vaddr);
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/monitor/monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ static inline int parse_args(int argc, char *argv[]) {
case 'M':
mem_dump_file = optarg;
break;
case 'A':
case 'A':
#ifdef CONFIG_MEMORY_REGION_ANALYSIS
Log("Set mem analysis log path %s", optarg);
memory_region_record_file = optarg;
Expand Down

0 comments on commit a080180

Please sign in to comment.