Skip to content
Permalink
Browse files

Check in working 64-bit RISC-V support with basic unit testing framew…

…ork. Correct device tree detection of CPU cores. Still a work in progress: next step is tidying up container ID code, get actual proper supervisor loading, then interrupts
  • Loading branch information...
diodesign committed Jul 9, 2019
1 parent 32ec999 commit b72e82eea27f60dc5bdbedfb40cd1b6ee1a08902
Showing with 79 additions and 46 deletions.
  1. +4 −4 .cargo/config
  2. +14 −4 .travis.yml
  3. +17 −18 BUILDING.md
  4. +1 −1 Cargo.toml
  5. +14 −10 README.md
  6. +18 −7 src/kernel/abort.rs
  7. +6 −0 src/kernel/main.rs
  8. +5 −2 src/platform/riscv/src/devicetree.rs
@@ -1,24 +1,24 @@
# set a default build triple
[build]
target = "riscv32imac-unknown-none-elf"
target = "riscv64gc-unknown-none-elf"

# Find the linker for 32-bit RISC-V (IMAC) targets
[target.riscv32imac-unknown-none-elf]
rustflags = [ "-Z", "pre-link-arg=-nostartfiles", "-C", "link-arg=-Tsrc/platform/riscv/link.ld" ]
linker = "riscv32-elf-ld"
ar = "riscv32-elf-ar"
runner = "qemu-system-riscv32 -nographic -machine virt -kernel"
runner = "qemu-system-riscv32 -nographic -machine virt -smp 4 -kernel"

# Find the linker for 64-bit RISC-V (IMAC) targets
[target.riscv64imac-unknown-none-elf]
rustflags = [ "-Z", "pre-link-arg=-nostartfiles", "-C", "link-arg=-Tsrc/platform/riscv/link.ld" ]
linker = "riscv64-elf-ld"
ar = "riscv64-elf-ar"
runner = "qemu-system-riscv64 -nographic -machine virt -kernel"
runner = "qemu-system-riscv64 -nographic -machine virt -smp 4 -kernel"

# Find the linker for 64-bit RISC-V (GC) targets
[target.riscv64gc-unknown-none-elf]
rustflags = [ "-Z", "pre-link-arg=-nostartfiles", "-C", "link-arg=-Tsrc/platform/riscv/link.ld" ]
linker = "riscv64-elf-ld"
ar = "riscv64-elf-ar"
runner = "qemu-system-riscv64 -nographic -machine virt -kernel"
runner = "qemu-system-riscv64 -nographic -machine virt -smp 4 -kernel"
@@ -25,17 +25,27 @@ install:
- make
- make install
- export PATH=$PATH:$HOME/cross/bin
- cd ..
- cd $HOME
- sudo apt-get -qq install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev
- git clone -b master https://github.com/qemu/qemu.git
- cd qemu
- ./configure --target-list=riscv32-softmmu,riscv64-softmmu
- make
- export PATH=$PATH:$HOME/qemu/riscv32-softmmu/qemu-system-riscv32
- export PATH=$PATH:$HOME/qemu/riscv64-softmmu/qemu-system-riscv64

before_script:
rustup target install riscv32imac-unknown-none-elf
rustup target install riscv64imac-unknown-none-elf
rustup target install riscv64gc-unknown-none-elf

script:
- cargo build --target riscv32imac-unknown-none-elf
- cargo build --target riscv64imac-unknown-none-elf
- cargo build --target riscv64gc-unknown-none-elf
- cargo build --release --target riscv32imac-unknown-none-elf
- cargo build --release --target riscv64imac-unknown-none-elf
- cargo build --release --target riscv64gc-unknown-none-elf
- cargo test --release --target riscv32imac-unknown-none-elf
- cargo test --release --target riscv64imac-unknown-none-elf
- cargo test --release --target riscv64gc-unknown-none-elf

branches:
only:
@@ -51,26 +51,26 @@ Close your terminal, and open a new one, to load the changes.

### Setting up your runtime environment

