Skip to content

Commit 914d14e

Browse files
authored
Merge pull request #46 from ranvd/PR_SMP
Preliminary SMP support
2 parents f98a8d8 + 9f3003c commit 914d14e

15 files changed

+648
-219
lines changed

Makefile

+9-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ OBJS := \
4545
plic.o \
4646
uart.o \
4747
main.o \
48+
clint.o \
4849
$(OBJS_EXTRA)
4950

5051
deps := $(OBJS:%.o=.%.o.d)
@@ -67,7 +68,13 @@ DTC ?= dtc
6768
# Reference: https://stackoverflow.com/questions/40886386
6869
E :=
6970
S := $E $E
70-
minimal.dtb: minimal.dts
71+
72+
SMP ?= 1
73+
.PHONY: riscv-harts.dtsi
74+
riscv-harts.dtsi:
75+
$(Q)python3 scripts/gen-hart-dts.py $@ $(SMP)
76+
77+
minimal.dtb: minimal.dts riscv-harts.dtsi
7178
$(VECHO) " DTC\t$@\n"
7279
$(Q)$(CC) -nostdinc -E -P -x assembler-with-cpp -undef \
7380
$(subst ^,$S,$(filter -D^SEMU_FEATURE_%, $(subst -D$(S)SEMU_FEATURE,-D^SEMU_FEATURE,$(CFLAGS)))) $< \
@@ -82,7 +89,7 @@ ext4.img:
8289

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

8794
build-image:
8895
scripts/build-image.sh

clint.c

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#include <stdint.h>
2+
#include "device.h"
3+
#include "riscv.h"
4+
#include "riscv_private.h"
5+
6+
void clint_update_interrupts(hart_t *hart, clint_state_t *clint)
7+
{
8+
if (clint->mtime > clint->mtimecmp[hart->mhartid])
9+
hart->sip |= RV_INT_STI_BIT;
10+
else
11+
hart->sip &= ~RV_INT_STI_BIT;
12+
13+
if (clint->msip[hart->mhartid]) {
14+
hart->sip |= RV_INT_SSI_BIT;
15+
} else
16+
hart->sip &= ~RV_INT_SSI_BIT;
17+
}
18+
19+
static bool clint_reg_read(clint_state_t *clint, uint32_t addr, uint32_t *value)
20+
{
21+
if (addr < 0x4000) {
22+
*value = clint->msip[addr >> 2];
23+
return true;
24+
}
25+
26+
if (addr < 0xBFF8) {
27+
addr -= 0x4000;
28+
*value =
29+
(uint32_t) (clint->mtimecmp[addr >> 3] >> (32 & -!!(addr & 0b100)));
30+
return true;
31+
}
32+
33+
if (addr < 0xBFFF) {
34+
*value = clint->mtime >> (32 & -!!(addr & 0b100));
35+
return true;
36+
}
37+
return false;
38+
}
39+
40+
static bool clint_reg_write(clint_state_t *clint, uint32_t addr, uint32_t value)
41+
{
42+
if (addr < 0x4000) {
43+
clint->msip[addr >> 2] = value;
44+
return true;
45+
}
46+
47+
if (addr < 0xBFF8) {
48+
addr -= 0x4000;
49+
int32_t upper = clint->mtimecmp[addr >> 3] >> 32;
50+
int32_t lowwer = clint->mtimecmp[addr >> 3];
51+
if (addr & 0b100)
52+
upper = value;
53+
else
54+
lowwer = value;
55+
56+
clint->mtimecmp[addr >> 3] = (uint64_t) upper << 32 | lowwer;
57+
return true;
58+
}
59+
60+
if (addr < 0xBFFF) {
61+
int32_t upper = clint->mtime >> 32;
62+
int32_t lowwer = clint->mtime;
63+
if (addr & 0b100)
64+
upper = value;
65+
else
66+
lowwer = value;
67+
68+
clint->mtime = (uint64_t) upper << 32 | lowwer;
69+
return true;
70+
}
71+
return false;
72+
}
73+
74+
void clint_read(hart_t *vm,
75+
clint_state_t *clint,
76+
uint32_t addr,
77+
uint8_t width,
78+
uint32_t *value)
79+
{
80+
if (!clint_reg_read(clint, addr, value))
81+
vm_set_exception(vm, RV_EXC_LOAD_FAULT, vm->exc_val);
82+
*value = (*value) >> (RV_MEM_SW - width);
83+
return;
84+
}
85+
86+
void clint_write(hart_t *vm,
87+
clint_state_t *clint,
88+
uint32_t addr,
89+
uint8_t width,
90+
uint32_t value)
91+
{
92+
if (!clint_reg_write(clint, addr, value >> (RV_MEM_SW - width)))
93+
vm_set_exception(vm, RV_EXC_STORE_FAULT, vm->exc_val);
94+
return;
95+
}

configs/linux.config

