summaryrefslogtreecommitdiff
path: root/riscv/riscv-probe/README.md
blob: 577e09de2f656f6c67dddd6413538b4713f4f676 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
# riscv-probe

Simple machine mode program to probe RISC-V control and status registers.

riscv-probe currently builds for
[Spike](https://github.com/riscv/riscv-isa-sim),
[QEMU](https://github.com/riscv/riscv-qemu) and the
[SiFive E21](https://www.sifive.com/products/risc-v-core-ip/e2/e21/) core.
riscv-probe is a testing tool designed be used to compare CSRs (Control and
Status Registers) between mutliple RISC-V simulators and RISC-V hardware
implementations.

riscv-probe contains libfemto which is a lightweight bare-metal C library
conforming to a reduced set ot the _POSIX.1-2017 / IEEE 1003.1-2017_ standard.
libfemto can be used as a starting point for bare metal RISC-V programs that
require interrupt handling, basic string routines and printf.

## Dependencies

A recent version of `riscv-tools` with a multilib build of RISC-V GCC.

- [riscv-tools](https://github.com/riscv/riscv-tools)
  - [riscv-isa-sim](https://github.com/riscv/riscv-isa-sim)
  - [riscv-openocd](https://github.com/riscv/riscv-openocd)
  - [riscv-gnu-toolchain](https://github.com/riscv/riscv-gnu-toolchain)
- [riscv-qemu](https://github.com/riscv/riscv-qemu)

## Build

The build system uses `CROSS_COMPILE` as the toolchain prefix and expects
the toolchain to be present in the `PATH` environment variable. The default
value for `CROSS_COMPILE` is `riscv64-unknown-elf-` however this can be
overridden e.g. `make CROSS_COMPILE=riscv64-unknown-linux-gnu-`. The build
system expects a multilib toolchain as it uses the same toolchain to build
for _riscv32_ and _riscv64_. Make sure to use `--enable-multilib` when
configuring [riscv-gnu-toolchain](https://github.com/riscv/riscv-gnu-toolchain).
The examples are all built with `-nostartfiles -nostdlib -nostdinc` so either
the RISC-V GCC Newlib toolchain or RISC-V GCC Glibc Linux toolchain can be used.

To build the examples after environent setup, type:

```
make
```

## Invocation

To invoke the probe example in spike and RISC-V QEMU:

- `$ spike --isa=RV32IMAFDC build/bin/rv32imac/spike/probe`
- `$ spike --isa=RV64IMAFDC build/bin/rv64imac/spike/probe`
- `$ qemu-system-riscv32 -nographic -machine spike -kernel build/bin/rv32imac/spike/probe` -bios none
- `$ qemu-system-riscv64 -nographic -machine spike -kernel build/bin/rv64imac/spike/probe` -bios none
- `$ qemu-system-riscv32 -nographic -machine virt -kernel build/bin/rv32imac/virt/probe` -bios none
- `$ qemu-system-riscv64 -nographic -machine virt -kernel build/bin/rv64imac/virt/probe` -bios none
- `$ qemu-system-riscv32 -nographic -machine sifive_e -kernel build/bin/rv32imac/qemu-sifive_e/probe` -bios none
- `$ qemu-system-riscv64 -nographic -machine sifive_e -kernel build/bin/rv64imac/qemu-sifive_e/probe` -bios none
- `$ qemu-system-riscv32 -nographic -machine sifive_u -kernel build/bin/rv32imac/qemu-sifive_u/probe` -bios none
- `$ qemu-system-riscv64 -nographic -machine sifive_u -kernel build/bin/rv64imac/qemu-sifive_u/probe` -bios none

## libfemto

libfemto is a lightweight bare-metal C library for embedded RISC-V development.
libfemto provides:

- Reduced set of the _POSIX.1-2017 / IEEE 1003.1-2017_ standard
- Simple lightweight hardware configuration mechanism
- RISC-V machine mode functions and macros
- Console and power device drivers

libfemto implements a reduced set of the _POSIX.1-2017 / IEEE 1003.1-2017_
standard, with the addition of glibc's `getauxval` API to access hardware
configuration in an auxiliary vector (`__auxv`) that contains tuples
describing the target environment. The auxiliary vector is intended as a
lightweight mechanism to pass dynamic configuration information on embedded
targets, serving as an alternative to compile time constants used during
hardware initialization. The auxiliary vector API has been repurposed to
allow retrieval of hardware configuration parameters such as clock
frequencies and device base addresses for use as a compact alternative to
(DTB) Device Tree Binary, which is not available on small embedded targets.

libfemto contains the following device drivers:

- HTIF (Host Target Interface)
- NS16550A UART Console
- SiFive UART Console
- SiFive Test Device
- Semihosting Syscalls

### Environments

This project contains a simple build system that allows building applications
targeting multiple embedded environments. A distinguishing characteristic of
the build system is that program objects do not need to be recompiled to target
a different environment, rather they are relinked with a different hardware
configuration and setup function. The config object causes the correct drivers
to be linked via compile time dependencies expressed by symbol references.
The following environments are currently supported:

- _default_ - environment where IO defaults to `ebreak`
- _spike_- the RISC-V ISA Simulator Golden Model
- _virt_ - the RISC-V VirtIO Virtual Machine
- _qemu-sifive_e_ - QEMU Functional Model of the SiFive E Series
- _qemu-sifive_u_ - QEMU Functional Model of the SiFive U Series
- _coreip-e2-arty_ - SiFive E2 CoreIP Arty A7 FPGA evaluation image

To create a new environment simply add a directory to `env` with two files:

- `default.lds` - linker script describing the target's memory layout
- `config.c` - environment specific configuration

The following is an example configuration from `env/<boardname>/config.c`
showing the auxiliary vector used by `getauxval` via the `setup` function
called by `_start` before entering `main`.

```
auxval_t __auxv[] = {
    { UART0_CLOCK_FREQ,         32000000   },
    { UART0_BAUD_RATE,          115200     },
    { SIFIVE_UART0_CTRL_ADDR,   0x20000000 },
    { SIFIVE_TEST_CTRL_ADDR,    0x4000     },
    { 0, 0 }
};

void setup()
{
    /*
     * clock setup code should be placed here and should modify the
     * uart clock speed before calling register_console, which calls
     * uart_init and reads the uart clock speed from the config array.
     */
    register_console(&console_sifive_uart);
    register_poweroff(&poweroff_sifive_test);
}
```

## Examples

The build system automatically includes any directory added to `examples`
which contains a `rules.mk` file.

### hello

The following is the `rules.mk` file from the _hello_ example:

```
$ cat examples/hello/rules.mk 
hello_objs = hello.o
```

and `hello.c`

```
$ cat examples/hello/hello.c 
#include <stdio.h>

int main(int argc, char **argv)
{
	printf("hello\n");
}
```

### symbols

libfemto linker scripts define the following special symbols:

Symbol           | Value
------           | -----
`_text_start`    | start of `.text` section
`_text_end`      | end of `.text` section
`_rodata_start`  | start of `.rodata` section
`_rodata_end`    | end of `.rodata` section
`_data_start`    | start of `.data` section
`_data_end`      | end of `.data` section
`_bss_start`     | start of `.bss` section
`_bss_end`       | end of `.bss` section
`_memory_start`  | start of RAM
`_memory_end`    | end of RAM

The symbols example program shows how to access these special symbols. They
can be used for example to locate data section in a flat image in ROM to copy
into memory and to zero the bss section.

### user

Simple example program that sets up PMP (Physical Memory Protection)
to allow all memory accesses and then switches to U mode. The code to
set up PMP to allow all memory access is `pmp_allow_all()` in `machine.h`.
The code is derived from _bbl_.

Note: PMP is enabled by default on systems that implement it, so it is
mandatory to include code to configure PMPs to allow memory access when
switching from M mode to S mode or U mode, otherwise memory accesses will trap.

### enclave

Simple enclave example using RISC-V PMP (Physical Memory Protection)

Physical memory protection is enabled for the program text (RX)
program data (RW), UART, and the hart is switch to U mode, however,
there is only one program and the default trap vector points into
the executable text, so traps are handled in M mode, in the same
executable text segment.

A future example will load a second process and provide ecall APIs
to the process running in the protected enclave.

### probe

`riscv-probe` is a utility that probes the Control and Status Register
address space of a RISC-V emulator, FPGA or board:

#### qemu-system-riscv32

```
$ qemu-system-riscv32 -nographic -machine spike_v1.10 -kernel build/bin/rv32/spike/probe
isa: rv32imafdcsu
csr: fflags          illegal_instruction cause=0x00000002 mtval=0x00000000
csr: frm             illegal_instruction cause=0x00000002 mtval=0x00000000
csr: fcsr            illegal_instruction cause=0x00000002 mtval=0x00000000
csr: mcycle          0xdbfa9cbd
csr: minstret        0xdc03f6a4
csr: mcycleh         0x0007c452
csr: minstreth       0x0007c452
csr: cycle           0xdc1d7e08
csr: time            illegal_instruction cause=0x00000002 mtval=0x00000000
csr: instret         0xdc393bf6
csr: cycleh          0x0007c452
csr: timeh           illegal_instruction cause=0x00000002 mtval=0x00000000
csr: instreth        0x0007c452
csr: mvendorid       0x00000000
csr: marchid         0x00000000
csr: mimpid          0x00000000
csr: mhartid         0x00000000
csr: mstatus         0x00000000
csr: misa            0x4014112d
csr: medeleg         0x00000000
csr: mideleg         0x00000000
csr: mie             0x00000000
csr: mtvec           0x80000004
csr: mcounteren      0x00000000
csr: mscratch        0x00000000
csr: mepc            0x800002a4
csr: mcause          0x00000002
csr: mtval           0x00000000
csr: mip             0x00000000
csr: sstatus         0x00000000
csr: sedeleg         illegal_instruction cause=0x00000002 mtval=0x00000000
csr: sideleg         illegal_instruction cause=0x00000002 mtval=0x00000000
csr: sie             0x00000000
csr: stvec           0x00000000
csr: scounteren      0x00000000
csr: sscratch        0x00000000
csr: sepc            0x00000000
csr: scause          0x00000000
csr: stval           0x00000000
csr: sip             0x00000000
csr: satp            0x00000000
csr: pmpcfg0         0x00000000
csr: pmpcfg1         0x00000000
csr: pmpcfg2         0x00000000
csr: pmpcfg3         0x00000000
csr: pmpaddr0        0x00000000
csr: pmpaddr1        0x00000000
csr: pmpaddr2        0x00000000
csr: pmpaddr3        0x00000000
csr: pmpaddr4        0x00000000
csr: pmpaddr5        0x00000000
csr: pmpaddr6        0x00000000
csr: pmpaddr7        0x00000000
csr: pmpaddr8        0x00000000
csr: pmpaddr9        0x00000000
csr: pmpaddr10       0x00000000
csr: pmpaddr11       0x00000000
csr: pmpaddr12       0x00000000
csr: pmpaddr13       0x00000000
csr: pmpaddr14       0x00000000
csr: pmpaddr15       0x00000000
```

#### qemu-system-riscv64

```
$ qemu-system-riscv64 -nographic -machine spike_v1.10 -kernel build/bin/rv64/spike/probe
isa: rv64imafdcsu
csr: fflags          illegal_instruction cause=0x00000002 mtval=0x00000000
csr: frm             illegal_instruction cause=0x00000002 mtval=0x00000000
csr: fcsr            illegal_instruction cause=0x00000002 mtval=0x00000000
csr: mcycle          0x0007c452dfeeddd3
csr: minstret        0x0007c452dff8a765
csr: mcycleh         illegal_instruction cause=0x00000002 mtval=0x00000000
csr: minstreth       illegal_instruction cause=0x00000002 mtval=0x00000000
csr: cycle           0x0007c452e01f105f
csr: time            illegal_instruction cause=0x00000002 mtval=0x00000000
csr: instret         0x0007c452e03d0a50
csr: cycleh          illegal_instruction cause=0x00000002 mtval=0x00000000
csr: timeh           illegal_instruction cause=0x00000002 mtval=0x00000000
csr: instreth        illegal_instruction cause=0x00000002 mtval=0x00000000
csr: mvendorid       0x0000000000000000
csr: marchid         0x0000000000000000
csr: mimpid          0x0000000000000000
csr: mhartid         0x0000000000000000
csr: mstatus         0x0000000000000000
csr: misa            0x800000000014112d
csr: medeleg         0x0000000000000000
csr: mideleg         0x0000000000000000
csr: mie             0x0000000000000000
csr: mtvec           0x0000000080000004
csr: mcounteren      0x0000000000000000
csr: mscratch        0x0000000000000000
csr: mepc            0x00000000800002f4
csr: mcause          0x0000000000000002
csr: mtval           0x0000000000000000
csr: mip             0x0000000000000000
csr: sstatus         0x0000000000000000
csr: sedeleg         illegal_instruction cause=0x00000002 mtval=0x00000000
csr: sideleg         illegal_instruction cause=0x00000002 mtval=0x00000000
csr: sie             0x0000000000000000
csr: stvec           0x0000000000000000
csr: scounteren      0x0000000000000000
csr: sscratch        0x0000000000000000
csr: sepc            0x0000000000000000
csr: scause          0x0000000000000000
csr: stval           0x0000000000000000
csr: sip             0x0000000000000000
csr: satp            0x0000000000000000
csr: pmpcfg0         0x0000000000000000
csr: pmpcfg1         0x0000000000000000
csr: pmpcfg2         0x0000000000000000
csr: pmpcfg3         0x0000000000000000
csr: pmpaddr0        0x0000000000000000
csr: pmpaddr1        0x0000000000000000
csr: pmpaddr2        0x0000000000000000
csr: pmpaddr3        0x0000000000000000
csr: pmpaddr4        0x0000000000000000
csr: pmpaddr5        0x0000000000000000
csr: pmpaddr6        0x0000000000000000
csr: pmpaddr7        0x0000000000000000
csr: pmpaddr8        0x0000000000000000
csr: pmpaddr9        0x0000000000000000
csr: pmpaddr10       0x0000000000000000
csr: pmpaddr11       0x0000000000000000
csr: pmpaddr12       0x0000000000000000
csr: pmpaddr13       0x0000000000000000
csr: pmpaddr14       0x0000000000000000
csr: pmpaddr15       0x0000000000000000
```