If you plan to run diosix on physical hardware then you can skip this part, and instead build diosix as needed and
copy it to the hardware platform of your choice and run it there. If you want to test and develop diosix in
If you plan to run diosix on physical hardware then you can skip this part, and instead build diosix as needed,
copy it to the hardware platform of your choice, and run it there. If you want to test and develop diosix in
[Qemu](https://www.qemu.org/), an emulator that is handy for debggging, then read on.

You can install Qemu from your prefered system package manager, although you may have to build it yourself
to include 32-bit and 64-bit RISC-V support. To do so, in a quick and easy way, clone the Qemu source code,
configure it to support RISC-V system emulation, build it, and add the resulting binaries to your path.
First, in your terminal, change directory to where you'd like to build Qemu, then follow these instructions:
First, in your terminal, `cd` to a directory in which you'd like to build Qemu, such as `~/src/` then follow these instructions:

```
sudo apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev
cd $HOME/src
git clone git://git.qemu-project.org/qemu.git
cd qemu
./configure --target-list=riscv32-softmmu,riscv64-softmmu
make
```

Then make sure the resulting Qemu binaries, `$HOME/src/qemu/riscv32-softmmu/qemu-system-riscv32`
and `$HOME/src/qemu/riscv64-softmmu/qemu-system-riscv64` are in your `$PATH`. For example, you could add the
following paths to your shell's `.rc` file:
following paths to your shell's `rc` file:

```
export PATH=$PATH:$HOME/src/qemu/riscv32-softmmu
@@ -86,16 +86,16 @@ whether it's emulated hardware, such as with Qemu, or on real hardware, such as
to do is build diosix for the correct CPU architecture. All the hardware needs to do is pass a device-tree
structure to the kernel so it can discover attached peripherals, controllers, and memory.

To get started, clone the `diosix` source into an appropriate place, and enter the code:
To get started, clone the `diosix` source into an appropriate place, such as `~/src` and enter the code. Here's one way of doing that:

```
cd $HOME/src
git clone https://github.com/diodesign/diosix.git
cd diosix
```

By default, `riscv32imac-unknown-none-elf` is the default CPU architecture. To compile for a specific
CPU architecture, run Rust's `cargo` with the `--target` paramter defining the required CPU architecture, in the form:
The default CPU architecture is `riscv64gc-unknown-none-elf`: this is chosen if you do not specify a CPU target.
To compile for a specific CPU architecture, run Rust's `cargo` with the `--target` paramter defining the required CPU architecture, in the form:

`cargo build --release --target <CPU architecture>`

@@ -105,22 +105,21 @@ So far, diosix supports the following CPU architure targets:
* `riscv64gc-unknown-none-elf`

Once built, the compiled kernel executable can be found in `target/<CPU architecture>/release/kernel` for the given
`<CPU architecture>`. So, for example,
`<CPU architecture>`. If `qemu-system-riscv32` and `qemu-system-riscv32` are in your run path, you can build and
run diosix with one command. To build or rebuild diosix for 32-bit RISC-V targets and run it in Qemu, use the following:

```
cargo build --release --target riscv32imac-unknown-none-elf
qemu-system-riscv32 -machine virt -kernel target/riscv32imac-unknown-none-elf/release/kernel -nographic
cargo run --release --target riscv32imac-unknown-none-elf
```

...will build diosix for machines powered by 32-bit RISC-V CPUs (those with support for IMAC features, specifically),
and run it in the Qemu emulator. Press `Ctrl-a` then `c` to escape to the Qemu monitor, then `q` to quit. To do the same for
64-bit RISC-V, try:
Specifically, this targets 32-bit RISC-V CPUs that support IMAC features, specifically. Press `Ctrl-a` then `c`
to escape to the Qemu monitor, then `q` to quit. To do the same for 64-bit RISC-V, try:

```
cargo build --release --target riscv64gc-unknown-none-elf
qemu-system-riscv64 -machine virt -kernel target/riscv64gc-unknown-none-elf/release/kernel -nographic
cargo run --release --target riscv64gc-unknown-none-elf
```

The commands used to invoke Qemu are in `.cargo/config` in the diosix root folder, if you wish to run it by hand.
To change the amount of memory allocated to diosix in Qemu, add a `-m <RAM size>` paramter to the command line, eg `-m 256M` to boot diosix
with 256MB of physical RAM. To change the number of CPU cores available, add a `-smp <N>` paramter to the command line, eg `-smp 4` to boot diosix
with 4 separate CPU cores alocated. Check out the Qemu manual for more settings.
with 256MB of physical RAM. To change the number of CPU cores available, add a `-smp <N>` paramter to the command line, eg `-smp 8` to boot diosix
with 8 separate CPU cores alocated. Check out the Qemu manual for more settings.
@@ -29,7 +29,7 @@ overflow-checks = false
opt-level = 3
incremental = false

# supported build targets - don't forget to update .cargo with details for the linker
# supported build targets - don't forget to update .cargo with details for the linker and runner
[target.riscv32imac-unknown-none-elf.dependencies]
platform = { path = "src/platform/riscv/" }
lazy_static = { path = "src/contrib/lazy-static.rs" }
@@ -20,21 +20,25 @@ hypervisors, kernels, and operating systems as required.

### Running and building

See the [build instructions](BUILDING.md) for step-by-step guides to compiling and running this project.
Here's a screenshot of the hypervisor-microkernel booting in a quad-core 64-bit RISC-V Qemu Virt hardware environment
with the default 128MB of physical RAM. It starts up a default supervisor-level container, and writes some debug out to the
virtual serial port, including logging a hypercall to the hypervisor from the supervisor within its container via CPU core 2:

[![Screenshot of SMP diosix in Qemu](https://raw.githubusercontent.com/diodesign/diosix/screenshots/docs/screenshots/riscv64-smp-qemu-early.png)](https://raw.githubusercontent.com/diodesign/diosix/screenshots/docs/screenshots/riscv64-smp-qemu-early.png)

Here's a screenshot of the hypervisor-microkernel booting in a dual-core 32-bit RISC-V Qemu Virt hardware environment
with 256MB of physical RAM. It starts up a default supervisor-level container, and writes some debug out to the
virtual serial port, including logging a hypercall to the hypervisor from the supervisor within its container:
The command to build this code for 64-bit RISC-V, once you've installed the necessary toolchain, and run it in Qemu is simply:

[![Screenshot of SMP diosix in Qemu](https://raw.githubusercontent.com/diodesign/diosix/screenshots/docs/screenshots/riscv32-smp-qemu-early.png)](https://raw.githubusercontent.com/diodesign/diosix/screenshots/docs/screenshots/riscv32-smp-qemu-early.png)
```
cargo run --release
```

The commands to build and run this code, once you've installed the necessary toolchain, are:
Press `Ctrl-a` then `c` to escape to the Qemu monitor, then `q` to quit. To build and run diosix within a 32-bit RISC-V environment, try:

```
cargo build --release --target riscv32imac-unknown-none-elf
qemu-system-riscv32 -machine virt -kernel target/riscv32imac-unknown-none-elf/release/kernel -nographic -smp 2 -m 256M
cargo run --release --target riscv32imac-unknown-none-elf
```
Press `Ctrl-a` then `c` to escape to the Qemu monitor, then `q` to quit.

See the [build instructions](BUILDING.md) for step-by-step guides to compiling and running this project.

### Todo

@@ -70,4 +74,4 @@ Copyright &copy; Chris Williams and contributors, 2018-2019. See LICENSE for dis
- src/contrib/spin-rs: Copyright &copy; 2014 Mathijs van de Nes.
- src/contrib/spin-rs/src/atomic.rs: Reimplements Rust's MIT-licensed [core::sync::atomic](https://github.com/rust-lang/rust/blob/master/src/libcore/sync/atomic.rs) API. Original implementation: Copyright &copy; The Rust Project Developers.

And thanks to [David Craven](https://github.com/dvc94ch), [Alex Bradbury](https://github.com/asb), and everyone else who brought Rust, LLVM, and RISC-V together; the RISC-V world for designing the CPU cores and system-on-chips in the first place; [Michael Clark](https://github.com/michaeljclark) and everyone else who worked on [Qemu](https://github.com/riscv/riscv-qemu) and other RISC-V emulators; Philipp Oppermann for his guide to writing [kernel-level Rust code](https://os.phil-opp.com/); and to the OSdev community for its [notes and documentation](http://wiki.osdev.org/Main_Page).
And thanks to [David Craven](https://github.com/dvc94ch), [Alex Bradbury](https://github.com/asb), [Vadim Kaushan](https://github.com/Disasm), and everyone else who brought Rust, LLVM, and RISC-V together; the RISC-V world for designing the CPU cores and system-on-chips in the first place; [Michael Clark](https://github.com/michaeljclark) and everyone else who worked on [Qemu](https://github.com/riscv/riscv-qemu) and other RISC-V emulators; Philipp Oppermann for his guide to writing [kernel-level Rust code](https://os.phil-opp.com/); and to the OSdev community for its [notes and documentation](http://wiki.osdev.org/Main_Page).
@@ -11,15 +11,26 @@ use core::panic::PanicInfo;
#[panic_handler]
pub fn panic(info: &PanicInfo) -> !
{
kalert!("Rust runtime panicked unexpectedly");
match info.location()
if cfg!(test)
{
Some(location) =>
/* signal to test environment we failed */
platform::test::end(Err(1));
}
else
{
/* try to inform the user what went wrong */
kalert!("Rust runtime panicked unexpectedly");
match info.location()
{
kalert!("... crashed in {}: {}", location.file(), location.line())
},
None => kalert!("... crash location unknown")
};
Some(location) =>
{
kalert!("... crashed in {}: {}", location.file(), location.line())
},
None => kalert!("... crash location unknown")
};
}

/* just halt here */
loop
{}
}
@@ -233,4 +233,10 @@ fn run_tests(unit_tests: &[&dyn Fn()])

/* exit cleanly once tests are complete */
platform::test::end(Ok(0));
}

#[test_case]
fn test_assertion()
{
assert_eq!(42, 42);
}
@@ -72,9 +72,12 @@ pub fn get_cpu_count(device_tree_buf: &u8) -> Option<usize>
};

let mut cpus = 0;
for _node in dev_tree.enum_subnodes("/cpus")
for node in dev_tree.enum_subnodes("/cpus")
{
cpus = cpus + 1;
if node.starts_with("cpu@")
{
cpus = cpus + 1;
}
}

return Some(cpus);

0 comments on commit b72e82e

Please sign in to comment.
You can’t perform that action at this time.