+1-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ CONFIG_ARCH_RV32I=y
223223
# CONFIG_CMODEL_MEDLOW is not set
224224
CONFIG_CMODEL_MEDANY=y
225225
CONFIG_MODULE_SECTIONS=y
226-
# CONFIG_SMP is not set
226+
CONFIG_SMP=y
227227
CONFIG_TUNE_GENERIC=y
228228
# CONFIG_RISCV_ISA_C is not set
229229
CONFIG_TOOLCHAIN_HAS_ZICBOM=y

device.h

+33-14
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99
#define DTB_SIZE (1 * 1024 * 1024)
1010
#define INITRD_SIZE (8 * 1024 * 1024)
1111

12-
void ram_read(vm_t *core,
12+
void ram_read(hart_t *core,
1313
uint32_t *mem,
1414
const uint32_t addr,
1515
const uint8_t width,
1616
uint32_t *value);
1717

18-
void ram_write(vm_t *core,
18+
void ram_write(hart_t *core,
1919
uint32_t *mem,
2020
const uint32_t addr,
2121
const uint8_t width,
@@ -25,19 +25,19 @@ void ram_write(vm_t *core,
2525

2626
typedef struct {
2727
uint32_t masked;
28-
uint32_t ip;
29-
uint32_t ie;
28+
uint32_t ip; /* support 32 interrupt sources only */
29+
uint32_t ie[32]; /* support 32 sources to 32 contexts only */
3030
/* state of input interrupt lines (level-triggered), set by environment */
3131
uint32_t active;
3232
} plic_state_t;
3333

34-
void plic_update_interrupts(vm_t *core, plic_state_t *plic);
35-
void plic_read(vm_t *core,
34+
void plic_update_interrupts(vm_t *vm, plic_state_t *plic);
35+
void plic_read(hart_t *core,
3636
plic_state_t *plic,
3737
uint32_t addr,
3838
uint8_t width,
3939
uint32_t *value);
40-
void plic_write(vm_t *core,
40+
void plic_write(hart_t *core,
4141
plic_state_t *plic,
4242
uint32_t addr,
4343
uint8_t width,
@@ -60,12 +60,12 @@ typedef struct {
6060
} u8250_state_t;
6161

6262
void u8250_update_interrupts(u8250_state_t *uart);
63-
void u8250_read(vm_t *core,
63+
void u8250_read(hart_t *core,
6464
u8250_state_t *uart,
6565
uint32_t addr,
6666
uint8_t width,
6767
uint32_t *value);
68-
void u8250_write(vm_t *core,
68+
void u8250_write(hart_t *core,
6969
u8250_state_t *uart,
7070
uint32_t addr,
7171
uint8_t width,
@@ -107,12 +107,12 @@ typedef struct {
107107
void *priv;
108108
} virtio_net_state_t;
109109

110-
void virtio_net_read(vm_t *core,
110+
void virtio_net_read(hart_t *core,
111111
virtio_net_state_t *vnet,
112112
uint32_t addr,
113113
uint8_t width,
114114
uint32_t *value);
115-
void virtio_net_write(vm_t *core,
115+
void virtio_net_write(hart_t *core,
116116
virtio_net_state_t *vnet,
117117
uint32_t addr,
118118
uint8_t width,
@@ -156,13 +156,13 @@ typedef struct {
156156
void *priv;
157157
} virtio_blk_state_t;
158158

159-
void virtio_blk_read(vm_t *vm,
159+
void virtio_blk_read(hart_t *vm,
160160
virtio_blk_state_t *vblk,
161161
uint32_t addr,
162162
uint8_t width,
163163
uint32_t *value);
164164

165-
void virtio_blk_write(vm_t *vm,
165+
void virtio_blk_write(hart_t *vm,
166166
virtio_blk_state_t *vblk,
167167
uint32_t addr,
168168
uint8_t width,
@@ -171,6 +171,25 @@ void virtio_blk_write(vm_t *vm,
171171
uint32_t *virtio_blk_init(virtio_blk_state_t *vblk, char *disk_file);
172172
#endif /* SEMU_HAS(VIRTIOBLK) */
173173

174+
/* clint */
175+
typedef struct {
176+
uint32_t msip[4096];
177+
uint64_t mtimecmp[4095];
178+
uint64_t mtime;
179+
} clint_state_t;
180+
181+
void clint_update_interrupts(hart_t *vm, clint_state_t *clint);
182+
void clint_read(hart_t *vm,
183+
clint_state_t *clint,
184+
uint32_t addr,
185+
uint8_t width,
186+
uint32_t *value);
187+
void clint_write(hart_t *vm,
188+
clint_state_t *clint,
189+
uint32_t addr,
190+
uint8_t width,
191+
uint32_t value);
192+
174193
/* memory mapping */
175194

176195
typedef struct {
@@ -185,5 +204,5 @@ typedef struct {
185204
#if SEMU_HAS(VIRTIOBLK)
186205
virtio_blk_state_t vblk;
187206
#endif
188-
uint64_t timer;
207+
clint_state_t clint;
189208
} emu_state_t;

0 commit comments

Comments
 (0)