Skip to content

Commit 9069999

Browse files
committed
Merge branch 'master' of https://github.com/sysprog21/semu
2 parents 469bcfa + 35517a0 commit 9069999

18 files changed

+233
-109
lines changed

.ci/autorun.sh

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env bash
2+
3+
function cleanup {
4+
sleep 1
5+
pkill -9 semu
6+
}
7+
8+
function ASSERT {
9+
$*
10+
local RES=$?
11+
if [ $RES -ne 0 ]; then
12+
echo 'Assert failed: "' $* '"'
13+
exit $RES
14+
fi
15+
}
16+
17+
cleanup
18+
19+
ASSERT expect <<DONE
20+
set timeout 90
21+
spawn make check
22+
expect "buildroot login:" { send "root\n" } timeout { exit 1 }
23+
expect "# " { send "uname -a\n" } timeout { exit 2 }
24+
expect "riscv32 GNU/Linux" { send "\x01"; send "x" } timeout { exit 3 }
25+
DONE
26+
27+
ret=$?
28+
cleanup
29+
30+
MESSAGES=("OK!" \
31+
"Fail to boot" \
32+
"Fail to login" \
33+
"Fail to run commands" \
34+
)
35+
36+
COLOR_G='\e[32;01m' # Green
37+
COLOR_N='\e[0m'
38+
printf "\n[ ${COLOR_G}${MESSAGES[$ret]}${COLOR_N} ]\n"
39+
40+
exit ${ret}

.github/workflows/main.yml

+7-3
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,24 @@ jobs:
66
rv32emu:
77
runs-on: ubuntu-22.04
88
steps:
9-
- uses: actions/checkout@v3
9+
- uses: actions/checkout@v4
1010
- name: install-dependencies
1111
run: |
1212
sudo apt-get install build-essential device-tree-compiler
13+
sudo apt-get install expect
1314
- name: default build
1415
run: make
1516
shell: bash
17+
- name: automated test
18+
run: .ci/autorun.sh
19+
shell: bash
1620

1721
coding_style:
1822
runs-on: ubuntu-22.04
1923
steps:
20-
- uses: actions/checkout@v3
24+
- uses: actions/checkout@v4
2125
- name: coding convention
2226
run: |
2327
sudo apt-get install -q -y clang-format-12
24-
sh .ci/check-format.sh
28+
.ci/check-format.sh
2529
shell: bash

CONTRIBUTING.md

+66-21
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,57 @@
22

33
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
44

