Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preliminary SMP support #46

Merged
merged 11 commits into from
Jul 10, 2024
11 changes: 9 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ OBJS := \
plic.o \
uart.o \
main.o \
clint.o \
$(OBJS_EXTRA)

deps := $(OBJS:%.o=.%.o.d)
Expand All @@ -67,7 +68,13 @@ DTC ?= dtc
# Reference: https://stackoverflow.com/questions/40886386
E :=
S := $E $E
minimal.dtb: minimal.dts

SMP ?= 1
.PHONY: riscv-harts.dtsi
riscv-harts.dtsi:
$(Q)python3 scripts/gen-hart-dts.py $@ $(SMP)

minimal.dtb: minimal.dts riscv-harts.dtsi
$(VECHO) " DTC\t$@\n"
$(Q)$(CC) -nostdinc -E -P -x assembler-with-cpp -undef \
$(subst ^,$S,$(filter -D^SEMU_FEATURE_%, $(subst -D$(S)SEMU_FEATURE,-D^SEMU_FEATURE,$(CFLAGS)))) $< \
Expand All @@ -82,7 +89,7 @@ ext4.img:

check: $(BIN) minimal.dtb $(KERNEL_DATA) $(INITRD_DATA) $(DISKIMG_FILE)
@$(call notice, Ready to launch Linux kernel. Please be patient.)
$(Q)./$(BIN) -k $(KERNEL_DATA) -b minimal.dtb -i $(INITRD_DATA) $(OPTS)
$(Q)./$(BIN) -k $(KERNEL_DATA) -c $(SMP) -b minimal.dtb -i $(INITRD_DATA) $(OPTS)

build-image:
scripts/build-image.sh
Expand Down
95 changes: 95 additions & 0 deletions clint.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include <stdint.h>
#include "device.h"
#include "riscv.h"
#include "riscv_private.h"

void clint_update_interrupts(hart_t *hart, clint_state_t *clint)
{
if (clint->mtime > clint->mtimecmp[hart->mhartid])
hart->sip |= RV_INT_STI_BIT;
else
hart->sip &= ~RV_INT_STI_BIT;

if (clint->msip[hart->mhartid]) {
hart->sip |= RV_INT_SSI_BIT;
} else
hart->sip &= ~RV_INT_SSI_BIT;
}

static bool clint_reg_read(clint_state_t *clint, uint32_t addr, uint32_t *value)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specify const qualifier when possible. i.e., const clint_state_t *clint.

{
if (addr < 0x4000) {
*value = clint->msip[addr >> 2];
return true;
}

if (addr < 0xBFF8) {
addr -= 0x4000;
*value =
(uint32_t) (clint->mtimecmp[addr >> 3] >> (32 & -!!(addr & 0b100)));
return true;
}

if (addr < 0xBFFF) {
*value = clint->mtime >> (32 & -!!(addr & 0b100));
return true;
}
return false;
}

static bool clint_reg_write(clint_state_t *clint, uint32_t addr, uint32_t value)
{
if (addr < 0x4000) {
clint->msip[addr >> 2] = value;
return true;
}

if (addr < 0xBFF8) {
addr -= 0x4000;
int32_t upper = clint->mtimecmp[addr >> 3] >> 32;
int32_t lowwer = clint->mtimecmp[addr >> 3];
if (addr & 0b100)
upper = value;
else
lowwer = value;

clint->mtimecmp[addr >> 3] = (uint64_t) upper << 32 | lowwer;
return true;
}

if (addr < 0xBFFF) {
int32_t upper = clint->mtime >> 32;
int32_t lowwer = clint->mtime;
if (addr & 0b100)
upper = value;
else
lowwer = value;

clint->mtime = (uint64_t) upper << 32 | lowwer;
return true;
}
return false;
}

void clint_read(hart_t *vm,
clint_state_t *clint,
uint32_t addr,
uint8_t width,
uint32_t *value)
{
if (!clint_reg_read(clint, addr, value))
vm_set_exception(vm, RV_EXC_LOAD_FAULT, vm->exc_val);
*value = (*value) >> (RV_MEM_SW - width);
return;
}

