Browse Source

Reform RustSBI project into a library

luojia65 3 years ago
parent
commit
6f98a3fd36
54 changed files with 30 additions and 2516 deletions
  1. 1 2
      CHANGELOG.md
  2. 26 12
      Cargo.toml
  3. 3 25
      README.md
  4. 0 132
      platform/README.md
  5. 0 7
      platform/k210/.cargo/config.toml
  6. 0 1
      platform/k210/.gitignore
  7. 0 15
      platform/k210/Cargo.toml
  8. 0 72
      platform/k210/README.md
  9. 0 18
      platform/k210/build.rs
  10. 0 30
      platform/k210/justfile
  11. BIN
      platform/k210/kendryte-k210.dtb
  12. 0 70
      platform/k210/kendryte-k210.dts
  13. 0 87
      platform/k210/link-k210.ld
  14. 0 586
      platform/k210/src/main.rs
  15. 0 7
      platform/qemu/.cargo/config.toml
  16. 0 21
      platform/qemu/Cargo.toml
  17. 0 32
      platform/qemu/README.md
  18. 0 18
      platform/qemu/build.rs
  19. 0 52
      platform/qemu/justfile
  20. 0 86
      platform/qemu/link-qemu.ld
  21. 0 39
      platform/qemu/src/hal.rs
  22. 0 67
      platform/qemu/src/hal/clint.rs
  23. 0 94
      platform/qemu/src/hal/ns16550a.rs
  24. 0 522
      platform/qemu/src/main.rs
  25. 0 28
      rustsbi/Cargo.toml
  26. 0 0
      src/ecall.rs
  27. 0 0
      src/ecall/base.rs
  28. 0 0
      src/ecall/hsm.rs
  29. 0 0
      src/ecall/ipi.rs
  30. 0 0
      src/ecall/legacy.rs
  31. 0 0
      src/ecall/rfence.rs
  32. 0 0
      src/ecall/srst.rs
  33. 0 0
      src/ecall/timer.rs
  34. 0 0
      src/extension.rs
  35. 0 0
      src/hart_mask.rs
  36. 0 0
      src/hsm.rs
  37. 0 0
      src/ipi.rs
  38. 0 0
      src/legacy_stdio.rs
  39. 0 0
      src/lib.rs
  40. 0 0
      src/logo.rs
  41. 0 0
      src/logo.txt
  42. 0 0
      src/privileged.rs
  43. 0 0
      src/reset.rs
  44. 0 0
      src/rfence.rs
  45. 0 0
      src/timer.rs
  46. 0 9
      test-kernel/.cargo/config.toml
  47. 0 12
      test-kernel/Cargo.toml
  48. 0 23
      test-kernel/build.rs
  49. 0 21
      test-kernel/justfile
  50. 0 40
      test-kernel/src/console.rs
  51. 0 38
      test-kernel/src/linker32.ld
  52. 0 43
      test-kernel/src/linker64.ld
  53. 0 181
      test-kernel/src/main.rs
  54. 0 126
      test-kernel/src/sbi.rs

+ 1 - 2
CHANGELOG.md

@@ -4,8 +4,6 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
-## [Unreleased]
-
 ## [0.2.0] - 2021-02-23
 ### Added
 - S-level Illegal instruction exception is now delegated into S-level software handler
@@ -14,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Support device tree binary in K210 platform
 
 ### Modified
+- Reform RustSBI project into a library
 - Function `rustsbi::ecall` now require 5 input parameters
 - Enhanced in-line code documents from SBI standard
 - Now IPI module requires to return an `SbiRet` value

+ 26 - 12
Cargo.toml