5-
The following is a set of guidelines for contributing to [semu](https://github.com/jserv/semu)
6-
hosted on GitHub. These are mostly guidelines, not rules. Use your best
7-
judgment, and feel free to propose changes to this document in a pull request.
5+
The following is a set of guidelines for contributing to [semu](https://github.com/sysprog21/semu)
6+
hosted on GitHub. These are mostly guidelines, not rules.
7+
Use your best judgment, and feel free to propose changes to this document in a pull request.
88

99
## Issues
1010

11-
This project uses GitHub Issues to track ongoing development, discuss project plans, and keep track of bugs. Be sure to search for existing issues before you create another one.
11+
This project uses GitHub Issues to track ongoing development, discuss project plans, and keep track of bugs.
12+
Be sure to search for existing issues before you create another one.
1213

13-
Visit our [Issues page on GitHub](https://github.com/jserv/semu/issues) to search and submit.
14+
Visit our [Issues page on GitHub](https://github.com/sysprog21/semu/issues) to search and submit.
1415

1516
## Coding Convention
1617

17-
We welcome all contributions from corporate, academic and individual developers. However, there are a number of fundamental ground rules that you must adhere to in order to participate. These rules are outlined as follows:
18-
* All code must adhere to the existing C coding style (see below). While we are somewhat flexible in basic style, you will adhere to what is currently in place. Uncommented, complicated algorithmic constructs will be rejected.
19-
* All external pull requests must contain sufficient documentation in the pull request comments in order to be accepted.
18+
Contributions from developers across corporations, academia, and individuals are welcome.
19+
However, participation requires adherence to fundamental ground rules:
20+
* Code must strictly adhere to the established C coding style (refer to the guidelines below).
21+
While there is some flexibility in basic style, it is crucial to stick to the current coding standards.
22+
Complex algorithmic constructs without proper comments will not be accepted.
23+
* External pull requests should include thorough documentation in the pull request comments for consideration.
2024

2125
Software requirement: [clang-format](https://clang.llvm.org/docs/ClangFormat.html) version 12 or later.
2226

23-
Use the command `$ clang-format -i *.[ch]` to enforce a consistent coding style.
27+
This repository consistently contains an up-to-date `.clang-format` file with rules that match the explained ones.
28+
For maintaining a uniform coding style, execute the command `clang-format -i *.[ch]`.
2429

2530
## Coding Style for Modern C
2631

27-
This coding style is a variation of the K&R style. Some general principles: honor tradition, but accept progress; be consistent;
28-
embrace the latest C standards; embrace modern compilers, their static analysis
29-
capabilities and sanitizers.
32+
This coding style is a variant of the K&R style.
33+
Adhere to established practices while being open to innovation.
34+
Maintain consistency, adopt the latest C standards,
35+
and embrace modern compilers along with their advanced static analysis capabilities and sanitizers.
3036

3137
### Indentation
3238

33-
Use 4 spaces rather than tabs.
39+
In this coding style guide, the use of 4 spaces for indentation instead of tabs is strongly enforced to ensure consistency.
40+
Consistently apply a single space before and after comparison and assignment operators to maintain readable code.
41+
Additionally, it is crucial to include a single space after every comma.
42+
e.g.,
43+
```c
44+
for (int i = 0; i < 10; i++) {
45+
printf("%d\n", i);
46+
/* some operations */
47+
}
48+
```
3449

3550
### Line length
3651

37-
All lines should generally be within 80 characters. Wrap long lines.
38-
There are some good reasons behind this:
39-
* It forces the developer to write more succinct code;
40-
* Humans are better at processing information in smaller quantity portions;
52+
All lines should typically stay within 80 characters, and longer lines should be wrapped.
53+
There are valid rationales for this practice:
54+
* It encourages concise code writing by developers.
55+
* Smaller portions of information are easier for humans to process.
4156
* It helps users of vi/vim (and potentially other editors) who use vertical splits.
4257

4358
### Comments
@@ -66,7 +81,12 @@ Leave two spaces between the statement and the inline comment.
6681
### Spacing and brackets
6782

6883
Use one space after the conditional or loop keyword, no spaces around
69-
their brackets, and one space before the opening curly bracket.
84+
their brackets, and one space before the opening curly bracket. e.g.,
85+
```c
86+
do {
87+
/* some operations */
88+
} while (condition);
89+
```
7090

7191
Functions (their declarations or calls), `sizeof` operator or similar
7292
macros shall not have a space after their name/keyword or around the
@@ -81,6 +101,8 @@ but otherwise avoid redundant or excessive brackets.
81101

82102
### Variable names and declarations
83103

104+
- Ensure that functions, variables, and comments are consistently named using English names/text.
105+
84106
- Use descriptive names for global variables and short names for locals.
85107
Find the right balance between descriptive and succinct.
86108

@@ -97,6 +119,29 @@ const uint8_t * const charmap; /* const pointer and const data */
97119
const void * restrict key; /* const pointer which does not alias */
98120
```
99121

122+
- Local variables of the same type should be declared in the same line.
123+
```c
124+
void func(void)
125+
{
126+
char a, b; /* OK */
127+
128+
char a;
129+
char b; /* Incorrect: A variable with char type already exists. */
130+
}
131+
```
132+
133+
- Always include a trailing comma in the last element of structure initialization, including its children, to assist clang-format in correctly formatting structures. However, this can be omitted in very simple and short structures.
134+
```c
135+
typedef struct {
136+
int width, height;
137+
} screen_t;
138+
139+
screen_t s = {
140+
.width = 640,
141+
.height = 480, /* comma here */
142+
}
143+
```
144+
100145
### Type definitions
101146

102147
Declarations shall be on the same line, e.g.,
@@ -418,9 +463,9 @@ printf("val %lld\n", SOME_CONSTANT);
418463

419464
#### Avoid unaligned access
420465

421-
Do not assume unaligned access is safe. It is not safe on Arm, POWER,
422-
and various other architectures. Moreover, even on x86 unaligned access
423-
is slower.
466+
Avoid assuming that unaligned access is safe.
467+
It is not secure on architectures like Arm, POWER, and others.
468+
Additionally, even on x86, unaligned access can be slower.
424469

425470
#### Avoid extreme portability
426471

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (C) 2022-2023 National Cheng Kung University, Taiwan.
3+
Copyright (C) 2022-2024 National Cheng Kung University, Taiwan.
44
All rights reserved.
55

66
Permission is hereby granted, free of charge, to any person obtaining a copy

device.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -239,5 +239,5 @@ typedef struct {
239239
#if SEMU_HAS(VIRTIOGPU)
240240
virtio_gpu_state_t vgpu;
241241
#endif
242-
uint32_t timer_lo, timer_hi;
242+
uint64_t timer;
243243
} emu_state_t;

main.c

+20-20
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,34 @@
1414
#include "riscv_private.h"
1515
#include "window.h"
1616

17+
#define PRIV(x) ((emu_state_t *) x->priv)
18+
1719
/* Define fetch separately since it is simpler (fixed width, already checked
1820
* alignment, only main RAM is executable).
1921
*/
20-
static void mem_fetch(vm_t *vm, uint32_t addr, uint32_t *value)
22+
static void mem_fetch(vm_t *vm, uint32_t n_pages, uint32_t **page_addr)
2123
{
22-
emu_state_t *data = (emu_state_t *) vm->priv;
23-
if (unlikely(addr >= RAM_SIZE)) {
24+
emu_state_t *data = PRIV(vm);
25+
if (unlikely(n_pages >= RAM_SIZE / RV_PAGE_SIZE)) {
2426
/* TODO: check for other regions */
2527
vm_set_exception(vm, RV_EXC_FETCH_FAULT, vm->exc_val);
2628
return;
2729
}
28-
*value = data->ram[addr >> 2];
30+
*page_addr = &data->ram[n_pages << (RV_PAGE_SHIFT - 2)];
2931
}
3032

3133
/* Similarly, only main memory pages can be used as page tables. */
3234
static uint32_t *mem_page_table(const vm_t *vm, uint32_t ppn)
3335
{
34-
emu_state_t *data = (emu_state_t *) vm->priv;
36+
emu_state_t *data = PRIV(vm);
3537
if (ppn < (RAM_SIZE / RV_PAGE_SIZE))
3638
return &data->ram[ppn << (RV_PAGE_SHIFT - 2)];
3739
return NULL;
3840
}
3941

4042
static void emu_update_uart_interrupts(vm_t *vm)
4143
{
42-
emu_state_t *data = (emu_state_t *) vm->priv;
44+
emu_state_t *data = PRIV(vm);
4345
u8250_update_interrupts(&data->uart);
4446
if (data->uart.pending_ints)
4547
data->plic.active |= IRQ_UART_BIT;
@@ -51,7 +53,7 @@ static void emu_update_uart_interrupts(vm_t *vm)
5153
#if SEMU_HAS(VIRTIONET)
5254
static void emu_update_vnet_interrupts(vm_t *vm)
5355
{
54-
emu_state_t *data = (emu_state_t *) vm->priv;
56+
emu_state_t *data = PRIV(vm);
5557
if (data->vnet.InterruptStatus)
5658
data->plic.active |= IRQ_VNET_BIT;
5759
else
@@ -63,7 +65,7 @@ static void emu_update_vnet_interrupts(vm_t *vm)
6365
#if SEMU_HAS(VIRTIOBLK)
6466
static void emu_update_vblk_interrupts(vm_t *vm)
6567
{
66-
emu_state_t *data = (emu_state_t *) vm->priv;
68+
emu_state_t *data = PRIV(vm);
6769
if (data->vblk.InterruptStatus)
6870
data->plic.active |= IRQ_VBLK_BIT;
6971
else
@@ -86,8 +88,7 @@ static void emu_update_vgpu_interrupts(vm_t *vm)
8688

8789
static void mem_load(vm_t *vm, uint32_t addr, uint8_t width, uint32_t *value)
8890
{
89-
emu_state_t *data = (emu_state_t *) vm->priv;
90-
91+
emu_state_t *data = PRIV(vm);
9192
/* RAM at 0x00000000 + RAM_SIZE */
9293
if (addr < RAM_SIZE) {
9394
ram_read(vm, data->ram, addr, width, value);
@@ -131,8 +132,7 @@ static void mem_load(vm_t *vm, uint32_t addr, uint8_t width, uint32_t *value)
131132

132133
static void mem_store(vm_t *vm, uint32_t addr, uint8_t width, uint32_t value)
133134
{
134-
emu_state_t *data = (emu_state_t *) vm->priv;
135-
135+
emu_state_t *data = PRIV(vm);
136136
/* RAM at 0x00000000 + RAM_SIZE */
137137
if (addr < RAM_SIZE) {
138138
ram_write(vm, data->ram, addr, width, value);
@@ -185,11 +185,11 @@ typedef struct {
185185

186186
static inline sbi_ret_t handle_sbi_ecall_TIMER(vm_t *vm, int32_t fid)
187187
{
188-
emu_state_t *data = (emu_state_t *) vm->priv;
188+
emu_state_t *data = PRIV(vm);
189189
switch (fid) {
190190
case SBI_TIMER__SET_TIMER:
191-
data->timer_lo = vm->x_regs[RV_R_A0];
192-
data->timer_hi = vm->x_regs[RV_R_A1];
191+
data->timer = (((uint64_t) vm->x_regs[RV_R_A1]) << 32) |
192+
(uint64_t) (vm->x_regs[RV_R_A0]);
193193
return (sbi_ret_t){SBI_SUCCESS, 0};
194194
default:
195195
return (sbi_ret_t){SBI_ERR_NOT_SUPPORTED, 0};
@@ -198,7 +198,7 @@ static inline sbi_ret_t handle_sbi_ecall_TIMER(vm_t *vm, int32_t fid)
198198

199199
static inline sbi_ret_t handle_sbi_ecall_RST(vm_t *vm, int32_t fid)
200200
{
201-
emu_state_t *data = (emu_state_t *) vm->priv;
201+
emu_state_t *data = PRIV(vm);
202202
switch (fid) {
203203
case SBI_RST__SYSTEM_RESET:
204204
fprintf(stderr, "system reset: type=%u, reason=%u\n",
@@ -211,7 +211,7 @@ static inline sbi_ret_t handle_sbi_ecall_RST(vm_t *vm, int32_t fid)
211211
}
212212

213213
#define RV_MVENDORID 0x12345678
214-
#define RV_MARCHID ((1 << 31) | 1)
214+
#define RV_MARCHID ((1ULL << 31) | 1)
215215
#define RV_MIMPID 1
216216

217217
static inline sbi_ret_t handle_sbi_ecall_BASE(vm_t *vm, int32_t fid)
@@ -395,6 +395,7 @@ static int semu_start(int argc, char **argv)
395395
.mem_store = mem_store,
396396
.mem_page_table = mem_page_table,
397397
};
398+
vm_init(&vm);
398399

399400
/* Set up RAM */
400401
emu.ram = mmap(NULL, RAM_SIZE, PROT_READ | PROT_WRITE,
@@ -431,7 +432,7 @@ static int semu_start(int argc, char **argv)
431432
atexit(unmap_files);
432433

433434
/* Set up RISC-V hart */
434-
emu.timer_hi = emu.timer_lo = 0xFFFFFFFF;
435+
emu.timer = 0xFFFFFFFFFFFFFFFF;
435436
vm.s_mode = true;
436437
vm.x_regs[RV_R_A0] = 0; /* hart ID. i.e., cpuid */
437438
vm.x_regs[RV_R_A1] = dtb_addr;
@@ -482,8 +483,7 @@ static int semu_start(int argc, char **argv)
482483
#endif
483484
}
484485

485-
if (vm.insn_count_hi > emu.timer_hi ||
486-
(vm.insn_count_hi == emu.timer_hi && vm.insn_count > emu.timer_lo))
486+
if (vm.insn_count > emu.timer)
487487
vm.sip |= RV_INT_STI_BIT;
488488
else
489489
vm.sip &= ~RV_INT_STI_BIT;

minimal.dts

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
model = "semu";
77

88
aliases {
9-
serial0 = "/soc/serial@4000000";
9+
serial0 = "/soc@F0000000/serial@4000000";
1010
};
1111

1212
chosen {
@@ -28,6 +28,7 @@
2828
mmu-type = "riscv,rv32";
2929
cpu0_intc: interrupt-controller {
3030
#interrupt-cells = <1>;
31+
#address-cells = <0>;
3132
interrupt-controller;
3233
compatible = "riscv,cpu-intc";
3334
};
@@ -40,7 +41,7 @@
4041
reg-names = "sram0";
4142
};
4243

43-
soc {
44+
soc: soc@F0000000 {
4445
#address-cells = <1>;
4546
#size-cells = <1>;
4647
compatible = "simple-bus";

0 commit comments

Comments
 (0)