void clint_write(hart_t *vm,
clint_state_t *clint,
uint32_t addr,
uint8_t width,
uint32_t value)
{
if (!clint_reg_write(clint, addr, value >> (RV_MEM_SW - width)))
vm_set_exception(vm, RV_EXC_STORE_FAULT, vm->exc_val);
return;
}
2 changes: 1 addition & 1 deletion configs/linux.config
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ CONFIG_ARCH_RV32I=y
# CONFIG_CMODEL_MEDLOW is not set
CONFIG_CMODEL_MEDANY=y
CONFIG_MODULE_SECTIONS=y
# CONFIG_SMP is not set
CONFIG_SMP=y
CONFIG_TUNE_GENERIC=y
# CONFIG_RISCV_ISA_C is not set
CONFIG_TOOLCHAIN_HAS_ZICBOM=y
Expand Down
47 changes: 33 additions & 14 deletions device.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
#define DTB_SIZE (1 * 1024 * 1024)
#define INITRD_SIZE (8 * 1024 * 1024)

void ram_read(vm_t *core,
void ram_read(hart_t *core,
uint32_t *mem,
const uint32_t addr,
const uint8_t width,
uint32_t *value);

void ram_write(vm_t *core,
void ram_write(hart_t *core,
uint32_t *mem,
const uint32_t addr,
const uint8_t width,
Expand All @@ -25,19 +25,19 @@ void ram_write(vm_t *core,

typedef struct {
uint32_t masked;
uint32_t ip;
uint32_t ie;
uint32_t ip; /* support 32 interrupt sources only */
uint32_t ie[32]; /* support 32 sources to 32 contexts only */
/* state of input interrupt lines (level-triggered), set by environment */
uint32_t active;
} plic_state_t;

void plic_update_interrupts(vm_t *core, plic_state_t *plic);
void plic_read(vm_t *core,
void plic_update_interrupts(vm_t *vm, plic_state_t *plic);
void plic_read(hart_t *core,
plic_state_t *plic,
uint32_t addr,
uint8_t width,
uint32_t *value);
void plic_write(vm_t *core,
void plic_write(hart_t *core,
plic_state_t *plic,
uint32_t addr,
uint8_t width,
Expand All @@ -60,12 +60,12 @@ typedef struct {
} u8250_state_t;

void u8250_update_interrupts(u8250_state_t *uart);
void u8250_read(vm_t *core,
void u8250_read(hart_t *core,
u8250_state_t *uart,
uint32_t addr,
uint8_t width,
uint32_t *value);
void u8250_write(vm_t *core,
void u8250_write(hart_t *core,
u8250_state_t *uart,
uint32_t addr,
uint8_t width,
Expand Down Expand Up @@ -107,12 +107,12 @@ typedef struct {
void *priv;
} virtio_net_state_t;

void virtio_net_read(vm_t *core,
void virtio_net_read(hart_t *core,
virtio_net_state_t *vnet,
uint32_t addr,
uint8_t width,
uint32_t *value);
void virtio_net_write(vm_t *core,
void virtio_net_write(hart_t *core,
virtio_net_state_t *vnet,
uint32_t addr,
uint8_t width,
Expand Down Expand Up @@ -156,13 +156,13 @@ typedef struct {
void *priv;
} virtio_blk_state_t;

void virtio_blk_read(vm_t *vm,
void virtio_blk_read(hart_t *vm,
virtio_blk_state_t *vblk,
uint32_t addr,
uint8_t width,
uint32_t *value);

void virtio_blk_write(vm_t *vm,
void virtio_blk_write(hart_t *vm,
virtio_blk_state_t *vblk,
uint32_t addr,
uint8_t width,
Expand All @@ -171,6 +171,25 @@ void virtio_blk_write(vm_t *vm,
uint32_t *virtio_blk_init(virtio_blk_state_t *vblk, char *disk_file);
#endif /* SEMU_HAS(VIRTIOBLK) */

/* clint */
typedef struct {
uint32_t msip[4096];
uint64_t mtimecmp[4095];
uint64_t mtime;
} clint_state_t;

void clint_update_interrupts(hart_t *vm, clint_state_t *clint);
void clint_read(hart_t *vm,
clint_state_t *clint,
uint32_t addr,
uint8_t width,
uint32_t *value);
void clint_write(hart_t *vm,
clint_state_t *clint,
uint32_t addr,
uint8_t width,
uint32_t value);

/* memory mapping */

typedef struct {
Expand All @@ -185,5 +204,5 @@ typedef struct {
#if SEMU_HAS(VIRTIOBLK)
virtio_blk_state_t vblk;
#endif
uint64_t timer;
clint_state_t clint;
} emu_state_t;
Loading