Update testcases.

testcases
Yifan Wu 5 years ago
parent e5a62b4330
commit 698b4553f5

@ -0,0 +1,3 @@
# Tutorial 第一章测试用例
第一章只需要在 RV64 裸机平台运行一个嵌入式应用,因此只要能够在 SBI 的帮助下在屏幕上输出一行字符串就算成功。

@ -0,0 +1,7 @@
[build]
target = "riscv64gc-unknown-none-elf"
[target.riscv64gc-unknown-none-elf]
rustflags = [
"-Clink-args=-Tsrc/linker.ld",
]

2
ch2/.gitignore vendored

@ -0,0 +1,2 @@
target/*
Cargo.lock

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MakefileSettings">
<option name="linkedExternalProjectsSettings">
<MakefileProjectSettings>
<option name="analyzerType" value="OUTPUT_PARSING" />
<option name="buildOptions" value="" />
<option name="buildTarget" value="all" />
<option name="cleanTarget" value="clean" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
<option name="switches" value="--just-print --print-directory --keep-going" />
</MakefileProjectSettings>
</option>
</component>
<component name="MakefileWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="External" type="CPP_MODULE" version="4">
<component name="FacetManager">
<facet type="Python" name="Python facet">
<configuration sdkName="Python 3.8 (user)" />
</facet>
</component>
</module>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="BranchesTreeState">
<expand>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="LOCAL_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="GROUP_NODE:origin" type="e8cecc67:BranchNodeDescriptor" />
</path>
</expand>
<select />
</component>
<component name="CMakeRunConfigurationManager" shouldGenerate="true" shouldDeleteObsolete="true">
<generated />
</component>
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" ENABLED="true" />
</configurations>
</component>
<component name="CargoProjects">
<cargoProject FILE="$PROJECT_DIR$/Cargo.toml" />
</component>
<component name="ChangeListManager">
<list default="true" id="7141abd6-a726-4e6d-beaf-d3ad4079ecae" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
</projectState>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Rust File" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component>
<component name="MacroExpansionManager">
<option name="directoryName" value="xz6ecuse" />
</component>
<component name="MakefileLocalSettings">
<option name="availableProjects">
<map>
<entry>
<key>
<ExternalProjectPojo>
<option name="name" value="user" />
<option name="path" value="$PROJECT_DIR$" />
</ExternalProjectPojo>
</key>
<value>
<list>
<ExternalProjectPojo>
<option name="name" value="user" />
<option name="path" value="$PROJECT_DIR$" />
</ExternalProjectPojo>
</list>
</value>
</entry>
</map>
</option>
<option name="projectSyncType">
<map>
<entry key="$PROJECT_DIR$" value="RE_IMPORT" />
</map>
</option>
</component>
<component name="ProjectId" id="1kTanhQMyfxvC9662Wn660ya9jI" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="cf.first.check.clang-format" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../../../kendryte-standalone-sdk" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.tslint" value="true" />
<property name="node.js.path.for.package.eslint" value="project" />
<property name="node.js.path.for.package.tslint" value="project" />
<property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="node.js.selected.package.tslint" value="(autodetect)" />
<property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" />
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
</component>
<component name="RunManager">
<configuration default="true" type="CLionExternalRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="CLION.EXTERNAL.BUILD" enabled="true" />
</method>
</configuration>
<configuration default="true" type="GradleAppRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="com.jetbrains.cidr.cpp.gradle.execution.GradleNativeBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
<component name="RustProjectSettings">
<option name="toolchainHomeDirectory" value="$USER_HOME$/.cargo/bin" />
<option name="version" value="2" />
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="7141abd6-a726-4e6d-beaf-d3ad4079ecae" name="Default Changelist" comment="" />
<created>1605727203780</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1605727203780</updated>
<workItem from="1605727206950" duration="2304000" />
<workItem from="1605751834879" duration="1034000" />
<workItem from="1605755411414" duration="300000" />
<workItem from="1605767379447" duration="2021000" />
<workItem from="1605785565921" duration="1662000" />
<workItem from="1605837573426" duration="2903000" />
<workItem from="1605853813741" duration="2031000" />
<workItem from="1605886782374" duration="314000" />
<workItem from="1606021324773" duration="727000" />
<workItem from="1606052465219" duration="82000" />
<workItem from="1606702751670" duration="1282000" />
<workItem from="1606721365601" duration="680000" />
<workItem from="1606784006574" duration="940000" />
<workItem from="1606814544720" duration="599000" />
<workItem from="1606872152767" duration="1098000" />
<workItem from="1606873285412" duration="666000" />
<workItem from="1606961052577" duration="132000" />
<workItem from="1606961207805" duration="611000" />
<workItem from="1607002608870" duration="599000" />
<workItem from="1607044229762" duration="599000" />
<workItem from="1607087662988" duration="1759000" />
<workItem from="1607135725594" duration="599000" />
<workItem from="1607204320022" duration="599000" />
<workItem from="1607213987951" duration="598000" />
<workItem from="1607220658448" duration="597000" />
<workItem from="1607233201088" duration="599000" />
<workItem from="1607334407529" duration="1463000" />
<workItem from="1607362135025" duration="304000" />
<workItem from="1607390604960" duration="599000" />
<workItem from="1607437302836" duration="3818000" />
<workItem from="1607477228877" duration="4208000" />
<workItem from="1607519840849" duration="1206000" />
<workItem from="1607562100026" duration="7978000" />
<workItem from="1607606744996" duration="5366000" />
<workItem from="1607652075707" duration="9055000" />
<workItem from="1607693154794" duration="1417000" />
<workItem from="1607790084516" duration="599000" />
<workItem from="1607822156325" duration="599000" />
<workItem from="1607909336129" duration="9433000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
<option name="oldMeFiltersMigrated" value="true" />
</component>
</project>

@ -0,0 +1,9 @@
[package]
name = "user_lib"
version = "0.1.0"
authors = ["Yifan Wu <shinbokuow@163.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

@ -0,0 +1,21 @@
TARGET := riscv64gc-unknown-none-elf
MODE := release
APP_DIR := src/bin
TARGET_DIR := target/$(TARGET)/$(MODE)
APPS := $(wildcard $(APP_DIR)/*.rs)
ELFS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%, $(APPS))
BINS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%.bin, $(APPS))
OBJDUMP := rust-objdump --arch-name=riscv64
OBJCOPY := rust-objcopy --binary-architecture=riscv64
elf:
@cargo build --release
@echo $(APPS)
@echo $(ELFS)
@echo $(BINS)
binary: elf
$(foreach elf, $(ELFS), $(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf));)
build: binary

@ -0,0 +1,20 @@
# Tutorial 第二章测试用例
第二章我们需要实现一个批处理系统。在 `src/bin` 目录中,我们可以找到三个应用程序:
* `00hello_world`
* `01store_fault`
* `02power`
我们需要按照编号从小到大的顺序去加载并运行它们。
应用被设计为运行在用户模式,批处理系统应运行在监督模式,它们都直接访问物理内存。
三个应用被需要被加载到同一个物理地址。
本章需要实现的系统调用:
* `sys_write` 用于向屏幕输出字符串;
* `sys_exit` 用于告知批处理系统当前应用退出,应切换到下一个应用。
注意:应用 `01store_fault` 会访问非法的物理地址,批处理系统需要杀死它并能够正常运行序列中的下一个应用 `02power`

@ -0,0 +1,11 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
#[no_mangle]
fn main() -> i32 {
println!("Hello, world!");
0
}

@ -0,0 +1,14 @@
#![no_std]
#![no_main]
#![feature(llvm_asm)]
#[macro_use]
extern crate user_lib;
#[no_mangle]
fn main() -> i32 {
println!("Into Test store_fault, we will insert an invalid store operation...");
println!("Kernel should kill this application!");
unsafe { (0x0 as *mut u8).write_volatile(0); }
0
}

@ -1,12 +1,16 @@
/// rCore application without user_lib.
/// Load it manually to 0x80040000.
/// It should OK.
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
const SIZE: usize = 10;
const P: u32 = 3;
const STEP: usize = 10000000;
const STEP: usize = 100000;
const MOD: u32 = 10007;
fn main() -> ! {
#[no_mangle]
fn main() -> i32 {
let mut pow = [0u32; SIZE];
let mut index: usize = 0;
pow[index] = 1;
@ -19,5 +23,5 @@ fn main() -> ! {
}
}
println!("Test power OK!");
loop {}
0
}

@ -0,0 +1,29 @@
use core::fmt::{self, Write};
use crate::syscall::{STDOUT, sys_write};
struct Stdout;
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
sys_write(STDOUT, s.as_bytes());
Ok(())
}
}
pub fn print(args: fmt::Arguments) {
Stdout.write_fmt(args).unwrap();
}
#[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,0 +1,10 @@
#[panic_handler]
fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
let err = panic_info.message().unwrap();
if let Some(location) = panic_info.location() {
println!("Panicked at {}:{}, {}", location.file(), location.line(), err);
} else {
println!("Panicked: {}", err);
}
loop {}
}

@ -0,0 +1,33 @@
#![no_std]
#![feature(llvm_asm)]
#![feature(linkage)]
#![feature(panic_info_message)]
#[macro_use]
pub mod console;
mod syscall;
mod lang_items;
#[no_mangle]
#[link_section = ".text.entry"]
pub extern "C" fn _start() -> ! {
clear_bss();
syscall::sys_exit(main());
panic!("unreachable after sys_exit!");
}
#[linkage = "weak"]
#[no_mangle]
fn main() -> i32 {
panic!("Cannot find main!");
}
fn clear_bss() {
extern "C" {
fn start_bss();
fn end_bss();
}
(start_bss as usize..end_bss as usize).for_each(|addr| {
unsafe { (addr as *mut u8).write_volatile(0); }
});
}

@ -0,0 +1,28 @@
OUTPUT_ARCH(riscv)
ENTRY(_start)
BASE_ADDRESS = 0x80040000;
SECTIONS
{
. = BASE_ADDRESS;
.text : {
*(.text.entry)
*(.text .text.*)
}
.rodata : {
*(.rodata .rodata.*)
}
.data : {
*(.data .data.*)
}
.bss : {
start_bss = .;
*(.bss .bss.*)
end_bss = .;
}
/DISCARD/ : {
*(.eh_frame)
*(.debug*)
}
}

@ -0,0 +1,25 @@
pub const STDOUT: usize = 1;
const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93;
fn syscall(id: usize, args: [usize; 3]) -> isize {
let mut ret: isize;
unsafe {
llvm_asm!("ecall"
: "={x10}" (ret)
: "{x10}" (args[0]), "{x11}" (args[1]), "{x12}" (args[2]), "{x17}" (id)
: "memory"
: "volatile"
);
}
ret
}
pub fn sys_write(fd: usize, buffer: &[u8]) -> isize {
syscall(SYSCALL_WRITE, [fd, buffer.as_ptr() as usize, buffer.len()])
}
pub fn sys_exit(xstate: i32) -> isize {
syscall(SYSCALL_EXIT, [xstate as usize, 0, 0])
}

@ -0,0 +1,7 @@
[build]
target = "riscv64gc-unknown-none-elf"
[target.riscv64gc-unknown-none-elf]
rustflags = [
"-Clink-args=-Tsrc/linker.ld",
]

@ -0,0 +1 @@
target/*

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MakefileSettings">
<option name="linkedExternalProjectsSettings">
<MakefileProjectSettings>
<option name="analyzerType" value="OUTPUT_PARSING" />
<option name="buildOptions" value="" />
<option name="buildTarget" value="all" />
<option name="cleanTarget" value="clean" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
<option name="switches" value="--just-print --print-directory --keep-going" />
</MakefileProjectSettings>
</option>
</component>
<component name="MakefileWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="External" type="CPP_MODULE" version="4">
<component name="FacetManager">
<facet type="Python" name="Python facet">
<configuration sdkName="Python 3.8 (user)" />
</facet>
</component>
</module>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="BranchesTreeState">
<expand>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="LOCAL_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="GROUP_NODE:origin" type="e8cecc67:BranchNodeDescriptor" />
</path>
</expand>
<select />
</component>
<component name="CMakeRunConfigurationManager" shouldGenerate="true" shouldDeleteObsolete="true">
<generated />
</component>
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" ENABLED="true" />
</configurations>
</component>
<component name="CargoProjects">
<cargoProject FILE="$PROJECT_DIR$/Cargo.toml" />
</component>
<component name="ChangeListManager">
<list default="true" id="7141abd6-a726-4e6d-beaf-d3ad4079ecae" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
</projectState>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Rust File" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component>
<component name="MacroExpansionManager">
<option name="directoryName" value="xz6ecuse" />
</component>
<component name="MakefileLocalSettings">
<option name="availableProjects">
<map>
<entry>
<key>
<ExternalProjectPojo>
<option name="name" value="user" />
<option name="path" value="$PROJECT_DIR$" />
</ExternalProjectPojo>
</key>
<value>
<list>
<ExternalProjectPojo>
<option name="name" value="user" />
<option name="path" value="$PROJECT_DIR$" />
</ExternalProjectPojo>
</list>
</value>
</entry>
</map>
</option>
<option name="projectSyncType">
<map>
<entry key="$PROJECT_DIR$" value="RE_IMPORT" />
</map>
</option>
</component>
<component name="ProjectId" id="1kTanhQMyfxvC9662Wn660ya9jI" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="cf.first.check.clang-format" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../../../kendryte-standalone-sdk" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.tslint" value="true" />
<property name="node.js.path.for.package.eslint" value="project" />
<property name="node.js.path.for.package.tslint" value="project" />
<property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="node.js.selected.package.tslint" value="(autodetect)" />
<property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" />
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
</component>
<component name="RunManager">
<configuration default="true" type="CLionExternalRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="CLION.EXTERNAL.BUILD" enabled="true" />
</method>
</configuration>
<configuration default="true" type="GradleAppRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="com.jetbrains.cidr.cpp.gradle.execution.GradleNativeBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
<component name="RustProjectSettings">
<option name="toolchainHomeDirectory" value="$USER_HOME$/.cargo/bin" />
<option name="version" value="2" />
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="7141abd6-a726-4e6d-beaf-d3ad4079ecae" name="Default Changelist" comment="" />
<created>1605727203780</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1605727203780</updated>
<workItem from="1605727206950" duration="2304000" />
<workItem from="1605751834879" duration="1034000" />
<workItem from="1605755411414" duration="300000" />
<workItem from="1605767379447" duration="2021000" />
<workItem from="1605785565921" duration="1662000" />
<workItem from="1605837573426" duration="2903000" />
<workItem from="1605853813741" duration="2031000" />
<workItem from="1605886782374" duration="314000" />
<workItem from="1606021324773" duration="727000" />
<workItem from="1606052465219" duration="82000" />
<workItem from="1606702751670" duration="1282000" />
<workItem from="1606721365601" duration="680000" />
<workItem from="1606784006574" duration="940000" />
<workItem from="1606814544720" duration="599000" />
<workItem from="1606872152767" duration="1098000" />
<workItem from="1606873285412" duration="666000" />
<workItem from="1606961052577" duration="132000" />
<workItem from="1606961207805" duration="611000" />
<workItem from="1607002608870" duration="599000" />
<workItem from="1607044229762" duration="599000" />
<workItem from="1607087662988" duration="1759000" />
<workItem from="1607135725594" duration="599000" />
<workItem from="1607204320022" duration="599000" />
<workItem from="1607213987951" duration="598000" />
<workItem from="1607220658448" duration="597000" />
<workItem from="1607233201088" duration="599000" />
<workItem from="1607334407529" duration="1463000" />
<workItem from="1607362135025" duration="304000" />
<workItem from="1607390604960" duration="599000" />
<workItem from="1607437302836" duration="3818000" />
<workItem from="1607477228877" duration="4208000" />
<workItem from="1607519840849" duration="1206000" />
<workItem from="1607562100026" duration="7978000" />
<workItem from="1607606744996" duration="5366000" />
<workItem from="1607652075707" duration="9055000" />
<workItem from="1607693154794" duration="1417000" />
<workItem from="1607790084516" duration="599000" />
<workItem from="1607822156325" duration="599000" />
<workItem from="1607909336129" duration="9433000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
<option name="oldMeFiltersMigrated" value="true" />
</component>
</project>

@ -0,0 +1,9 @@
[package]
name = "user_lib"
version = "0.1.0"
authors = ["Yifan Wu <shinbokuow@163.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

@ -0,0 +1,23 @@
TARGET := riscv64gc-unknown-none-elf
MODE := release
APP_DIR := src/bin
TARGET_DIR := target/$(TARGET)/$(MODE)
APPS := $(wildcard $(APP_DIR)/*.rs)
ELFS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%, $(APPS))
BINS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%.bin, $(APPS))
OBJDUMP := rust-objdump --arch-name=riscv64
OBJCOPY := rust-objcopy --binary-architecture=riscv64
elf: $(APPS)
@python3 build.py
binary: elf
$(foreach elf, $(ELFS), $(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf));)
build: binary
clean:
@cargo clean
.PHONY: elf binary build clean

@ -0,0 +1,4 @@
# Tutorial 第三章测试用例 part1
在 Tutorial 第三章第一阶段中,只需实现一个非抢占式调度的分时多任务系统。

@ -0,0 +1,25 @@
import os
base_address = 0x80100000
step = 0x20000
linker = 'src/linker.ld'
app_id = 0
apps = os.listdir('src/bin')
apps.sort()
for app in apps:
app = app[:app.find('.')]
lines = []
lines_before = []
with open(linker, 'r') as f:
for line in f.readlines():
lines_before.append(line)
line = line.replace(hex(base_address), hex(base_address+step*app_id))
lines.append(line)
with open(linker, 'w+') as f:
f.writelines(lines)
os.system('cargo build --bin %s --release' % app)
print('[build.py] application %s start with address %s' %(app, hex(base_address+step*app_id)))
with open(linker, 'w+') as f:
f.writelines(lines_before)
app_id = app_id + 1

@ -0,0 +1,21 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::sys_yield;
const WIDTH: usize = 10;
const HEIGHT: usize = 5;
#[no_mangle]
fn main() -> i32 {
for i in 0..HEIGHT {
for _ in 0..WIDTH { print!("A"); }
println!(" [{}/{}]", i + 1, HEIGHT);
sys_yield();
}
println!("Test write_a OK!");
0
}

@ -0,0 +1,21 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::sys_yield;
const WIDTH: usize = 10;
const HEIGHT: usize = 2;
#[no_mangle]
fn main() -> i32 {
for i in 0..HEIGHT {
for _ in 0..WIDTH { print!("B"); }
println!(" [{}/{}]", i + 1, HEIGHT);
sys_yield();
}
println!("Test write_b OK!");
0
}

@ -0,0 +1,21 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::sys_yield;
const WIDTH: usize = 10;
const HEIGHT: usize = 3;
#[no_mangle]
fn main() -> i32 {
for i in 0..HEIGHT {
for _ in 0..WIDTH { print!("C"); }
println!(" [{}/{}]", i + 1, HEIGHT);
sys_yield();
}
println!("Test write_c OK!");
0
}

@ -0,0 +1,29 @@
use core::fmt::{self, Write};
use crate::syscall::{STDOUT, sys_write};
struct Stdout;
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
sys_write(STDOUT, s.as_bytes());
Ok(())
}
}
pub fn print(args: fmt::Arguments) {
Stdout.write_fmt(args).unwrap();
}
#[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,0 +1,10 @@
#[panic_handler]
fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
let err = panic_info.message().unwrap();
if let Some(location) = panic_info.location() {
println!("Panicked at {}:{}, {}", location.file(), location.line(), err);
} else {
println!("Panicked: {}", err);
}
loop {}
}

@ -0,0 +1,35 @@
#![no_std]
#![feature(llvm_asm)]
#![feature(linkage)]
#![feature(panic_info_message)]
#[macro_use]
pub mod console;
mod syscall;
mod lang_items;
#[no_mangle]
#[link_section = ".text.entry"]
pub extern "C" fn _start() -> ! {
clear_bss();
syscall::sys_exit(main());
panic!("unreachable after sys_exit!");
}
#[linkage = "weak"]
#[no_mangle]
fn main() -> i32 {
panic!("Cannot find main!");
}
fn clear_bss() {
extern "C" {
fn start_bss();
fn end_bss();
}
(start_bss as usize..end_bss as usize).for_each(|addr| {
unsafe { (addr as *mut u8).write_volatile(0); }
});
}
pub use syscall::*;

@ -0,0 +1,29 @@
OUTPUT_ARCH(riscv)
ENTRY(_start)
BASE_ADDRESS = 0x80100000;
SECTIONS
{
. = BASE_ADDRESS;
.text : {
*(.text.entry)
*(.text .text.*)
}
.rodata : {
*(.rodata .rodata.*)
}
.data : {
*(.data .data.*)
}
.bss : {
start_bss = .;
*(.bss .bss.*)
end_bss = .;
}
/DISCARD/ : {
*(.eh_frame)
*(.debug*)
}
}

@ -0,0 +1,35 @@
pub const STDOUT: usize = 1;
const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93;
const SYSCALL_YIELD: usize = 124;
const SYSCALL_GET_TIME: usize = 169;
fn syscall(id: usize, args: [usize; 3]) -> isize {
let mut ret: isize;
unsafe {
llvm_asm!("ecall"
: "={x10}" (ret)
: "{x10}" (args[0]), "{x11}" (args[1]), "{x12}" (args[2]), "{x17}" (id)
: "memory"
: "volatile"
);
}
ret
}
pub fn sys_write(fd: usize, buffer: &[u8]) -> isize {
syscall(SYSCALL_WRITE, [fd, buffer.as_ptr() as usize, buffer.len()])
}
pub fn sys_exit(xstate: i32) -> isize {
syscall(SYSCALL_EXIT, [xstate as usize, 0, 0])
}
pub fn sys_yield() -> isize {
syscall(SYSCALL_YIELD, [0, 0, 0])
}
pub fn sys_get_time() -> isize {
syscall(SYSCALL_GET_TIME, [0, 0, 0])
}

@ -0,0 +1,7 @@
[build]
target = "riscv64gc-unknown-none-elf"
[target.riscv64gc-unknown-none-elf]
rustflags = [
"-Clink-args=-Tsrc/linker.ld",
]

1
ch3/.gitignore vendored

@ -0,0 +1 @@
target/*

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MakefileSettings">
<option name="linkedExternalProjectsSettings">
<MakefileProjectSettings>
<option name="analyzerType" value="OUTPUT_PARSING" />
<option name="buildOptions" value="" />
<option name="buildTarget" value="all" />
<option name="cleanTarget" value="clean" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
<option name="switches" value="--just-print --print-directory --keep-going" />
</MakefileProjectSettings>
</option>
</component>
<component name="MakefileWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="External" type="CPP_MODULE" version="4">
<component name="FacetManager">
<facet type="Python" name="Python facet">
<configuration sdkName="Python 3.8 (user)" />
</facet>
</component>
</module>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="BranchesTreeState">
<expand>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="LOCAL_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="GROUP_NODE:origin" type="e8cecc67:BranchNodeDescriptor" />
</path>
</expand>
<select />
</component>
<component name="CMakeRunConfigurationManager" shouldGenerate="true" shouldDeleteObsolete="true">
<generated />
</component>
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" ENABLED="true" />
</configurations>
</component>
<component name="CargoProjects">
<cargoProject FILE="$PROJECT_DIR$/Cargo.toml" />
</component>
<component name="ChangeListManager">
<list default="true" id="7141abd6-a726-4e6d-beaf-d3ad4079ecae" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
</projectState>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Rust File" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component>
<component name="MacroExpansionManager">
<option name="directoryName" value="xz6ecuse" />
</component>
<component name="MakefileLocalSettings">
<option name="availableProjects">
<map>
<entry>
<key>
<ExternalProjectPojo>
<option name="name" value="user" />
<option name="path" value="$PROJECT_DIR$" />
</ExternalProjectPojo>
</key>
<value>
<list>
<ExternalProjectPojo>
<option name="name" value="user" />
<option name="path" value="$PROJECT_DIR$" />
</ExternalProjectPojo>
</list>
</value>
</entry>
</map>
</option>
<option name="projectSyncType">
<map>
<entry key="$PROJECT_DIR$" value="RE_IMPORT" />
</map>
</option>
</component>
<component name="ProjectId" id="1kTanhQMyfxvC9662Wn660ya9jI" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="cf.first.check.clang-format" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../../../kendryte-standalone-sdk" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.tslint" value="true" />
<property name="node.js.path.for.package.eslint" value="project" />
<property name="node.js.path.for.package.tslint" value="project" />
<property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="node.js.selected.package.tslint" value="(autodetect)" />
<property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" />
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
</component>
<component name="RunManager">
<configuration default="true" type="CLionExternalRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="CLION.EXTERNAL.BUILD" enabled="true" />
</method>
</configuration>
<configuration default="true" type="GradleAppRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="com.jetbrains.cidr.cpp.gradle.execution.GradleNativeBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
<component name="RustProjectSettings">
<option name="toolchainHomeDirectory" value="$USER_HOME$/.cargo/bin" />
<option name="version" value="2" />
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="7141abd6-a726-4e6d-beaf-d3ad4079ecae" name="Default Changelist" comment="" />
<created>1605727203780</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1605727203780</updated>
<workItem from="1605727206950" duration="2304000" />
<workItem from="1605751834879" duration="1034000" />
<workItem from="1605755411414" duration="300000" />
<workItem from="1605767379447" duration="2021000" />
<workItem from="1605785565921" duration="1662000" />
<workItem from="1605837573426" duration="2903000" />
<workItem from="1605853813741" duration="2031000" />
<workItem from="1605886782374" duration="314000" />
<workItem from="1606021324773" duration="727000" />
<workItem from="1606052465219" duration="82000" />
<workItem from="1606702751670" duration="1282000" />
<workItem from="1606721365601" duration="680000" />
<workItem from="1606784006574" duration="940000" />
<workItem from="1606814544720" duration="599000" />
<workItem from="1606872152767" duration="1098000" />
<workItem from="1606873285412" duration="666000" />
<workItem from="1606961052577" duration="132000" />
<workItem from="1606961207805" duration="611000" />
<workItem from="1607002608870" duration="599000" />
<workItem from="1607044229762" duration="599000" />
<workItem from="1607087662988" duration="1759000" />
<workItem from="1607135725594" duration="599000" />
<workItem from="1607204320022" duration="599000" />
<workItem from="1607213987951" duration="598000" />
<workItem from="1607220658448" duration="597000" />
<workItem from="1607233201088" duration="599000" />
<workItem from="1607334407529" duration="1463000" />
<workItem from="1607362135025" duration="304000" />
<workItem from="1607390604960" duration="599000" />
<workItem from="1607437302836" duration="3818000" />
<workItem from="1607477228877" duration="4208000" />
<workItem from="1607519840849" duration="1206000" />
<workItem from="1607562100026" duration="7978000" />
<workItem from="1607606744996" duration="5366000" />
<workItem from="1607652075707" duration="9055000" />
<workItem from="1607693154794" duration="1417000" />
<workItem from="1607790084516" duration="599000" />
<workItem from="1607822156325" duration="599000" />
<workItem from="1607909336129" duration="9433000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
<option name="oldMeFiltersMigrated" value="true" />
</component>
</project>

@ -0,0 +1,9 @@
[package]
name = "user_lib"
version = "0.1.0"
authors = ["Yifan Wu <shinbokuow@163.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

@ -0,0 +1,23 @@
TARGET := riscv64gc-unknown-none-elf
MODE := release
APP_DIR := src/bin
TARGET_DIR := target/$(TARGET)/$(MODE)
APPS := $(wildcard $(APP_DIR)/*.rs)
ELFS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%, $(APPS))
BINS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%.bin, $(APPS))
OBJDUMP := rust-objdump --arch-name=riscv64
OBJCOPY := rust-objcopy --binary-architecture=riscv64
elf: $(APPS)
@python3 build.py
binary: elf
$(foreach elf, $(ELFS), $(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf));)
build: binary
clean:
@cargo clean
.PHONY: elf binary build clean

@ -0,0 +1,25 @@
import os
base_address = 0x80100000
step = 0x20000
linker = 'src/linker.ld'
app_id = 0
apps = os.listdir('src/bin')
apps.sort()
for app in apps:
app = app[:app.find('.')]
lines = []
lines_before = []
with open(linker, 'r') as f:
for line in f.readlines():
lines_before.append(line)
line = line.replace(hex(base_address), hex(base_address+step*app_id))
lines.append(line)
with open(linker, 'w+') as f:
f.writelines(lines)
os.system('cargo build --bin %s --release' % app)
print('[build.py] application %s start with address %s' %(app, hex(base_address+step*app_id)))
with open(linker, 'w+') as f:
f.writelines(lines_before)
app_id = app_id + 1

@ -0,0 +1,28 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
const LEN: usize = 100;
#[no_mangle]
fn main() -> i32 {
let p = 3u64;
let m = 998244353u64;
let iter: usize = 200000;
let mut s = [0u64; LEN];
let mut cur = 0usize;
s[cur] = 1;
for i in 1..=iter {
let next = if cur + 1 == LEN { 0 } else { cur + 1 };
s[next] = s[cur] * p % m;
cur = next;
if i % 10000 == 0 {
println!("power_3 [{}/{}]", i, iter);
}
}
println!("{}^{} = {}", p, iter, s[cur]);
println!("Test power_3 OK!");
0
}

@ -0,0 +1,28 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
const LEN: usize = 100;
#[no_mangle]
fn main() -> i32 {
let p = 5u64;
let m = 998244353u64;
let iter: usize = 140000;
let mut s = [0u64; LEN];
let mut cur = 0usize;
s[cur] = 1;
for i in 1..=iter {
let next = if cur + 1 == LEN { 0 } else { cur + 1 };
s[next] = s[cur] * p % m;
cur = next;
if i % 10000 == 0 {
println!("power_5 [{}/{}]", i, iter);
}
}
println!("{}^{} = {}", p, iter, s[cur]);
println!("Test power_5 OK!");
0
}

@ -0,0 +1,28 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
const LEN: usize = 100;
#[no_mangle]
fn main() -> i32 {
let p = 7u64;
let m = 998244353u64;
let iter: usize = 160000;
let mut s = [0u64; LEN];
let mut cur = 0usize;
s[cur] = 1;
for i in 1..=iter {
let next = if cur + 1 == LEN { 0 } else { cur + 1 };
s[next] = s[cur] * p % m;
cur = next;
if i % 10000 == 0 {
println!("power_7 [{}/{}]", i, iter);
}
}
println!("{}^{} = {}", p, iter, s[cur]);
println!("Test power_7 OK!");
0
}

@ -0,0 +1,18 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{sys_get_time, sys_yield};
#[no_mangle]
fn main() -> i32 {
let current_timer = sys_get_time();
let wait_for = current_timer + 10000000;
while sys_get_time() < wait_for {
sys_yield();
}
println!("Test sleep OK!");
0
}

@ -0,0 +1,29 @@
use core::fmt::{self, Write};
use crate::syscall::{STDOUT, sys_write};
struct Stdout;
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
sys_write(STDOUT, s.as_bytes());
Ok(())
}
}
pub fn print(args: fmt::Arguments) {
Stdout.write_fmt(args).unwrap();
}
#[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,0 +1,10 @@
#[panic_handler]
fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
let err = panic_info.message().unwrap();
if let Some(location) = panic_info.location() {
println!("Panicked at {}:{}, {}", location.file(), location.line(), err);
} else {
println!("Panicked: {}", err);
}
loop {}
}

@ -0,0 +1,35 @@
#![no_std]
#![feature(llvm_asm)]
#![feature(linkage)]
#![feature(panic_info_message)]
#[macro_use]
pub mod console;
mod syscall;
mod lang_items;
#[no_mangle]
#[link_section = ".text.entry"]
pub extern "C" fn _start() -> ! {
clear_bss();
syscall::sys_exit(main());
panic!("unreachable after sys_exit!");
}
#[linkage = "weak"]
#[no_mangle]
fn main() -> i32 {
panic!("Cannot find main!");
}
fn clear_bss() {
extern "C" {
fn start_bss();
fn end_bss();
}
(start_bss as usize..end_bss as usize).for_each(|addr| {
unsafe { (addr as *mut u8).write_volatile(0); }
});
}
pub use syscall::*;

@ -0,0 +1,29 @@
OUTPUT_ARCH(riscv)
ENTRY(_start)
BASE_ADDRESS = 0x80100000;
SECTIONS
{
. = BASE_ADDRESS;
.text : {
*(.text.entry)
*(.text .text.*)
}
.rodata : {
*(.rodata .rodata.*)
}
.data : {
*(.data .data.*)
}
.bss : {
start_bss = .;
*(.bss .bss.*)
end_bss = .;
}
/DISCARD/ : {
*(.eh_frame)
*(.debug*)
}
}

@ -0,0 +1,35 @@
pub const STDOUT: usize = 1;
const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93;
const SYSCALL_YIELD: usize = 124;
const SYSCALL_GET_TIME: usize = 169;
fn syscall(id: usize, args: [usize; 3]) -> isize {
let mut ret: isize;
unsafe {
llvm_asm!("ecall"
: "={x10}" (ret)
: "{x10}" (args[0]), "{x11}" (args[1]), "{x12}" (args[2]), "{x17}" (id)
: "memory"
: "volatile"
);
}
ret
}
pub fn sys_write(fd: usize, buffer: &[u8]) -> isize {
syscall(SYSCALL_WRITE, [fd, buffer.as_ptr() as usize, buffer.len()])
}
pub fn sys_exit(xstate: i32) -> isize {
syscall(SYSCALL_EXIT, [xstate as usize, 0, 0])
}
pub fn sys_yield() -> isize {
syscall(SYSCALL_YIELD, [0, 0, 0])
}
pub fn sys_get_time() -> isize {
syscall(SYSCALL_GET_TIME, [0, 0, 0])
}

@ -0,0 +1,7 @@
[build]
target = "riscv64gc-unknown-none-elf"
[target.riscv64gc-unknown-none-elf]
rustflags = [
"-Clink-args=-Tsrc/linker.ld",
]

1
ch4/.gitignore vendored

@ -0,0 +1 @@
target/*

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MakefileSettings">
<option name="linkedExternalProjectsSettings">
<MakefileProjectSettings>
<option name="analyzerType" value="OUTPUT_PARSING" />
<option name="buildOptions" value="" />
<option name="buildTarget" value="all" />
<option name="cleanTarget" value="clean" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
<option name="switches" value="--just-print --print-directory --keep-going" />
</MakefileProjectSettings>
</option>
</component>
<component name="MakefileWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="External" type="CPP_MODULE" version="4">
<component name="FacetManager">
<facet type="Python" name="Python facet">
<configuration sdkName="Python 3.8 (user)" />
</facet>
</component>
</module>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="BranchesTreeState">
<expand>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="LOCAL_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="GROUP_NODE:origin" type="e8cecc67:BranchNodeDescriptor" />
</path>
</expand>
<select />
</component>
<component name="CMakeRunConfigurationManager" shouldGenerate="true" shouldDeleteObsolete="true">
<generated />
</component>
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" ENABLED="true" />
</configurations>
</component>
<component name="CargoProjects">
<cargoProject FILE="$PROJECT_DIR$/Cargo.toml" />
</component>
<component name="ChangeListManager">
<list default="true" id="7141abd6-a726-4e6d-beaf-d3ad4079ecae" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
</projectState>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Rust File" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component>
<component name="MacroExpansionManager">
<option name="directoryName" value="xz6ecuse" />
</component>
<component name="MakefileLocalSettings">
<option name="availableProjects">
<map>
<entry>
<key>
<ExternalProjectPojo>
<option name="name" value="user" />
<option name="path" value="$PROJECT_DIR$" />
</ExternalProjectPojo>
</key>
<value>
<list>
<ExternalProjectPojo>
<option name="name" value="user" />
<option name="path" value="$PROJECT_DIR$" />
</ExternalProjectPojo>
</list>
</value>
</entry>
</map>
</option>
<option name="projectSyncType">
<map>
<entry key="$PROJECT_DIR$" value="RE_IMPORT" />
</map>
</option>
</component>
<component name="ProjectId" id="1kTanhQMyfxvC9662Wn660ya9jI" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="cf.first.check.clang-format" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../../../kendryte-standalone-sdk" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.tslint" value="true" />
<property name="node.js.path.for.package.eslint" value="project" />
<property name="node.js.path.for.package.tslint" value="project" />
<property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="node.js.selected.package.tslint" value="(autodetect)" />
<property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" />
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
</component>
<component name="RunManager">
<configuration default="true" type="CLionExternalRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="CLION.EXTERNAL.BUILD" enabled="true" />
</method>
</configuration>
<configuration default="true" type="GradleAppRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="com.jetbrains.cidr.cpp.gradle.execution.GradleNativeBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
<component name="RustProjectSettings">
<option name="toolchainHomeDirectory" value="$USER_HOME$/.cargo/bin" />
<option name="version" value="2" />
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="7141abd6-a726-4e6d-beaf-d3ad4079ecae" name="Default Changelist" comment="" />
<created>1605727203780</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1605727203780</updated>
<workItem from="1605727206950" duration="2304000" />
<workItem from="1605751834879" duration="1034000" />
<workItem from="1605755411414" duration="300000" />
<workItem from="1605767379447" duration="2021000" />
<workItem from="1605785565921" duration="1662000" />
<workItem from="1605837573426" duration="2903000" />
<workItem from="1605853813741" duration="2031000" />
<workItem from="1605886782374" duration="314000" />
<workItem from="1606021324773" duration="727000" />
<workItem from="1606052465219" duration="82000" />
<workItem from="1606702751670" duration="1282000" />
<workItem from="1606721365601" duration="680000" />
<workItem from="1606784006574" duration="940000" />
<workItem from="1606814544720" duration="599000" />
<workItem from="1606872152767" duration="1098000" />
<workItem from="1606873285412" duration="666000" />
<workItem from="1606961052577" duration="132000" />
<workItem from="1606961207805" duration="611000" />
<workItem from="1607002608870" duration="599000" />
<workItem from="1607044229762" duration="599000" />
<workItem from="1607087662988" duration="1759000" />
<workItem from="1607135725594" duration="599000" />
<workItem from="1607204320022" duration="599000" />
<workItem from="1607213987951" duration="598000" />
<workItem from="1607220658448" duration="597000" />
<workItem from="1607233201088" duration="599000" />
<workItem from="1607334407529" duration="1463000" />
<workItem from="1607362135025" duration="304000" />
<workItem from="1607390604960" duration="599000" />
<workItem from="1607437302836" duration="3818000" />
<workItem from="1607477228877" duration="4208000" />
<workItem from="1607519840849" duration="1206000" />
<workItem from="1607562100026" duration="7978000" />
<workItem from="1607606744996" duration="5366000" />
<workItem from="1607652075707" duration="9055000" />
<workItem from="1607693154794" duration="1417000" />
<workItem from="1607790084516" duration="599000" />
<workItem from="1607822156325" duration="599000" />
<workItem from="1607909336129" duration="9433000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
<option name="oldMeFiltersMigrated" value="true" />
</component>
</project>

@ -0,0 +1,9 @@
[package]
name = "user_lib"
version = "0.1.0"
authors = ["Yifan Wu <shinbokuow@163.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

@ -0,0 +1,23 @@
TARGET := riscv64gc-unknown-none-elf
MODE := release
APP_DIR := src/bin
TARGET_DIR := target/$(TARGET)/$(MODE)
APPS := $(wildcard $(APP_DIR)/*.rs)
ELFS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%, $(APPS))
BINS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%.bin, $(APPS))
OBJDUMP := rust-objdump --arch-name=riscv64
OBJCOPY := rust-objcopy --binary-architecture=riscv64
elf: $(APPS)
@cargo build --release
binary: elf
$(foreach elf, $(ELFS), $(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf));)
build: binary
clean:
@cargo clean
.PHONY: elf binary build clean

@ -0,0 +1,29 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
const LEN: usize = 100;
static mut S: [u64; LEN] = [0u64; LEN];
#[no_mangle]
unsafe fn main() -> i32 {
let p = 3u64;
let m = 998244353u64;
let iter: usize = 300000;
let mut cur = 0usize;
S[cur] = 1;
for i in 1..=iter {
let next = if cur + 1 == LEN { 0 } else { cur + 1 };
S[next] = S[cur] * p % m;
cur = next;
if i % 10000 == 0 {
println!("power_3 [{}/{}]", i, iter);
}
}
println!("{}^{} = {}(mod {})", p, iter, S[cur], m);
println!("Test power_3 OK!");
0
}

@ -0,0 +1,29 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
const LEN: usize = 100;
static mut S: [u64; LEN] = [0u64; LEN];
#[no_mangle]
unsafe fn main() -> i32 {
let p = 5u64;
let m = 998244353u64;
let iter: usize = 210000;
let mut cur = 0usize;
S[cur] = 1;
for i in 1..=iter {
let next = if cur + 1 == LEN { 0 } else { cur + 1 };
S[next] = S[cur] * p % m;
cur = next;
if i % 10000 == 0 {
println!("power_5 [{}/{}]", i, iter);
}
}
println!("{}^{} = {}(mod {})", p, iter, S[cur], m);
println!("Test power_5 OK!");
0
}

@ -0,0 +1,29 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
const LEN: usize = 100;
static mut S: [u64; LEN] = [0u64; LEN];
#[no_mangle]
unsafe fn main() -> i32 {
let p = 7u64;
let m = 998244353u64;
let iter: usize = 240000;
let mut cur = 0usize;
S[cur] = 1;
for i in 1..=iter {
let next = if cur + 1 == LEN { 0 } else { cur + 1 };
S[next] = S[cur] * p % m;
cur = next;
if i % 10000 == 0 {
println!("power_7 [{}/{}]", i, iter);
}
}
println!("{}^{} = {}(mod {})", p, iter, S[cur], m);
println!("Test power_7 OK!");
0
}

@ -0,0 +1,18 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{sys_get_time, sys_yield};
#[no_mangle]
fn main() -> i32 {
let current_timer = sys_get_time();
let wait_for = current_timer + 10000000;
while sys_get_time() < wait_for {
sys_yield();
}
println!("Test sleep OK!");
0
}

@ -0,0 +1,29 @@
use core::fmt::{self, Write};
use crate::syscall::{STDOUT, sys_write};
struct Stdout;
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
sys_write(STDOUT, s.as_bytes());
Ok(())
}
}
pub fn print(args: fmt::Arguments) {
Stdout.write_fmt(args).unwrap();
}
#[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,0 +1,10 @@
#[panic_handler]
fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
let err = panic_info.message().unwrap();
if let Some(location) = panic_info.location() {
println!("Panicked at {}:{}, {}", location.file(), location.line(), err);
} else {
println!("Panicked: {}", err);
}
loop {}
}

@ -0,0 +1,25 @@
#![no_std]
#![feature(llvm_asm)]
#![feature(linkage)]
#![feature(panic_info_message)]
#[macro_use]
pub mod console;
mod syscall;
mod lang_items;
#[no_mangle]
#[link_section = ".text.entry"]
pub extern "C" fn _start() -> ! {
syscall::sys_exit(main());
panic!("unreachable after sys_exit!");
}
#[linkage = "weak"]
#[no_mangle]
fn main() -> i32 {
panic!("Cannot find main!");
}
pub use syscall::*;

@ -0,0 +1,29 @@
OUTPUT_ARCH(riscv)
ENTRY(_start)
BASE_ADDRESS = 0x0;
SECTIONS
{
. = BASE_ADDRESS;
.text : {
*(.text.entry)
*(.text .text.*)
}
. = ALIGN(4K);
.rodata : {
*(.rodata .rodata.*)
}
. = ALIGN(4K);
.data : {
*(.data .data.*)
}
.bss : {
*(.bss .bss.*)
}
/DISCARD/ : {
*(.eh_frame)
*(.debug*)
}
}

@ -0,0 +1,35 @@
pub const STDOUT: usize = 1;
const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93;
const SYSCALL_YIELD: usize = 124;
const SYSCALL_GET_TIME: usize = 169;
fn syscall(id: usize, args: [usize; 3]) -> isize {
let mut ret: isize;
unsafe {
llvm_asm!("ecall"
: "={x10}" (ret)
: "{x10}" (args[0]), "{x11}" (args[1]), "{x12}" (args[2]), "{x17}" (id)
: "memory"
: "volatile"
);
}
ret
}
pub fn sys_write(fd: usize, buffer: &[u8]) -> isize {
syscall(SYSCALL_WRITE, [fd, buffer.as_ptr() as usize, buffer.len()])
}
pub fn sys_exit(xstate: i32) -> isize {
syscall(SYSCALL_EXIT, [xstate as usize, 0, 0])
}
pub fn sys_yield() -> isize {
syscall(SYSCALL_YIELD, [0, 0, 0])
}
pub fn sys_get_time() -> isize {
syscall(SYSCALL_GET_TIME, [0, 0, 0])
}

@ -0,0 +1,7 @@
[build]
target = "riscv64gc-unknown-none-elf"
[target.riscv64gc-unknown-none-elf]
rustflags = [
"-Clink-args=-Tsrc/linker.ld",
]

1
ch5/.gitignore vendored

@ -0,0 +1 @@
target/*

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MakefileSettings">
<option name="linkedExternalProjectsSettings">
<MakefileProjectSettings>
<option name="analyzerType" value="OUTPUT_PARSING" />
<option name="buildOptions" value="" />
<option name="buildTarget" value="all" />
<option name="cleanTarget" value="clean" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
<option name="switches" value="--just-print --print-directory --keep-going" />
</MakefileProjectSettings>
</option>
</component>
<component name="MakefileWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="External" type="CPP_MODULE" version="4">
<component name="FacetManager">
<facet type="Python" name="Python facet">
<configuration sdkName="Python 3.8 (user)" />
</facet>
</component>
</module>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="BranchesTreeState">
<expand>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="LOCAL_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="GROUP_NODE:origin" type="e8cecc67:BranchNodeDescriptor" />
</path>
</expand>
<select />
</component>
<component name="CMakeRunConfigurationManager" shouldGenerate="true" shouldDeleteObsolete="true">
<generated />
</component>
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" ENABLED="true" />
</configurations>
</component>
<component name="CargoProjects">
<cargoProject FILE="$PROJECT_DIR$/Cargo.toml" />
</component>
<component name="ChangeListManager">
<list default="true" id="7141abd6-a726-4e6d-beaf-d3ad4079ecae" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
</projectState>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Rust File" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component>
<component name="MacroExpansionManager">
<option name="directoryName" value="xz6ecuse" />
</component>
<component name="MakefileLocalSettings">
<option name="availableProjects">
<map>
<entry>
<key>
<ExternalProjectPojo>
<option name="name" value="user" />
<option name="path" value="$PROJECT_DIR$" />
</ExternalProjectPojo>
</key>
<value>
<list>
<ExternalProjectPojo>
<option name="name" value="user" />
<option name="path" value="$PROJECT_DIR$" />
</ExternalProjectPojo>
</list>
</value>
</entry>
</map>
</option>
<option name="projectSyncType">
<map>
<entry key="$PROJECT_DIR$" value="RE_IMPORT" />
</map>
</option>
</component>
<component name="ProjectId" id="1kTanhQMyfxvC9662Wn660ya9jI" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="cf.first.check.clang-format" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../../../kendryte-standalone-sdk" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.tslint" value="true" />
<property name="node.js.path.for.package.eslint" value="project" />
<property name="node.js.path.for.package.tslint" value="project" />
<property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="node.js.selected.package.tslint" value="(autodetect)" />
<property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" />
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
</component>
<component name="RunManager">
<configuration default="true" type="CLionExternalRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="CLION.EXTERNAL.BUILD" enabled="true" />
</method>
</configuration>
<configuration default="true" type="GradleAppRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="com.jetbrains.cidr.cpp.gradle.execution.GradleNativeBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
<component name="RustProjectSettings">
<option name="toolchainHomeDirectory" value="$USER_HOME$/.cargo/bin" />
<option name="version" value="2" />
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="7141abd6-a726-4e6d-beaf-d3ad4079ecae" name="Default Changelist" comment="" />
<created>1605727203780</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1605727203780</updated>
<workItem from="1605727206950" duration="2304000" />
<workItem from="1605751834879" duration="1034000" />
<workItem from="1605755411414" duration="300000" />
<workItem from="1605767379447" duration="2021000" />
<workItem from="1605785565921" duration="1662000" />
<workItem from="1605837573426" duration="2903000" />
<workItem from="1605853813741" duration="2031000" />
<workItem from="1605886782374" duration="314000" />
<workItem from="1606021324773" duration="727000" />
<workItem from="1606052465219" duration="82000" />
<workItem from="1606702751670" duration="1282000" />
<workItem from="1606721365601" duration="680000" />
<workItem from="1606784006574" duration="940000" />
<workItem from="1606814544720" duration="599000" />
<workItem from="1606872152767" duration="1098000" />
<workItem from="1606873285412" duration="666000" />
<workItem from="1606961052577" duration="132000" />
<workItem from="1606961207805" duration="611000" />
<workItem from="1607002608870" duration="599000" />
<workItem from="1607044229762" duration="599000" />
<workItem from="1607087662988" duration="1759000" />
<workItem from="1607135725594" duration="599000" />
<workItem from="1607204320022" duration="599000" />
<workItem from="1607213987951" duration="598000" />
<workItem from="1607220658448" duration="597000" />
<workItem from="1607233201088" duration="599000" />
<workItem from="1607334407529" duration="1463000" />
<workItem from="1607362135025" duration="304000" />
<workItem from="1607390604960" duration="599000" />
<workItem from="1607437302836" duration="3818000" />
<workItem from="1607477228877" duration="4208000" />
<workItem from="1607519840849" duration="1206000" />
<workItem from="1607562100026" duration="7978000" />
<workItem from="1607606744996" duration="5366000" />
<workItem from="1607652075707" duration="9055000" />
<workItem from="1607693154794" duration="1417000" />
<workItem from="1607790084516" duration="599000" />
<workItem from="1607822156325" duration="599000" />
<workItem from="1607909336129" duration="9433000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
<option name="oldMeFiltersMigrated" value="true" />
</component>
</project>

@ -0,0 +1,10 @@
[package]
name = "user_lib"
version = "0.1.0"
authors = ["Yifan Wu <shinbokuow@163.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
buddy_system_allocator = "0.6"

@ -0,0 +1,23 @@
TARGET := riscv64gc-unknown-none-elf
MODE := release
APP_DIR := src/bin
TARGET_DIR := target/$(TARGET)/$(MODE)
APPS := $(wildcard $(APP_DIR)/*.rs)
ELFS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%, $(APPS))
BINS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%.bin, $(APPS))
OBJDUMP := rust-objdump --arch-name=riscv64
OBJCOPY := rust-objcopy --binary-architecture=riscv64
elf: $(APPS)
@cargo build --release
binary: elf
$(foreach elf, $(ELFS), $(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf));)
build: binary
clean:
@cargo clean
.PHONY: elf binary build clean

@ -0,0 +1,29 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{fork, yield_, waitpid, exit, wait};
const MAGIC: i32 = -0x10384;
#[no_mangle]
pub fn main() -> i32 {
println!("I am the parent. Forking the child...");
let pid = fork();
if pid == 0 {
println!("I am the child.");
for _ in 0..7 { yield_(); }
exit(MAGIC);
} else {
println!("I am parent, fork a child pid {}", pid);
}
println!("I am the parent, waiting now..");
let mut xstate: i32 = 0;
assert!(waitpid(pid as usize, &mut xstate) == pid && xstate == MAGIC);
assert!(waitpid(pid as usize, &mut xstate) < 0 && wait(&mut xstate) <= 0);
println!("waitpid {} ok.", pid);
println!("exit pass.");
0
}

@ -0,0 +1,44 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
macro_rules! color_text {
($text:expr, $color:expr) => {{
format_args!("\x1b[{}m{}\x1b[0m", $color, $text)
}};
}
#[no_mangle]
pub fn main() -> i32 {
println!(
"{}{}{}{}{} {}{}{}{} {}{}{}{}{}{}",
color_text!("H", 31),
color_text!("e", 32),
color_text!("l", 33),
color_text!("l", 34),
color_text!("o", 35),
color_text!("R", 36),
color_text!("u", 37),
color_text!("s", 90),
color_text!("t", 91),
color_text!("u", 92),
color_text!("C", 93),
color_text!("o", 94),
color_text!("r", 95),
color_text!("e", 96),
color_text!("!", 97),
);
let text =
"reguler \x1b[4munderline\x1b[24m \x1b[7mreverse\x1b[27m \x1b[9mstrikethrough\x1b[29m";
println!("\x1b[47m{}\x1b[0m", color_text!(text, 30));
for i in 31..38 {
println!("{}", color_text!(text, i));
}
for i in 90..98 {
println!("{}", color_text!(text, i));
}
0
}

@ -0,0 +1,34 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{fork, wait, exit};
const MAX_CHILD: usize = 40;
#[no_mangle]
pub fn main() -> i32 {
for i in 0..MAX_CHILD {
let pid = fork();
if pid == 0 {
println!("I am child {}", i);
exit(0);
} else {
println!("forked child pid = {}", pid);
}
assert!(pid > 0);
}
let mut exit_code: i32 = 0;
for _ in 0..MAX_CHILD {
if wait(&mut exit_code) <= 0 {
panic!("wait stopped early");
}
}
if wait(&mut exit_code) > 0 {
panic!("wait got too many");
}
println!("forktest pass.");
0
}

@ -0,0 +1,33 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{fork, wait, getpid, exit, sleep, get_time};
static NUM: usize = 30;
#[no_mangle]
pub fn main() -> i32 {
for _ in 0..NUM {
let pid = fork();
if pid == 0 {
let current_time = get_time();
let sleep_length = (current_time as i32 as isize) * (current_time as i32 as isize) % 1000 + 1000;
println!("pid {} sleep for {} ms", getpid(), sleep_length);
sleep(sleep_length as usize);
println!("pid {} OK!", getpid());
exit(0);
}
}
let mut xstate: i32 = 0;
for _ in 0..NUM {
assert!(wait(&mut xstate) > 0);
assert_eq!(xstate, 0);
}
assert!(wait(&mut xstate) < 0);
println!("forktest2 test passed!");
0
}

@ -0,0 +1,28 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{fork, getpid, wait};
#[no_mangle]
pub fn main() -> i32 {
assert_eq!(wait(&mut 0i32), -1);
println!("sys_wait without child process test passed!");
println!("parent start, pid = {}!", getpid());
let pid = fork();
if pid == 0 {
// child process
println!("hello child process!");
100
} else {
// parent process
let mut xstate: i32 = 0;
println!("ready waiting on parent process!");
assert_eq!(pid, wait(&mut xstate));
assert_eq!(xstate, 100);
println!("child process pid = {}, exit code = {}", pid, xstate);
0
}
}

@ -0,0 +1,37 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{sleep, getpid, fork, exit, yield_};
const DEPTH: usize = 4;
fn fork_child(cur: &str, branch: char) {
let mut next = [0u8; DEPTH + 1];
let l = cur.len();
if l >= DEPTH {
return;
}
&mut next[..l].copy_from_slice(cur.as_bytes());
next[l] = branch as u8;
if fork() == 0 {
fork_tree(core::str::from_utf8(&next[..l + 1]).unwrap());
yield_();
exit(0);
}
}
fn fork_tree(cur: &str) {
println!("pid{}: {}", getpid(), cur);
fork_child(cur, '0');
fork_child(cur, '1');
}
#[no_mangle]
pub fn main() -> i32 {
fork_tree("");
sleep(3000);
0
}

@ -0,0 +1,11 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
#[no_mangle]
pub fn main() -> i32 {
println!("Hello world from user mode program!");
0
}

@ -0,0 +1,34 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{
fork,
wait,
exec,
yield_,
};
#[no_mangle]
fn main() -> i32 {
if fork() == 0 {
exec("user_shell\0");
} else {
loop {
let mut exit_code: i32 = 0;
let pid = wait(&mut exit_code);
if pid == -1 {
yield_();
continue;
}
println!(
"[initproc] Released a zombie process, pid={}, exit_code={}",
pid,
exit_code,
);
}
}
0
}

@ -0,0 +1,68 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{fork, wait, yield_, exit, getpid, get_time};
static NUM: usize = 35;
const N: usize = 10;
static P: i32 = 10007;
type Arr = [[i32; N]; N];
fn work(times: isize) {
let mut a: Arr = Default::default();
let mut b: Arr = Default::default();
let mut c: Arr = Default::default();
for i in 0..N {
for j in 0..N {
a[i][j] = 1;
b[i][j] = 1;
}
}
yield_();
println!("pid {} is running ({} times)!.", getpid(), times);
for _ in 0..times {
for i in 0..N {
for j in 0..N {
c[i][j] = 0;
for k in 0..N {
c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % P;
}
}
}
for i in 0..N {
for j in 0..N {
a[i][j] = c[i][j];
b[i][j] = c[i][j];
}
}
}
println!("pid {} done!.", getpid());
exit(0);
}
#[no_mangle]
pub fn main() -> i32 {
for _ in 0..NUM {
let pid = fork();
if pid == 0 {
let current_time = get_time();
let times = (current_time as i32 as isize) * (current_time as i32 as isize) % 1000;
work(times * 10);
}
}
println!("fork ok.");
let mut xstate: i32 = 0;
for _ in 0..NUM {
if wait(&mut xstate) < 0 {
panic!("wait failed.");
}
}
assert!(wait(&mut xstate) < 0);
println!("matrix passed.");
0
}

@ -0,0 +1,30 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{sleep, exit, get_time, fork, waitpid};
fn sleepy() {
let time: usize = 100;
for i in 0..5 {
sleep(time);
println!("sleep {} x {} msecs.", i + 1, time);
}
exit(0);
}
#[no_mangle]
pub fn main() -> i32 {
let current_time = get_time();
let pid = fork();
let mut xstate: i32 = 0;
if pid == 0 {
sleepy();
}
assert!(waitpid(pid as usize, &mut xstate) == pid && xstate == 0);
println!("use {} msecs.", get_time() - current_time);
println!("sleep pass.");
0
}

@ -0,0 +1,19 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{get_time, sleep};
#[no_mangle]
pub fn main() -> i32 {
println!("into sleep test!");
let start = get_time();
println!("current time_msec = {}", start);
sleep(100);
let end = get_time();
println!("time_msec = {} after sleeping 100 ticks, delta = {}ms!", end, end - start);
println!("r_sleep passed!");
0
}

@ -0,0 +1,17 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
fn f(d: usize) {
println!("d = {}",d);
f(d + 1);
}
#[no_mangle]
pub fn main() -> i32 {
println!("It should trigger segmentation fault!");
f(0);
0
}

@ -0,0 +1,70 @@
#![no_std]
#![no_main]
extern crate alloc;
#[macro_use]
extern crate user_lib;
const LF: u8 = 0x0au8;
const CR: u8 = 0x0du8;
const DL: u8 = 0x7fu8;
const BS: u8 = 0x08u8;
use alloc::string::String;
use user_lib::{fork, exec, waitpid, yield_};
use user_lib::console::getchar;
#[no_mangle]
pub fn main() -> i32 {
println!("Rust user shell");
let mut line: String = String::new();
print!(">> ");
loop {
let c = getchar();
match c {
LF | CR => {
println!("");
if !line.is_empty() {
line.push('\0');
let pid = fork();
if pid == 0 {
// child process
if exec(line.as_str()) == -1 {
println!("Error when executing!");
return -4;
}
unreachable!();
} else {
let mut xstate: i32 = 0;
let mut exit_pid: isize;
loop {
exit_pid = waitpid(pid as usize, &mut xstate);
if exit_pid == -1 {
yield_();
} else {
assert_eq!(pid, exit_pid);
println!("Shell: Process {} exited with code {}", pid, xstate);
break;
}
}
}
line.clear();
}
print!(">> ");
}
BS | DL => {
if !line.is_empty() {
print!("{}", BS as char);
print!(" ");
print!("{}", BS as char);
line.pop();
}
}
_ => {
print!("{}", c as char);
line.push(c as char);
}
}
}
}

@ -0,0 +1,40 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
static TESTS: &[&str] = &[
"exit\0",
"fantastic_text\0",
"forktest\0",
"forktest2\0",
"forktest_simple\0",
"hello_world\0",
"matrix\0",
"sleep\0",
"sleep_simple\0",
"stack_overflow\0",
"yield\0",
];
use user_lib::{exec, fork, waitpid};
#[no_mangle]
pub fn main() -> i32 {
for test in TESTS {
println!("Usertests: Running {}", test);
let pid = fork();
if pid == 0 {
exec(*test);
panic!("unreachable!");
} else {
let mut xstate: i32 = Default::default();
let wait_pid = waitpid(pid as usize, &mut xstate);
assert_eq!(pid, wait_pid);
println!("\x1b[32mUsertests: Test {} in Process {} exited with code {}\x1b[0m", test, pid, xstate);
}
}
println!("Usertests passed!");
0
}

@ -0,0 +1,17 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{getpid, yield_};
#[no_mangle]
pub fn main() -> i32 {
println!("Hello, I am process {}.", getpid());
for i in 0..5 {
yield_();
println!("Back in process {}, iteration {}.", getpid(), i);
}
println!("yield pass.");
0
}

@ -0,0 +1,39 @@
use core::fmt::{self, Write};
const STDIN: usize = 0;
const STDOUT: usize = 1;
use super::{read, write};
struct Stdout;
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
write(STDOUT, s.as_bytes());
Ok(())
}
}
pub fn print(args: fmt::Arguments) {
Stdout.write_fmt(args).unwrap();
}
#[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)+)?));
}
}
pub fn getchar() -> u8 {
let mut c = [0u8; 1];
read(STDIN, &mut c);
c[0]
}

@ -0,0 +1,10 @@
#[panic_handler]
fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
let err = panic_info.message().unwrap();
if let Some(location) = panic_info.location() {
println!("Panicked at {}:{}, {}", location.file(), location.line(), err);
} else {
println!("Panicked: {}", err);
}
loop {}
}

@ -0,0 +1,75 @@
#![no_std]
#![feature(llvm_asm)]
#![feature(linkage)]
#![feature(panic_info_message)]
#![feature(alloc_error_handler)]
#[macro_use]
pub mod console;
mod syscall;
mod lang_items;
use syscall::*;
use buddy_system_allocator::LockedHeap;
const USER_HEAP_SIZE: usize = 16384;
static mut HEAP_SPACE: [u8; USER_HEAP_SIZE] = [0; USER_HEAP_SIZE];
#[global_allocator]
static HEAP: LockedHeap = LockedHeap::empty();
#[alloc_error_handler]
pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! {
panic!("Heap allocation error, layout = {:?}", layout);
}
#[no_mangle]
#[link_section = ".text.entry"]
pub extern "C" fn _start() -> ! {
unsafe {
HEAP.lock()
.init(HEAP_SPACE.as_ptr() as usize, USER_HEAP_SIZE);
}
exit(main());
}
#[linkage = "weak"]
#[no_mangle]
fn main() -> i32 {
panic!("Cannot find main!");
}
pub fn read(fd: usize, buf: &mut [u8]) -> isize { sys_read(fd, buf) }
pub fn write(fd: usize, buf: &[u8]) -> isize { sys_write(fd, buf) }
pub fn exit(exit_code: i32) -> ! { sys_exit(exit_code); }
pub fn yield_() -> isize { sys_yield() }
pub fn get_time() -> isize { sys_get_time() }
pub fn getpid() -> isize { sys_getpid() }
pub fn fork() -> isize { sys_fork() }
pub fn exec(path: &str) -> isize { sys_exec(path) }
pub fn wait(exit_code: &mut i32) -> isize {
loop {
match sys_waitpid(-1, exit_code as *mut _) {
-2 => { yield_(); }
// -1 or a real pid
exit_pid => return exit_pid,
}
}
}
pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize {
loop {
match sys_waitpid(pid as isize, exit_code as *mut _) {
-2 => { yield_(); }
// -1 or a real pid
exit_pid => return exit_pid,
}
}
}
pub fn sleep(period_ms: usize) {
let start = sys_get_time();
while sys_get_time() < start + period_ms as isize {
sys_yield();
}
}

@ -0,0 +1,29 @@
OUTPUT_ARCH(riscv)
ENTRY(_start)
BASE_ADDRESS = 0x0;
SECTIONS
{
. = BASE_ADDRESS;
.text : {
*(.text.entry)
*(.text .text.*)
}
. = ALIGN(4K);
.rodata : {
*(.rodata .rodata.*)
}
. = ALIGN(4K);
.data : {
*(.data .data.*)
}
.bss : {
*(.bss .bss.*)
}
/DISCARD/ : {
*(.eh_frame)
*(.debug*)
}
}

@ -0,0 +1,59 @@
const SYSCALL_READ: usize = 63;
const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93;
const SYSCALL_YIELD: usize = 124;
const SYSCALL_GET_TIME: usize = 169;
const SYSCALL_GETPID: usize = 172;
const SYSCALL_FORK: usize = 220;
const SYSCALL_EXEC: usize = 221;
const SYSCALL_WAITPID: usize = 260;
fn syscall(id: usize, args: [usize; 3]) -> isize {
let mut ret: isize;
unsafe {
llvm_asm!("ecall"
: "={x10}" (ret)
: "{x10}" (args[0]), "{x11}" (args[1]), "{x12}" (args[2]), "{x17}" (id)
: "memory"
: "volatile"
);
}
ret
}
pub fn sys_read(fd: usize, buffer: &mut [u8]) -> isize {
syscall(SYSCALL_READ, [fd, buffer.as_mut_ptr() as usize, buffer.len()])
}
pub fn sys_write(fd: usize, buffer: &[u8]) -> isize {
syscall(SYSCALL_WRITE, [fd, buffer.as_ptr() as usize, buffer.len()])
}
pub fn sys_exit(exit_code: i32) -> ! {
syscall(SYSCALL_EXIT, [exit_code as usize, 0, 0]);
panic!("sys_exit never returns!");
}
pub fn sys_yield() -> isize {
syscall(SYSCALL_YIELD, [0, 0, 0])
}
pub fn sys_get_time() -> isize {
syscall(SYSCALL_GET_TIME, [0, 0, 0])
}
pub fn sys_getpid() -> isize {
syscall(SYSCALL_GETPID, [0, 0, 0])
}
pub fn sys_fork() -> isize {
syscall(SYSCALL_FORK, [0, 0, 0])
}
pub fn sys_exec(path: &str) -> isize {
syscall(SYSCALL_EXEC, [path.as_ptr() as usize, 0, 0])
}
pub fn sys_waitpid(pid: isize, xstatus: *mut i32) -> isize {
syscall(SYSCALL_WAITPID, [pid as usize, xstatus as usize, 0])
}

@ -0,0 +1,7 @@
[build]
target = "riscv64gc-unknown-none-elf"
[target.riscv64gc-unknown-none-elf]
rustflags = [
"-Clink-args=-Tsrc/linker.ld",
]

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save