Merge pull request #5 from equation314/user-img

Create multi-arch user SFS image
master
Wang Runji 6 years ago committed by GitHub
commit 52a2e24021
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

9
.gitignore vendored

@ -1,11 +1,10 @@
build
target
/kernel/src/arch/x86_64/interrupt/vector.asm
/crate/bit-allocator/Cargo.lock
/crate/memory/Cargo.lock
/crate/bbl/Cargo.lock
/crate/sync/Cargo.lock
/crate/process/Cargo.lock
Cargo.lock
!kernel/Cargo.lock
!user/Cargo.lock
.DS_Store

@ -1,14 +0,0 @@
[[package]]
name = "atags"
version = "0.1.0"
dependencies = [
"volatile 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "volatile"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum volatile 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ca391c55768e479d5c2f8beb40c136df09257292a809ea514e82cfdfc15d00"

@ -63,6 +63,7 @@ minimum-image-size = 0 # The minimum output file size (in MiB)
# (the "{}" will be replaced with the path to the bootable disk image)
run-command = ["qemu-system-x86_64",
"-drive", "format=raw,file={}",
# TODO: use SFSIMG environment variable
"-drive", "format=raw,file=../user/img/ucore-i386-pic.img,media=disk,cache=writeback",
"-serial", "mon:stdio",
"-device", "isa-debug-exit",

@ -12,6 +12,7 @@
# d = int | in_asm | ... QEMU debug info
# mode = debug | release
# LOG = off | error | warn | info | debug | trace
# SFSIMG = SFS image path of user programs
# smp = 1 | 2 | ... SMP core number
# board = fpga Only available on riscv32, build without bbl, run on board
# | raspi3 Only available on aarch64, run on Raspberry Pi 3 Model B/B+
@ -31,6 +32,14 @@ kernel := target/$(target)/$(mode)/ucore
bin := target/$(target)/$(mode)/kernel.bin
bootimage := target/$(target)/bootimage.bin
user_dir := ../user
user_bin_path := $(user_dir)/target/$(arch)-ucore/debug
user_bins := $(patsubst $(user_bin_path)/%.d, $(user_bin_path)/%, $(wildcard $(user_bin_path)/*.d))
user_obj := build/$(arch)/user.o
export ARCH = $(arch)
export SFSIMG = $(user_dir)/build/user-$(arch).img
### qemu options ###
qemu_opts := \
-smp cores=$(smp) \
@ -39,7 +48,7 @@ qemu_opts := \
ifeq ($(arch), x86_64)
qemu_opts += \
-drive format=raw,file=$(bootimage) \
-drive format=raw,file="../user/img/ucore-i386-pic.img",media=disk,cache=writeback \
-drive format=raw,file=$(SFSIMG),media=disk,cache=writeback \
-serial mon:stdio \
-device isa-debug-exit
@ -101,18 +110,19 @@ cc := $(prefix)gcc
as := $(prefix)as
gdb := $(prefix)gdb
.PHONY: all clean run build asm doc justrun kernel
.PHONY: all clean run build asm doc justrun debug kernel sfsimg install
all: kernel
clean:
@cargo clean
@cd $(user_dir) && make clean
@rm -rf ../riscv-pk/build
doc:
@cargo rustdoc -- --document-private-items
run: build justrun
run: build sfsimg justrun
justrun:
@qemu-system-$(arch) $(qemu_opts) || [ $$? -eq 11 ] # run qemu and assert it exit 11
@ -158,17 +168,30 @@ else ifeq ($(arch), aarch64)
@$(objcopy) $(kernel) --strip-all -O binary $@
endif
kernel:
ifeq ($(arch), x86_64)
kernel:
@bootimage build $(build_args)
else
kernel: sfsimg
ifeq ($(arch), riscv32)
@-patch -p0 -N -b \
$(shell rustc --print sysroot)/lib/rustlib/src/rust/src/libcore/sync/atomic.rs \
src/arch/riscv32/atomic.patch
endif
@CC=$(cc) cargo xbuild $(build_args)
endif
### user programs ###
sfsimg:
@cd $(user_dir) && make sfsimg
# make user.o from binary files
$(user_obj): $(user_bins)
@cd $(user_bin_path) && \
$(ld) -o $(abspath $@) $(patsubst %, -b binary %, $(notdir $(user_bins)))
### install ###
ifeq ($(board), raspi3)
sd_card ?=

@ -1,23 +1,42 @@
extern crate cc;
use std::fs::File;
use std::io::{Write, Result};
use std::path::Path;
use std::io::{Result, Write};
fn main() {
if std::env::var("TARGET").unwrap().find("x86_64").is_some() {
// cc::Build::new()
// .file("src/arch/x86_64/driver/apic/lapic.c")
// .file("src/arch/x86_64/driver/keyboard/keyboard.c")
// .flag("-mcmodel=large")
// .compile("cobj");
gen_vector_asm().unwrap();
}
if std::env::var("TARGET").unwrap().find("riscv32").is_some() {
cc::Build::new()
.file("src/arch/riscv32/compiler_rt.c")
.flag("-march=rv32ia")
.flag("-mabi=ilp32")
.compile("atomic_rt");
println!("cargo:rerun-if-env-changed=LOG");
let arch: String = std::env::var("ARCH").unwrap();
match arch.as_str() {
"x86_64" => {
// cc::Build::new()
// .file("src/arch/x86_64/driver/apic/lapic.c")
// .file("src/arch/x86_64/driver/keyboard/keyboard.c")
// .flag("-mcmodel=large")
// .compile("cobj");
gen_vector_asm().unwrap();
}
"riscv32" => {
cc::Build::new()
.file("src/arch/riscv32/compiler_rt.c")
.flag("-march=rv32ia")
.flag("-mabi=ilp32")
.compile("atomic_rt");
if let Ok(file_path) = gen_sfsimg_asm() {
cc::Build::new()
.file(&file_path)
.flag("-march=rv32ia")
.flag("-mabi=ilp32")
.compile("sfsimg");
}
}
"aarch64" => {
if let Ok(file_path) = gen_sfsimg_asm() {
cc::Build::new().file(&file_path).compile("sfsimg");
}
}
_ => panic!("Unknown arch {}", arch),
}
}
@ -43,4 +62,28 @@ fn gen_vector_asm() -> Result<()> {
writeln!(f, "\t.quad vector{}", i)?;
}
Ok(())
}
}
fn gen_sfsimg_asm() -> Result<std::path::PathBuf> {
let out_dir = std::env::var("OUT_DIR").unwrap();
let sfsimg = std::env::var("SFSIMG").unwrap();
let file_path = Path::new(&out_dir).join("sfsimg.S");
let mut f = File::create(&file_path).unwrap();
write!(f, "# generated by build.rs - do not edit")?;
write!(f, r#"
.section .rodata
.align 12
.global _user_img_start
.global _user_img_end
_user_img_start:
.incbin "{}"
_user_img_end:
"#, sfsimg)?;
println!("cargo:rerun-if-changed={}", sfsimg);
println!("cargo:rerun-if-env-changed=SFSIMG");
Ok(file_path)
}

@ -8,30 +8,6 @@ use crate::arch::driver::ide;
use crate::sync::Condvar;
use crate::sync::SpinNoIrqLock as Mutex;
// Hard link user program
#[cfg(target_arch = "riscv32")]
global_asm!(r#"
.section .rodata
.align 12
.global _user_img_start
.global _user_img_end
_user_img_start:
.incbin "../user/img/ucore-rv32.img"
_user_img_end:
"#);
// Hard link user program
#[cfg(target_arch = "aarch64")]
global_asm!(r#"
.section .rodata
.align 12
.global _user_img_start
.global _user_img_end
_user_img_start:
.incbin "../user/img/ucore-aarch64.img"
_user_img_end:
"#);
lazy_static! {
pub static ref ROOT_INODE: Arc<INode> = {
#[cfg(any(target_arch = "riscv32", target_arch = "aarch64"))]
@ -40,6 +16,7 @@ lazy_static! {
fn _user_img_start();
fn _user_img_end();
}
// Hard link user program
Box::new(unsafe { MemBuf::new(_user_img_start, _user_img_end) })
};
#[cfg(target_arch = "x86_64")]

@ -6,12 +6,15 @@ use crate::fs::{ROOT_INODE, INodeExt};
use crate::process::*;
pub fn run_user_shell() {
let inode = ROOT_INODE.lookup("sh").unwrap();
let data = inode.read_as_vec().unwrap();
processor().manager().add(ContextImpl::new_user(data.as_slice(), "sh".split(' ')), 0);
if let Ok(inode) = ROOT_INODE.lookup("sh") {
let data = inode.read_as_vec().unwrap();
processor().manager().add(ContextImpl::new_user(data.as_slice(), "sh".split(' ')), 0);
} else {
processor().manager().add(ContextImpl::new_kernel(shell, 0), 0);
}
}
pub fn shell() {
pub extern fn shell(_arg: usize) -> ! {
let files = ROOT_INODE.list().unwrap();
println!("Available programs: {:?}", files);

@ -284,6 +284,7 @@ fn get_file(fd: usize) -> Result<&'static Arc<Mutex<File>>, SysError> {
pub type SysResult = Result<i32, SysError>;
#[repr(i32)]
#[derive(Debug)]
pub enum SysError {
VfsError,
InvalidFile,

@ -1,5 +1,59 @@
# arch = {riscv32, x86_64, aarch64}
arch := riscv32
# mode = {debug, release}
arch ?= riscv32
mode ?= debug
all:
cargo xbuild --target $(arch)-ucore.json
rust_src_dir := src/bin
rust_bin_path := target/$(arch)-ucore/$(mode)
user_rust_bins := $(patsubst $(rust_src_dir)/%.rs, $(rust_bin_path)/%, $(wildcard $(rust_src_dir)/*.rs))
c_src_dir :=
c_bin_path :=
user_c_bins :=
user_bins := $(user_rust_bins) $(user_c_bins)
build_path := build
sfsroot := $(build_path)/sfsroot-$(arch)
sfsimg := $(build_path)/user-$(arch).img
mksfs := mksfs
build_args := --target $(arch)-ucore.json
ifeq ($(mode), release)
build_args := $(build_args) --release
endif
.PHONY: all clean build-rust build-c build mksfs sfsimg
all: $(sfsimg)
build-rust:
@echo Building user rust programs
@cargo xbuild $(build_args)
build-c:
@echo Building user C programs
build: build-rust build-c
$(user_rust_bins): build-rust
$(user_c_bins): build-c
mksfs:
ifeq ($(shell which $(mksfs)),)
@cargo install --git https://github.com/wangrunji0408/SimpleFileSystem-Rust --features="std"
endif
$(sfsroot): $(user_bins)
@mkdir -p $@
@cp $^ $@/
$(sfsimg): $(user_bins) $(sfsroot) | mksfs
@echo Creating SFS image at $@
@$(mksfs) zip $(sfsroot) $@
sfsimg: $(sfsimg)
clean:
@cargo clean
@rm -rf $(build_path)

@ -13,6 +13,11 @@
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"linker-is-gnu": true,
"pre-link-args": {
"ld.lld": [
"-Tsrc/arch/aarch64/user.ld"
]
},
"llvm-target": "aarch64-unknown-none",
"no-compiler-rt": true,
"features": "+a53,+strict-align,-neon",

@ -11,6 +11,11 @@
"max-atomic-width": "32",
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"pre-link-args": {
"ld.lld": [
"-Tsrc/arch/riscv32/user.ld"
]
},
"executables": true,
"panic-strategy": "abort",
"relocation-model": "static",
@ -27,4 +32,4 @@
"msp430-interrupt",
"x86-interrupt"
]
}
}

@ -0,0 +1,46 @@
/* Simple linker script for ucore user-level programs.
See the GNU ld 'info' manual ("info ld") to learn the syntax. */
OUTPUT_ARCH(aarch64)
ENTRY(_start)
SECTIONS {
/* Load programs at this address: "." means the current address */
. = 0xffff000000000000;
.text : {
*(.text .stub .text.* .gnu.linkonce.t.*)
}
PROVIDE(etext = .); /* Define the 'etext' symbol to this value */
.rodata : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
}
/* Adjust the address for the data segment to the next page */
. = ALIGN(0x1000);
/* The data segment */
.data : {
*(.data)
*(.data.*)
}
.sdata : {
*(.sdata)
*(.sdata.*)
}
PROVIDE(edata = .);
.bss : {
*(.bss)
}
PROVIDE(end = .);
/DISCARD/ : {
*(.eh_frame .note.GNU-stack .comment)
}
}

@ -0,0 +1,46 @@
/* Simple linker script for ucore user-level programs.
See the GNU ld 'info' manual ("info ld") to learn the syntax. */
OUTPUT_ARCH(riscv)
ENTRY(_start)
SECTIONS {
/* Load programs at this address: "." means the current address */
. = 0x800020;
.text : {
*(.text .stub .text.* .gnu.linkonce.t.*)
}
PROVIDE(etext = .); /* Define the 'etext' symbol to this value */
.rodata : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
}
/* Adjust the address for the data segment to the next page */
. = ALIGN(0x1000);
/* The data segment */
.data : {
*(.data)
*(.data.*)
}
.sdata : {
*(.sdata)
*(.sdata.*)
}
PROVIDE(edata = .);
.bss : {
*(.bss)
}
PROVIDE(end = .);
/DISCARD/ : {
*(.eh_frame .note.GNU-stack .comment)
}
}

@ -0,0 +1,46 @@
/* Simple linker script for ucore user-level programs.
See the GNU ld 'info' manual ("info ld") to learn the syntax. */
OUTPUT_ARCH(x86_64)
ENTRY(_start)
SECTIONS {
/* Load programs at this address: "." means the current address */
. = 0x800020;
.text : {
*(.text .stub .text.* .gnu.linkonce.t.*)
}
PROVIDE(etext = .); /* Define the 'etext' symbol to this value */
.rodata : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
}
/* Adjust the address for the data segment to the next page */
. = ALIGN(0x1000);
/* The data segment */
.data : {
*(.data)
*(.data.*)
}
.sdata : {
*(.sdata)
*(.sdata.*)
}
PROVIDE(edata = .);
.bss : {
*(.bss)
}
PROVIDE(end = .);
/DISCARD/ : {
*(.eh_frame .note.GNU-stack .comment)
}
}

@ -7,5 +7,7 @@ extern crate ucore_ulib;
// IMPORTANT: Must define main() like this
#[no_mangle]
pub fn main() {
println!("Hello uCore!");
println!("Hello Rust uCore!");
println!("I am process {}.", ucore_ulib::syscall::sys_getpid());
println!("hello pass.");
}

@ -1,15 +1,47 @@
use crate::syscall::sys_exit;
use crate::syscall::{sys_close, sys_dup, sys_exit, sys_open};
use crate::syscall::{O_RDONLY, O_WRONLY};
use core::alloc::Layout;
use core::panic::PanicInfo;
// used for panic
macro_rules! print {
($($arg:tt)*) => ({
$crate::syscall::print_putc(format_args!($($arg)*));
});
}
#[linkage = "weak"]
#[no_mangle]
fn main() {
panic!("No main() linked");
}
fn initfd(fd2: usize, path: &str, open_flags: usize) -> i32 {
let fd1 = sys_open(path, open_flags);
if fd1 < 0 {
return fd1;
}
let mut ret = fd1;
let fd1 = fd1 as usize;
if fd1 != fd2 {
sys_close(fd2);
ret = sys_dup(fd1, fd2);
sys_close(fd1);
}
return ret;
}
#[no_mangle]
pub extern fn _start(_argc: isize, _argv: *const *const u8) -> ! {
pub extern "C" fn _start(_argc: isize, _argv: *const *const u8) -> ! {
let fd = initfd(0, "stdin:", O_RDONLY);
if fd < 0 {
panic!("open <stdin> failed: {}.", fd);
}
let fd = initfd(1, "stdout:", O_WRONLY);
if fd < 0 {
panic!("open <stdout> failed: {}.", fd);
}
main();
sys_exit(0)
}
@ -31,12 +63,12 @@ fn oom(_: Layout) -> ! {
}
#[no_mangle]
pub extern fn abort() -> ! {
pub extern "C" fn abort() -> ! {
sys_exit(2)
}
#[no_mangle]
pub extern fn __mulsi3(mut a: u32, mut b: u32) -> u32 {
pub extern "C" fn __mulsi3(mut a: u32, mut b: u32) -> u32 {
let mut r: u32 = 0;
while a > 0 {
@ -48,4 +80,4 @@ pub extern fn __mulsi3(mut a: u32, mut b: u32) -> u32 {
}
r
}
}

@ -17,14 +17,29 @@ pub fn print(args: fmt::Arguments) {
StdOut.write_fmt(args).unwrap();
}
pub fn print_putc(args: fmt::Arguments) {
SysPutc.write_fmt(args).unwrap();
}
struct StdOut;
struct SysPutc;
impl fmt::Write for StdOut {
fn write_str(&mut self, s: &str) -> fmt::Result {
match sys_write(0, s.as_ptr(), s.len()) {
0 => Ok(()),
_ => Err(fmt::Error::default()),
if sys_write(1, s.as_ptr(), s.len()) >= 0 {
Ok(())
} else {
Err(fmt::Error::default())
}
}
}
impl fmt::Write for SysPutc {
fn write_str(&mut self, s: &str) -> fmt::Result {
for c in s.bytes() {
sys_putc(c as char);
}
Ok(())
}
}
@ -77,6 +92,10 @@ pub fn sys_close(fd: usize) -> i32 {
sys_call(SYS_CLOSE, fd, 0, 0, 0, 0, 0)
}
pub fn sys_dup(fd1: usize, fd2: usize) -> i32 {
sys_call(SYS_DUP, fd1, fd2, 0, 0, 0, 0)
}
/// Fork the current process. Return the child's PID.
pub fn sys_fork() -> i32 {
sys_call(SYS_FORK, 0, 0, 0, 0, 0, 0)
@ -144,3 +163,15 @@ const SYS_GETCWD: usize = 121;
const SYS_GETDIRENTRY: usize = 128;
const SYS_DUP: usize = 130;
const SYS_LAB6_SET_PRIORITY: usize = 255;
/* VFS flags */
// TODO: use bitflags
// flags for open: choose one of these
pub const O_RDONLY: usize = 0; // open for reading only
pub const O_WRONLY: usize = 1; // open for writing only
pub const O_RDWR: usize = 2; // open for reading and writing
// then or in any of these:
pub const O_CREAT: usize = 0x00000004; // create file if it does not exist
pub const O_EXCL: usize = 0x00000008; // error if O_CREAT and the file exists
pub const O_TRUNC: usize = 0x00000010; // truncate file upon open
pub const O_APPEND: usize = 0x00000020; // append on each write

@ -9,7 +9,12 @@
"executables": true,
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"pre-link-args": {
"ld.lld": [
"-Tsrc/arch/x86_64/user.ld"
]
},
"panic-strategy": "abort",
"disable-redzone": true,
"features": "-mmx,-sse,+soft-float"
}
}

Loading…
Cancel
Save