@@ -1,14 +1,28 @@
-[workspace]
-# RustSBI library and all supported platforms
-members = [
-    "rustsbi",
-    "platform/*",
-    "test-kernel",
-]
+[package]
+name = "rustsbi"
+description = "Minimal RISC-V's SBI implementation library in Rust"
+version = "0.2.0-alpha.3"
+authors = ["luojia65 <[email protected]>"]
+repository = "https://github.com/luojia65/rustsbi"
+documentation = "https://docs.rs/rustsbi"
+license = "MulanPSL-2.0 OR MIT"
+readme = "README.md"
+keywords = ["riscv", "sbi", "rustsbi"]
+categories = ["os", "embedded", "hardware-support", "no-std"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
-# these profiles are required for test kernel, not RustSBI library itself
-[profile.dev]
-panic = "abort"
+[package.metadata.docs.rs]
+default-target = "riscv64imac-unknown-none-elf"
+targets = [
+    "riscv32i-unknown-none-elf", "riscv32imc-unknown-none-elf", "riscv32imac-unknown-none-elf",
+    "riscv64imac-unknown-none-elf",
+]
 
-[profile.release]
-panic = "abort"
+[dependencies]
+embedded-hal = "1.0.0-alpha.1"
+nb = "1.0"
+riscv = "0.6"
+spin = "0.7"
+lazy_static = { version = "1", features = ["spin_no_std"] }

+ 3 - 25
README.md

@@ -8,12 +8,8 @@ RISC-V Supervisor Binary Interface ([SBI](https://github.com/riscv/riscv-sbi-doc
 
 ## Binary downloads
 
-See [releases](https://github.com/luojia65/rustsbi/releases).
-
-Binaries are available for platforms which can be found on
-[platform support page](https://github.com/luojia65/rustsbi/tree/master/platform).
-This page includes an instruction to write your own RustSBI implementation on production use,
-and some reference implementations for experiments.
+From version 0.2.0, RustSBI is reformed into a library, thus no longer provides binary downloads for specific platforms. 
+You may visit RustSBI-QEMU or RustSBI-K210 projects depending on the platforms you need. 
 
 ## Features
 
@@ -26,15 +22,6 @@ and some reference implementations for experiments.
 - Supports QEMU emulator (priv. spec v1.11)
 - Backward compatible to Kendryte K210 with spec v1.9, MMU and S-Mode
 
-## Components
-
-The RustSBI project contains three parts: the RustSBI library `rustsbi`, reference implementation
-in `platform`, and a simple operating system kernel to test SBI implementations in `test-kernel`.
-
-The test kernel is used to test SBI functions. Boot this kernel using your platform,
-it will call all SBI calls and run instructions to test if underlying SBI environment is okay.
-if this kernel reports 'SUCCESS' and exits normally, it means that your SBI implementation is correct.
-
 ## Frequently asked questions
 
 1. Can I use RustSBI on C based kernels?
@@ -64,10 +51,7 @@ Slides (Chinese):
 
 1. RustSBI can be used as a library. Under normal circumstances, RustSBI platform can be implemented
    with embedded Rust's `embedded-hal` libraries.
-2. On both QEMU and K210 platform, we supports CLINT and PLIC peripherals. Embedded Rust's community
-   still need more SoCs taped out to discuss on common libraries on RISC-V ecosystem. After these works
-   are done, we may use crates then to implement QEMU, without the `hal` module we have now.
-3. Contributions are welcomed! We welcome to implement RustSBI for both FPGA cores and real cores.
+2. Contributions are welcomed! We welcome to implement RustSBI for both FPGA cores and real cores.
    Implementations for emulators are also welcomed. Fire a pull request if you are ready!
 
 ## License & Copyright
@@ -76,9 +60,3 @@ This project is licensed under either of
 
 - MIT license ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
 - Mulan PSL v2 ([LICENSE-MULAN](LICENSE-MULAN) or [https://opensource.org/licenses/MulanPSL-2.0](https://opensource.org/licenses/MulanPSL-2.0))
-
-This project contains documents from [RISC-V SBI specification](https://github.com/riscv/riscv-sbi-doc)
-repository. These documents are (C) RISC-V community under CC-BY 4.0 license.
-
-Reference implementaion K210 includes Kendryte K210 DTS file from Western Digital, this file is
-(C) Western Digital Corporation or its affiliates under BSD-2-Clause license.

+ 0 - 132
platform/README.md

@@ -1,132 +0,0 @@
-# RustSBI platforms
-
-Currently provided reference platform support projects:
-
-| Platform | Legacy | Base | IPI | Timer | RFENCE | HSM | SRST | Note |
-|:---------|:------:|:----:|:---:|:-----:|:------:|:---:|:----:|:-----|
-| [Kendryte K210](./k210) | √ | √ | √ | √ | P | P | P | Privileged spec version: 1.9.1 |
-| [QEMU](./qemu)          | √ | √ | √ | √ | P | P | √ | - |
-
-P: Pending
-
-## Notes for binary releases
-
-These platform implementations are only for reference.
-Although binaries are released along with RustSBI library itself,
-platform developers should consider using RustSBI as a library,
-other than adding code into forked project's 'platforms' and make a pull request.
-
-The RustSBI project will release these platform binaries in release page.
-A RustSBI implementation in production is typically a separate project other than squashed into 'platform' path;
-but if you really want to contribute to these reference implementations, you may need to build these
-platform packages by yourself.
-
-### Build and install
-
-To build provided reference platforms, you should install the command runner `just`.
-Like `make`, [`just`](https://github.com/casey/just#just) is a handy way to save and run project specific commands.
-To install just, refer to `just` packages [link](https://github.com/casey/just#packages) and pick
-a install command according to your operating system used for development.
-
-Each reference platform have provided `justfile` configuration file.
-You may `cd` into project path and run command `just build` to build binary package.
-The binary package should be ready in some place under `target` folder.
-Or, use `just run` to build and execute it in emulator with a test kernel.
-
-## Support your own platform
-
-There are RISC-V cores, SoC's, and boards, we can not support them one by one with any software,
-typically platform vendor should provide their own SBI support package.
-RustSBI is designed as a 'building block' library to help on these support packages.
-
-To implement for their own platforms, vendor would typically follow these steps:
-
-1. Pick an RISC-V software runtime
-2. Initialize SBI functions into RustSBI
-3. Add additional support features
-
-### Pick a runtime
-
-When the processor is powering up, it executes few instructions to jump to a processor specific entry address.
-Your SBI implementation should be there, ready to be executed to prepare an environment for Rust code
-and interrupt environment.
-
-This runtime should contain two parts: programming language runtime and interrupt handler.
-Typically, processor vendor or SoC vendor should provide with a minimal runtime.
-Or else, [`riscv-rt`](https://github.com/rust-embedded/riscv-rt) project would be okay to be a runtime
-for all RISC-V chips, this project is provided by community to minimally support Rust language on
-standard RISC-V hardware.
-
-If we have to write own runtime, the runtime should initialize `bss` and `data` sections.
-Crate [`r0`](https://github.com/rust-embedded/r0) would help a lot if we do this work manually.
-
-When you begin to work with custom hardware e.g. interrupt controller, you should use vendor
-provided platform specific packages. Load trap configurations into registers in vendor defined procedures.
-This will provide a machine level trap handler for SBI implementation.
-
-After you pick a runtime, there should be one main entry function and a trap entry function.
-
-### Initialize and use SBI functions
-
-All SBI modules in RustSBI are described as Rust traits. Read RISC-V SBI manual carefully,
-or research on the operating systems you want to support to make a list of modules your SBI should support.
-
-Although it's a legacy function, `console_putchar` function by now is commonly used as an early debug output.
-Use an on-board serial transmitter half, or other ways to implemenet this function's corresponding Rust trait.
-Then, use `init_legacy_stdio` etc. to load this module into RustSBI. RustSBI's documentation lists all these
-traits that RustSBI supports.
-
-Basical function like `mvendorid` and module detections are handled by RustSBI.
-After the modules are initialized, RustSBI automatically implement module detection functions
-and provide an `ecall` handler. You should use this `ecall` handler in runtime defined trap handler,
-see documentation of `rustsbi::ecall` for details.
-
-RustSBI implmenetaion may print `rustsbi::LOGO` and `misa` onto early debug screen.
-There are also some functions in trap handler and entry which a typical SBI implmentation would write.
-Here's a checklist of these functions:
-
-- Delegate exceptions and interrupts to S privilege in `medeleg` and `mideleg`;
-- Emulate `rdtime` instruction in illegal instruction exception;
-- Raise invalid instruction to supervisor if `mstatus::MPP` is not `Machine`.
-
-When we write code for SBI functions, `embedded-hal` packages would be helpful.
-Some of these packages provide a universal abstract for SoC peripherals and are normally provided by SoC vendor.
-If our board uses peripheral outside the SoC, other packages would come into effect.
-
-After SBI functions are written, you should use `enter_privileged` function provided by RustSBI.
-This function uses an entry address of operating system where RustSBI would change privilege level
-and jump into. It would also requires a second opaque parameter that the OS would make use of.
-Now your operating system should boot up and function normally. Congratulations!
-
-### Additional support features
-
-Your prototype bootloader is functional now, to complete its design you may provide more features
-as a software product.
-
-On PC, SBI software would be flashed onto unique flash or small MCU to help boot the processor.
-The processor may be upgraded or replaced. You should check if the processor and its memory is okay.
-Pick or design a small program to check all RISC-V registers, instructions to check if the processor
-is not broken and is ready to run operating system.
-
-According to your platform, there could be a minimal hardware requirement. Personal computer platform
-may require a graphic hardware to boot, you should scan if your processor or board provides one graphic
-hardware. Scan other hardware to prepare for later boot sequences, like setting CPU clocks.
-
-The operating system could be placed anywhere. According to your platform, you may scan for storage
-or connect to the Internet for a functional operating system kernel. Fetch the kernel and provide
-its entry address into `enter_privileged` as mentioned above.
-If multiple operating systems are present, provide a user interface to help your user to select which
-kernel we should boot.
-
-During boot procedure, provide a way to debug hardware errors. For servers and developers,
-activate your on-board buzzer, or provide a debug interface like JTAG to tell where the error comes from.
-For DIY users and overclockers, you may provide EZDebug lights on your board and use SBI to control them.
-
-A full boot sequence may be different on different vendors, and wrong settings on boot sequence can be
-hard to debug. Read its manual carefully or consult the vendor to work out common bugs.
-
-## Reference
-
-Implement your SBI platform is easy! There exists some reference implementations in addition to this repository.
-
-- `terminus_bl` project is a RustSBI implementation for `terminus` emulator: [shady831213/terminus_bl](https://github.com/shady831213/terminus_bl).

+ 0 - 7
platform/k210/.cargo/config.toml

@@ -1,7 +0,0 @@
-[build]
-target = "riscv64imac-unknown-none-elf"
-
-[target.riscv64imac-unknown-none-elf]
-rustflags = [
-    "-C", "link-arg=-Tlink-k210.ld",
-]

+ 0 - 1
platform/k210/.gitignore

@@ -1 +0,0 @@
-kflash.py

+ 0 - 15
platform/k210/Cargo.toml

@@ -1,15 +0,0 @@
-[package]
-name = "rustsbi-k210"
-version = "0.2.0"
-authors = ["luojia65 <[email protected]>"]
-edition = "2018"
-publish = false
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-rustsbi = { path = "../../rustsbi" }
-riscv = { git = "https://github.com/rust-embedded/riscv", rev = "16e4870f", features = ["inline-asm"] }
-linked_list_allocator = "0.9"
-k210-hal = { git = "https://github.com/riscv-rust/k210-hal" }
-r0 = "1.0"

+ 0 - 72
platform/k210/README.md

@@ -1,72 +0,0 @@
-# K210 support module
-
-Kendryte K210 is a dual-core RISC-V RV64GC chip with hardware accelerated AI peripheral.
-According to its manual, K210 is taped out in TSMC 7nm and can speed up to 400MHz.
-
-## Implementation details
-
-The K210 SoC implements version 1.9.1 of RISC-V's privileged specification.
-This version differents from latest version (by current version 1.11) in the following aspects:
-
-1. Register `sstatus.sum` (in 1.11) or `sstatus.pum` (in 1.9) bits;
-2. Instruction `sfence.vma` (1.11) or `sfence.vm` (1.9), register `satp` (1.11) or `sptbr` (1.9);
-3. There's no S-level external interrupt in 1.9, but there is in 1.11;
-4. Independent page fault exceptions does not exist in 1.9, but they exist in 1.11.
-
-To prolong lifecycle of K210 chip we uses RustSBI as a compatible layer. We emulate sfence.vma 
-using sfence.vm to solve issue 2. We modify regster values to solve issue 4. For issue 3, 
-we introduce an SBI call local to RustSBI to register S-level interrupt handler by the supervisor 
-itself. The issue 1 should left to be concerned by supervisors above SBI implementations.
-
-Machine external handler and timer set calls is modified to meet the requirement of custom S-level
-interrupt handlers.
-
-If there are mistakes or missing features in current support module, we welcome further contributions!
-
-## Implementation specific SBI functions
-
-To solve the issue 3 in previous section, RustSBI's current implementation includes a RustSBI specific
-SBI call as a function. 
-
-The K210 supervisor-level external interrupt handler register function is declared as:
-
-```rust
-fn sbi_rustsbi_k210_sext(phys_addr: usize) -> SbiRet;
-```
-
-This function registers a device interrupt handler to machine level environment. 
-On any machine-level external interrupt, the RustSBI's K210 environment would call the function provided.
-
-The function's physical address shall be stored in register `a0` before calling this function.
-RustSBI will regard `a0` as a function without any parameters and any return values, or a `phys_addr: fn()`.
-
-This function will always return `SbiRet` value of zero and error code of `SBI_SUCCESS`.
-
-### Function Listing
-
-According to RISC-V SBI specification:
-
-> Firmware Code Base Specific SBI Extension Space, Extension Ids 0x0A000000 through 0x0AFFFFFF
-> 
-> Low bits is SBI implementation ID. The firmware code base SBI extension is the additional SBI extensions to SBI
-> implementation. That provides the firmware code base specific SBI functions which are defined in the external
-> firmware specification.
-
-Since RustSBI has the implementation ID 4, its specific SBI extension is `0x0A000004`. We add the function
-mentioned above to this specific SBI extension.
-
-| Function Name | Function ID | Extension ID |
-|:-----|:----|:----|
-| sbi_rustsbi_k210_sext | 0x210 | 0x0A000004 |
-
-### Notes for implementation developers
-
-## Recompile device tree binary file
-
-Use following command:
-
-```bash
-dtc -I dts -O dtb -o kendryte-k210.dtb kendryte-k210.dts
-```
-
-You need to have `device-tree-compiler` package installed in linux before using this command.

+ 0 - 18
platform/k210/build.rs

@@ -1,18 +0,0 @@
-use std::env;
-use std::fs;
-use std::io::Write;
-use std::path::PathBuf;
-
-fn main() {
-    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
-
-    // Put the linker script somewhere the linker can find it
-    fs::File::create(out_dir.join("link-k210.ld"))
-        .unwrap()
-        .write_all(include_bytes!("link-k210.ld"))
-        .unwrap();
-    println!("cargo:rustc-link-search={}", out_dir.display());
-
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-changed=link-k210.ld");
-}

+ 0 - 30
platform/k210/justfile

@@ -1,30 +0,0 @@
-target := "riscv64imac-unknown-none-elf"
-mode := "debug"
-build-path := "../../target/" + target + "/" + mode + "/"
-rustsbi-elf := build-path + "rustsbi-k210"
-rustsbi-bin := build-path + "rustsbi-k210.bin"
-test-kernel-elf := build-path + "test-kernel"
-test-kernel-bin := build-path + "test-kernel.bin"
-fused-bin := build-path + "k210-fused.bin"
-
-k210-serialport := "COM17"
-
-objdump := "riscv64-unknown-elf-objdump"
-objcopy := "rust-objcopy --binary-architecture=riscv64"
-
-build: rustsbi test-kernel
-    @{{objcopy}} {{rustsbi-elf}} --strip-all -O binary {{rustsbi-bin}}
-
-rustsbi:
-    @cargo build --target={{target}}
-
-test-kernel:
-    @just -f "../../test-kernel/justfile" build
-
-run: build
-    @cp {{rustsbi-bin}} {{fused-bin}}
-    @dd if={{test-kernel-bin}} of={{fused-bin}} bs=128k seek=1
-    @python ./kflash.py --port {{k210-serialport}} -b 1500000 --terminal {{fused-bin}}
-
-asm: build
-    @{{objdump}} -D {{rustsbi-elf}} | less

BIN
platform/k210/kendryte-k210.dtb


+ 0 - 70
platform/k210/kendryte-k210.dts

@@ -1,70 +0,0 @@
-/*
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2019 Western Digital Corporation or its affiliates.
- *
- * Authors:
- *   Damien Le Moal <[email protected]>
- */
-
-/dts-v1/;
-/ {
-	#address-cells = <2>;
-	#size-cells = <2>;
-	compatible = "kendryte,k210";
-
-	chosen {
-        bootargs = "console=hvc0 earlycon=sbi";
-	};
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		cpu0: cpu@0 {
-			device_type = "cpu";
-			clock-frequency = <390000000>;
-			i-cache-size = <32768>;
-			d-cache-size = <32768>;
-			mmu-type = "none";
-			reg = <0>;
-			riscv,isa = "rv64imafdc";
-			status = "okay";
-			cpu0_intc: interrupt-controller {
-				#interrupt-cells = <1>;
-				compatible = "riscv,cpu-intc";
-				interrupt-controller;
-			};
-		};
-		cpu1: cpu@1 {
-			device_type = "cpu";
-			clock-frequency = <390000000>;
-			d-cache-size = <32768>;
-			i-cache-size = <32768>;
-			mmu-type = "none";
-			reg = <1>;
-			riscv,isa = "rv64imafdc";
-			status = "okay";
-			cpu1_intc: interrupt-controller {
-				#interrupt-cells = <1>;
-				compatible = "riscv,cpu-intc";
-				interrupt-controller;
-			};
-		};
-	};
-
-	memory@80000000 {
-		/* Bank 0: 4 MB, Bank 1: 2 MB, AI chip SRAM: 2MB */
-		device_type = "memory";
-		reg = <0x00000000 0x80000000 0x00000000 0x00800000>;
-	};
-
-	plic0: interrupt-controller@C000000 {
-		#interrupt-cells = <1>;
-		compatible = "riscv,plic0";
-		interrupt-controller;
-		interrupts-extended =
-			<&cpu0_intc 11 &cpu0_intc 9
-			 &cpu1_intc 11 &cpu1_intc 9>;
-		reg = <0x0 0xc000000 0x0 0x4000000>;
-	};
-};

+ 0 - 87
platform/k210/link-k210.ld

@@ -1,87 +0,0 @@
-MEMORY {
-    /* 存储单元的物理地址 */
-    SRAM : ORIGIN = 0x80000000, LENGTH = 128K
-}
-
-_max_hart_id = 1; 
-
-PROVIDE(_stext = 0x80000000);
-PROVIDE(_heap_size = 32K);
-PROVIDE(_hart_stack_size = 16K);
-
-REGION_ALIAS("REGION_TEXT", SRAM);
-REGION_ALIAS("REGION_RODATA", SRAM);
-REGION_ALIAS("REGION_DATA", SRAM);
-REGION_ALIAS("REGION_BSS", SRAM);
-REGION_ALIAS("REGION_HEAP", SRAM);
-REGION_ALIAS("REGION_STACK", SRAM);
-
-OUTPUT_ARCH(riscv)
-
-ENTRY(_start)
-
-PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
-
-SECTIONS
-{
-    /* .text 字段 */
-    .text _stext : {
-        /* 把 entry 函数放在最前面 */
-        *(.text.entry)
-        /* 要链接的文件的 .text 字段集中放在这里 */
-        *(.text .text.*)
-        _etext = .;
-    } > REGION_TEXT
-
-    /* .rodata 字段 */
-    .rodata : ALIGN(4) {
-        _srodata = .;
-        /* 要链接的文件的 .rodata 字段集中放在这里 */
-        *(.rodata .rodata.*)
-        . = ALIGN(4);
-        _erodata = .;
-    } > REGION_RODATA
-
-    /* .data 字段 */
-    .data : ALIGN(4) { 
-        _sidata = LOADADDR(.data);
-        _sdata = .;
-        /* Must be called __global_pointer$ for linker relaxations to work. */
-        PROVIDE(__global_pointer$ = . + 0x800);
-        /* 要链接的文件的 .data 字段集中放在这里 */
-        *(.sdata .sdata.* .sdata2 .sdata2.*);
-        *(.data .data.*)
-        . = ALIGN(4);
-        _edata = .;
-    } > REGION_DATA
-
-    /* .bss 字段 */
-    .bss (NOLOAD) : {
-        _sbss = .;
-        /* 要链接的文件的 .bss 字段集中放在这里 */
-        *(.sbss .bss .bss.*)
-        . = ALIGN(4);
-        _ebss = .;
-    } > REGION_BSS
-
-    .heap (NOLOAD) : {
-        _sheap = .;
-        . += _heap_size;
-        . = ALIGN(4);
-        _eheap = .;
-    } > REGION_HEAP
-
-    /* fictitious region that represents the memory available for the stack */
-    .stack (NOLOAD) : {
-        _estack = .;
-        . = _stack_start;
-        . = ALIGN(4);
-        _sstack = .;
-    } > REGION_STACK
-
-    /* Discard .eh_frame, we are not doing unwind on panic so it is not needed */
-    /DISCARD/ :
-    {
-        *(.eh_frame .eh_frame_hdr);
-    }
-}

+ 0 - 586
platform/k210/src/main.rs

@@ -1,586 +0,0 @@
-#![no_std]
-#![no_main]
-#![feature(alloc_error_handler)]
-#![feature(global_asm)]
-#![feature(llvm_asm)]
-
-#[cfg(not(test))]
-use core::alloc::Layout;
-#[cfg(not(test))]
-use core::panic::PanicInfo;
-use k210_hal::{clock::Clocks, fpioa, pac, prelude::*};
-use linked_list_allocator::LockedHeap;
-use rustsbi::{enter_privileged, print, println};
-use riscv::register::{
-    mcause::{self, Exception, Interrupt, Trap},
-    medeleg, mepc, mhartid, mideleg, mie, mip, misa::{self, MXL},
-    mstatus::{self, MPP, SPP},
-    mtval,
-    mtvec::{self, TrapMode},
-    satp, stvec, scause, stval, sepc,
-};
-
-#[global_allocator]
-static ALLOCATOR: LockedHeap = LockedHeap::empty();
-
-static mut DEVINTRENTRY: usize = 0;
-
-static DEVICE_TREE_BINARY: &[u8] = include_bytes!("../kendryte-k210.dtb");
-
-#[cfg(not(test))]
-#[panic_handler]
-fn panic(info: &PanicInfo) -> ! {
-    println!("[rustsbi] {}", info);
-    loop {}
-}
-
-#[cfg(not(test))]
-#[alloc_error_handler]
-fn oom(layout: Layout) -> ! {
-    println!("[rustsbi] out of memory for layout {:?}", layout);
-    loop {}
-}
-
-fn mp_hook() -> bool {
-    use riscv::asm::wfi;
-    use k210_hal::clint::msip;
-
-    let hartid = mhartid::read();
-    if hartid == 0 {
-        true
-    } else {
-        unsafe {
-            // Clear IPI
-            msip::clear_ipi(hartid);
-            // Start listening for software interrupts
-            mie::set_msoft();
-
-            loop {
-                wfi();
-                if mip::read().msoft() {
-                    break;
-                }
-            }
-
-            // Stop listening for software interrupts
-            mie::clear_msoft();
-            // Clear IPI
-            msip::clear_ipi(hartid);
-        }
-        false
-    }
-}
-
-#[export_name = "_start"]
-#[link_section = ".text.entry"] // this is stable
-fn main() -> ! {
-    unsafe {
-        llvm_asm!(
-            "
-        csrr    a2, mhartid
-        lui     t0, %hi(_max_hart_id)
-        add     t0, t0, %lo(_max_hart_id)
-        bgtu    a2, t0, _start_abort
-        la      sp, _stack_start
-        lui     t0, %hi(_hart_stack_size)
-        add     t0, t0, %lo(_hart_stack_size)
-    .ifdef __riscv_mul
-        mul     t0, a2, t0
-    .else
-        beqz    a2, 2f  // Jump if single-hart
-        mv      t1, a2
-        mv      t2, t0
-    1:
-        add     t0, t0, t2
-        addi    t1, t1, -1
-        bnez    t1, 1b
-    2:
-    .endif
-        sub     sp, sp, t0
-        csrw    mscratch, zero
-        j _start_success
-        
-    _start_abort:
-        wfi
-        j _start_abort
-    _start_success:
-        
-    "
-        )
-    };
-    if mp_hook() {
-        extern "C" {
-            static mut _ebss: u32;
-            static mut _sbss: u32;
-            static mut _edata: u32;
-            static mut _sdata: u32;
-            static _sidata: u32;
-        }
-        unsafe {
-            r0::zero_bss(&mut _sbss, &mut _ebss);
-            r0::init_data(&mut _sdata, &mut _edata, &_sidata);
-        } 
-    }
-
-    extern "C" {
-        fn _start_trap();
-    }
-    unsafe {
-        mtvec::write(_start_trap as usize, TrapMode::Direct);
-    }
-    if mhartid::read() == 0 {
-        extern "C" {
-            fn _sheap();
-            fn _heap_size();
-        }
-        let sheap = &mut _sheap as *mut _ as usize;
-        let heap_size = &_heap_size as *const _ as usize;
-        unsafe {
-            ALLOCATOR.lock().init(sheap, heap_size);
-        }
-
-        let p = pac::Peripherals::take().unwrap();
-
-        let mut sysctl = p.SYSCTL.constrain();
-        let fpioa = p.FPIOA.split(&mut sysctl.apb0);
-        let clocks = Clocks::new();
-        let _uarths_tx = fpioa.io5.into_function(fpioa::UARTHS_TX);
-        let _uarths_rx = fpioa.io4.into_function(fpioa::UARTHS_RX);
-        // Configure UART
-        let serial = p.UARTHS.configure(115_200.bps(), &clocks);
-        let (tx, rx) = serial.split();
-        use rustsbi::legacy_stdio::init_legacy_stdio_embedded_hal_fuse;
-        init_legacy_stdio_embedded_hal_fuse(tx, rx);
-
-        struct Ipi;
-        impl rustsbi::Ipi for Ipi {
-            fn max_hart_id(&self) -> usize {
-                1
-            }
-            fn send_ipi_many(&mut self, hart_mask: rustsbi::HartMask) -> rustsbi::SbiRet {
-                use k210_hal::clint::msip;
-                for i in 0..=1 {
-                    if hart_mask.has_bit(i) {
-                        msip::set_ipi(i);
-                        msip::clear_ipi(i);
-                    }
-                }
-                rustsbi::SbiRet::ok(0)
-            }
-        }
-        use rustsbi::init_ipi;
-        init_ipi(Ipi);
-        struct Timer;
-        impl rustsbi::Timer for Timer {
-            fn set_timer(&mut self, stime_value: u64) {
-                // This function must clear the pending timer interrupt bit as well.
-                use k210_hal::clint::mtimecmp;
-                mtimecmp::write(mhartid::read(), stime_value);
-                unsafe { mip::clear_mtimer() };
-            }
-        }
-        use rustsbi::init_timer;
-        init_timer(Timer);
-
-        struct Reset;
-        impl rustsbi::Reset for Reset {
-            fn system_reset(&self, reset_type: usize, reset_reason: usize) -> rustsbi::SbiRet {
-                println!("[rustsbi] reset triggered! todo: shutdown all harts on k210; program halt. Type: {}, reason: {}", reset_type, reset_reason);
-                loop {}
-            }
-        }
-        use rustsbi::init_reset;
-        init_reset(Reset);
-
-        use k210_hal::plic::Priority;
-        use k210_hal::pac::Interrupt;
-        use k210_hal::gpiohs::Edge;
-        unsafe { 
-            pac::PLIC::set_threshold(mhartid::read(), Priority::P0);
-        }
-        let gpiohs = p.GPIOHS.split();
-        fpioa.io16.into_function(fpioa::GPIOHS0);
-        let mut boot = gpiohs.gpiohs0.into_pull_up_input();
-        boot.trigger_on_edge(Edge::RISING | Edge::FALLING);
-        unsafe {
-            pac::PLIC::set_priority(Interrupt::GPIOHS0, Priority::P1);
-            pac::PLIC::unmask(mhartid::read(), Interrupt::GPIOHS0);
-        }
-        boot.clear_interrupt_pending_bits();
-    }
-
-    unsafe {
-        //mideleg::set_sext();
-        mideleg::set_stimer();
-        mideleg::set_ssoft();
-        medeleg::set_instruction_misaligned();
-        medeleg::set_breakpoint();
-        medeleg::set_user_env_call();
-        /* MMU Exception Delegation
-        /* Page Faults are *Reserved* in 1.9.1 version */
-        - medeleg::set_instruction_page_fault();
-        - medeleg::set_load_page_fault();
-        - medeleg::set_store_page_fault();
-        /* Actually, in 1.9.1 they are merged into more general exceptions */
-        + medeleg::set_instruction_fault();
-        + medeleg::set_load_fault();
-        + medeleg::set_store_fault(); */
-        medeleg::set_instruction_fault();
-        medeleg::set_load_fault();
-        medeleg::set_store_fault();
-        // 默认不打开mie::set_mext
-        // 不打开mie::set_mtimer
-        mie::set_msoft();
-    }
-
-    if mhartid::read() == 0 {
-        println!("[rustsbi] RustSBI version {}", rustsbi::VERSION);
-        println!("{}", rustsbi::LOGO);
-        println!("[rustsbi] Platform: K210 (Version {})", env!("CARGO_PKG_VERSION"));
-        let isa = misa::read();
-        if let Some(isa) = isa {
-            let mxl_str = match isa.mxl() {
-                MXL::XLEN32 => "RV32",
-                MXL::XLEN64 => "RV64",
-                MXL::XLEN128 => "RV128",
-            };
-            print!("[rustsbi] misa: {}", mxl_str);
-            for ext in 'A'..='Z' {
-                if isa.has_extension(ext) {
-                    print!("{}", ext);
-                }
-            }
-            println!("");
-        }
-        println!("[rustsbi] mideleg: {:#x}", mideleg::read().bits());
-        println!("[rustsbi] medeleg: {:#x}", medeleg::read().bits());
-        println!("[rustsbi] Kernel entry: 0x80020000");
-    }
-    extern "C" {
-        fn _s_mode_start();
-    }
-    unsafe {
-        mepc::write(_s_mode_start as usize);
-        mstatus::set_mpp(MPP::Supervisor);
-        enter_privileged(mhartid::read(), DEVICE_TREE_BINARY.as_ptr() as usize);
-    }
-}
-
-global_asm!(
-    "
-    .section .text
-    .globl _s_mode_start
-_s_mode_start:
-1:  auipc ra, %pcrel_hi(1f)
-    ld ra, %pcrel_lo(1b)(ra)
-    jr ra
-.align  3
-1:  .dword 0x80020000
-"
-);
-
-// todo: configurable target address
-
-global_asm!(
-    "
-    .equ REGBYTES, 8
-    .macro STORE reg, offset
-        sd  \\reg, \\offset*REGBYTES(sp)
-    .endm
-    .macro LOAD reg, offset
-        ld  \\reg, \\offset*REGBYTES(sp)
-    .endm
-    .section .text
-    .global _start_trap
-    .p2align 2
-_start_trap:
-    csrrw   sp, mscratch, sp
-    bnez    sp, 1f
-    /* from M level, load sp */
-    csrrw   sp, mscratch, zero
-1:
-    addi    sp, sp, -16 * REGBYTES
-    STORE   ra, 0
-    STORE   t0, 1
-    STORE   t1, 2
-    STORE   t2, 3
-    STORE   t3, 4
-    STORE   t4, 5
-    STORE   t5, 6
-    STORE   t6, 7
-    STORE   a0, 8
-    STORE   a1, 9
-    STORE   a2, 10
-    STORE   a3, 11
-    STORE   a4, 12
-    STORE   a5, 13
-    STORE   a6, 14
-    STORE   a7, 15
-    mv      a0, sp
-    call    _start_trap_rust
-    LOAD    ra, 0
-    LOAD    t0, 1
-    LOAD    t1, 2
-    LOAD    t2, 3
-    LOAD    t3, 4
-    LOAD    t4, 5
-    LOAD    t5, 6
-    LOAD    t6, 7
-    LOAD    a0, 8
-    LOAD    a1, 9
-    LOAD    a2, 10
-    LOAD    a3, 11
-    LOAD    a4, 12
-    LOAD    a5, 13
-    LOAD    a6, 14
-    LOAD    a7, 15
-    addi    sp, sp, 16 * REGBYTES
-    csrrw   sp, mscratch, sp
-    mret
-"
-);
-
-#[allow(unused)]
-struct TrapFrame {
-    ra: usize,
-    t0: usize,
-    t1: usize,
-    t2: usize,
-    t3: usize,
-    t4: usize,
-    t5: usize,
-    t6: usize,
-    a0: usize,
-    a1: usize,
-    a2: usize,
-    a3: usize,
-    a4: usize,
-    a5: usize,
-    a6: usize,
-    a7: usize,
-}
-
-impl core::fmt::Display for TrapFrame {
-    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
-        writeln!(f, "")?;
-        writeln!(f, "ra: {:016x}, t0: {:016x}, t1: {:016x}, t2: {:016x}", self.ra, self.t0, self.t1, self.t2)?;
-        writeln!(f, "t3: {:016x}, t4: {:016x}, t5: {:016x}, t6: {:016x}", self.t3, self.t4, self.t5, self.t6)?;
-        writeln!(f, "a0: {:016x}, a1: {:016x}, a2: {:016x}, a3: {:016x}", self.a0, self.a1, self.a2, self.a3)?;
-        writeln!(f, "a4: {:016x}, a5: {:016x}, a6: {:016x}, a7: {:016x}", self.a4, self.a5, self.a6, self.a7)
-    }
-}
-
-#[export_name = "_start_trap_rust"]
-extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
-    let cause = mcause::read().cause();
-    match cause {
-        Trap::Exception(Exception::SupervisorEnvCall) => {
-            if trap_frame.a7 == 0x0A000004 && trap_frame.a6 == 0x210 {
-                // We use implementation specific sbi_rustsbi_k210_sext function (extension 
-                // id: 0x0A000004, function id: 0x210) to register S-level interrupt handler
-                // for K210 chip only. This chip uses 1.9.1 version of privileged spec,
-                // which did not declare any S-level external interrupts. 
-                unsafe { DEVINTRENTRY = trap_frame.a0; }
-                // enable mext
-                unsafe { mie::set_mext(); }
-                // return values
-                trap_frame.a0 = 0; // SbiRet::error = SBI_SUCCESS
-                trap_frame.a1 = 0; // SbiRet::value = 0
-            } else {
-                // Due to legacy 1.9.1 version of privileged spec, if we are in S-level
-                // timer handler (delegated from M mode), and we call SBI's `set_timer`,
-                // a M-level external interrupt may be triggered. This may try to obtain
-                // data structures locked previously by S-level interrupt handler, which
-                // results in a deadlock. 
-                // Ref: https://github.com/luojia65/rustsbi/pull/5 
-                if trap_frame.a7 == 0x0 {
-                    unsafe {
-                        let mtip = mip::read().mtimer();
-                        if mtip {
-                            if DEVINTRENTRY != 0 {
-                                mie::set_mext();
-                            }
-                        }
-                    }
-                }
-                // Actual ecall handler which is common for all RustSBI platforms
-                let params = [trap_frame.a0, trap_frame.a1, trap_frame.a2, trap_frame.a3, trap_frame.a4];
-                let ans = rustsbi::ecall(trap_frame.a7, trap_frame.a6, params);
-                trap_frame.a0 = ans.error;
-                trap_frame.a1 = ans.value;
-            }
-            mepc::write(mepc::read().wrapping_add(4));
-        }
-        Trap::Interrupt(Interrupt::MachineSoft) => {
-            // Forward to S-level software interrupt
-            unsafe {
-                mip::set_ssoft(); // set S-soft interrupt flag
-                mie::clear_msoft(); // mask M-soft interrupt
-            }
-        }
-        Trap::Interrupt(Interrupt::MachineTimer) => {
-            // Forward to S-level timer interrupt
-            unsafe {
-                mip::set_stimer(); // set S-timer interrupt flag
-                mie::clear_mext(); // Ref: Pull request #5
-                mie::clear_mtimer(); // mask M-timer interrupt
-            }
-        }
-        Trap::Interrupt(Interrupt::MachineExternal) => {
-            /* legacy software delegation
-            // to make UARTHS interrupt soft delegation work; ref: pull request #1
-            // PLIC target0(Always Hart0-M-Interrupt) acquire
-            let irq_id = unsafe { (0x0c20_0004 as *const u32).read_volatile() };
-            // read from UARTHS RXFIFO
-            let ch: u8 = unsafe { (0x3800_0004 as *const u32).read_volatile() & 0xFF } as u8;
-            // black magic @_@, soft delegation won't success without it!
-            print!("{}", 0 as char);
-            // PLIC complete
-            unsafe { (0x0c20_0004 as *mut u32).write_volatile(irq_id); }
-            // communicate with delegated interrupt with stval CSR 
-            unsafe { llvm_asm!("csrw stval, $0" :: "r"(ch as usize) :: "volatile"); }
-            // soft delegate to S Mode soft interrupt
-            unsafe { mip::set_ssoft(); }
-             */
-            unsafe {
-                let mut mstatus: usize;
-                llvm_asm!("csrr $0, mstatus" : "=r"(mstatus) ::: "volatile");
-                // set mstatus.mprv
-                mstatus |= 1 << 17;
-                // it may trap from U/S Mode
-                // save mpp and set mstatus.mpp to S Mode
-                let mpp = (mstatus >> 11) & 3;
-                mstatus = mstatus & !(3 << 11);
-                mstatus |= 1 << 11;
-                // drop mstatus.mprv protection
-                llvm_asm!("csrw mstatus, $0" :: "r"(mstatus) :: "volatile");
-                fn devintr() {
-                    unsafe {
-                        // call devintr defined in application
-                        // we have to ask compiler save ra explicitly
-                        llvm_asm!("jalr 0($0)" :: "r"(DEVINTRENTRY) : "ra" : "volatile");
-                    }
-                }
-                // compiler helps us save/restore caller-saved registers
-                devintr();
-                // restore mstatus
-                mstatus = mstatus &!(3 << 11);
-                mstatus |= mpp << 11;
-                mstatus -= 1 << 17;
-                llvm_asm!("csrw mstatus, $0" :: "r"(mstatus) :: "volatile");
-            }
-        }
-        Trap::Exception(Exception::IllegalInstruction) => {
-            let vaddr = mepc::read();
-            let ins = unsafe { get_vaddr_u32(vaddr) };
-            if ins & 0xFFFFF07F == 0xC0102073 { // rdtime instruction
-                // rdtime is actually a csrrw instruction
-                let rd = ((ins >> 7) & 0b1_1111) as u8;
-                let mtime = k210_hal::clint::mtime::read();
-                let time_usize = mtime as usize;
-                set_rd(trap_frame, rd, time_usize);
-                mepc::write(mepc::read().wrapping_add(4)); // skip current instruction 
-            } else if ins & 0xFE007FFF == 0x12000073 { // sfence.vma instruction
-                // There is no `sfence.vma` in 1.9.1 privileged spec; however there is a `sfence.vm`.
-                // For backward compability, here we emulate the first instruction using the second one.
-                // sfence.vma: | 31..25 funct7=SFENCE.VMA(0001001) | 24..20 rs2/asid | 19..15 rs1/vaddr | 
-                //               14..12 funct3=PRIV(000) | 11..7 rd, =0 | 6..0 opcode=SYSTEM(1110011) |
-                // sfence.vm(1.9):  | 31..=20 SFENCE.VM(000100000100) | 19..15 rs1/vaddr |
-                //               14..12 funct3=PRIV(000) | 11..7 rd, =0 | 6..0 opcode=SYSTEM(1110011) |
-                // discard rs2 // let _rs2_asid = ((ins >> 20) & 0b1_1111) as u8;
-                // let rs1_vaddr = ((ins >> 15) & 0b1_1111) as u8;
-                // read paging mode from satp (sptbr)
-                let satp_bits = satp::read().bits();
-                // bit 63..20 is not readable and writeable on K210, so we cannot
-                // decide paging type from the 'satp' register.
-                // that also means that the asid function is not usable on this chip.
-                // we have to fix it to be Sv39.
-                let ppn = satp_bits & 0xFFF_FFFF_FFFF; // 43..0 PPN WARL
-                // write to sptbr
-                let sptbr_bits = ppn & 0x3F_FFFF_FFFF;
-                unsafe { llvm_asm!("csrw 0x180, $0"::"r"(sptbr_bits)) }; // write to sptbr
-                // enable paging (in v1.9.1, mstatus: | 28..24 VM[4:0] WARL | ... )
-                let mut mstatus_bits: usize; 
-                unsafe { llvm_asm!("csrr $0, mstatus":"=r"(mstatus_bits)) };
-                mstatus_bits &= !0x1F00_0000;
-                mstatus_bits |= 9 << 24; 
-                unsafe { llvm_asm!("csrw mstatus, $0"::"r"(mstatus_bits)) };
-                // emulate with sfence.vm (declared in privileged spec v1.9)
-                unsafe { llvm_asm!(".word 0x10400073") }; // sfence.vm x0
-                // ::"r"(rs1_vaddr)
-                mepc::write(mepc::read().wrapping_add(4)); // skip current instruction
-            } else if mstatus::read().mpp() != MPP::Machine { // invalid instruction, can't emulate, raise to supervisor
-                // 出现非法指令异常,转发到S特权层
-                unsafe { 
-                    scause::set(scause::Trap::Exception(scause::Exception::IllegalInstruction));
-                    stval::write(mtval::read());
-                    sepc::write(mepc::read());
-                    mstatus::set_mpp(MPP::Supervisor);
-                    mstatus::set_spp(SPP::Supervisor);
-                    if mstatus::read().sie() {
-                        mstatus::set_spie()
-                    }
-                    mstatus::clear_sie();
-                    mepc::write(stvec::read().address());
-                };
-            } else { // 真正来自M特权层的异常
-                panic!(
-                    "invalid instruction from machine level, mepc: {:016x?}, instruction: {:08x?}, trap frame: {}", 
-                    mepc::read(), ins, trap_frame
-                );
-            }
-        }
-        cause => panic!(
-            "unhandled trap, mcause: {:?}, mepc: {:016x?}, mtval: {:016x?}, trap frame: {}",
-            cause,
-            mepc::read(),
-            mtval::read(),
-            trap_frame
-        ),
-    }
-}
-
-#[inline]
-unsafe fn get_vaddr_u32(vaddr: usize) -> u32 {
-    // todo: comment
-    get_vaddr_u16(vaddr) as u32 | 
-    ((get_vaddr_u16(vaddr.wrapping_add(2)) as u32) << 16)
-}
-
-#[inline]
-unsafe fn get_vaddr_u16(vaddr: usize) -> u16 {
-    let mut ans: u16;
-    llvm_asm!("
-        li      t0, (1 << 17)
-        csrrs   t0, mstatus, t0
-        lhu     $0, 0($1)
-        csrw    mstatus, t0
-    "
-        :"=r"(ans) 
-        :"r"(vaddr)
-        :"t0", "t1");
-    ans
-}
-
-#[inline]
-fn set_rd(trap_frame: &mut TrapFrame, rd: u8, value: usize) {
-    match rd {
-        10 => trap_frame.a0 = value,
-        11 => trap_frame.a1 = value,
-        12 => trap_frame.a2 = value,
-        13 => trap_frame.a3 = value,
-        14 => trap_frame.a4 = value,
-        15 => trap_frame.a5 = value,
-        16 => trap_frame.a6 = value,
-        17 => trap_frame.a7 = value,
-        5  => trap_frame.t0 = value,
-        6  => trap_frame.t1 = value,
-        7  => trap_frame.t2 = value,
-        28 => trap_frame.t3 = value,
-        29 => trap_frame.t4 = value,
-        30 => trap_frame.t5 = value,
-        31 => trap_frame.t6 = value,
-        _ => panic!("invalid target `rd`"),
-    }
-}
-

+ 0 - 7
platform/qemu/.cargo/config.toml

@@ -1,7 +0,0 @@
-[build]
-target = "riscv64imac-unknown-none-elf"
-
-[target.riscv64imac-unknown-none-elf]
-rustflags = [
-    "-C", "link-arg=-Tlink-qemu.ld",
-]

+ 0 - 21
platform/qemu/Cargo.toml

@@ -1,21 +0,0 @@
-[package]
-name = "rustsbi-qemu"
-version = "0.2.0"
-authors = ["luojia65 <[email protected]>"]
-edition = "2018"
-publish = false
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-rustsbi = { path = "../../rustsbi" }
-
-linked_list_allocator = "0.8"
-lazy_static = { version = "1", features = ["spin_no_std"] }
-spin = "0.7"
-riscv = { git = "https://github.com/rust-embedded/riscv", rev = "7e9d2e5b", features = ["inline-asm"] }
-device_tree = { git = "https://github.com/rcore-os/device_tree-rs/" }
-
-# 这几个其实不用,应该使用对应的hal库实现
-embedded-hal = "1.0.0-alpha.1"
-nb = "1"

+ 0 - 32
platform/qemu/README.md

@@ -1,32 +0,0 @@
-# QEMU example support using RustSBI
-
-Compile and run with:
-
-```shell
-just run
-```
-
-When running `just run`, the test kernel will build and run. Expected output should be:
-
-```shell
-   Compiling rustsbi-qemu v0.1.0 (.../rustsbi/platform/qemu)
-    Finished dev [unoptimized + debuginfo] target(s) in 1.62s
-[rustsbi] RustSBI version 0.1.1
-.______       __    __      _______.___________.  _______..______   __
-|   _  \     |  |  |  |    /       |           | /       ||   _  \ |  |
-|  |_)  |    |  |  |  |   |   (----`---|  |----`|   (----`|  |_)  ||  |
-|      /     |  |  |  |    \   \       |  |      \   \    |   _  < |  |
-|  |\  \----.|  `--'  |.----)   |      |  |  .----)   |   |  |_)  ||  |
-| _| `._____| \______/ |_______/       |__|  |_______/    |______/ |__|
-
-[rustsbi] Platform: QEMU (Version 0.1.0)
-[rustsbi] misa: RV64ACDFIMSU
-[rustsbi] mideleg: 0x222
-[rustsbi] medeleg: 0xb1ab
-[rustsbi-dtb] Hart count: cluster0 with 2 cores
-[rustsbi] Kernel entry: 0x80200000
-<< Test-kernel: Hart id = 0, DTB physical address = 0x1020
->> Test-kernel: Trigger illegal exception
-<< Test-kernel: Illegal exception delegate success
-<< Test-kernel: SBI test SUCCESS, shutdown
-```

+ 0 - 18
platform/qemu/build.rs

@@ -1,18 +0,0 @@
-use std::env;
-use std::fs;
-use std::io::Write;
-use std::path::PathBuf;
-
-fn main() {
-    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
-
-    // Put the linker script somewhere the linker can find it
-    fs::File::create(out_dir.join("link-qemu.ld"))
-        .unwrap()
-        .write_all(include_bytes!("link-qemu.ld"))
-        .unwrap();
-    println!("cargo:rustc-link-search={}", out_dir.display());
-
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-changed=link-qemu.ld");
-}

+ 0 - 52
platform/qemu/justfile

@@ -1,52 +0,0 @@
-target := "riscv64imac-unknown-none-elf"
-mode := "debug"
-build-path := "../../target/" + target + "/" + mode + "/"
-rustsbi-elf := build-path + "rustsbi-qemu"
-rustsbi-bin := build-path + "rustsbi-qemu.bin"
-test-kernel-elf := build-path + "test-kernel"
-test-kernel-bin := build-path + "test-kernel.bin"
-
-objdump := "riscv64-unknown-elf-objdump"
-objcopy := "rust-objcopy --binary-architecture=riscv64"
-gdb := "riscv64-unknown-elf-gdb"
-
-threads := "2"
-
-build: rustsbi test-kernel
-    @{{objcopy}} {{rustsbi-elf}} --strip-all -O binary {{rustsbi-bin}}
-
-rustsbi:
-    @cargo build --target={{target}}
-
-test-kernel:
-    @just -f "../../test-kernel/justfile" build
-
-qemu: build
-    @qemu-system-riscv64 \
-            -machine virt \
-            -nographic \
-            -bios none \
-            -device loader,file={{rustsbi-bin}},addr=0x80000000 \
-            -device loader,file={{test-kernel-bin}},addr=0x80200000 \
-            -smp threads={{threads}}
-
-run: build qemu
-
-asm: build
-    @{{objdump}} -D {{rustsbi-elf}} | less
-
-debug: build
-    @qemu-system-riscv64 \
-            -machine virt \
-            -nographic \
-            -bios none \
-            -device loader,file={{rustsbi-bin}},addr=0x80000000 \
-            -device loader,file={{test-kernel-bin}},addr=0x80200000 \
-            -smp threads={{threads}} \
-            -gdb tcp::1234 -S
-
-gdb: 
-    @{{gdb}} --eval-command="file {{rustsbi-elf}}" --eval-command="target remote localhost:1234"
-
-gdb-kernel: 
-    @{{gdb}} --eval-command="file {{test-kernel-elf}}" --eval-command="target remote localhost:1234"

+ 0 - 86
platform/qemu/link-qemu.ld

@@ -1,86 +0,0 @@
-MEMORY {
-    /* 存储单元的物理地址 */
-    SRAM : ORIGIN = 0x80000000, LENGTH = 2M
-}
-
-PROVIDE(_stext = 0x80000000);
-PROVIDE(_heap_size = 128K);
-PROVIDE(_hart_stack_size = 64K);
-PROVIDE(_max_hart_id = 7); /* todo */
-
-REGION_ALIAS("REGION_TEXT", SRAM);
-REGION_ALIAS("REGION_RODATA", SRAM);
-REGION_ALIAS("REGION_DATA", SRAM);
-REGION_ALIAS("REGION_BSS", SRAM);
-REGION_ALIAS("REGION_HEAP", SRAM);
-REGION_ALIAS("REGION_STACK", SRAM);
-
-OUTPUT_ARCH(riscv)
-
-ENTRY(_start)
-
-PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
-
-SECTIONS
-{
-    /* .text 字段 */
-    .text _stext : {
-        /* 把 entry 函数放在最前面 */
-        *(.text.entry)
-        /* 要链接的文件的 .text 字段集中放在这里 */
-        *(.text .text.*)
-        _etext = .;
-    } > REGION_TEXT
-
-    /* .rodata 字段 */
-    .rodata : ALIGN(4) {
-        _srodata = .;
-        /* 要链接的文件的 .rodata 字段集中放在这里 */
-        *(.rodata .rodata.*)
-        . = ALIGN(4);
-        _erodata = .;
-    } > REGION_RODATA
-
-    /* .data 字段 */
-    .data : ALIGN(4) { 
-        _sidata = LOADADDR(.data);
-        _sdata = .;
-        /* Must be called __global_pointer$ for linker relaxations to work. */
-        PROVIDE(__global_pointer$ = . + 0x800);
-        /* 要链接的文件的 .data 字段集中放在这里 */
-        *(.sdata .sdata.* .sdata2 .sdata2.*);
-        *(.data .data.*)
-        . = ALIGN(4);
-        _edata = .;
-    } > REGION_DATA
-
-    /* .bss 字段 */
-    .bss (NOLOAD) : {
-        _sbss = .;
-        /* 要链接的文件的 .bss 字段集中放在这里 */
-        *(.sbss .bss .bss.*)
-        . = ALIGN(4);
-        _ebss = .;
-    } > REGION_BSS
-
-    .heap (NOLOAD) : {
-        _sheap = .;
-        . += _heap_size;
-        . = ALIGN(4);
-        _eheap = .;
-    } > REGION_HEAP
-
-    /* fictitious region that represents the memory available for the stack */
-    .stack (NOLOAD) : {
-        _estack = .;
-        . = _stack_start;
-        . = ALIGN(4);
-        _sstack = .;
-    } > REGION_STACK
-
-    /* Discard .eh_frame, we are not doing unwind on panic so it is not needed */
-    /DISCARD/ :
-    {
-        *(.eh_frame .eh_frame_hdr);
-    }
-}

+ 0 - 39
platform/qemu/src/hal.rs

@@ -1,39 +0,0 @@
-// Ref: MeowSBI
-
-mod ns16550a;
-pub use ns16550a::Ns16550a;
-
-mod clint;
-pub use clint::Clint;
-
-// Ref: https://github.com/repnop/vanadinite/blob/651163fd435d97dc9de728279b64176cdd46ec28/src/arch/virt/mod.rs#L45-L71
-
-pub struct Reset;
-
-const TEST_FAIL: u32 = 0x3333;
-const TEST_PASS: u32 = 0x5555;
-const TEST_RESET: u32 = 0x7777;
-
-impl rustsbi::Reset for Reset {
-    fn system_reset(&self, reset_type: usize, reset_reason: usize) -> rustsbi::SbiRet {
-        // todo: only exit after all harts finished
-        // loop {}
-        const VIRT_TEST: *mut u32 = 0x10_0000 as *mut u32;
-        // Fail = 0x3333,
-        // Pass = 0x5555,
-        // Reset = 0x7777,
-        let mut value = match reset_type {
-            rustsbi::reset::RESET_TYPE_SHUTDOWN => TEST_PASS,
-            rustsbi::reset::RESET_TYPE_COLD_REBOOT => TEST_RESET,
-            rustsbi::reset::RESET_TYPE_WARM_REBOOT => TEST_RESET,
-            _ => TEST_FAIL,
-        };
-        if reset_reason == rustsbi::reset::RESET_REASON_SYSTEM_FAILURE {
-            value = TEST_FAIL;
-        };
-        unsafe {
-            core::ptr::write_volatile(VIRT_TEST, value);
-        }
-        unreachable!()
-    }
-}

+ 0 - 67
platform/qemu/src/hal/clint.rs

@@ -1,67 +0,0 @@
-// 这部分其实是运行时提供的,不应该做到实现库里面
-use rustsbi::SbiRet;
-
-pub struct Clint {
-    base: usize,
-}
-
-impl Clint {
-    pub fn new(base: *mut u8) -> Clint {
-        Clint {
-            base: base as usize,
-        }
-    }
-
-    pub fn get_mtime(&self) -> u64 {
-        unsafe {
-            let base = self.base as *mut u8;
-            core::ptr::read_volatile(base.add(0xbff8) as *mut u64)
-        }
-    }
-
-    pub fn set_timer(&mut self, hart_id: usize, instant: u64) {
-        unsafe {
-            let base = self.base as *mut u8;
-            core::ptr::write_volatile((base.offset(0x4000) as *mut u64).add(hart_id), instant);
-        }
-    }
-
-    pub fn send_soft(&mut self, hart_id: usize) {
-        unsafe {
-            let base = self.base as *mut u8;
-            core::ptr::write_volatile((base as *mut u32).add(hart_id), 1);
-        }
-    }
-
-    pub fn clear_soft(&mut self, hart_id: usize) {
-        unsafe {
-            let base = self.base as *mut u8;
-            core::ptr::write_volatile((base as *mut u32).add(hart_id), 0);
-        }
-    }
-}
-
-use rustsbi::{HartMask, Ipi, Timer};
-
-impl Ipi for Clint {
-    fn max_hart_id(&self) -> usize {
-        // 这个值将在初始化的时候加载,会从dtb_pa读取设备树,然后数里面有几个核
-        *crate::MAX_HART_ID.lock()
-    }
-
-    fn send_ipi_many(&mut self, hart_mask: HartMask) -> SbiRet {
-        for i in 0..=self.max_hart_id() {
-            if hart_mask.has_bit(i) {
-                self.send_soft(i);
-            }
-        }
-        SbiRet::ok(0)
-    }
-}
-
-impl Timer for Clint {
-    fn set_timer(&mut self, time_value: u64) {
-        let this_mhartid = riscv::register::mhartid::read();
-        self.set_timer(this_mhartid, time_value);
-    }
-}

+ 0 - 94
platform/qemu/src/hal/ns16550a.rs

@@ -1,94 +0,0 @@
-use core::convert::Infallible;
-use core::ptr::{read_volatile, write_volatile};
-use embedded_hal::serial::{Read, Write};
-
-pub struct Ns16550a {
-    base: usize,
-    shift: usize,
-}
-
-impl Ns16550a {
-    pub fn new(base: usize, shift: usize, clk: u64, baud: u64) -> Self {
-        // init process; ref: MeowSBI/utils/uart.rs
-        unsafe {
-            write_volatile((base + (offsets::LCR << shift)) as *mut u8, 0x80); // DLAB
-
-            let latch = clk / (16 * baud);
-            write_volatile((base + (offsets::DLL << shift)) as *mut u8, latch as u8);
-            write_volatile(
-                (base + (offsets::DLH << shift)) as *mut u8,
-                (latch >> 8) as u8,
-            );
-
-            write_volatile((base + (offsets::LCR << shift)) as *mut u8, 3); // WLEN8 & !DLAB
-
-            write_volatile((base + (offsets::MCR << shift)) as *mut u8, 0);
-            write_volatile((base + (offsets::IER << shift)) as *mut u8, 0);
-            write_volatile((base + (offsets::FCR << shift)) as *mut u8, 0x7); // FIFO enable + FIFO reset
-
-            // No interrupt for now
-        }
-        // init finished
-        Self { base, shift }
-    }
-}
-
-impl Read<u8> for Ns16550a {
-    // 其实是可能出错的,overrun啊,这些
-    type Error = Infallible;
-
-    fn try_read(&mut self) -> nb::Result<u8, Self::Error> {
-        let pending =
-            unsafe { read_volatile((self.base + (offsets::LSR << self.shift)) as *const u8) }
-                & masks::DR;
-        if pending != 0 {
-            let word =
-                unsafe { read_volatile((self.base + (offsets::RBR << self.shift)) as *const u8) };
-            Ok(word)
-        } else {
-            Err(nb::Error::WouldBlock)
-        }
-    }
-}
-
-impl Write<u8> for Ns16550a {
-    type Error = Infallible;
-
-    fn try_write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
-        // 写,但是不刷新
-        unsafe { write_volatile((self.base + (offsets::THR << self.shift)) as *mut u8, word) };
-        Ok(())
-    }
-
-    fn try_flush(&mut self) -> nb::Result<(), Self::Error> {
-        let pending =
-            unsafe { read_volatile((self.base + (offsets::LSR << self.shift)) as *const u8) }
-                & masks::THRE;
-        if pending != 0 {
-            // 发送已经结束了
-            Ok(())
-        } else {
-            // 发送还没有结束,继续等
-            Err(nb::Error::WouldBlock)
-        }
-    }
-}
-
-mod offsets {
-    pub const RBR: usize = 0x0;
-    pub const THR: usize = 0x0;
-
-    pub const IER: usize = 0x1;
-    pub const FCR: usize = 0x2;
-    pub const LCR: usize = 0x3;
-    pub const MCR: usize = 0x4;
-    pub const LSR: usize = 0x5;
-
-    pub const DLL: usize = 0x0;
-    pub const DLH: usize = 0x1;
-}
-
-mod masks {
-    pub const THRE: u8 = 1 << 5;
-    pub const DR: u8 = 1;
-}

+ 0 - 522
platform/qemu/src/main.rs

@@ -1,522 +0,0 @@
-#![no_std]
-#![no_main]
-#![feature(naked_functions)]
-#![feature(alloc_error_handler)]
-#![feature(llvm_asm)]
-#![feature(asm)]
-#![feature(global_asm)]
-
-mod hal;
-
-#[cfg(not(test))]
-use core::alloc::Layout;
-#[cfg(not(test))]
-use core::panic::PanicInfo;
-use linked_list_allocator::LockedHeap;
-
-use rustsbi::{print, println};
-
-use riscv::register::{
-    mcause::{self, Exception, Interrupt, Trap},
-    medeleg, mepc, mhartid, mideleg, mie, mip, misa::{self, MXL},
-    mstatus::{self, MPP, SPP},
-    mtval,
-    mtvec::{self, TrapMode},
-    stvec, scause, stval, sepc,
-};
-
-#[global_allocator]
-static ALLOCATOR: LockedHeap = LockedHeap::empty();
-
-#[cfg(not(test))]
-#[panic_handler]
-fn panic(info: &PanicInfo) -> ! {
-    let hart_id = mhartid::read();
-    // 输出的信息大概是“[rustsbi-panic] hart 0 panicked at ...”
-    println!("[rustsbi-panic] hart {} {}", hart_id, info);
-    println!("[rustsbi-panic] system shutdown scheduled due to RustSBI panic");
-    use rustsbi::Reset;
-    hal::Reset.system_reset(
-        rustsbi::reset::RESET_TYPE_SHUTDOWN,
-        rustsbi::reset::RESET_REASON_SYSTEM_FAILURE
-    );
-    loop { }
-}
-
-#[cfg(not(test))]
-#[alloc_error_handler]
-fn oom(_layout: Layout) -> ! {
-    loop {}
-}
-
-lazy_static::lazy_static! {
-    // 最大的硬件线程编号;只在启动时写入,跨核软中断发生时读取
-    pub static ref MAX_HART_ID: spin::Mutex<usize> = 
-        spin::Mutex::new(compiled_max_hartid());
-}
-
-// #[export_name = "_mp_hook"]
-pub extern "C" fn mp_hook() -> bool {
-    let hartid = mhartid::read();
-    if hartid == 0 {
-        true
-    } else {
-        use riscv::asm::wfi;
-        use hal::Clint;
-        unsafe {
-            let mut clint = Clint::new(0x200_0000 as *mut u8);
-            // Clear IPI
-            clint.clear_soft(hartid);
-            // Start listening for software interrupts
-            mie::set_msoft();
-
-            loop {
-                wfi();
-                if mip::read().msoft() {
-                    break;
-                }
-            }
-
-            // Stop listening for software interrupts
-            mie::clear_msoft();
-            // Clear IPI
-            clint.clear_soft(hartid);
-        }
-        false
-    }
-}
-
-#[export_name = "_start"]
-#[link_section = ".text.entry"] // this is stable
-#[naked]
-// extern "C" for Rust ABI is by now unsupported for naked functions
-unsafe extern "C" fn start() -> ! {
-    asm!(
-            "
-        csrr    a2, mhartid
-        lui     t0, %hi(_max_hart_id)
-        add     t0, t0, %lo(_max_hart_id)
-        bgtu    a2, t0, _start_abort
-        la      sp, _stack_start
-        lui     t0, %hi(_hart_stack_size)
-        add     t0, t0, %lo(_hart_stack_size)
-    .ifdef __riscv_mul
-        mul     t0, a2, t0
-    .else
-        beqz    a2, 2f  // Jump if single-hart
-        mv      t1, a2
-        mv      t2, t0
-    1:
-        add     t0, t0, t2
-        addi    t1, t1, -1
-        bnez    t1, 1b
-    2:
-    .endif
-        sub     sp, sp, t0
-        csrw    mscratch, zero
-        j       main
-        
-    _start_abort:
-        wfi
-        j _start_abort
-    ", options(noreturn))
-}
-
-#[export_name = "main"]
-extern "C" fn main(_mhartid: usize, dtb_pa: usize) -> ! {
-    // dtb_pa is put into a1 register on qemu boot
-    // Ref: https://github.com/qemu/qemu/blob/aeb07b5f6e69ce93afea71027325e3e7a22d2149/hw/riscv/boot.c#L243
-
-    if mp_hook() {
-        // init
-    }
-
-    /* setup trap */
-
-    extern "C" {
-        fn _start_trap();
-    }
-    unsafe {
-        mtvec::write(_start_trap as usize, TrapMode::Direct);
-    }
-
-
-    /* main function start */
-
-    extern "C" {
-        static mut _sheap: u8;
-        static _heap_size: u8;
-    }
-    if mhartid::read() == 0 {
-        let sheap = unsafe { &mut _sheap } as *mut _ as usize;
-        let heap_size = unsafe { &_heap_size } as *const u8 as usize;
-        unsafe {
-            ALLOCATOR.lock().init(sheap, heap_size);
-        }
-
-        // 其实这些参数不用提供,直接通过pac库生成
-        let serial = hal::Ns16550a::new(0x10000000, 0, 11_059_200, 115200);
-
-        // use through macro
-        use rustsbi::legacy_stdio::init_legacy_stdio_embedded_hal;
-        init_legacy_stdio_embedded_hal(serial);
-
-        let clint = hal::Clint::new(0x2000000 as *mut u8);
-        use rustsbi::init_ipi;
-        init_ipi(clint);
-        // todo: do not create two instances
-        let clint = hal::Clint::new(0x2000000 as *mut u8);
-        use rustsbi::init_timer;
-        init_timer(clint);
-
-        use rustsbi::init_reset;
-        init_reset(hal::Reset);
-    }
-
-    // 把S的中断全部委托给S层
-    unsafe {
-        mideleg::set_sext();
-        mideleg::set_stimer();
-        mideleg::set_ssoft();
-        medeleg::set_instruction_misaligned();
-        medeleg::set_breakpoint();
-        medeleg::set_user_env_call();
-        medeleg::set_instruction_page_fault();
-        medeleg::set_load_page_fault();
-        medeleg::set_store_page_fault();
-        medeleg::set_instruction_fault();
-        medeleg::set_load_fault();
-        medeleg::set_store_fault();
-        mie::set_mext();
-        // 不打开mie::set_mtimer
-        mie::set_msoft();
-    }
-
-    if mhartid::read() == 0 {
-        println!("[rustsbi] RustSBI version {}", rustsbi::VERSION);
-        println!("{}", rustsbi::LOGO);
-        println!("[rustsbi] Platform: QEMU (Version {})", env!("CARGO_PKG_VERSION"));
-        let isa = misa::read();
-        if let Some(isa) = isa {
-            let mxl_str = match isa.mxl() {
-                MXL::XLEN32 => "RV32",
-                MXL::XLEN64 => "RV64",
-                MXL::XLEN128 => "RV128",
-            };
-            print!("[rustsbi] misa: {}", mxl_str);
-            for ext in 'A'..='Z' {
-                if isa.has_extension(ext) {
-                    print!("{}", ext);
-                }
-            }
-            println!("");
-        }
-        println!("[rustsbi] mideleg: {:#x}", mideleg::read().bits());
-        println!("[rustsbi] medeleg: {:#x}", medeleg::read().bits());
-        let mut guard = MAX_HART_ID.lock();
-        *guard = unsafe { count_harts(dtb_pa) };
-        drop(guard);
-        println!("[rustsbi] Kernel entry: 0x80200000");
-    }
-
-    unsafe {
-        mepc::write(s_mode_start as usize);
-        mstatus::set_mpp(MPP::Supervisor);
-        rustsbi::enter_privileged(mhartid::read(), dtb_pa)
-    }
-}
-
-#[naked]
-#[link_section = ".text"] // must add link section for all naked functions
-unsafe extern "C" fn s_mode_start() -> ! {
-    asm!("
-1:  auipc ra, %pcrel_hi(1f)
-    ld ra, %pcrel_lo(1b)(ra)
-    jr ra
-.align  3
-1:  .dword 0x80200000
-    ", options(noreturn))
-}
-
-unsafe fn count_harts(dtb_pa: usize) -> usize {
-    use device_tree::{DeviceTree, Node};
-    const DEVICE_TREE_MAGIC: u32 = 0xD00DFEED;
-    // 遍历“cpu_map”结构
-    // 这个结构的子结构是“处理核簇”(cluster)
-    // 每个“处理核簇”的子结构分别表示一个处理器核
-    fn enumerate_cpu_map(cpu_map_node: &Node) -> usize {
-        let mut tot = 0;
-        for cluster_node in cpu_map_node.children.iter() {
-            let name = &cluster_node.name;
-            let count = cluster_node.children.iter().count();
-            // 会输出:Hart count: cluster0 with 2 cores
-            // 在justfile的“threads := "2"”处更改
-            println!("[rustsbi-dtb] Hart count: {} with {} cores", name, count);
-            tot += count;
-        }
-        tot
-    }
-    #[repr(C)]
-    struct DtbHeader { magic: u32, size: u32 }
-    let header = &*(dtb_pa as *const DtbHeader);
-    // from_be 是大小端序的转换(from big endian)
-    let magic = u32::from_be(header.magic);
-    if magic == DEVICE_TREE_MAGIC {
-        let size = u32::from_be(header.size);
-        // 拷贝数据,加载并遍历
-        let data = core::slice::from_raw_parts(dtb_pa as *const u8, size as usize);
-        if let Ok(dt) = DeviceTree::load(data) {
-            if let Some(cpu_map) = dt.find("/cpus/cpu-map") {
-                return enumerate_cpu_map(cpu_map)
-            }
-        }
-    }
-    // 如果DTB的结构不对(读不到/cpus/cpu-map),返回默认的8个核
-    let ans = compiled_max_hartid();
-    println!("[rustsbi-dtb] Could not read '/cpus/cpu-map' from 'dtb_pa' device tree root; assuming {} cores", ans);
-    ans
-}
-
-#[inline]
-fn compiled_max_hartid() -> usize {
-    let ans;
-    unsafe { asm!("
-        lui     {ans}, %hi(_max_hart_id)
-        add     {ans}, {ans}, %lo(_max_hart_id)
-    ", ans = out(reg) ans) };
-    ans
-}
-
-global_asm!(
-    "
-    .equ REGBYTES, 8
-    .macro STORE reg, offset
-        sd  \\reg, \\offset*REGBYTES(sp)
-    .endm
-    .macro LOAD reg, offset
-        ld  \\reg, \\offset*REGBYTES(sp)
-    .endm
-    .section .text
-    .global _start_trap
-    .p2align 2
-_start_trap:
-    csrrw   sp, mscratch, sp
-    bnez    sp, 1f
-    /* from M level, load sp */
-    csrrw   sp, mscratch, zero
-1:
-    addi    sp, sp, -16 * REGBYTES
-    STORE   ra, 0
-    STORE   t0, 1
-    STORE   t1, 2
-    STORE   t2, 3
-    STORE   t3, 4
-    STORE   t4, 5
-    STORE   t5, 6
-    STORE   t6, 7
-    STORE   a0, 8
-    STORE   a1, 9
-    STORE   a2, 10
-    STORE   a3, 11
-    STORE   a4, 12
-    STORE   a5, 13
-    STORE   a6, 14
-    STORE   a7, 15
-    mv      a0, sp
-    call    _start_trap_rust
-    LOAD    ra, 0
-    LOAD    t0, 1
-    LOAD    t1, 2
-    LOAD    t2, 3
-    LOAD    t3, 4
-    LOAD    t4, 5
-    LOAD    t5, 6
-    LOAD    t6, 7
-    LOAD    a0, 8
-    LOAD    a1, 9
-    LOAD    a2, 10
-    LOAD    a3, 11
-    LOAD    a4, 12
-    LOAD    a5, 13
-    LOAD    a6, 14
-    LOAD    a7, 15
-    addi    sp, sp, 16 * REGBYTES
-    csrrw   sp, mscratch, sp
-    mret
-    "
-);
-
-// #[doc(hidden)]
-// #[export_name = "_mp_hook"]
-// pub extern "Rust" fn _mp_hook() -> bool {
-//     match mhartid::read() {
-//         0 => true,
-//         _ => loop {
-//             unsafe { riscv::asm::wfi() }
-//         },
-//     }
-// }
-
-#[allow(unused)]
-#[derive(Debug)]
-struct TrapFrame {
-    ra: usize,
-    t0: usize,
-    t1: usize,
-    t2: usize,
-    t3: usize,
-    t4: usize,
-    t5: usize,
-    t6: usize,
-    a0: usize,
-    a1: usize,
-    a2: usize,
-    a3: usize,
-    a4: usize,
-    a5: usize,
-    a6: usize,
-    a7: usize,
-}
-
-impl TrapFrame {
-    #[inline]
-    fn set_register_xi(&mut self, i: u8, data: usize) {
-        match i {
-            10 => self.a0 = data,
-            11 => self.a1 = data,
-            12 => self.a2 = data,
-            13 => self.a3 = data,
-            14 => self.a4 = data,
-            15 => self.a5 = data,
-            16 => self.a6 = data,
-            17 => self.a7 = data,
-            5 =>  self.t0 = data,
-            6 =>  self.t1 = data,
-            7 =>  self.t2 = data,
-            28 => self.t3 = data,
-            29 => self.t4 = data,
-            30 => self.t5 = data,
-            31 => self.t6 = data,
-            _ => panic!("invalid target"),
-        }
-    }
-}
-
-impl core::fmt::Display for TrapFrame {
-    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
-        writeln!(f, "")?;
-        #[cfg(target_pointer_width = "64")] {
-            writeln!(f, "ra: {:016x}, t0: {:016x}, t1: {:016x}, t2: {:016x}", self.ra, self.t0, self.t1, self.t2)?;
-            writeln!(f, "t3: {:016x}, t4: {:016x}, t5: {:016x}, t6: {:016x}", self.t3, self.t4, self.t5, self.t6)?;
-            writeln!(f, "a0: {:016x}, a1: {:016x}, a2: {:016x}, a3: {:016x}", self.a0, self.a1, self.a2, self.a3)?;
-            writeln!(f, "a4: {:016x}, a5: {:016x}, a6: {:016x}, a7: {:016x}", self.a4, self.a5, self.a6, self.a7)
-        }
-        #[cfg(target_pointer_width = "32")] {
-            writeln!(f, "ra: {:08x}, t0: {:08x}, t1: {:08x}, t2: {:08x}", self.ra, self.t0, self.t1, self.t2)?;
-            writeln!(f, "t3: {:08x}, t4: {:08x}, t5: {:08x}, t6: {:08x}", self.t3, self.t4, self.t5, self.t6)?;
-            writeln!(f, "a0: {:08x}, a1: {:08x}, a2: {:08x}, a3: {:08x}", self.a0, self.a1, self.a2, self.a3)?;
-            writeln!(f, "a4: {:08x}, a5: {:08x}, a6: {:08x}, a7: {:08x}", self.a4, self.a5, self.a6, self.a7)
-        }
-    }
-}
-
-#[export_name = "_start_trap_rust"]
-extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
-    let cause = mcause::read().cause();
-    match cause {
-        Trap::Exception(Exception::SupervisorEnvCall) => {
-            let params = [trap_frame.a0, trap_frame.a1, trap_frame.a2, trap_frame.a3, trap_frame.a4];
-            // Call RustSBI procedure
-            let ans = rustsbi::ecall(trap_frame.a7, trap_frame.a6, params);
-            // Return the return value to TrapFrame
-            trap_frame.a0 = ans.error;
-            trap_frame.a1 = ans.value;
-            // Skip ecall instruction
-            mepc::write(mepc::read().wrapping_add(4));
-        }
-        Trap::Interrupt(Interrupt::MachineSoft) => {
-            // 机器软件中断返回给S层
-            unsafe {
-                mip::set_ssoft();
-                mie::clear_msoft();
-            }
-        }
-        Trap::Interrupt(Interrupt::MachineTimer) => {
-            // 机器时间中断返回给S层
-            unsafe {
-                mip::set_stimer();
-                mie::clear_mtimer();
-            }
-        }
-        Trap::Exception(Exception::IllegalInstruction) => {
-            #[inline]
-            unsafe fn get_vaddr_u32(vaddr: usize) -> u32 {
-                let mut ans: u32;
-                asm!("
-                    li      {tmp}, (1 << 17)
-                    csrrs   {tmp}, mstatus, {tmp}
-                    lwu     {ans}, 0({vaddr})
-                    csrw    mstatus, {tmp}
-                    ",
-                    tmp = out(reg) _,
-                    vaddr = in(reg) vaddr,
-                    ans = lateout(reg) ans
-                );
-                ans
-            }
-            let vaddr = mepc::read();
-            let ins = unsafe { get_vaddr_u32(vaddr) };
-            if ins & 0xFFFFF07F == 0xC0102073 {
-                // rdtime
-                let rd = ((ins >> 7) & 0b1_1111) as u8;
-                // todo: one instance only
-                let clint = hal::Clint::new(0x2000000 as *mut u8);
-                let time_usize = clint.get_mtime() as usize;
-                trap_frame.set_register_xi(rd, time_usize);
-                mepc::write(mepc::read().wrapping_add(4)); // 跳过指令
-            } else if mstatus::read().mpp() != MPP::Machine { // invalid instruction, can't emulate, raise to supervisor
-                // 出现非法指令异常,转发到S特权层
-                unsafe { 
-                    // 设置S层异常原因为:非法指令
-                    scause::set(scause::Trap::Exception(scause::Exception::IllegalInstruction));
-                    // 填写异常指令的指令内容
-                    stval::write(mtval::read());
-                    // 填写S层需要返回到的地址,这里的mepc会被随后的代码覆盖掉
-                    sepc::write(mepc::read());
-                    // 设置中断位
-                    mstatus::set_mpp(MPP::Supervisor);
-                    mstatus::set_spp(SPP::Supervisor);
-                    if mstatus::read().sie() {
-                        mstatus::set_spie()
-                    }
-                    mstatus::clear_sie();
-                    // 设置返回地址,返回到S层
-                    // 注意,无论是Direct还是Vectored模式,所有异常的向量偏移都是0,不需要处理中断向量,跳转到入口地址即可
-                    mepc::write(stvec::read().address());
-                };
-            } else {
-                // 真·非法指令异常,是M层出现的
-                #[cfg(target_pointer_width = "64")]
-                panic!("invalid instruction from machine level, mepc: {:016x?}, instruction: {:016x?}, trap frame: {}", mepc::read(), ins, trap_frame);
-                #[cfg(target_pointer_width = "32")]
-                panic!("invalid instruction from machine level, mepc: {:08x?}, instruction: {:08x?}, trap frame: {}", mepc::read(), ins, trap_frame);
-            }
-        }
-        #[cfg(target_pointer_width = "64")]
-        cause => panic!(
-            "Unhandled exception! mcause: {:?}, mepc: {:016x?}, mtval: {:016x?}, trap frame: {:x?}",
-            cause,
-            mepc::read(),
-            mtval::read(),
-            trap_frame
-        ),
-        #[cfg(target_pointer_width = "32")]
-        cause => panic!(
-            "Unhandled exception! mcause: {:?}, mepc: {:08x?}, mtval: {:08x?}, trap frame: {:x?}",
-            cause,
-            mepc::read(),
-            mtval::read(),
-            trap_frame
-        ),
-    }
-}

+ 0 - 28
rustsbi/Cargo.toml

@@ -1,28 +0,0 @@
-[package]
-name = "rustsbi"
-description = "Minimal RISC-V's SBI implementation library in Rust"
-version = "0.2.0-alpha.3"
-authors = ["luojia65 <[email protected]>"]
-repository = "https://github.com/luojia65/rustsbi"
-documentation = "https://docs.rs/rustsbi"
-license = "MulanPSL-2.0 OR MIT"
-readme = "../README.md"
-keywords = ["riscv", "sbi", "rustsbi"]
-categories = ["os", "embedded", "hardware-support", "no-std"]
-edition = "2018"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[package.metadata.docs.rs]
-default-target = "riscv64imac-unknown-none-elf"
-targets = [
-    "riscv32i-unknown-none-elf", "riscv32imc-unknown-none-elf", "riscv32imac-unknown-none-elf",
-    "riscv64imac-unknown-none-elf",
-]
-
-[dependencies]
-embedded-hal = "1.0.0-alpha.1"
-nb = "1.0"
-riscv = "0.6"
-spin = "0.7"
-lazy_static = { version = "1", features = ["spin_no_std"] }

+ 0 - 0
rustsbi/src/ecall.rs → src/ecall.rs


+ 0 - 0
rustsbi/src/ecall/base.rs → src/ecall/base.rs


+ 0 - 0
rustsbi/src/ecall/hsm.rs → src/ecall/hsm.rs


+ 0 - 0
rustsbi/src/ecall/ipi.rs → src/ecall/ipi.rs


+ 0 - 0
rustsbi/src/ecall/legacy.rs → src/ecall/legacy.rs


+ 0 - 0
rustsbi/src/ecall/rfence.rs → src/ecall/rfence.rs


+ 0 - 0
rustsbi/src/ecall/srst.rs → src/ecall/srst.rs


+ 0 - 0
rustsbi/src/ecall/timer.rs → src/ecall/timer.rs


+ 0 - 0
rustsbi/src/extension.rs → src/extension.rs


+ 0 - 0
rustsbi/src/hart_mask.rs → src/hart_mask.rs


+ 0 - 0
rustsbi/src/hsm.rs → src/hsm.rs


+ 0 - 0
rustsbi/src/ipi.rs → src/ipi.rs


+ 0 - 0
rustsbi/src/legacy_stdio.rs → src/legacy_stdio.rs


+ 0 - 0
rustsbi/src/lib.rs → src/lib.rs


+ 0 - 0
rustsbi/src/logo.rs → src/logo.rs


+ 0 - 0
rustsbi/src/logo.txt → src/logo.txt


+ 0 - 0
rustsbi/src/privileged.rs → src/privileged.rs


+ 0 - 0
rustsbi/src/reset.rs → src/reset.rs


+ 0 - 0
rustsbi/src/rfence.rs → src/rfence.rs


+ 0 - 0
rustsbi/src/timer.rs → src/timer.rs


+ 0 - 9
test-kernel/.cargo/config.toml

@@ -1,9 +0,0 @@
-[target.riscv64imac-unknown-none-elf]
-rustflags = [
-    "-C", "link-arg=-Tlinker64.ld",
-]
-
-[target.riscv32imac-unknown-none-elf]
-rustflags = [
-    "-C", "link-arg=-Tlinker32.ld",
-]

+ 0 - 12
test-kernel/Cargo.toml

@@ -1,12 +0,0 @@
-[package]
-name = "test-kernel"
-version = "0.1.0"
-authors = ["luojia65 <[email protected]>"]
-edition = "2018"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-riscv = "0.6"
-spin = "0.7"
-lazy_static = { version = "1", features = ["spin_no_std"] }

+ 0 - 23
test-kernel/build.rs

@@ -1,23 +0,0 @@
-use std::env;
-use std::fs;
-use std::io::Write;
-use std::path::PathBuf;
-
-fn main() {
-    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
-
-    // Put the linker script somewhere the linker can find it
-    fs::File::create(out_dir.join("linker64.ld"))
-        .unwrap()
-        .write_all(include_bytes!("src/linker64.ld"))
-        .unwrap();
-    fs::File::create(out_dir.join("linker32.ld"))
-        .unwrap()
-        .write_all(include_bytes!("src/linker32.ld"))
-        .unwrap();
-    println!("cargo:rustc-link-search={}", out_dir.display());
-
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-changed=src/linker64.ld");
-    println!("cargo:rerun-if-changed=src/linker32.ld");
-}

+ 0 - 21
test-kernel/justfile

@@ -1,21 +0,0 @@
-target := "riscv64imac-unknown-none-elf"
-mode := "debug"
-build-path := "../target/" + target + "/" + mode + "/"
-test-kernel-elf := build-path + "test-kernel"
-test-kernel-bin := build-path + "test-kernel.bin"
-
-objdump := "riscv64-unknown-elf-objdump"
-objcopy := "rust-objcopy --binary-architecture=riscv64"
-size := "rust-size"
-
-build: firmware
-    @{{objcopy}} {{test-kernel-elf}} --strip-all -O binary {{test-kernel-bin}}
-
-firmware:
-    @cargo build --target={{target}}
-
-asm: build
-    @{{objdump}} -D {{test-kernel-elf}} | less
-
-size: build
-    @{{size}} -A -x {{test-kernel-elf}} 

+ 0 - 40
test-kernel/src/console.rs

@@ -1,40 +0,0 @@
-use crate::sbi::*;
-use core::fmt::{self, Write};
-use spin::Mutex;
-
-struct Stdout;
-
-impl Write for Stdout {
-    fn write_str(&mut self, s: &str) -> fmt::Result {
-        let mut buffer = [0u8; 4];
-        for c in s.chars() {
-            for code_point in c.encode_utf8(&mut buffer).as_bytes().iter() {
-                console_putchar(*code_point as usize);
-            }
-        }
-        Ok(())
-    }
-}
-
-#[allow(unused)]
-pub fn print(args: fmt::Arguments) {
-    STDOUT.lock().write_fmt(args).unwrap();
-}
-
-lazy_static::lazy_static! {
-    static ref STDOUT: Mutex<Stdout> = Mutex::new(Stdout);
-}
-
-#[macro_export]
-macro_rules! print {
-    ($fmt: literal $(, $($arg: tt)+)?) => {
-        $crate::console::print(format_args!($fmt $(, $($arg)+)?));
-    }
-}
-
-#[macro_export]
-macro_rules! println {
-    ($fmt: literal $(, $($arg: tt)+)?) => {
-        $crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?));
-    }
-}

+ 0 - 38
test-kernel/src/linker32.ld

@@ -1,38 +0,0 @@
-OUTPUT_ARCH(riscv)
-ENTRY(_start)
-
-BASE_ADDRESS = 0x80400000;
-
-SECTIONS
-{
-    /* Load the kernel at this address: "." means the current address */
-    . = BASE_ADDRESS;
-    start = .;
-
-    .text : ALIGN(4K) {
-        _stext = .;
-        *(.text.entry)
-        *(.text .text.*)
-        _etext = .;
-    }
-
-    .rodata : ALIGN(4K) {
-        _srodata = .;
-        *(.rodata .rodata.*)
-        _erodata = .;
-    }
-
-    .data : ALIGN(4K) {
-        _sdata = .;
-        *(.data .data.*)
-        _edata = .;
-    }
-
-    .bss (NOLOAD) : ALIGN(4K)  {
-        _sbss = .;
-        *(.sbss .bss .bss.*)
-        _ebss = .;
-    }
-
-    PROVIDE(end = .);
-}

+ 0 - 43
test-kernel/src/linker64.ld

@@ -1,43 +0,0 @@
-/* Copy from bbl-ucore : https://ring00.github.io/bbl-ucore      */
-
-/* Simple linker script for the ucore kernel.
-   See the GNU ld 'info' manual ("info ld") to learn the syntax. */
-
-OUTPUT_ARCH(riscv)
-ENTRY(_start)
-
-BASE_ADDRESS = 0x80200000;
-
-SECTIONS
-{
-    /* Load the kernel at this address: "." means the current address */
-    . = BASE_ADDRESS;
-    start = .;
-
-    .text : ALIGN(4K) {
-        _stext = .;
-        *(.text.entry)
-        *(.text .text.*)
-        _etext = .;
-    }
-
-    .rodata : ALIGN(4K) {
-        _srodata = .;
-        *(.rodata .rodata.*)
-        _erodata = .;
-    }
-
-    .data : ALIGN(4K) {
-        _sdata = .;
-        *(.data .data.*)
-        _edata = .;
-    }
-
-    .bss (NOLOAD) : ALIGN(4K)  {
-        _sbss = .;
-        *(.sbss .bss .bss.*)
-        _ebss = .;
-    }
-
-    PROVIDE(end = .);
-}

+ 0 - 181
test-kernel/src/main.rs

@@ -1,181 +0,0 @@
-// A test kernel to test RustSBI function on all platforms
-#![feature(naked_functions, asm)]
-#![no_std]
-#![no_main]
-
-#[macro_use]
-mod console;
-mod sbi;
-
-use riscv::register::{sepc, stvec::{self, TrapMode}, scause::{self, Trap, Exception}};
-
-pub extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
-    println!("<< Test-kernel: Hart id = {}, DTB physical address = {:#x}", hartid, dtb_pa);
-    test_base_extension();
-    test_sbi_ins_emulation();
-    unsafe { stvec::write(start_trap as usize, TrapMode::Direct) };
-    println!(">> Test-kernel: Trigger illegal exception");
-    unsafe { asm!("csrw mcycle, x0") }; // mcycle cannot be written, this is always a 4-byte illegal instruction
-    println!("<< Test-kernel: SBI test SUCCESS, shutdown");
-    sbi::shutdown()
-}
-
-fn test_base_extension() {
-    println!(">> Test-kernel: Testing base extension");
-    let base_version = sbi::probe_extension(sbi::EXTENSION_BASE);
-    if base_version == 0 {
-        println!("!! Test-kernel: no base extension probed; SBI call returned value '0'");
-        println!("!! Test-kernel: This SBI implementation may only have legacy extension implemented");
-        println!("!! Test-kernel: SBI test FAILED due to no base extension found");
-        sbi::shutdown()
-    }
-    println!("<< Test-kernel: Base extension version: {:x}", base_version);
-    println!("<< Test-kernel: SBI specification version: {:x}", sbi::get_spec_version());
-    println!("<< Test-kernel: SBI implementation Id: {:x}", sbi::get_sbi_impl_id());
-    println!("<< Test-kernel: SBI implementation version: {:x}", sbi::get_sbi_impl_version());
-    println!("<< Test-kernel: Device mvendorid: {:x}", sbi::get_mvendorid());
-    println!("<< Test-kernel: Device marchid: {:x}", sbi::get_marchid());
-    println!("<< Test-kernel: Device mimpid: {:x}", sbi::get_mimpid());
-}
-
-fn test_sbi_ins_emulation() {
-    println!(">> Test-kernel: Testing SBI instruction emulation");
-    let time = riscv::register::time::read64();
-    println!("<< Test-kernel: Current time: {:x}", time);
-}
-
-pub extern "C" fn rust_trap_exception() {
-    let cause = scause::read().cause();
-    println!("<< Test-kernel: Value of scause: {:?}", cause);
-    if cause != Trap::Exception(Exception::IllegalInstruction) {
-        println!("!! Test-kernel: Wrong cause associated to illegal instruction");
-        sbi::shutdown()
-    }
-    println!("<< Test-kernel: Illegal exception delegate success");
-    sepc::write(sepc::read().wrapping_add(4));
-}
-
-use core::panic::PanicInfo;
-
-#[cfg_attr(not(test), panic_handler)]
-#[allow(unused)]
-fn panic(info: &PanicInfo) -> ! {
-    println!("!! Test-kernel: {}", info);
-    println!("!! Test-kernel: SBI test FAILED due to panic");
-    sbi::shutdown()
-}
-
-const BOOT_STACK_SIZE: usize = 4096 * 4 * 8;
-
-static mut BOOT_STACK: [u8; BOOT_STACK_SIZE] = [0; BOOT_STACK_SIZE];
-
-#[naked]
-#[link_section = ".text.entry"] 
-#[export_name = "_start"]
-unsafe extern "C" fn entry() -> ! {
-    asm!("
-    # 1. set sp
-    # sp = bootstack + (hartid + 1) * 0x10000
-    add     t0, a0, 1
-    slli    t0, t0, 14
-1:  auipc   sp, %pcrel_hi({boot_stack})
-    addi    sp, sp, %pcrel_lo(1b)
-    add     sp, sp, t0
-
-    # 2. jump to rust_main (absolute address)
-1:  auipc   t0, %pcrel_hi({rust_main})
-    addi    t0, t0, %pcrel_lo(1b)
-    jr      t0
-    ", 
-    boot_stack = sym BOOT_STACK, 
-    rust_main = sym rust_main,
-    options(noreturn))
-}
-
-
-#[cfg(target_pointer_width = "128")]
-macro_rules! define_store_load {
-    () => {
-        ".altmacro
-        .macro STORE reg, offset
-            sq  \\reg, \\offset* {REGBYTES} (sp)
-        .endm
-        .macro LOAD reg, offset
-            lq  \\reg, \\offset* {REGBYTES} (sp)
-        .endm"
-    };
-}
-
-#[cfg(target_pointer_width = "64")]
-macro_rules! define_store_load {
-    () => {
-        ".altmacro
-        .macro STORE reg, offset
-            sd  \\reg, \\offset* {REGBYTES} (sp)
-        .endm
-        .macro LOAD reg, offset
-            ld  \\reg, \\offset* {REGBYTES} (sp)
-        .endm"
-    };
-}
-
-#[cfg(target_pointer_width = "32")]
-macro_rules! define_store_load {
-    () => {
-        ".altmacro
-        .macro STORE reg, offset
-            sw  \\reg, \\offset* {REGBYTES} (sp)
-        .endm
-        .macro LOAD reg, offset
-            lw  \\reg, \\offset* {REGBYTES} (sp)
-        .endm"
-    };
-}
-
-#[naked]
-#[link_section = ".text"]
-unsafe extern "C" fn start_trap() {
-    asm!(define_store_load!(), "
-    .p2align 2
-    addi    sp, sp, -16 * {REGBYTES}
-    STORE   ra, 0
-    STORE   t0, 1
-    STORE   t1, 2
-    STORE   t2, 3
-    STORE   t3, 4
-    STORE   t4, 5
-    STORE   t5, 6
-    STORE   t6, 7
-    STORE   a0, 8
-    STORE   a1, 9
-    STORE   a2, 10
-    STORE   a3, 11
-    STORE   a4, 12
-    STORE   a5, 13
-    STORE   a6, 14
-    STORE   a7, 15
-    mv      a0, sp
-    call    {rust_trap_exception}
-    LOAD    ra, 0
-    LOAD    t0, 1
-    LOAD    t1, 2
-    LOAD    t2, 3
-    LOAD    t3, 4
-    LOAD    t4, 5
-    LOAD    t5, 6
-    LOAD    t6, 7
-    LOAD    a0, 8
-    LOAD    a1, 9
-    LOAD    a2, 10
-    LOAD    a3, 11
-    LOAD    a4, 12
-    LOAD    a5, 13
-    LOAD    a6, 14
-    LOAD    a7, 15
-    addi    sp, sp, 16 * {REGBYTES}
-    sret
-    ",
-    REGBYTES = const core::mem::size_of::<usize>(),
-    rust_trap_exception = sym rust_trap_exception,
-    options(noreturn))
-}

+ 0 - 126
test-kernel/src/sbi.rs

@@ -1,126 +0,0 @@
-#![allow(unused)]
-
-pub const EXTENSION_BASE: usize = 0x10;
-pub const EXTENSION_TIMER: usize = 0x54494D45;
-pub const EXTENSION_IPI: usize = 0x735049;
-pub const EXTENSION_RFENCE: usize = 0x52464E43;
-pub const EXTENSION_HSM: usize = 0x48534D;
-pub const EXTENSION_SRST: usize = 0x53525354;
-
-const FUNCTION_BASE_GET_SPEC_VERSION: usize = 0x0;
-const FUNCTION_BASE_GET_SBI_IMPL_ID: usize = 0x1;
-const FUNCTION_BASE_GET_SBI_IMPL_VERSION: usize = 0x2;
-const FUNCTION_BASE_PROBE_EXTENSION: usize = 0x3;
-const FUNCTION_BASE_GET_MVENDORID: usize = 0x4;
-const FUNCTION_BASE_GET_MARCHID: usize = 0x5;
-const FUNCTION_BASE_GET_MIMPID: usize = 0x6;
-
-#[repr(C)]
-pub struct SbiRet {
-    /// Error number
-    pub error: usize,
-    /// Result value
-    pub value: usize,
-}
-
-#[inline(always)]
-fn sbi_call(extension: usize, function: usize, arg0: usize, arg1: usize, arg2: usize) -> SbiRet {
-    let (error, value);
-    match () {
-        #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
-        () => unsafe { asm!(
-            "ecall", 
-            in("a0") arg0, in("a1") arg1, in("a2") arg2,
-            in("a6") function, in("a7") extension,
-            lateout("a0") error, lateout("a1") value,
-        ) },
-        #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
-        () => {
-            drop((extension, function, arg0, arg1, arg2));
-            unimplemented!("not RISC-V instruction set architecture")
-        }
-    };
-    SbiRet { error, value }
-}
-
-#[inline]
-pub fn get_spec_version() -> usize {
-    sbi_call(EXTENSION_BASE, FUNCTION_BASE_GET_SPEC_VERSION, 0, 0, 0).value
-}
-
-#[inline]
-pub fn get_sbi_impl_id() -> usize {
-    sbi_call(EXTENSION_BASE, FUNCTION_BASE_GET_SBI_IMPL_ID, 0, 0, 0).value
-}
-
-#[inline]
-pub fn get_sbi_impl_version() -> usize {
-    sbi_call(EXTENSION_BASE, FUNCTION_BASE_GET_SBI_IMPL_VERSION, 0, 0, 0).value
-}
-
-#[inline]
-pub fn probe_extension(extension_id: usize) -> usize {
-    sbi_call(EXTENSION_BASE, FUNCTION_BASE_PROBE_EXTENSION, extension_id, 0, 0).value
-}
-
-#[inline]
-pub fn get_mvendorid() -> usize {
-    sbi_call(EXTENSION_BASE, FUNCTION_BASE_GET_MVENDORID, 0, 0, 0).value
-}
-
-#[inline]
-pub fn get_marchid() -> usize {
-    sbi_call(EXTENSION_BASE, FUNCTION_BASE_GET_MARCHID, 0, 0, 0).value
-}
-
-#[inline]
-pub fn get_mimpid() -> usize {
-    sbi_call(EXTENSION_BASE, FUNCTION_BASE_GET_MIMPID, 0, 0, 0).value
-}
-
-#[inline(always)]
-fn sbi_call_legacy(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
-    let ret;
-    match () {
-        #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
-        () => unsafe { asm!(
-            "ecall", 
-            in("a0") arg0, in("a1") arg1, in("a2") arg2,
-            in("a7") which,
-            lateout("a0") ret,
-        ) },
-        #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
-        () => {
-            drop((which, arg0, arg1, arg2));
-            unimplemented!("not RISC-V instruction set architecture")
-        }
-    };
-    ret
-}
-
-const SBI_SET_TIMER: usize = 0;
-const SBI_CONSOLE_PUTCHAR: usize = 1;
-const SBI_CONSOLE_GETCHAR: usize = 2;
-const SBI_CLEAR_IPI: usize = 3;
-const SBI_SEND_IPI: usize = 4;
-const SBI_REMOTE_FENCE_I: usize = 5;
-const SBI_REMOTE_SFENCE_VMA: usize = 6;
-const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7;
-const SBI_SHUTDOWN: usize = 8;
-
-pub fn console_putchar(c: usize) {
-    sbi_call_legacy(SBI_CONSOLE_PUTCHAR, c, 0, 0);
-}
-
-pub fn console_getchar() -> usize {
-    sbi_call_legacy(SBI_CONSOLE_GETCHAR, 0, 0, 0)
-}
-
-pub fn shutdown() -> ! {
-    sbi_call_legacy(SBI_SHUTDOWN, 0, 0, 0);
-    unreachable!()
-}
-
-pub fn set_timer(time: usize) {
-    sbi_call_legacy(SBI_SET_TIMER, time, 0, 0);
-}