From ec476c3acb600c6d437454e74fb3e0eb6c452de4 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Fri, 29 Mar 2019 17:31:51 +0800 Subject: [PATCH 01/39] Bump rcore-fs-fuse version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 651c0e3..aacc46a 100644 --- a/Makefile +++ b/Makefile @@ -134,7 +134,7 @@ $(out_qcow2): $(out_img) rcore-fs-fuse: ifeq ($(shell which rcore-fs-fuse),) @echo Installing rcore-fs-fuse - @cargo install rcore-fs-fuse --git https://github.com/rcore-os/rcore-fs --rev ff3dd7d + @cargo install rcore-fs-fuse --git https://github.com/rcore-os/rcore-fs --rev c611248 endif clean: From de875a4a712cf4fe1de1f0ead16f630f5e3c1422 Mon Sep 17 00:00:00 2001 From: Fan Jiang Date: Sun, 31 Mar 2019 14:56:45 +0800 Subject: [PATCH 02/39] echo is not POSIX compliant on \n --- nginx/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nginx/Makefile b/nginx/Makefile index 014fa04..ca8e62c 100644 --- a/nginx/Makefile +++ b/nginx/Makefile @@ -21,8 +21,8 @@ $(nginx_dir)/objs/nginx: $(nginx_dir) sed -i 's/ngx_feature_run=yes/ngx_feature_run=no/' $(nginx_dir)/auto/cc/name sed -i 's/ngx_test="$$CC /ngx_test="gcc /' $(nginx_dir)/auto/types/sizeof cd $(nginx_dir) && ./configure --with-cc=$(cc) --with-cc-opt=-static --with-ld-opt=-static --without-pcre --without-http_rewrite_module --without-http_gzip_module --with-poll_module --without-http_upstream_zone_module - cd $(nginx_dir) && echo "#ifndef NGX_SYS_NERR\n#define NGX_SYS_NERR 132\n#endif\n" >> objs/ngx_auto_config.h - cd $(nginx_dir) && echo "#ifndef NGX_HAVE_SVSVSHM\n#define NGX_HAVE_SYSVSHM 1\n#endif\n" >> objs/ngx_auto_config.h + cd $(nginx_dir) && printf "#ifndef NGX_SYS_NERR\n#define NGX_SYS_NERR 132\n#endif\n" >> objs/ngx_auto_config.h + cd $(nginx_dir) && printf "#ifndef NGX_HAVE_SVSVSHM\n#define NGX_HAVE_SYSVSHM 1\n#endif\n" >> objs/ngx_auto_config.h cd $(nginx_dir) && make $(bin_unstripped): $(nginx_dir)/objs/nginx From 88a036dbf0618b95611f859012e3f3b87f799711 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Thu, 4 Apr 2019 11:37:26 +0800 Subject: [PATCH 03/39] Building redis for rv64 works with prebuilt toolchain but not the one from source --- Makefile | 2 -- README.md | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index aacc46a..a0f6ece 100644 --- a/Makefile +++ b/Makefile @@ -87,7 +87,6 @@ endif endif redis: -ifneq ($(arch), riscv64) ifneq ($(shell uname), Darwin) @echo Building redis @mkdir -p $(out_dir) @@ -96,7 +95,6 @@ ifneq ($(shell uname), Darwin) @cp redis/build/$(arch)/redis-cli $(out_dir)/redis-cli @cp redis/redis.conf $(out_dir)/redis.conf endif -endif iperf3: ifeq ($(arch), x86_64) diff --git a/README.md b/README.md index a1810da..7645062 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ To build biscuit programs, install musl toolchain first: # 2.1 for macOS musl toolchain for x86_64(,aarch64) $ brew install FileSottile/musl-cross/musl-cross {--with-aarch64} # 2.2 for ubuntu 16.04, we should build gcc-musl for newest musl-1.1.21, please see build-gcc-musl.md for instructions -# 2.3 for riscv musl toolchain, please install [musl-riscv-toolchain](https://github.com/jiegec/musl-riscv-toolchain) +# 2.3 for riscv musl toolchain, please install [musl-riscv-toolchain](https://github.com/jiegec/musl-riscv-toolchain), however, this one might not be able to build redis on rv64 for lack of libatomic ``` Then, build userspace programs for rCore: @@ -57,7 +57,7 @@ A rootfs is created at `build/$(arch)` and converted to `qcow2`. | rust | ✅ | ✅ | ✅ | ✅ | | biscuit | ✅ | ✅ | ❌ | ✅ | | nginx (linux only) | ✅ | ✅ | ❌ | ✅ | -| redis (linux only) | ✅ | ✅ | ✅ | ❌ | +| redis (linux only) | ✅ | ✅ | ✅ | ✅ | | busybox | ✅ | ✅ | ❌ | ✅ | | alpine rootfs | ✅ | ✅ | ❌ | ❌ | | iperf3 | ✅ | ❌ | ❌ | ❌ | @@ -66,7 +66,7 @@ A rootfs is created at `build/$(arch)` and converted to `qcow2`. ### How to use Redis -If redis is dynamically linked to musl (default if you use commands above), you might need to copy `ld-musl-$(arch).so.1` to rootfs `/lib` . Alpine rootfs includes one as well. +If redis is dynamically linked to musl (default if you use commands above), you might need to copy `ld-musl-$(arch).so.1` to rootfs `/lib` by yourself .Alpine rootfs includes one as well. After building redis, you should be able to run redis-server in rCore. Then, start `redis-server` in rCore: From 60bc1a54d207a50c56cf273d3894c5459b2f3589 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Thu, 4 Apr 2019 11:53:54 +0800 Subject: [PATCH 04/39] Port ucore, rust, biscuit to mipsel Signed-off-by: Harry Chen --- .gitignore | 1 + Makefile | 4 +- README.md | 24 +++++----- biscuit/CMakeLists.txt | 7 +-- biscuit/c/usertests.c | 7 +++ rust/src/syscall.rs | 6 +++ rust/targets/mipsel-rcore.json | 32 ++++++++++++++ ucore/CMakeLists.txt | 2 + ucore/src/arch/mipsel/arch.h | 14 ++++++ ucore/src/arch/mipsel/atomic.h | 75 ++++++++++++++++++++++++++++++++ ucore/src/arch/mipsel/initcode.S | 10 +++++ ucore/src/arch/mipsel/regdef.h | 55 +++++++++++++++++++++++ ucore/src/libs/defs.h | 2 +- ucore/src/libs/elf.h | 2 +- 14 files changed, 222 insertions(+), 19 deletions(-) create mode 100644 rust/targets/mipsel-rcore.json create mode 100644 ucore/src/arch/mipsel/arch.h create mode 100644 ucore/src/arch/mipsel/atomic.h create mode 100644 ucore/src/arch/mipsel/initcode.S create mode 100644 ucore/src/arch/mipsel/regdef.h diff --git a/.gitignore b/.gitignore index 87f3c62..f165ffe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build/ target/ .DS_Store +.vscode diff --git a/Makefile b/Makefile index aacc46a..6409454 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# arch = {riscv32, riscv64, x86_64, aarch64} +# arch = {riscv32, riscv64, x86_64, aarch64, mipsel} # mode = {debug, release} arch ?= riscv32 mode ?= debug @@ -46,7 +46,7 @@ ifneq ($(arch), x86_64) endif biscuit: -ifeq ($(arch), $(filter $(arch), x86_64 aarch64 riscv64)) +ifeq ($(arch), $(filter $(arch), x86_64 aarch64 riscv64 mipsel)) ifneq ($(shell uname)-$(arch), Darwin-riscv64) @echo Building biscuit programs @mkdir -p biscuit/build diff --git a/README.md b/README.md index a1810da..006415a 100644 --- a/README.md +++ b/README.md @@ -42,25 +42,25 @@ $ brew install FileSottile/musl-cross/musl-cross {--with-aarch64} Then, build userspace programs for rCore: ```bash -$ make {ucore,biscuit,rust,nginx,redis,all} arch={x86_64,aarch64,riscv32,riscv64} +$ make {ucore,biscuit,rust,nginx,redis,all} arch={x86_64,aarch64,riscv32,riscv64,mipsel} $ make alpine arch={x86_64,aarch64} # if you want to use alpine rootfs -$ make sfsimg arch={x86_64,aarch64,riscv32,riscv64} +$ make sfsimg arch={x86_64,aarch64,riscv32,riscv64,mipsel} ``` A rootfs is created at `build/$(arch)` and converted to `qcow2`. ## Support matrix -| | x86_64 | aarch64 | riscv32 | riscv64 | -| ------------------ | ------ | ------- | ------- | ------- | -| ucore | ❌ | ✅ | ✅ | ✅ | -| rust | ✅ | ✅ | ✅ | ✅ | -| biscuit | ✅ | ✅ | ❌ | ✅ | -| nginx (linux only) | ✅ | ✅ | ❌ | ✅ | -| redis (linux only) | ✅ | ✅ | ✅ | ❌ | -| busybox | ✅ | ✅ | ❌ | ✅ | -| alpine rootfs | ✅ | ✅ | ❌ | ❌ | -| iperf3 | ✅ | ❌ | ❌ | ❌ | +| | x86_64 | aarch64 | riscv32 | riscv64 | mipsel | +| ------------------ | ------ | ------- | ------- | ------- | ------ | +| ucore | ❌ | ✅ | ✅ | ✅ | ✅ | +| rust | ✅ | ✅ | ✅ | ✅ | ✅ | +| biscuit | ✅ | ✅ | ❌ | ✅ | ✅ | +| nginx (linux only) | ✅ | ✅ | ❌ | ✅ | ❓ | +| redis (linux only) | ✅ | ✅ | ✅ | ❌ | ❓ | +| busybox | ✅ | ✅ | ❌ | ✅ | ❓ | +| alpine rootfs | ✅ | ✅ | ❌ | ❌ | ❌ | +| iperf3 | ✅ | ❌ | ❌ | ❌ | ❓ | ## How to run real world programs diff --git a/biscuit/CMakeLists.txt b/biscuit/CMakeLists.txt index f05f3d2..31df56a 100644 --- a/biscuit/CMakeLists.txt +++ b/biscuit/CMakeLists.txt @@ -23,17 +23,18 @@ find_path(KERNEL_HEADERS_DIR ) # Toolchain + +set(PREFIX ${ARCH}-linux-musl-) + if (${ARCH} STREQUAL x86_64) - set(PREFIX x86_64-linux-musl-) set(CMAKE_C_FLAGS "-m64 -mno-red-zone") elseif (${ARCH} STREQUAL riscv32) set(PREFIX riscv64-unknown-elf-) set(CMAKE_C_FLAGS "-march=rv32imac -mabi=ilp32 -mcmodel=medany") elseif (${ARCH} STREQUAL riscv64) - set(PREFIX riscv64-linux-musl-) set(CMAKE_C_FLAGS "-march=rv64imafdc -mabi=lp64d -mcmodel=medany") elseif (${ARCH} STREQUAL aarch64) - set(PREFIX aarch64-linux-musl-) +elseif (${ARCH} STREQUAL mipsel) else () message("Unsupported arch: ${ARCH}") endif () diff --git a/biscuit/c/usertests.c b/biscuit/c/usertests.c index 851fd20..9faceca 100644 --- a/biscuit/c/usertests.c +++ b/biscuit/c/usertests.c @@ -2803,7 +2803,11 @@ static void *_locker(void *v) asm volatile("pause\n":::"memory"); #elif defined(__aarch64__) asm volatile("yield\n":::"memory"); +#else +#warning Yield instruction is not implemented + {} #endif + pthread_mutex_t *m = (pthread_mutex_t *)v; int i; for (i = 0; i < ltimes; i++) { @@ -2922,6 +2926,9 @@ static void _condtest(const int nt) asm volatile("pause\n":::"memory"); #elif defined(__aarch64__) asm volatile("yield\n":::"memory"); +#else +#warning Yield instruction is not implemented + {} #endif } diff --git a/rust/src/syscall.rs b/rust/src/syscall.rs index 5b36464..a49d09f 100644 --- a/rust/src/syscall.rs +++ b/rust/src/syscall.rs @@ -31,6 +31,12 @@ fn sys_call(syscall_id: SyscallId, arg0: usize, arg1: usize, arg2: usize, arg3: : "{x8}" (id), "{x0}" (arg0), "{x1}" (arg1), "{x2}" (arg2), "{x3}" (arg3), "{x4}" (arg4), "{x5}" (arg5) : "memory" : "volatile"); + #[cfg(target_arch = "mips")] + asm!("syscall" + : "={v0}" (ret) + : "{t0}" (id), "{a0}" (arg0), "{a1}" (arg1), "{a2}" (arg2), "{a3}" (arg3), "{s0}" (arg4), "{s1}" (arg5) + : "memory" + : "volatile"); } ret } diff --git a/rust/targets/mipsel-rcore.json b/rust/targets/mipsel-rcore.json new file mode 100644 index 0000000..582df4f --- /dev/null +++ b/rust/targets/mipsel-rcore.json @@ -0,0 +1,32 @@ +{ + "arch": "mips", + "cpu": "mips32r2", + "llvm-target": "mipsel-unknown-none", + "data-layout": "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", + "target-endian": "little", + "target-pointer-width": "32", + "target-c-int-width": "32", + "os": "none", + "features": "+mips32r2,+soft-float", + "max-atomic-width": "32", + "linker": "rust-lld", + "linker-flavor": "ld.lld", + "executables": true, + "panic-strategy": "abort", + "relocation-model": "static", + "abi-blacklist": [ + "cdecl", + "stdcall", + "fastcall", + "vectorcall", + "thiscall", + "aapcs", + "win64", + "sysv64", + "ptx-kernel", + "msp430-interrupt", + "x86-interrupt" + ], + "eliminate-frame-pointer": false + } + \ No newline at end of file diff --git a/ucore/CMakeLists.txt b/ucore/CMakeLists.txt index 0f393cc..3cdce4a 100644 --- a/ucore/CMakeLists.txt +++ b/ucore/CMakeLists.txt @@ -35,6 +35,8 @@ elseif (${ARCH} STREQUAL aarch64) set(PREFIX aarch64-elf-) endif () set(CMAKE_C_FLAGS "-mgeneral-regs-only") +elseif (${ARCH} STREQUAL mipsel) + set(PREFIX mipsel-linux-musl-) else() message("Unsupported arch: ${ARCH}") endif () diff --git a/ucore/src/arch/mipsel/arch.h b/ucore/src/arch/mipsel/arch.h new file mode 100644 index 0000000..f7fb742 --- /dev/null +++ b/ucore/src/arch/mipsel/arch.h @@ -0,0 +1,14 @@ +// See LICENSE for license details. + +#ifndef __LIBS_MIPSEL_H__ +#define __LIBS_MIPSEL_H__ + +#define do_div(n, base) \ + ({ \ + int __res; \ + __res = ((unsigned long)n) % (unsigned)base; \ + n = ((unsigned long)n) / (unsigned)base; \ + __res; \ + }) + +#endif diff --git a/ucore/src/arch/mipsel/atomic.h b/ucore/src/arch/mipsel/atomic.h new file mode 100644 index 0000000..bbbb8da --- /dev/null +++ b/ucore/src/arch/mipsel/atomic.h @@ -0,0 +1,75 @@ +#ifndef __LIBS_ATOMIC_H__ +#define __LIBS_ATOMIC_H__ + +// TODO: implement atomic operations for aarch64 + +/* Atomic operations that C can't guarantee us. Useful for resource counting etc.. */ + +static inline void set_bit(int nr, volatile void *addr) __attribute__((always_inline)); +static inline void clear_bit(int nr, volatile void *addr) __attribute__((always_inline)); +static inline void change_bit(int nr, volatile void *addr) __attribute__((always_inline)); +static inline bool test_and_set_bit(int nr, volatile void *addr) __attribute__((always_inline)); +static inline bool test_and_clear_bit(int nr, volatile void *addr) __attribute__((always_inline)); +static inline bool test_bit(int nr, volatile void *addr) __attribute__((always_inline)); + +/* * + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + * */ +static inline void set_bit(int nr, volatile void *addr) { + /* unimplemented */ +} + +/* * + * clear_bit - Atomically clears a bit in memory + * @nr: the bit to clear + * @addr: the address to start counting from + * */ +static inline void clear_bit(int nr, volatile void *addr) { + /* unimplemented */ +} + +/* * + * change_bit - Atomically toggle a bit in memory + * @nr: the bit to change + * @addr: the address to start counting from + * */ +static inline void change_bit(int nr, volatile void *addr) { + /* unimplemented */ +} + +/* * + * test_bit - Determine whether a bit is set + * @nr: the bit to test + * @addr: the address to count from + * */ +static inline bool test_bit(int nr, volatile void *addr) { + /* unimplemented */ + return 0; +} + +/* * + * test_and_set_bit - Atomically set a bit and return its old value + * @nr: the bit to set + * @addr: the address to count from + * */ +static inline bool test_and_set_bit(int nr, volatile void *addr) { + /* unimplemented */ + return 0; +} + +/* * + * test_and_clear_bit - Atomically clear a bit and return its old value + * @nr: the bit to clear + * @addr: the address to count from + * */ +static inline bool test_and_clear_bit(int nr, volatile void *addr) { + /* unimplemented */ + return 0; +} + +#endif /* !__LIBS_ATOMIC_H__ */ diff --git a/ucore/src/arch/mipsel/initcode.S b/ucore/src/arch/mipsel/initcode.S new file mode 100644 index 0000000..0c56ff2 --- /dev/null +++ b/ucore/src/arch/mipsel/initcode.S @@ -0,0 +1,10 @@ +#include + +.text +.globl _start +_start: + # call user-program function + lw a0, 0(sp) + addiu a1, sp, 8 + b umain + nop diff --git a/ucore/src/arch/mipsel/regdef.h b/ucore/src/arch/mipsel/regdef.h new file mode 100644 index 0000000..14721cb --- /dev/null +++ b/ucore/src/arch/mipsel/regdef.h @@ -0,0 +1,55 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1985 MIPS Computer Systems, Inc. + * Copyright (C) 1994, 95, 99, 2003 by Ralf Baechle + * Copyright (C) 1990 - 1992, 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_REGDEF_H +#define _ASM_REGDEF_H + + + +/* + * Symbolic register names for 32 bit ABI + */ +#define zero $0 /* wired zero */ +#define AT $1 /* assembler temp - uppercase because of ".set at" */ +#define v0 $2 /* return value */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 /* caller saved */ +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 /* callee saved */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* caller saved */ +#define t9 $25 +#define jp $25 /* PIC jump register */ +#define k0 $26 /* kernel scratch */ +#define k1 $27 +#define gp $28 /* global pointer */ +#define sp $29 /* stack pointer */ +#define fp $30 /* frame pointer */ +#define s8 $30 /* same like fp! */ +#define ra $31 /* return address */ + + + +#endif /* _ASM_REGDEF_H */ diff --git a/ucore/src/libs/defs.h b/ucore/src/libs/defs.h index ad73668..2c66c6f 100644 --- a/ucore/src/libs/defs.h +++ b/ucore/src/libs/defs.h @@ -32,7 +32,7 @@ typedef unsigned long long uint64_t; #if __riscv_xlen == 64 || defined(__x86_64__) || defined(__aarch64__) typedef int64_t intptr_t; typedef uint64_t uintptr_t; -#elif __riscv_xlen == 32 || defined(__i386__) +#elif __riscv_xlen == 32 || defined(__i386__) || defined(__mips__) typedef int32_t intptr_t; typedef uint32_t uintptr_t; #endif diff --git a/ucore/src/libs/elf.h b/ucore/src/libs/elf.h index f8958d3..ed973ea 100644 --- a/ucore/src/libs/elf.h +++ b/ucore/src/libs/elf.h @@ -36,7 +36,7 @@ struct proghdr { uint64_t p_memsz; // size of segment in memory (bigger if contains bss) uint64_t p_align; // required alignment, invariably hardware page size }; -#elif __riscv_xlen == 32 || defined(__i386__) +#elif __riscv_xlen == 32 || defined(__i386__) || defined(__mipsel) struct proghdr { uint32_t p_type; // loadable code or data, dynamic linking info,etc. uint32_t p_offset; // file offset of segment From b09e4e24ad1cfe3b6eae2b40231f389070cdb9e2 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Thu, 4 Apr 2019 12:13:15 +0800 Subject: [PATCH 05/39] Make redis run under mipsel Signed-off-by: Harry Chen --- README.md | 8 ++++---- redis/Makefile | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0ce5d48..a1230a3 100644 --- a/README.md +++ b/README.md @@ -56,11 +56,11 @@ A rootfs is created at `build/$(arch)` and converted to `qcow2`. | ucore | ❌ | ✅ | ✅ | ✅ | ✅ | | rust | ✅ | ✅ | ✅ | ✅ | ✅ | | biscuit | ✅ | ✅ | ❌ | ✅ | ✅ | -| nginx (linux only) | ✅ | ✅ | ❌ | ✅ | ❓ | -| redis (linux only) | ✅ | ✅ | ✅ | ✅ | ❓ | -| busybox | ✅ | ✅ | ❌ | ✅ | ❓ | +| nginx (linux only) | ✅ | ✅ | 🚧 | ✅ | 🚧 | +| redis (linux only) | ✅ | ✅ | ✅ | ✅ | ✅ | +| busybox | ✅ | ✅ | ❌ | ✅ | 🚧 | | alpine rootfs | ✅ | ✅ | ❌ | ❌ | ❌ | -| iperf3 | ✅ | ❌ | ❌ | ❌ | ❓ | +| iperf3 | ✅ | ❌ | ❌ | ❌ | ❌ | ## How to run real world programs diff --git a/redis/Makefile b/redis/Makefile index 263edbd..96e3245 100644 --- a/redis/Makefile +++ b/redis/Makefile @@ -25,7 +25,7 @@ $(redis_dir)/src/redis-server: $(redis_dir)/src/config.h sed -i 's/#define HAVE_EPOLL 1//' $(redis_dir)/src/config.h # our accept does not have backlog sed -i 's/#define MAX_ACCEPTS_PER_CALL 1000/#define MAX_ACCEPTS_PER_CALL 1/' $(redis_dir)/src/networking.c - cd $(redis_dir) && make CC=$(cc) MALLOC=libc + cd $(redis_dir) && make CC=$(cc) LDFLAGS="${LDFLAGS} -latomic" MALLOC=libc $(bin_server_unstripped): $(redis_dir)/src/redis-server cp $(redis_dir)/src/redis-server $(bin_server_unstripped) From 1829ca47d47a278688778edf7d72448066a9c980 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Thu, 4 Apr 2019 13:46:09 +0800 Subject: [PATCH 06/39] Make nginx compile on 32bit platform, fix bitcuit on riscv Signed-off-by: Harry Chen --- Makefile | 4 ---- README.md | 4 ++-- biscuit/CMakeLists.txt | 3 +-- nginx/Makefile | 3 ++- redis/Makefile | 1 + 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 7c82aff..5626ef5 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,6 @@ ifneq ($(arch), x86_64) endif biscuit: -ifeq ($(arch), $(filter $(arch), x86_64 aarch64 riscv64 mipsel)) ifneq ($(shell uname)-$(arch), Darwin-riscv64) @echo Building biscuit programs @mkdir -p biscuit/build @@ -54,7 +53,6 @@ ifneq ($(shell uname)-$(arch), Darwin-riscv64) @rm -rf $(out_dir)/biscuit && mkdir -p $(out_dir)/biscuit @cp $(biscuit_bin_path)/* $(out_dir)/biscuit endif -endif $(busybox): ifeq ($(arch), x86_64) @@ -75,7 +73,6 @@ endif busybox: $(busybox) nginx: -ifneq ($(arch), riscv32) ifneq ($(shell uname), Darwin) @echo Building nginx mkdir -p $(out_dir)/usr/local/nginx/conf @@ -84,7 +81,6 @@ ifneq ($(shell uname), Darwin) @cp nginx/build/$(arch)/nginx $(out_dir) @cp nginx/nginx.conf $(out_dir)/usr/local/nginx/conf endif -endif redis: ifneq ($(shell uname), Darwin) diff --git a/README.md b/README.md index a1230a3..cb59801 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,8 @@ A rootfs is created at `build/$(arch)` and converted to `qcow2`. | ------------------ | ------ | ------- | ------- | ------- | ------ | | ucore | ❌ | ✅ | ✅ | ✅ | ✅ | | rust | ✅ | ✅ | ✅ | ✅ | ✅ | -| biscuit | ✅ | ✅ | ❌ | ✅ | ✅ | -| nginx (linux only) | ✅ | ✅ | 🚧 | ✅ | 🚧 | +| biscuit | ✅ | ✅ | ✅ | ✅ | ✅ | +| nginx (linux only) | ✅ | ✅ | ✅ | ✅ | ✅ | | redis (linux only) | ✅ | ✅ | ✅ | ✅ | ✅ | | busybox | ✅ | ✅ | ❌ | ✅ | 🚧 | | alpine rootfs | ✅ | ✅ | ❌ | ❌ | ❌ | diff --git a/biscuit/CMakeLists.txt b/biscuit/CMakeLists.txt index 31df56a..30a518d 100644 --- a/biscuit/CMakeLists.txt +++ b/biscuit/CMakeLists.txt @@ -29,8 +29,7 @@ set(PREFIX ${ARCH}-linux-musl-) if (${ARCH} STREQUAL x86_64) set(CMAKE_C_FLAGS "-m64 -mno-red-zone") elseif (${ARCH} STREQUAL riscv32) - set(PREFIX riscv64-unknown-elf-) - set(CMAKE_C_FLAGS "-march=rv32imac -mabi=ilp32 -mcmodel=medany") + set(CMAKE_C_FLAGS "-march=rv32imafdc -mabi=ilp32d -mcmodel=medany") elseif (${ARCH} STREQUAL riscv64) set(CMAKE_C_FLAGS "-march=rv64imafdc -mabi=lp64d -mcmodel=medany") elseif (${ARCH} STREQUAL aarch64) diff --git a/nginx/Makefile b/nginx/Makefile index ca8e62c..efe57d9 100644 --- a/nginx/Makefile +++ b/nginx/Makefile @@ -23,7 +23,8 @@ $(nginx_dir)/objs/nginx: $(nginx_dir) cd $(nginx_dir) && ./configure --with-cc=$(cc) --with-cc-opt=-static --with-ld-opt=-static --without-pcre --without-http_rewrite_module --without-http_gzip_module --with-poll_module --without-http_upstream_zone_module cd $(nginx_dir) && printf "#ifndef NGX_SYS_NERR\n#define NGX_SYS_NERR 132\n#endif\n" >> objs/ngx_auto_config.h cd $(nginx_dir) && printf "#ifndef NGX_HAVE_SVSVSHM\n#define NGX_HAVE_SYSVSHM 1\n#endif\n" >> objs/ngx_auto_config.h - cd $(nginx_dir) && make + # FIXME: overflow will occur on 32-bit platforms, this is only a temporary workaround + cd $(nginx_dir) && make CFLAGS="${CFLGAS} -Wno-error=overflow" $(bin_unstripped): $(nginx_dir)/objs/nginx cp $(nginx_dir)/objs/nginx $(bin_unstripped) diff --git a/redis/Makefile b/redis/Makefile index 96e3245..dd82ade 100644 --- a/redis/Makefile +++ b/redis/Makefile @@ -25,6 +25,7 @@ $(redis_dir)/src/redis-server: $(redis_dir)/src/config.h sed -i 's/#define HAVE_EPOLL 1//' $(redis_dir)/src/config.h # our accept does not have backlog sed -i 's/#define MAX_ACCEPTS_PER_CALL 1000/#define MAX_ACCEPTS_PER_CALL 1/' $(redis_dir)/src/networking.c + # note: on some platforms gcc seems to forget linking with libatomic, fix it anyway cd $(redis_dir) && make CC=$(cc) LDFLAGS="${LDFLAGS} -latomic" MALLOC=libc $(bin_server_unstripped): $(redis_dir)/src/redis-server From a1d9dcc78cce58418ad0e022206a7e93fa393105 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Thu, 4 Apr 2019 14:47:02 +0800 Subject: [PATCH 07/39] Fix ucore user app compiling on x86_64 Signed-off-by: Harry Chen --- Makefile | 2 -- README.md | 2 +- ucore/src/arch/{i386 => x86_64}/arch.h | 0 ucore/src/arch/{i386 => x86_64}/atomic.h | 0 ucore/src/arch/{i386 => x86_64}/initcode.S | 12 ++---------- 5 files changed, 3 insertions(+), 13 deletions(-) rename ucore/src/arch/{i386 => x86_64}/arch.h (100%) rename ucore/src/arch/{i386 => x86_64}/atomic.h (100%) rename ucore/src/arch/{i386 => x86_64}/initcode.S (61%) diff --git a/Makefile b/Makefile index 5626ef5..1a94164 100644 --- a/Makefile +++ b/Makefile @@ -37,13 +37,11 @@ rust: @cp $(rust_bins) $(out_dir)/rust ucore: -ifneq ($(arch), x86_64) @echo Building ucore programs @mkdir -p ucore/build @cd ucore/build && cmake $(cmake_build_args) .. && make @rm -rf $(out_dir)/ucore && mkdir -p $(out_dir)/ucore @cp $(ucore_bin_path)/* $(out_dir)/ucore -endif biscuit: ifneq ($(shell uname)-$(arch), Darwin-riscv64) diff --git a/README.md b/README.md index cb59801..ad90504 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ A rootfs is created at `build/$(arch)` and converted to `qcow2`. | | x86_64 | aarch64 | riscv32 | riscv64 | mipsel | | ------------------ | ------ | ------- | ------- | ------- | ------ | -| ucore | ❌ | ✅ | ✅ | ✅ | ✅ | +| ucore | ✅ | ✅ | ✅ | ✅ | ✅ | | rust | ✅ | ✅ | ✅ | ✅ | ✅ | | biscuit | ✅ | ✅ | ✅ | ✅ | ✅ | | nginx (linux only) | ✅ | ✅ | ✅ | ✅ | ✅ | diff --git a/ucore/src/arch/i386/arch.h b/ucore/src/arch/x86_64/arch.h similarity index 100% rename from ucore/src/arch/i386/arch.h rename to ucore/src/arch/x86_64/arch.h diff --git a/ucore/src/arch/i386/atomic.h b/ucore/src/arch/x86_64/atomic.h similarity index 100% rename from ucore/src/arch/i386/atomic.h rename to ucore/src/arch/x86_64/atomic.h diff --git a/ucore/src/arch/i386/initcode.S b/ucore/src/arch/x86_64/initcode.S similarity index 61% rename from ucore/src/arch/i386/initcode.S rename to ucore/src/arch/x86_64/initcode.S index e6b4936..40e6ff4 100644 --- a/ucore/src/arch/i386/initcode.S +++ b/ucore/src/arch/x86_64/initcode.S @@ -4,21 +4,13 @@ _start: # set ebp for backtrace movl $0x0, %ebp - # load argc and argv - movl (%esp), %ebx - lea 0x4(%esp), %ecx - - # move down the esp register # since it may cause page fault in backtrace subl $0x20, %esp - # save argc and argv on stack - pushl %ecx - pushl %ebx - # call user-program function + # according to fastcall ABI, the first 6 parameters are in registes + # so we do not need to copy (argc, argv) as on i386 call umain -1: jmp 1b From 97bae0c39a7aeaab07654d99c3ba3bcb4d01658c Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Thu, 4 Apr 2019 21:55:10 +0800 Subject: [PATCH 08/39] Add busybox for riscv32 and mipsel, update README Signed-off-by: Harry Chen --- Makefile | 4 ++-- README.md | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 1a94164..1faca35 100644 --- a/Makefile +++ b/Makefile @@ -64,8 +64,8 @@ ifeq ($(arch), $(filter $(arch), x86_64 aarch64)) @mv tmp/bin/busybox $(busybox) @rm -rf tmp && rm busybox.tar.xz endif -ifeq ($(arch), riscv64) - @wget https://github.com/rcore-os/busybox-riscv-prebuilts/raw/master/busybox-1.30.1-riscv64/busybox -O $(busybox) +ifeq ($(arch), $(filter $(arch), riscv64 riscv32 mipsel)) + @wget https://github.com/rcore-os/busybox-prebuilts/raw/master/busybox-1.30.1-${arch}/busybox -O $(busybox) endif busybox: $(busybox) diff --git a/README.md b/README.md index ad90504..a3029fe 100644 --- a/README.md +++ b/README.md @@ -53,15 +53,18 @@ A rootfs is created at `build/$(arch)` and converted to `qcow2`. | | x86_64 | aarch64 | riscv32 | riscv64 | mipsel | | ------------------ | ------ | ------- | ------- | ------- | ------ | -| ucore | ✅ | ✅ | ✅ | ✅ | ✅ | +| ucore | ✅ | ✅ | ✅ | ✅ | ❗ | | rust | ✅ | ✅ | ✅ | ✅ | ✅ | | biscuit | ✅ | ✅ | ✅ | ✅ | ✅ | -| nginx (linux only) | ✅ | ✅ | ✅ | ✅ | ✅ | +| nginx (linux only) | ✅ | ✅ | ❗ | ✅ | ❗ | | redis (linux only) | ✅ | ✅ | ✅ | ✅ | ✅ | -| busybox | ✅ | ✅ | ❌ | ✅ | 🚧 | +| busybox | ✅ | ✅ | ✅ | ✅ | ✅ | | alpine rootfs | ✅ | ✅ | ❌ | ❌ | ❌ | | iperf3 | ✅ | ❌ | ❌ | ❌ | ❌ | + +Note: ❗ means workarounds are used so that they may not work properly. ❌ means failure in compiling or not existed on such platform. + ## How to run real world programs ### How to use Redis From 42c0f22ed3fb8a0eca382fdbdc7d21cdadc67df6 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Fri, 5 Apr 2019 13:50:52 +0800 Subject: [PATCH 09/39] Add half baked raw_socket app --- rust/src/bin/raw_socket.rs | 107 +++++++++++++++++++++++++++++++++++++ rust/src/syscall.rs | 24 +++++++++ 2 files changed, 131 insertions(+) create mode 100644 rust/src/bin/raw_socket.rs diff --git a/rust/src/bin/raw_socket.rs b/rust/src/bin/raw_socket.rs new file mode 100644 index 0000000..a38790c --- /dev/null +++ b/rust/src/bin/raw_socket.rs @@ -0,0 +1,107 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate rcore_user; + +use rcore_user::syscall::{sys_socket, sys_read, sys_setsockopt, sys_sendto, sys_ioctl}; +use core::mem::size_of; +use core::default::Default; + +#[repr(C)] +#[derive(Default)] +pub struct SockAddrLl { + sll_family: u16, + sll_protocol: u16, + sll_ifindex: u32, + sll_hatype: u16, + sll_pkttype: u8, + sll_halen: u8, + sll_addr: [u8; 8], +} + +#[repr(C)] +#[derive(Default)] +pub struct SockAddrIn { + sin_family: u16, + sin_port: u16, + sin_addr: u32, + sin_zero: [u8; 8], +} + +#[repr(C)] +#[derive(Default)] +pub struct SockAddrHa { + sha_family: u16, + sha_data: [u8; 14] +} + +#[repr(C)] +#[derive(Default)] +struct ArpReq { + arp_pa: SockAddrIn, + arp_ha: SockAddrHa, + arp_flags: u32, + arp_netmask: SockAddrIn, + arp_dev: [u8; 16] +} + +// IMPORTANT: Must define main() like this +#[no_mangle] +pub unsafe fn main() { + println!("Raw socket test"); + // raw socket, icmp + let capture_fd = sys_socket(2, 3, 1); + // inet socket, udp + let arp_fd = sys_socket(2, 2, 0); + // packet socket, raw + let packet = sys_socket(17, 3, 0); + let mut buffer = [0u8; 2048]; + // set header included + let included = 1u32; + sys_setsockopt(capture_fd as usize, 0, 3, &included as *const u32 as usize, 4); + + let mut addr: SockAddrLl = Default::default(); + // packet + addr.sll_family = 17; + const ETHER_HEADER_LEN: usize = 6+6+2; + // ethertype 0x0800 ipv4 + buffer[12] = 0x08; + buffer[13] = 0x00; + + let mut arp: ArpReq = Default::default(); + // inet + arp.arp_pa.sin_family = 2; + arp.arp_dev[0..9].copy_from_slice(&[b'e', b'n', b'p', b'0', b's', b'4', b'f', b'0', 0]); + loop { + let len = sys_read(capture_fd as usize, buffer.as_mut_ptr().add(ETHER_HEADER_LEN), buffer.len()) as usize; + println!("Got packet of len {}", len); + if ETHER_HEADER_LEN + len > 20 && buffer[ETHER_HEADER_LEN + 0] == 0x45 { + // ipv4 + let ttl = buffer[ETHER_HEADER_LEN + 8]; + if ttl > 1 { + println!("ttl {}", ttl); + let dst_ip = (buffer[ETHER_HEADER_LEN + 19] as u32) << 24 | + (buffer[ETHER_HEADER_LEN + 18] as u32) << 16 | + (buffer[ETHER_HEADER_LEN + 17] as u32) << 8 | + (buffer[ETHER_HEADER_LEN + 16] as u32); + println!("dst_ip {:#X}", dst_ip); + arp.arp_pa.sin_addr = dst_ip; + // SIOCGARP + sys_ioctl(arp_fd as usize, 0x8954, &arp as *const ArpReq as usize); + println!("dst_mac {:X?}", &arp.arp_ha.sha_data[0..6]); + + // fill src and dst mac + // todo: get mac from if instead of hard coding + buffer[0..6].copy_from_slice(&[0, 0x16, 0x31, 0xFF, 0xA4, 0x9F]); + buffer[6..12].copy_from_slice(&arp.arp_ha.sha_data[0..6]); + buffer[ETHER_HEADER_LEN + 8] = ttl - 1; + let checksum = (buffer[ETHER_HEADER_LEN + 10] as u16) << 8 | (buffer[ETHER_HEADER_LEN + 11] as u16); + buffer[ETHER_HEADER_LEN + 10] = ((checksum + 1) >> 8) as u8; + buffer[ETHER_HEADER_LEN + 11] = checksum as u8; + addr.sll_ifindex = 0; + sys_sendto(packet as usize, buffer.as_ptr(), len as usize + ETHER_HEADER_LEN, 0, &addr as *const SockAddrLl as usize, size_of::()); + } + } + } +} diff --git a/rust/src/syscall.rs b/rust/src/syscall.rs index a49d09f..94f4387 100644 --- a/rust/src/syscall.rs +++ b/rust/src/syscall.rs @@ -177,6 +177,22 @@ pub fn sys_mmap(addr: usize, len: usize, prot: usize, flags: usize, fd: usize, o sys_call(SyscallId::Mmap, addr, len, prot, flags, fd, offset) } +pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> i32 { + sys_call(SyscallId::Socket, domain, socket_type, protocol, 0, 0, 0) +} + +pub fn sys_setsockopt(fd: usize, level: usize, opt: usize, optval: usize, optlen: usize) -> i32 { + sys_call(SyscallId::SetSockOpt, fd, level, opt, optval, optlen, 0) +} + +pub fn sys_sendto(fd: usize, base: *const u8, len: usize, flags: usize, addr: usize, addr_len: usize) -> i32 { + sys_call(SyscallId::SendTo, fd, base as usize, len, flags, addr, addr_len) +} + +pub fn sys_ioctl(fd: usize, request: usize, arg1: usize) -> i32 { + sys_call(SyscallId::Ioctl, fd, request, arg1, 0, 0, 0) +} + #[cfg(target_arch = "x86_64")] #[allow(dead_code)] enum SyscallId { @@ -187,9 +203,13 @@ enum SyscallId { Seek = 8, Mmap = 9, Munmap = 11, + Ioctl = 16, Yield = 24, Sleep = 35, GetPid = 39, + Socket = 41, + SendTo = 44, + SetSockOpt = 54, Clone = 56, Exec = 59, Exit = 60, @@ -220,7 +240,11 @@ enum SyscallId { Seek = 62, Mmap = 222, Munmap = 215, + Ioctl = 29, Yield = 124, + Socket = 198, + SendTo = 206, + SetSockOpt = 208, Sleep = 101, GetPid = 172, Clone = 220, From 67890aeb4205083d5a95b1f70de92ae39b549c8c Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 6 Apr 2019 00:38:11 +0800 Subject: [PATCH 10/39] Add __start as ucore mipsel entry point Signed-off-by: Harry Chen --- ucore/src/arch/mipsel/initcode.S | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ucore/src/arch/mipsel/initcode.S b/ucore/src/arch/mipsel/initcode.S index 0c56ff2..9f01acd 100644 --- a/ucore/src/arch/mipsel/initcode.S +++ b/ucore/src/arch/mipsel/initcode.S @@ -1,8 +1,12 @@ #include .text -.globl _start +.globl __start +.global _start + +# seems different toolchains look for different entry points _start: +__start: # call user-program function lw a0, 0(sp) addiu a1, sp, 8 From 0dc44ae9cb1d21bf109325b6ef1d5165f6d8238a Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Sat, 6 Apr 2019 11:28:43 +0800 Subject: [PATCH 11/39] Fix ip checksum calculation --- Makefile | 2 ++ rust/src/bin/fantastic_text.rs | 3 +- rust/src/bin/float.rs | 1 - rust/src/bin/raw_socket.rs | 50 +++++++++++++++++++++++----------- rust/src/bin/sh.rs | 2 +- rust/src/bin/tls.rs | 2 +- 6 files changed, 40 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index 1faca35..9184610 100644 --- a/Makefile +++ b/Makefile @@ -45,12 +45,14 @@ ucore: biscuit: ifneq ($(shell uname)-$(arch), Darwin-riscv64) +ifneq ($(shell uname)-$(arch), Darwin-aarch64) @echo Building biscuit programs @mkdir -p biscuit/build @cd biscuit/build && cmake $(cmake_build_args) .. && make @rm -rf $(out_dir)/biscuit && mkdir -p $(out_dir)/biscuit @cp $(biscuit_bin_path)/* $(out_dir)/biscuit endif +endif $(busybox): ifeq ($(arch), x86_64) diff --git a/rust/src/bin/fantastic_text.rs b/rust/src/bin/fantastic_text.rs index b1403ed..d0770ad 100644 --- a/rust/src/bin/fantastic_text.rs +++ b/rust/src/bin/fantastic_text.rs @@ -32,7 +32,8 @@ pub fn main() { color_text!("!", 97), ); - let text = "reguler \x1b[4munderline\x1b[24m \x1b[7mreverse\x1b[27m \x1b[9mstrikethrough\x1b[29m"; + 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)); diff --git a/rust/src/bin/float.rs b/rust/src/bin/float.rs index 578ba8e..a07c97d 100644 --- a/rust/src/bin/float.rs +++ b/rust/src/bin/float.rs @@ -7,7 +7,6 @@ extern crate rcore_user; use rcore_user::syscall::*; - // IMPORTANT: Must define main() like this #[no_mangle] pub fn main() { diff --git a/rust/src/bin/raw_socket.rs b/rust/src/bin/raw_socket.rs index a38790c..fdb7350 100644 --- a/rust/src/bin/raw_socket.rs +++ b/rust/src/bin/raw_socket.rs @@ -4,9 +4,9 @@ #[macro_use] extern crate rcore_user; -use rcore_user::syscall::{sys_socket, sys_read, sys_setsockopt, sys_sendto, sys_ioctl}; -use core::mem::size_of; use core::default::Default; +use core::mem::size_of; +use rcore_user::syscall::{sys_ioctl, sys_read, sys_sendto, sys_setsockopt, sys_socket}; #[repr(C)] #[derive(Default)] @@ -33,7 +33,7 @@ pub struct SockAddrIn { #[derive(Default)] pub struct SockAddrHa { sha_family: u16, - sha_data: [u8; 14] + sha_data: [u8; 14], } #[repr(C)] @@ -43,7 +43,7 @@ struct ArpReq { arp_ha: SockAddrHa, arp_flags: u32, arp_netmask: SockAddrIn, - arp_dev: [u8; 16] + arp_dev: [u8; 16], } // IMPORTANT: Must define main() like this @@ -59,12 +59,18 @@ pub unsafe fn main() { let mut buffer = [0u8; 2048]; // set header included let included = 1u32; - sys_setsockopt(capture_fd as usize, 0, 3, &included as *const u32 as usize, 4); + sys_setsockopt( + capture_fd as usize, + 0, + 3, + &included as *const u32 as usize, + 4, + ); let mut addr: SockAddrLl = Default::default(); // packet addr.sll_family = 17; - const ETHER_HEADER_LEN: usize = 6+6+2; + const ETHER_HEADER_LEN: usize = 6 + 6 + 2; // ethertype 0x0800 ipv4 buffer[12] = 0x08; buffer[13] = 0x00; @@ -74,33 +80,45 @@ pub unsafe fn main() { arp.arp_pa.sin_family = 2; arp.arp_dev[0..9].copy_from_slice(&[b'e', b'n', b'p', b'0', b's', b'4', b'f', b'0', 0]); loop { - let len = sys_read(capture_fd as usize, buffer.as_mut_ptr().add(ETHER_HEADER_LEN), buffer.len()) as usize; + let len = sys_read( + capture_fd as usize, + buffer.as_mut_ptr().add(ETHER_HEADER_LEN), + buffer.len(), + ) as usize; println!("Got packet of len {}", len); if ETHER_HEADER_LEN + len > 20 && buffer[ETHER_HEADER_LEN + 0] == 0x45 { // ipv4 let ttl = buffer[ETHER_HEADER_LEN + 8]; if ttl > 1 { println!("ttl {}", ttl); - let dst_ip = (buffer[ETHER_HEADER_LEN + 19] as u32) << 24 | - (buffer[ETHER_HEADER_LEN + 18] as u32) << 16 | - (buffer[ETHER_HEADER_LEN + 17] as u32) << 8 | - (buffer[ETHER_HEADER_LEN + 16] as u32); + let dst_ip = (buffer[ETHER_HEADER_LEN + 19] as u32) << 24 + | (buffer[ETHER_HEADER_LEN + 18] as u32) << 16 + | (buffer[ETHER_HEADER_LEN + 17] as u32) << 8 + | (buffer[ETHER_HEADER_LEN + 16] as u32); println!("dst_ip {:#X}", dst_ip); arp.arp_pa.sin_addr = dst_ip; // SIOCGARP sys_ioctl(arp_fd as usize, 0x8954, &arp as *const ArpReq as usize); println!("dst_mac {:X?}", &arp.arp_ha.sha_data[0..6]); - + // fill src and dst mac // todo: get mac from if instead of hard coding buffer[0..6].copy_from_slice(&[0, 0x16, 0x31, 0xFF, 0xA4, 0x9F]); buffer[6..12].copy_from_slice(&arp.arp_ha.sha_data[0..6]); buffer[ETHER_HEADER_LEN + 8] = ttl - 1; - let checksum = (buffer[ETHER_HEADER_LEN + 10] as u16) << 8 | (buffer[ETHER_HEADER_LEN + 11] as u16); - buffer[ETHER_HEADER_LEN + 10] = ((checksum + 1) >> 8) as u8; - buffer[ETHER_HEADER_LEN + 11] = checksum as u8; + let checksum = (buffer[ETHER_HEADER_LEN + 10] as u16) << 8 + | (buffer[ETHER_HEADER_LEN + 11] as u16); + buffer[ETHER_HEADER_LEN + 10] = ((checksum + 0x0100) >> 8) as u8; + buffer[ETHER_HEADER_LEN + 11] = (checksum + 0x0100) as u8; addr.sll_ifindex = 0; - sys_sendto(packet as usize, buffer.as_ptr(), len as usize + ETHER_HEADER_LEN, 0, &addr as *const SockAddrLl as usize, size_of::()); + sys_sendto( + packet as usize, + buffer.as_ptr(), + len as usize + ETHER_HEADER_LEN, + 0, + &addr as *const SockAddrLl as usize, + size_of::(), + ); } } } diff --git a/rust/src/bin/sh.rs b/rust/src/bin/sh.rs index c7932d4..d271209 100644 --- a/rust/src/bin/sh.rs +++ b/rust/src/bin/sh.rs @@ -10,7 +10,7 @@ use alloc::vec::Vec; use core::ptr; use rcore_user::io::get_line; -use rcore_user::syscall::{sys_exec, sys_vfork, sys_wait, sys_getcwd, sys_chdir, sys_access}; +use rcore_user::syscall::{sys_access, sys_chdir, sys_exec, sys_getcwd, sys_vfork, sys_wait}; // IMPORTANT: Must define main() like this #[no_mangle] diff --git a/rust/src/bin/tls.rs b/rust/src/bin/tls.rs index a963704..631bf0f 100644 --- a/rust/src/bin/tls.rs +++ b/rust/src/bin/tls.rs @@ -5,7 +5,7 @@ #[macro_use] extern crate rcore_user; -use rcore_user::syscall::{sys_arch_prctl, sys_vfork, sys_getpid, sys_sleep}; +use rcore_user::syscall::{sys_arch_prctl, sys_getpid, sys_sleep, sys_vfork}; fn set_tls(tls: usize, pid: usize) { #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] From a460c5b32744292ed50922a159fa22c830aa61b9 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Sun, 7 Apr 2019 00:52:17 +0800 Subject: [PATCH 12/39] Fix mips rust programs --- rust/src/lang_items.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rust/src/lang_items.rs b/rust/src/lang_items.rs index 67624ad..878a046 100644 --- a/rust/src/lang_items.rs +++ b/rust/src/lang_items.rs @@ -17,6 +17,12 @@ fn init_heap() { unsafe { ALLOCATOR.lock().init(HEAP.as_ptr() as usize, HEAP_SIZE); } } +/// MIPS use __start for entry point instead of _start +#[no_mangle] +pub extern "C" fn __start(argc: isize, argv: *const *const u8) -> ! { + _start(argc, argv) +} + #[no_mangle] pub extern "C" fn _start(_argc: isize, _argv: *const *const u8) -> ! { init_heap(); From b00a4d266a6922739b1e652e2aa070ef1ae1de90 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Sun, 7 Apr 2019 11:57:59 +0800 Subject: [PATCH 13/39] Complete working raw socket forwarding --- rust/Cargo.lock | 7 ++ rust/Cargo.toml | 3 +- rust/src/bin/raw_socket.rs | 140 +++++++++++++++++++++++++++++-------- rust/src/io.rs | 4 +- rust/src/lang_items.rs | 6 +- rust/src/lib.rs | 4 +- rust/src/syscall.rs | 125 ++++++++++++++++++++++++++++----- 7 files changed, 232 insertions(+), 57 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 66f055c..ffa716a 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -62,6 +62,7 @@ dependencies = [ "buddy_system_allocator 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "isomorphic_drivers 0.1.0 (git+https://github.com/rcore-os/isomorphic_drivers)", "smoltcp 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "treebitmap 0.3.1 (git+https://github.com/jiegec/treebitmap)", ] [[package]] @@ -80,6 +81,11 @@ name = "spin" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "treebitmap" +version = "0.3.1" +source = "git+https://github.com/jiegec/treebitmap#9c0ddcfaed0c960fb86a66c2b5abb5af70d6f1d1" + [[package]] name = "volatile" version = "0.2.6" @@ -96,4 +102,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcec5e97041c7f0f1c5b7d93f12e57293c831c646f4cc7a5db59460c7ea8de6" "checksum smoltcp 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fef582369edb298c6c41319a544ca9c4e83622f226055ccfcb35974fbb55ed34" "checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" +"checksum treebitmap 0.3.1 (git+https://github.com/jiegec/treebitmap)" = "" "checksum volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6af0edf5b4faacc31fc51159244d78d65ec580f021afcef7bd53c04aeabc7f29" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 5c55341..aa3a560 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -7,4 +7,5 @@ edition = "2018" [dependencies] buddy_system_allocator = "0.1" isomorphic_drivers = { git = "https://github.com/rcore-os/isomorphic_drivers", default-features = false, features = ["log"]} -smoltcp = { version = "0.5.0", default-features = false, features = ["alloc", "log", "proto-ipv4", "socket-tcp", "socket-raw"] } \ No newline at end of file +smoltcp = { version = "0.5.0", default-features = false, features = ["alloc", "log", "proto-ipv4", "socket-tcp", "socket-raw"] } +treebitmap = { git = "https://github.com/jiegec/treebitmap" , features = ["alloc"] } \ No newline at end of file diff --git a/rust/src/bin/raw_socket.rs b/rust/src/bin/raw_socket.rs index fdb7350..0c903c7 100644 --- a/rust/src/bin/raw_socket.rs +++ b/rust/src/bin/raw_socket.rs @@ -1,12 +1,18 @@ +#![feature(alloc)] #![no_std] #![no_main] #[macro_use] extern crate rcore_user; +extern crate alloc; +extern crate treebitmap; + +use alloc::format; use core::default::Default; use core::mem::size_of; use rcore_user::syscall::{sys_ioctl, sys_read, sys_sendto, sys_setsockopt, sys_socket}; +use treebitmap::*; #[repr(C)] #[derive(Default)] @@ -46,16 +52,40 @@ struct ArpReq { arp_dev: [u8; 16], } +pub fn get_routing_table() -> IpLookupTable { + let mut table = IpLookupTable::new(); + // iface 0 10.0.0.0/24 00:16:31:ff:a4:9f enp0s4f0 + table.insert( + Ipv4Addr::new(10, 0, 0, 0), + 24, + (0, [0x00, 0x16, 0x31, 0xff, 0xa4, 0x9f], "enp0s4f0\0"), + ); + // iface 1 10.0.1.0/24 54:51:9f:71:c0:01 enp0s5f0 + table.insert( + Ipv4Addr::new(10, 0, 1, 0), + 24, + (1, [0x54, 0x51, 0x9f, 0x71, 0xc0, 0x01], "enp0s5f0\0"), + ); + + table +} + // IMPORTANT: Must define main() like this #[no_mangle] pub unsafe fn main() { println!("Raw socket test"); + // raw socket, icmp let capture_fd = sys_socket(2, 3, 1); // inet socket, udp let arp_fd = sys_socket(2, 2, 0); // packet socket, raw - let packet = sys_socket(17, 3, 0); + let packet_fd = sys_socket(17, 3, 0); + // netlink socket, raw + let netlink_fd = sys_socket(16, 3, 0); + + let table = get_routing_table(); + let mut buffer = [0u8; 2048]; // set header included let included = 1u32; @@ -78,7 +108,6 @@ pub unsafe fn main() { let mut arp: ArpReq = Default::default(); // inet arp.arp_pa.sin_family = 2; - arp.arp_dev[0..9].copy_from_slice(&[b'e', b'n', b'p', b'0', b's', b'4', b'f', b'0', 0]); loop { let len = sys_read( capture_fd as usize, @@ -86,39 +115,88 @@ pub unsafe fn main() { buffer.len(), ) as usize; println!("Got packet of len {}", len); - if ETHER_HEADER_LEN + len > 20 && buffer[ETHER_HEADER_LEN + 0] == 0x45 { + // check ethertype and ip version ihl + if ETHER_HEADER_LEN + len > 20 + && buffer[12] == 0x08 + && buffer[13] == 0x00 + && buffer[ETHER_HEADER_LEN + 0] == 0x45 + { // ipv4 let ttl = buffer[ETHER_HEADER_LEN + 8]; if ttl > 1 { - println!("ttl {}", ttl); - let dst_ip = (buffer[ETHER_HEADER_LEN + 19] as u32) << 24 - | (buffer[ETHER_HEADER_LEN + 18] as u32) << 16 - | (buffer[ETHER_HEADER_LEN + 17] as u32) << 8 - | (buffer[ETHER_HEADER_LEN + 16] as u32); - println!("dst_ip {:#X}", dst_ip); - arp.arp_pa.sin_addr = dst_ip; - // SIOCGARP - sys_ioctl(arp_fd as usize, 0x8954, &arp as *const ArpReq as usize); - println!("dst_mac {:X?}", &arp.arp_ha.sha_data[0..6]); - - // fill src and dst mac - // todo: get mac from if instead of hard coding - buffer[0..6].copy_from_slice(&[0, 0x16, 0x31, 0xFF, 0xA4, 0x9F]); - buffer[6..12].copy_from_slice(&arp.arp_ha.sha_data[0..6]); - buffer[ETHER_HEADER_LEN + 8] = ttl - 1; - let checksum = (buffer[ETHER_HEADER_LEN + 10] as u16) << 8 - | (buffer[ETHER_HEADER_LEN + 11] as u16); - buffer[ETHER_HEADER_LEN + 10] = ((checksum + 0x0100) >> 8) as u8; - buffer[ETHER_HEADER_LEN + 11] = (checksum + 0x0100) as u8; - addr.sll_ifindex = 0; - sys_sendto( - packet as usize, - buffer.as_ptr(), - len as usize + ETHER_HEADER_LEN, - 0, - &addr as *const SockAddrLl as usize, - size_of::(), + if buffer[ETHER_HEADER_LEN + 19] == 2 { + // to myself + println!("packet to myself"); + continue; + } + let lookup_ip = Ipv4Addr::new( + buffer[ETHER_HEADER_LEN + 16], + buffer[ETHER_HEADER_LEN + 17], + buffer[ETHER_HEADER_LEN + 18], + buffer[ETHER_HEADER_LEN + 19], ); + let route_match = table.longest_match(lookup_ip); + match route_match { + Some((_, _, (out_if, mac, name))) => { + let dst_ip = (buffer[ETHER_HEADER_LEN + 19] as u32) << 24 + | (buffer[ETHER_HEADER_LEN + 18] as u32) << 16 + | (buffer[ETHER_HEADER_LEN + 17] as u32) << 8 + | (buffer[ETHER_HEADER_LEN + 16] as u32); + arp.arp_pa.sin_addr = dst_ip; + arp.arp_dev[0..9].copy_from_slice(name.as_bytes()); + // SIOCGARP + if sys_ioctl(arp_fd as usize, 0x8954, &arp as *const ArpReq as usize) < 0 { + println!("dst ip not in arp table, skipping"); + continue; + } + + let message = format!("from {}.{}.{}.{} {:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X} to {}.{}.{}.{} {:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X} dev {}:{} with ttl {}", buffer[ETHER_HEADER_LEN + 12], + buffer[ETHER_HEADER_LEN+ 13], + buffer[ETHER_HEADER_LEN+ 14], + buffer[ETHER_HEADER_LEN+ 15], + mac[0], + mac[1], + mac[2], + mac[3], + mac[4], + mac[5], + buffer[ETHER_HEADER_LEN+ 16], + buffer[ETHER_HEADER_LEN+ 17], + buffer[ETHER_HEADER_LEN+ 18], + buffer[ETHER_HEADER_LEN+ 19], + arp.arp_ha.sha_data[0], + arp.arp_ha.sha_data[1], + arp.arp_ha.sha_data[2], + arp.arp_ha.sha_data[3], + arp.arp_ha.sha_data[4], + arp.arp_ha.sha_data[5], + out_if, + name, + ttl, + ); + println!("{}", message); + + // fill dst and src mac + // todo: get mac from if instead of hard coding + buffer[0..6].copy_from_slice(&arp.arp_ha.sha_data[0..6]); + buffer[6..12].copy_from_slice(mac); + buffer[ETHER_HEADER_LEN + 8] = ttl - 1; + let checksum = (buffer[ETHER_HEADER_LEN + 10] as u16) << 8 + | (buffer[ETHER_HEADER_LEN + 11] as u16); + buffer[ETHER_HEADER_LEN + 10] = ((checksum + 0x0100) >> 8) as u8; + buffer[ETHER_HEADER_LEN + 11] = (checksum + 0x0100) as u8; + addr.sll_ifindex = *out_if; + sys_sendto( + packet_fd as usize, + buffer.as_ptr(), + len as usize + ETHER_HEADER_LEN, + 0, + &addr as *const SockAddrLl as usize, + size_of::(), + ); + } + None => continue, + } } } } diff --git a/rust/src/io.rs b/rust/src/io.rs index 370101b..21bd6f3 100644 --- a/rust/src/io.rs +++ b/rust/src/io.rs @@ -194,8 +194,8 @@ impl fmt::Write for StdOut { 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: + // 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 \ No newline at end of file +pub const O_APPEND: usize = 0x00000020; // append on each write diff --git a/rust/src/lang_items.rs b/rust/src/lang_items.rs index 878a046..1900d18 100644 --- a/rust/src/lang_items.rs +++ b/rust/src/lang_items.rs @@ -1,9 +1,9 @@ use crate::syscall::sys_exit; use crate::ALLOCATOR; +use super::syscall::*; use core::alloc::Layout; use core::panic::PanicInfo; -use super::syscall::*; #[linkage = "weak"] #[no_mangle] @@ -14,7 +14,9 @@ fn main() { fn init_heap() { const HEAP_SIZE: usize = 0x1000; static mut HEAP: [u8; HEAP_SIZE] = [0; HEAP_SIZE]; - unsafe { ALLOCATOR.lock().init(HEAP.as_ptr() as usize, HEAP_SIZE); } + unsafe { + ALLOCATOR.lock().init(HEAP.as_ptr() as usize, HEAP_SIZE); + } } /// MIPS use __start for entry point instead of _start diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 1b22e9a..e345aba 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -10,10 +10,10 @@ extern crate alloc; #[macro_use] pub mod io; -pub mod syscall; pub mod lang_items; +pub mod syscall; use buddy_system_allocator::LockedHeap; #[global_allocator] -static ALLOCATOR: LockedHeap = LockedHeap::empty(); \ No newline at end of file +static ALLOCATOR: LockedHeap = LockedHeap::empty(); diff --git a/rust/src/syscall.rs b/rust/src/syscall.rs index 94f4387..6f7d378 100644 --- a/rust/src/syscall.rs +++ b/rust/src/syscall.rs @@ -2,37 +2,45 @@ use crate::ALLOCATOR; use alloc::string::String; #[inline(always)] -fn sys_call(syscall_id: SyscallId, arg0: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) -> i32 { +fn sys_call( + syscall_id: SyscallId, + arg0: usize, + arg1: usize, + arg2: usize, + arg3: usize, + arg4: usize, + arg5: usize, +) -> i32 { let id = syscall_id as usize; let ret: i32; unsafe { #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - asm!("ecall" + asm!("ecall" : "={x10}" (ret) : "{x17}" (id), "{x10}" (arg0), "{x11}" (arg1), "{x12}" (arg2), "{x13}" (arg3), "{x14}" (arg4), "{x15}" (arg5) : "memory" : "volatile"); #[cfg(target_arch = "x86")] - asm!("int 0x80" + asm!("int 0x80" : "={eax}" (ret) : "{eax}" (id), "{edx}" (arg0), "{ecx}" (arg1), "{ebx}" (arg2), "{edi}" (arg3), "{esi}" (arg4) : "memory" : "intel" "volatile"); #[cfg(target_arch = "x86_64")] - asm!("syscall" + asm!("syscall" : "={rax}" (ret) : "{rax}" (id), "{rdi}" (arg0), "{rsi}" (arg1), "{rdx}" (arg2), "{r10}" (arg3), "{r8}" (arg4), "{r9}" (arg5) : "rcx" "r11" "memory" : "intel" "volatile"); #[cfg(target_arch = "aarch64")] - asm!("svc 0" + asm!("svc 0" : "={x0}" (ret) : "{x8}" (id), "{x0}" (arg0), "{x1}" (arg1), "{x2}" (arg2), "{x3}" (arg3), "{x4}" (arg4), "{x5}" (arg5) : "memory" : "volatile"); #[cfg(target_arch = "mips")] - asm!("syscall" + asm!("syscall" : "={v0}" (ret) : "{t0}" (id), "{a0}" (arg0), "{a1}" (arg1), "{a2}" (arg2), "{a3}" (arg3), "{s0}" (arg4), "{s1}" (arg5) : "memory" @@ -44,7 +52,9 @@ fn sys_call(syscall_id: SyscallId, arg0: usize, arg1: usize, arg2: usize, arg3: pub fn enlarge_heap() { const HEAP_SIZE: usize = 16 * 1024 * 1024; let addr = sys_mmap(0, HEAP_SIZE, 0x3, 0x22, 0, 0) as usize; - unsafe { ALLOCATOR.lock().init(addr, HEAP_SIZE); } + unsafe { + ALLOCATOR.lock().init(addr, HEAP_SIZE); + } } pub fn sys_exit(code: usize) -> ! { @@ -52,9 +62,16 @@ pub fn sys_exit(code: usize) -> ! { unreachable!() } - pub fn sys_exec(name: *const u8, argv: *const *const u8, envp: *const *const u8) -> i32 { - sys_call(SyscallId::Exec, name as usize, argv as usize, envp as usize, 0, 0, 0) + sys_call( + SyscallId::Exec, + name as usize, + argv as usize, + envp as usize, + 0, + 0, + 0, + ) } pub fn sys_write(fd: usize, base: *const u8, len: usize) -> i32 { @@ -71,7 +88,15 @@ pub fn sys_open(path: &str, flags: usize) -> i32 { let end = unsafe { &mut *(path.as_ptr().offset(path.len() as isize) as *mut u8) }; let backup = replace(end, 0); const AT_FDCWD: isize = -100; - let ret = sys_call(SyscallId::Openat, AT_FDCWD as usize, path.as_ptr() as usize, flags, 0, 0, 0); + let ret = sys_call( + SyscallId::Openat, + AT_FDCWD as usize, + path.as_ptr() as usize, + flags, + 0, + 0, + 0, + ); *end = backup; ret } @@ -95,7 +120,15 @@ pub fn sys_vfork() -> i32 { const CLONE_VFORK: usize = 0x00004000; const CLONE_VM: usize = 0x00000100; const SIGCHILD: usize = 17; - sys_call(SyscallId::Clone, CLONE_VFORK | CLONE_VM | SIGCHILD, sp, 0, 0, 0, 0) + sys_call( + SyscallId::Clone, + CLONE_VFORK | CLONE_VM | SIGCHILD, + sp, + 0, + 0, + 0, + 0, + ) } /// Wait the process exit. @@ -128,13 +161,29 @@ pub fn sys_getcwd() -> String { /// Change the current working directory pub fn sys_chdir(path: &str) { let path = String::from(path) + "\0"; - sys_call(SyscallId::Chdir, path.as_bytes().as_ptr() as usize, 0, 0, 0, 0, 0); + sys_call( + SyscallId::Chdir, + path.as_bytes().as_ptr() as usize, + 0, + 0, + 0, + 0, + 0, + ); } /// Check file accessibility pub fn sys_access(path: &str) -> i32 { let path = String::from(path) + "\0"; - sys_call(SyscallId::FAccessAt, -100isize as usize, path.as_bytes().as_ptr() as usize, 0, 0, 0, 0) + sys_call( + SyscallId::FAccessAt, + -100isize as usize, + path.as_bytes().as_ptr() as usize, + 0, + 0, + 0, + 0, + ) } #[repr(C)] @@ -147,9 +196,17 @@ pub struct TimeSpec { pub fn sys_sleep(time: usize) -> i32 { let ts = TimeSpec { sec: time as u64, - nsec: 0 + nsec: 0, }; - sys_call(SyscallId::Sleep, &ts as *const TimeSpec as usize, 0, 0, 0, 0, 0) + sys_call( + SyscallId::Sleep, + &ts as *const TimeSpec as usize, + 0, + 0, + 0, + 0, + 0, + ) } pub fn sys_get_time() -> i32 { @@ -170,10 +227,25 @@ pub fn sys_map_pci_device(vendor: usize, product: usize) -> i32 { pub fn sys_get_paddr(vaddr: &[u64], paddr: &mut [u64]) -> i32 { assert_eq!(vaddr.len(), paddr.len()); - sys_call(SyscallId::GetPaddr, vaddr.as_ptr() as usize, paddr.as_ptr() as usize, vaddr.len(), 0, 0, 0) + sys_call( + SyscallId::GetPaddr, + vaddr.as_ptr() as usize, + paddr.as_ptr() as usize, + vaddr.len(), + 0, + 0, + 0, + ) } -pub fn sys_mmap(addr: usize, len: usize, prot: usize, flags: usize, fd: usize, offset: usize) -> i32 { +pub fn sys_mmap( + addr: usize, + len: usize, + prot: usize, + flags: usize, + fd: usize, + offset: usize, +) -> i32 { sys_call(SyscallId::Mmap, addr, len, prot, flags, fd, offset) } @@ -185,8 +257,23 @@ pub fn sys_setsockopt(fd: usize, level: usize, opt: usize, optval: usize, optlen sys_call(SyscallId::SetSockOpt, fd, level, opt, optval, optlen, 0) } -pub fn sys_sendto(fd: usize, base: *const u8, len: usize, flags: usize, addr: usize, addr_len: usize) -> i32 { - sys_call(SyscallId::SendTo, fd, base as usize, len, flags, addr, addr_len) +pub fn sys_sendto( + fd: usize, + base: *const u8, + len: usize, + flags: usize, + addr: usize, + addr_len: usize, +) -> i32 { + sys_call( + SyscallId::SendTo, + fd, + base as usize, + len, + flags, + addr, + addr_len, + ) } pub fn sys_ioctl(fd: usize, request: usize, arg1: usize) -> i32 { From 77dd4b1e805521c0cc5c23199a462b9913900347 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Sun, 7 Apr 2019 12:06:21 +0800 Subject: [PATCH 14/39] Bump treebitmap version --- rust/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index ffa716a..1b3e65a 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -84,7 +84,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "treebitmap" version = "0.3.1" -source = "git+https://github.com/jiegec/treebitmap#9c0ddcfaed0c960fb86a66c2b5abb5af70d6f1d1" +source = "git+https://github.com/jiegec/treebitmap#a89d725c1308719e327993dc5c5c0357c43dccf1" [[package]] name = "volatile" From c730e9c8dafe86ab18657ac388ac76143e5ad71c Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 7 Apr 2019 16:10:09 +0800 Subject: [PATCH 15/39] Use MIPS N32 abi in all user programs Signed-off-by: Harry Chen --- biscuit/CMakeLists.txt | 1 + biscuit/c/usertests.c | 12 ++++++++---- iperf3/Makefile | 10 ++++++++-- nginx/Makefile | 10 ++++++++-- redis/Makefile | 10 ++++++++-- rust/src/syscall.rs | 14 +++++++++++--- ucore/CMakeLists.txt | 2 +- ucore/src/ulibs/syscall.c | 16 ++++++++++++++++ 8 files changed, 61 insertions(+), 14 deletions(-) diff --git a/biscuit/CMakeLists.txt b/biscuit/CMakeLists.txt index 30a518d..a95a3b2 100644 --- a/biscuit/CMakeLists.txt +++ b/biscuit/CMakeLists.txt @@ -34,6 +34,7 @@ elseif (${ARCH} STREQUAL riscv64) set(CMAKE_C_FLAGS "-march=rv64imafdc -mabi=lp64d -mcmodel=medany") elseif (${ARCH} STREQUAL aarch64) elseif (${ARCH} STREQUAL mipsel) + set(PREFIX ${ARCH}-linux-musln32-) else () message("Unsupported arch: ${ARCH}") endif () diff --git a/biscuit/c/usertests.c b/biscuit/c/usertests.c index 9faceca..42c7a47 100644 --- a/biscuit/c/usertests.c +++ b/biscuit/c/usertests.c @@ -2798,15 +2798,17 @@ static volatile int go; static void *_locker(void *v) { - while (go != 1) + while (go != 1) { #if defined(__x86_64__) asm volatile("pause\n":::"memory"); #elif defined(__aarch64__) asm volatile("yield\n":::"memory"); +#elif defined(__mips__) || defined(__riscv32__) || defined(__riscv64__) + asm volatile("nop\n":::"memory"); #else #warning Yield instruction is not implemented - {} #endif + } pthread_mutex_t *m = (pthread_mutex_t *)v; int i; @@ -2921,15 +2923,17 @@ static void _condtest(const int nt) go = 0; if (pthread_create(&t[i], NULL, _condsleep, &args[i])) errx(-1, "pthread_ create"); - while (go == 0) + while (go == 0) { #if defined(__x86_64__) asm volatile("pause\n":::"memory"); #elif defined(__aarch64__) asm volatile("yield\n":::"memory"); +#elif defined(__mips__) || defined(__riscv32__) || defined(__riscv64__) + asm volatile("nop\n":::"memory"); #else #warning Yield instruction is not implemented - {} #endif + } } for (i = 0; i < nt; i++) diff --git a/iperf3/Makefile b/iperf3/Makefile index 15f34d3..1b6b0b2 100644 --- a/iperf3/Makefile +++ b/iperf3/Makefile @@ -3,11 +3,17 @@ iperf3_tarball := iperf3-$(iperf3_version).tar.gz iperf3_tarball_path := src/$(iperf3_tarball) build_dir := build/$(arch) iperf3_dir := $(build_dir)/iperf-$(iperf3_version) -cc := $(arch)-linux-musl-gcc -strip := $(arch)-linux-musl-strip +prefix := $(arch)-linux-musl- bin_unstripped := build/$(arch)/iperf3_unstripped bin := build/$(arch)/iperf3 +ifeq ($(arch), mipsel) + prefix := mipsel-linux-musln32- +endif + +cc := $(prefix)gcc +strip := $(prefix)strip + $(iperf3_tarball_path): wget https://github.com/esnet/iperf/archive/$(iperf3_version).tar.gz -O $(iperf3_tarball_path) diff --git a/nginx/Makefile b/nginx/Makefile index efe57d9..de22b74 100644 --- a/nginx/Makefile +++ b/nginx/Makefile @@ -3,11 +3,17 @@ nginx_tarball := nginx-$(nginx_version).tar.gz nginx_tarball_path := src/nginx-$(nginx_version).tar.gz build_dir := build/$(arch) nginx_dir := $(build_dir)/nginx-$(nginx_version) -cc := $(arch)-linux-musl-gcc -strip := $(arch)-linux-musl-strip +prefix := $(arch)-linux-musl- bin_unstripped := build/$(arch)/nginx_unstripped bin := build/$(arch)/nginx +ifeq ($(arch), mipsel) + prefix := mipsel-linux-musln32- +endif + +cc := $(prefix)gcc +strip := $(prefix)strip + $(nginx_tarball_path): wget https://nginx.org/download/$(nginx_tarball) -O $(nginx_tarball_path) diff --git a/redis/Makefile b/redis/Makefile index dd82ade..c25e3d2 100644 --- a/redis/Makefile +++ b/redis/Makefile @@ -3,13 +3,19 @@ redis_tarball := redis-$(redis_version).tar.gz redis_tarball_path := src/redis-$(redis_version).tar.gz build_dir := build/$(arch) redis_dir := $(build_dir)/redis-$(redis_version) -cc := $(arch)-linux-musl-gcc -strip := $(arch)-linux-musl-strip +prefix := $(arch)-linux-musl- bin_server_unstripped := build/$(arch)/redis-server-unstripped bin_server := build/$(arch)/redis-server bin_cli_unstripped := build/$(arch)/redis-cli-unstripped bin_cli := build/$(arch)/redis-cli +ifeq ($(arch), mipsel) + prefix := mipsel-linux-musln32- +endif + +cc := $(prefix)gcc +strip := $(prefix)strip + # $ARCH is also used in redis internal Makefile, avoid clashing undefine ARCH diff --git a/rust/src/syscall.rs b/rust/src/syscall.rs index 94f4387..9e012b7 100644 --- a/rust/src/syscall.rs +++ b/rust/src/syscall.rs @@ -4,7 +4,8 @@ use alloc::string::String; #[inline(always)] fn sys_call(syscall_id: SyscallId, arg0: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) -> i32 { let id = syscall_id as usize; - let ret: i32; + let mut ret: i32; + let mut failed: i32 = 0; unsafe { #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] @@ -32,11 +33,18 @@ fn sys_call(syscall_id: SyscallId, arg0: usize, arg1: usize, arg2: usize, arg3: : "memory" : "volatile"); #[cfg(target_arch = "mips")] + { asm!("syscall" - : "={v0}" (ret) - : "{t0}" (id), "{a0}" (arg0), "{a1}" (arg1), "{a2}" (arg2), "{a3}" (arg3), "{s0}" (arg4), "{s1}" (arg5) + // v0 for syscall id + : "={$2}" (ret), "={$7}" (failed) + // v0, a0, a1, a2, a3, a4, a5 + : "{$2}" (id), "{$4}" (arg0), "{$5}" (arg1), "{$6}" (arg2), "{$7}" (arg3), "{$8}" (arg4), "{$9}" (arg5) : "memory" : "volatile"); + if failed != 0 { + ret = - ret; + } + } } ret } diff --git a/ucore/CMakeLists.txt b/ucore/CMakeLists.txt index 3cdce4a..6c53058 100644 --- a/ucore/CMakeLists.txt +++ b/ucore/CMakeLists.txt @@ -36,7 +36,7 @@ elseif (${ARCH} STREQUAL aarch64) endif () set(CMAKE_C_FLAGS "-mgeneral-regs-only") elseif (${ARCH} STREQUAL mipsel) - set(PREFIX mipsel-linux-musl-) + set(PREFIX ${ARCH}-linux-musln32-) else() message("Unsupported arch: ${ARCH}") endif () diff --git a/ucore/src/ulibs/syscall.c b/ucore/src/ulibs/syscall.c index bddd1ed..59aa563 100644 --- a/ucore/src/ulibs/syscall.c +++ b/ucore/src/ulibs/syscall.c @@ -65,6 +65,22 @@ syscall(int num, ...) { "m" (a[4]) : "cc", "memory" ); +#elif defined(__mips__) +// mips n32 abi + register long a0 __asm__("$4") = a[0]; + register long a1 __asm__("$5") = a[1]; + register long a2 __asm__("$6") = a[2]; + register long a3 __asm__("$7") = a[3]; + register long a4 __asm__("$8") = a[4]; + register long a5 __asm__("$9") = a[5]; + register long v0 __asm__("$2"); + __asm__ __volatile__ ( + "addu $2,$0,%2 ; syscall" + : "=&r"(v0), "=r"(a3) + : "ir"(num), "0"(v0), "1"(a3), "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5) + : "$1", "$3", "$10", "$11", "$12", "$13", + "$14", "$15", "$24", "$25", "hi", "lo", "memory"); + ret = a3 ? -v0 : v0; #endif return ret; } From a2985b6e80b14996bb7c767d2c202d237e82aa0d Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 7 Apr 2019 17:54:52 +0800 Subject: [PATCH 16/39] Use syscall numbers from o32 ABI (which musl uses) Signed-off-by: Harry Chen --- rust/src/syscall.rs | 43 +++++++++++++++++++++++++++++++++++++++-- ucore/src/libs/unistd.h | 29 +++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/rust/src/syscall.rs b/rust/src/syscall.rs index d743b69..7647d64 100644 --- a/rust/src/syscall.rs +++ b/rust/src/syscall.rs @@ -13,7 +13,7 @@ fn sys_call( ) -> i32 { let id = syscall_id as usize; let mut ret: i32; - let mut failed: i32 = 0; + let failed: i32; unsafe { #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] @@ -325,7 +325,46 @@ enum SyscallId { GetPaddr = 998, } -#[cfg(not(target_arch = "x86_64"))] +// only for mips N32 abi +// see https://git.linux-mips.org/cgit/ralf/linux.git/tree/arch/mips/include/uapi/asm/unistd.h +#[cfg(target_arch = "mips")] +#[allow(dead_code)] +enum SyscallId { + Read = 4003, + Write = 4004, + Close = 4006, + Fstat = 4198, + Seek = 4018, + Mmap = 4090, + Munmap = 4091, + Ioctl = 4054, + Yield = 4162, + Sleep = 4166, + GetPid = 4020, + Socket = 4183, + SendTo = 4180, + SetSockOpt = 4181, + Clone = 4120, + Exec = 4011, + Exit = 4001, + Wait = 4007, + Kill = 4037, + Fsync = 4118, + GetCwd = 4203, + Chdir = 4012, + GetTime = 4078, + SetPriority = 4097, + ArchPrctl = -1, + GetDirEntry64 = 4219, + Openat = 4288, + FAccessAt = 4300, + Dup3 = 4327, + // custom + MapPciDevice = 999, + GetPaddr = 998, +} + +#[cfg(any(all(target_arch = "x86_64", target_arch = "mips")))] #[allow(dead_code)] enum SyscallId { Read = 63, diff --git a/ucore/src/libs/unistd.h b/ucore/src/libs/unistd.h index 1e2e833..088237e 100644 --- a/ucore/src/libs/unistd.h +++ b/ucore/src/libs/unistd.h @@ -33,6 +33,35 @@ /* ONLY FOR LAB6 */ #define SYS_set_priority 141 +#elif defined(__mips__) +#define MIPS_SYSCALL 6000 +#define SYS_exit (MIPS_SYSCALL + 1) +#define SYS_fork (MIPS_SYSCALL + 2) +#define SYS_wait (MIPS_SYSCALL + 7) +#define SYS_exec (MIPS_SYSCALL + 11) +#define SYS_clone (MIPS_SYSCALL + 120) +#define SYS_yield (MIPS_SYSCALL + 162) +#define SYS_sleep (MIPS_SYSCALL + 166) +#define SYS_kill (MIPS_SYSCALL + 37) +#define SYS_gettime (MIPS_SYSCALL + 78) +#define SYS_getpid (MIPS_SYSCALL + 20) +#define SYS_mmap (MIPS_SYSCALL + 90) +#define SYS_munmap (MIPS_SYSCALL + 91) +#define SYS_shmem (-1) +#define SYS_pgdir (-1) +#define SYS_openat (MIPS_SYSCALL + 288) +#define SYS_close (MIPS_SYSCALL + 6) +#define SYS_read (MIPS_SYSCALL + 3) +#define SYS_write (MIPS_SYSCALL + 4) +#define SYS_seek (MIPS_SYSCALL + 18) +#define SYS_fstat (MIPS_SYSCALL + 198) +#define SYS_fsync (MIPS_SYSCALL + 118) +#define SYS_getcwd (MIPS_SYSCALL + 203) +#define SYS_getdirentry64 (MIPS_SYSCALL + 219) +#define SYS_dup3 (MIPS_SYSCALL + 327) +/* ONLY FOR LAB6 */ +#define SYS_set_priority 141 + #else #define SYS_exit 93 From 215b8c52b33ef5f31935fe6be1abec57b64d8866 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 7 Apr 2019 18:58:42 +0800 Subject: [PATCH 17/39] Fix WAIT syscall number for mipsel Signed-off-by: Harry Chen --- rust/src/syscall.rs | 2 +- ucore/src/libs/unistd.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/src/syscall.rs b/rust/src/syscall.rs index 7647d64..80a82f1 100644 --- a/rust/src/syscall.rs +++ b/rust/src/syscall.rs @@ -347,7 +347,7 @@ enum SyscallId { Clone = 4120, Exec = 4011, Exit = 4001, - Wait = 4007, + Wait = 4114, Kill = 4037, Fsync = 4118, GetCwd = 4203, diff --git a/ucore/src/libs/unistd.h b/ucore/src/libs/unistd.h index 088237e..03d7b22 100644 --- a/ucore/src/libs/unistd.h +++ b/ucore/src/libs/unistd.h @@ -37,7 +37,7 @@ #define MIPS_SYSCALL 6000 #define SYS_exit (MIPS_SYSCALL + 1) #define SYS_fork (MIPS_SYSCALL + 2) -#define SYS_wait (MIPS_SYSCALL + 7) +#define SYS_wait (MIPS_SYSCALL + 114) #define SYS_exec (MIPS_SYSCALL + 11) #define SYS_clone (MIPS_SYSCALL + 120) #define SYS_yield (MIPS_SYSCALL + 162) From 07619a48d4e8051766c294d9d616337869e4c1a0 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 7 Apr 2019 23:44:01 +0800 Subject: [PATCH 18/39] Fix mips syscall number Signed-off-by: Harry Chen --- ucore/src/libs/unistd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ucore/src/libs/unistd.h b/ucore/src/libs/unistd.h index 03d7b22..0298890 100644 --- a/ucore/src/libs/unistd.h +++ b/ucore/src/libs/unistd.h @@ -34,7 +34,7 @@ #define SYS_set_priority 141 #elif defined(__mips__) -#define MIPS_SYSCALL 6000 +#define MIPS_SYSCALL 4000 #define SYS_exit (MIPS_SYSCALL + 1) #define SYS_fork (MIPS_SYSCALL + 2) #define SYS_wait (MIPS_SYSCALL + 114) From aeea2b569efe90e38b39d3c72edb4bc015837d14 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 8 Apr 2019 22:30:37 +0800 Subject: [PATCH 19/39] Update ucore/forktest to fit rcore convention. --- ucore/src/forktest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ucore/src/forktest.c b/ucore/src/forktest.c index 3eda228..8227622 100644 --- a/ucore/src/forktest.c +++ b/ucore/src/forktest.c @@ -19,12 +19,12 @@ main(void) { } for (; n > 0; n --) { - if (wait() != 0) { + if (wait() <= 0) { panic("wait stopped early\n"); } } - if (wait() == 0) { + if (wait() > 0) { panic("wait got too many\n"); } From 4de7713835faf6e1845a8e060254e446fbdfee03 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 8 Apr 2019 23:30:19 +0800 Subject: [PATCH 20/39] Fix ucore/matrix. --- ucore/src/matrix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ucore/src/matrix.c b/ucore/src/matrix.c index c5ec869..7bd203f 100644 --- a/ucore/src/matrix.c +++ b/ucore/src/matrix.c @@ -64,7 +64,7 @@ main(void) { cprintf("fork ok.\n"); for (i = 0; i < total; i ++) { - if (wait() != 0) { + if (wait() <= 0) { cprintf("wait failed.\n"); goto failed; } From 2c80f1e46fbd6808b80bee9b7fbbb24c11afd29d Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 8 Apr 2019 23:42:19 +0800 Subject: [PATCH 21/39] Update ucore/exit for rcore. --- ucore/src/exit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ucore/src/exit.c b/ucore/src/exit.c index c3ac5f8..d72c05e 100644 --- a/ucore/src/exit.c +++ b/ucore/src/exit.c @@ -24,8 +24,8 @@ main(void) { assert(pid > 0); cprintf("I am the parent, waiting now..\n"); - assert(waitpid(pid, &code) == 0 && code == magic); - assert(waitpid(pid, &code) != 0 && wait() != 0); + assert(waitpid(pid, &code) > 0 && code == magic); + assert(waitpid(pid, &code) <= 0 && wait() <= 0); cprintf("waitpid %d ok.\n", pid); cprintf("exit pass.\n"); From fdaa1be8635944d88ff128da13bf0464f7ce2eb6 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 9 Apr 2019 12:21:46 +0800 Subject: [PATCH 22/39] Fix syscall and add mipsel to travis CI Signed-off-by: Harry Chen --- .travis.yml | 16 +++++++++++++--- rust/src/syscall.rs | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index dad0dc3..8e59c0f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,7 @@ env: - ARCH="aarch64" SRC="all" - ARCH="riscv32" SRC="all" - ARCH="riscv64" SRC="all" + - ARCH="mipsel" SRC="all" matrix: allow_failures: @@ -42,7 +43,7 @@ install: if [ $TRAVIS_OS_NAME = linux ]; then export FILE="gcc-arm-8.2-2018.11-x86_64-aarch64-elf"; wget https://developer.arm.com/-/media/Files/downloads/gnu-a/8.2-2018.11/$FILE.tar.xz; - tar -xvf $FILE.tar.xz; + tar -xf $FILE.tar.xz; export PATH=$PATH:$PWD/$FILE/bin; sudo apt update; sudo apt install linux-headers-$(uname -r); @@ -73,7 +74,7 @@ install: sudo apt update; sudo apt install linux-headers-$(uname -r); wget https://musl.cc/riscv32-linux-musl-cross.tgz; - tar -xvf riscv32-linux-musl-cross.tgz; + tar -xf riscv32-linux-musl-cross.tgz; export PATH=$PATH:$PWD/riscv32-linux-musl-cross/bin; fi; fi @@ -82,10 +83,19 @@ install: sudo apt update; sudo apt install linux-headers-$(uname -r); wget https://musl.cc/riscv64-linux-musl-cross.tgz; - tar -xvf riscv64-linux-musl-cross.tgz; + tar -xf riscv64-linux-musl-cross.tgz; export PATH=$PATH:$PWD/riscv64-linux-musl-cross/bin; fi; fi + - if [ $ARCH = mipsel ]; then + if [ $TRAVIS_OS_NAME = linux ]; then + sudo apt update; + sudo apt install linux-headers-$(uname -r); + wget https://musl.cc/mipsel-linux-musln32-cross.tgz; + tar -xvf mipsel-linux-musln32-cross.tgz; + export PATH=$PATH:$PWD/mipsel-linux-musln32-cross/bin; + fi; + fi before_script: diff --git a/rust/src/syscall.rs b/rust/src/syscall.rs index 80a82f1..18dc2bd 100644 --- a/rust/src/syscall.rs +++ b/rust/src/syscall.rs @@ -364,7 +364,7 @@ enum SyscallId { GetPaddr = 998, } -#[cfg(any(all(target_arch = "x86_64", target_arch = "mips")))] +#[cfg(not(any(target_arch = "x86_64", target_arch = "mips")))] #[allow(dead_code)] enum SyscallId { Read = 63, From a9bc66382c69b402ca61d9b11fffa1b69ad6963d Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 15 Apr 2019 14:15:12 +0800 Subject: [PATCH 23/39] Support TLS for MIPS. --- rust/src/bin/tls.rs | 9 +++++++++ rust/src/syscall.rs | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/rust/src/bin/tls.rs b/rust/src/bin/tls.rs index 631bf0f..d0135a0 100644 --- a/rust/src/bin/tls.rs +++ b/rust/src/bin/tls.rs @@ -7,6 +7,9 @@ extern crate rcore_user; use rcore_user::syscall::{sys_arch_prctl, sys_getpid, sys_sleep, sys_vfork}; +#[cfg(target_arch = "mips")] +use rcore_user::syscall::sys_set_theaad_area; + fn set_tls(tls: usize, pid: usize) { #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] unsafe { @@ -23,6 +26,8 @@ fn set_tls(tls: usize, pid: usize) { // set fs base sys_arch_prctl(0x1002, &DATA[pid] as *const usize as usize); } + #[cfg(target_arch = "mips")] + sys_set_theaad_area(tls); } fn get_tls() -> usize { @@ -39,6 +44,10 @@ fn get_tls() -> usize { unsafe { asm!("mov %fs:0, $0" : "=r"(tls) :); } + #[cfg(target_arch = "mips")] + unsafe { + asm!("rdhwr $0, $$29" : "=r"(tls) :); + } tls } diff --git a/rust/src/syscall.rs b/rust/src/syscall.rs index 80a82f1..78ab96d 100644 --- a/rust/src/syscall.rs +++ b/rust/src/syscall.rs @@ -325,6 +325,11 @@ enum SyscallId { GetPaddr = 998, } +#[cfg(target_arch = "mips")] +pub fn sys_set_theaad_area(tls: usize) { + sys_call(SyscallId::SetThreadArea, tls, 0, 0, 0, 0, 0); +} + // only for mips N32 abi // see https://git.linux-mips.org/cgit/ralf/linux.git/tree/arch/mips/include/uapi/asm/unistd.h #[cfg(target_arch = "mips")] @@ -354,6 +359,7 @@ enum SyscallId { Chdir = 4012, GetTime = 4078, SetPriority = 4097, + SetThreadArea = 4283, ArchPrctl = -1, GetDirEntry64 = 4219, Openat = 4288, @@ -364,7 +370,7 @@ enum SyscallId { GetPaddr = 998, } -#[cfg(any(all(target_arch = "x86_64", target_arch = "mips")))] +#[cfg(not(any(target_arch = "x86_64", target_arch = "mips")))] #[allow(dead_code)] enum SyscallId { Read = 63, From 836a007de9a9eb00a222ddb05974df411bafc7e5 Mon Sep 17 00:00:00 2001 From: Yuhao Zhou Date: Mon, 15 Apr 2019 18:08:05 +0800 Subject: [PATCH 24/39] Fix off_t in mipsn32. --- biscuit/c/ls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biscuit/c/ls.c b/biscuit/c/ls.c index 293b48d..2423fc2 100644 --- a/biscuit/c/ls.c +++ b/biscuit/c/ls.c @@ -34,7 +34,7 @@ void dprint(int fd, char *par, int left, int rec) spec = 's'; else spec = '-'; - printf("%crwxr-xr-x %ld %s\n", spec, st.st_size, de->d_name); + printf("%crwxr-xr-x %ld %s\n", spec, (long)st.st_size, de->d_name); } if (!rec) { if (closedir(dir) == -1) From 8dbc0edb935a62d748aaac39258d4a985de0ae17 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Wed, 17 Apr 2019 07:59:22 +0800 Subject: [PATCH 25/39] Disable biscuit for Darwin-riscv32 --- Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 9184610..d961b32 100644 --- a/Makefile +++ b/Makefile @@ -44,15 +44,13 @@ ucore: @cp $(ucore_bin_path)/* $(out_dir)/ucore biscuit: -ifneq ($(shell uname)-$(arch), Darwin-riscv64) -ifneq ($(shell uname)-$(arch), Darwin-aarch64) +ifneq ($(shell uname)-$(arch), Darwin-$(filter $(arch), riscv32 riscv64 aarch64)) @echo Building biscuit programs @mkdir -p biscuit/build @cd biscuit/build && cmake $(cmake_build_args) .. && make @rm -rf $(out_dir)/biscuit && mkdir -p $(out_dir)/biscuit @cp $(biscuit_bin_path)/* $(out_dir)/biscuit endif -endif $(busybox): ifeq ($(arch), x86_64) From 633b28f273eba81e7524e43e554cab36d9f99bf5 Mon Sep 17 00:00:00 2001 From: chyyuu Date: Sat, 20 Apr 2019 09:47:53 +0800 Subject: [PATCH 26/39] add little source codes and compiled .o, .exe codes from alpine linux for testing --- testsuits_alpine/HelloWorld.class | Bin 0 -> 425 bytes testsuits_alpine/HelloWorld.java | 6 + testsuits_alpine/brk.c | 27 ++ testsuits_alpine/brk2.c | 18 ++ testsuits_alpine/build.sh | 10 + testsuits_alpine/dlmain | Bin 0 -> 18568 bytes testsuits_alpine/dlmain.c | 6 + testsuits_alpine/dlmain.o | Bin 0 -> 1392 bytes testsuits_alpine/env.c | 26 ++ testsuits_alpine/env1 | Bin 0 -> 18888 bytes testsuits_alpine/env1.c | 26 ++ testsuits_alpine/env1.i | 490 ++++++++++++++++++++++++++++++ testsuits_alpine/env1.o | Bin 0 -> 2608 bytes testsuits_alpine/env1.s | 94 ++++++ testsuits_alpine/env2 | Bin 0 -> 18760 bytes testsuits_alpine/env2.c | 25 ++ testsuits_alpine/env2.s | 243 +++++++++++++++ testsuits_alpine/func.c | 5 + testsuits_alpine/func.h | 5 + testsuits_alpine/func.o | Bin 0 -> 1520 bytes testsuits_alpine/hello.go | 5 + testsuits_alpine/hello.py | 1 + testsuits_alpine/libfunc.so | Bin 0 -> 17008 bytes testsuits_alpine/main.rs | 3 + testsuits_alpine/main_rs_static | Bin 0 -> 239248 bytes testsuits_alpine/map | Bin 0 -> 18792 bytes testsuits_alpine/map.c | 19 ++ testsuits_alpine/readfile | Bin 0 -> 18808 bytes testsuits_alpine/readfile.c | 16 + testsuits_alpine/stack | Bin 0 -> 18808 bytes testsuits_alpine/stack.c | 16 + 31 files changed, 1041 insertions(+) create mode 100644 testsuits_alpine/HelloWorld.class create mode 100644 testsuits_alpine/HelloWorld.java create mode 100644 testsuits_alpine/brk.c create mode 100644 testsuits_alpine/brk2.c create mode 100755 testsuits_alpine/build.sh create mode 100755 testsuits_alpine/dlmain create mode 100644 testsuits_alpine/dlmain.c create mode 100644 testsuits_alpine/dlmain.o create mode 100644 testsuits_alpine/env.c create mode 100755 testsuits_alpine/env1 create mode 100644 testsuits_alpine/env1.c create mode 100644 testsuits_alpine/env1.i create mode 100644 testsuits_alpine/env1.o create mode 100644 testsuits_alpine/env1.s create mode 100755 testsuits_alpine/env2 create mode 100644 testsuits_alpine/env2.c create mode 100644 testsuits_alpine/env2.s create mode 100644 testsuits_alpine/func.c create mode 100644 testsuits_alpine/func.h create mode 100644 testsuits_alpine/func.o create mode 100644 testsuits_alpine/hello.go create mode 100644 testsuits_alpine/hello.py create mode 100755 testsuits_alpine/libfunc.so create mode 100644 testsuits_alpine/main.rs create mode 100755 testsuits_alpine/main_rs_static create mode 100755 testsuits_alpine/map create mode 100644 testsuits_alpine/map.c create mode 100755 testsuits_alpine/readfile create mode 100644 testsuits_alpine/readfile.c create mode 100755 testsuits_alpine/stack create mode 100644 testsuits_alpine/stack.c diff --git a/testsuits_alpine/HelloWorld.class b/testsuits_alpine/HelloWorld.class new file mode 100644 index 0000000000000000000000000000000000000000..ec7eb393922200a5e85a574f6a42e6d7ec7dbab5 GIT binary patch literal 425 zcmZutO-sW-5Ph5GyV2Cv)X#z*gy_Lsyj8pi;-RPz(SxU?UCNeCA~6yCS$a_L;1BRe ziL>z#3hrTM_PsZ=Z}$7=^9#TUMlMYF4tiL#(RVSxx`n{Pkik3^xv0(`8!t0gFYd8&9uo{O4@;LnjL zq8qYPktv>JV}?O9V;N?!9+gPaE +#include +#include + +int main(int argc, char ** argv) +{ + int *curr_brk, *tmp_brk = NULL; + int num,i; + if(argc >1) { num=atoi(argv[1]);} + printf("Welcome to sbrk example:%d num %d\n", getpid(),num); + for(i=0;i +#include + +int main(void) { + void *b; + char *p, *end; + + b = sbrk(0); + p = (char *)b; + end = p + 0x1000000; + brk(end); + while (p < end) { + *(p++) = 1; + } + brk(b); + return 0; +} diff --git a/testsuits_alpine/build.sh b/testsuits_alpine/build.sh new file mode 100755 index 0000000..d56d777 --- /dev/null +++ b/testsuits_alpine/build.sh @@ -0,0 +1,10 @@ +gcc -c dlmain.c -o dlmain.o +gcc -c func.c -o func.o +cc -shared -fPIC func.c -o libfunc.so +gcc dlmain.c libfunc.so -o dlmain + +go build hello.go + +javac HelloWorld.java + +#java HelloWorld diff --git a/testsuits_alpine/dlmain b/testsuits_alpine/dlmain new file mode 100755 index 0000000000000000000000000000000000000000..5065f0ebef9d4c4a937a2fe63c142fe9286301af GIT binary patch literal 18568 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 TU1btkP<&i&>ZI%G5r6zQ!L3m; literal 0 HcmV?d00001 diff --git a/testsuits_alpine/env.c b/testsuits_alpine/env.c new file mode 100644 index 0000000..f606a33 --- /dev/null +++ b/testsuits_alpine/env.c @@ -0,0 +1,26 @@ +#include +#include +#include + +extern char **environ; +char **env ; +int main() +{ +env= environ; +while(*environ){ + puts(*environ); + environ++; +} + +char * p; +puts("----------------------\n"); +if((p=getenv("USER"))) +printf("USER =%s\n",p); +setenv("USER","test",1); +printf("USER=%s\n",getenv("USER")); +//unsetenv("USER"); +//printf("USER=%s\n",getenv("USER")); +char * argv[]={"env2", NULL}; +execve("./env2",argv,env); +return 0; +} diff --git a/testsuits_alpine/env1 b/testsuits_alpine/env1 new file mode 100755 index 0000000000000000000000000000000000000000..650eabceb3e0179bfec1903e4bd7e275e4179fa3 GIT binary patch literal 18888 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 +#include +#include + +extern char **environ; +char **env ; +int main() +{ +env= environ; +while(*environ){ + puts(*environ); + environ++; +} + +char * p; +puts("----------------------\n"); +if((p=getenv("USER"))) +printf("USER =%s\n",p); +setenv("USER","test",1); +printf("USER=%s\n",getenv("USER")); +//unsetenv("USER"); +//printf("USER=%s\n",getenv("USER")); +char * argv[]={"env2", NULL}; +execve("./env2",argv,env); +return 0; +} diff --git a/testsuits_alpine/env1.i b/testsuits_alpine/env1.i new file mode 100644 index 0000000..37475d7 --- /dev/null +++ b/testsuits_alpine/env1.i @@ -0,0 +1,490 @@ +# 1 "env1.c" +# 1 "" +# 1 "" +# 31 "" +# 1 "/usr/include/stdc-predef.h" 1 3 4 +# 32 "" 2 +# 1 "env1.c" +# 1 "/usr/include/stdlib.h" 1 3 4 + + + + + + + +# 1 "/usr/include/features.h" 1 3 4 +# 9 "/usr/include/stdlib.h" 2 3 4 +# 19 "/usr/include/stdlib.h" 3 4 +# 1 "/usr/include/bits/alltypes.h" 1 3 4 +# 18 "/usr/include/bits/alltypes.h" 3 4 + +# 18 "/usr/include/bits/alltypes.h" 3 4 +typedef int wchar_t; +# 101 "/usr/include/bits/alltypes.h" 3 4 +typedef unsigned long size_t; +# 20 "/usr/include/stdlib.h" 2 3 4 + +int atoi (const char *); +long atol (const char *); +long long atoll (const char *); +double atof (const char *); + +float strtof (const char *restrict, char **restrict); +double strtod (const char *restrict, char **restrict); +long double strtold (const char *restrict, char **restrict); + +long strtol (const char *restrict, char **restrict, int); +unsigned long strtoul (const char *restrict, char **restrict, int); +long long strtoll (const char *restrict, char **restrict, int); +unsigned long long strtoull (const char *restrict, char **restrict, int); + +int rand (void); +void srand (unsigned); + +void *malloc (size_t); +void *calloc (size_t, size_t); +void *realloc (void *, size_t); +void free (void *); +void *aligned_alloc(size_t, size_t); + +_Noreturn void abort (void); +int atexit (void (*) (void)); +_Noreturn void exit (int); +_Noreturn void _Exit (int); +int at_quick_exit (void (*) (void)); +_Noreturn void quick_exit (int); + +char *getenv (const char *); + +int system (const char *); + +void *bsearch (const void *, const void *, size_t, size_t, int (*)(const void *, const void *)); +void qsort (void *, size_t, size_t, int (*)(const void *, const void *)); + +int abs (int); +long labs (long); +long long llabs (long long); + +typedef struct { int quot, rem; } div_t; +typedef struct { long quot, rem; } ldiv_t; +typedef struct { long long quot, rem; } lldiv_t; + +div_t div (int, int); +ldiv_t ldiv (long, long); +lldiv_t lldiv (long long, long long); + +int mblen (const char *, size_t); +int mbtowc (wchar_t *restrict, const char *restrict, size_t); +int wctomb (char *, wchar_t); +size_t mbstowcs (wchar_t *restrict, const char *restrict, size_t); +size_t wcstombs (char *restrict, const wchar_t *restrict, size_t); + + + + +size_t __ctype_get_mb_cur_max(void); +# 99 "/usr/include/stdlib.h" 3 4 +int posix_memalign (void **, size_t, size_t); +int setenv (const char *, const char *, int); +int unsetenv (const char *); +int mkstemp (char *); +int mkostemp (char *, int); +char *mkdtemp (char *); +int getsubopt (char **, char *const *, char **); +int rand_r (unsigned *); + + + + + + +char *realpath (const char *restrict, char *restrict); +long int random (void); +void srandom (unsigned int); +char *initstate (unsigned int, char *, size_t); +char *setstate (char *); +int putenv (char *); +int posix_openpt (int); +int grantpt (int); +int unlockpt (int); +char *ptsname (int); +char *l64a (long); +long a64l (const char *); +void setkey (const char *); +double drand48 (void); +double erand48 (unsigned short [3]); +long int lrand48 (void); +long int nrand48 (unsigned short [3]); +long mrand48 (void); +long jrand48 (unsigned short [3]); +void srand48 (long); +unsigned short *seed48 (unsigned short [3]); +void lcong48 (unsigned short [7]); + + + +# 1 "/usr/include/alloca.h" 1 3 4 +# 9 "/usr/include/alloca.h" 3 4 +# 1 "/usr/include/bits/alltypes.h" 1 3 4 +# 10 "/usr/include/alloca.h" 2 3 4 + +void *alloca(size_t); +# 139 "/usr/include/stdlib.h" 2 3 4 +char *mktemp (char *); +int mkstemps (char *, int); +int mkostemps (char *, int, int); +void *valloc (size_t); +void *memalign(size_t, size_t); +int getloadavg(double *, int); +int clearenv(void); +# 2 "env1.c" 2 +# 1 "/usr/include/stdio.h" 1 3 4 +# 22 "/usr/include/stdio.h" 3 4 +# 1 "/usr/include/bits/alltypes.h" 1 3 4 + + + + + +typedef __builtin_va_list va_list; + + + + +typedef __builtin_va_list __isoc_va_list; +# 116 "/usr/include/bits/alltypes.h" 3 4 +typedef long ssize_t; +# 203 "/usr/include/bits/alltypes.h" 3 4 +typedef long off_t; +# 356 "/usr/include/bits/alltypes.h" 3 4 +typedef struct _IO_FILE FILE; +# 23 "/usr/include/stdio.h" 2 3 4 +# 50 "/usr/include/stdio.h" 3 4 +typedef union _G_fpos64_t { + char __opaque[16]; + long long __lldata; + double __align; +} fpos_t; + +extern FILE *const stdin; +extern FILE *const stdout; +extern FILE *const stderr; + + + + + +FILE *fopen(const char *restrict, const char *restrict); +FILE *freopen(const char *restrict, const char *restrict, FILE *restrict); +int fclose(FILE *); + +int remove(const char *); +int rename(const char *, const char *); + +int feof(FILE *); +int ferror(FILE *); +int fflush(FILE *); +void clearerr(FILE *); + +int fseek(FILE *, long, int); +long ftell(FILE *); +void rewind(FILE *); + +int fgetpos(FILE *restrict, fpos_t *restrict); +int fsetpos(FILE *, const fpos_t *); + +size_t fread(void *restrict, size_t, size_t, FILE *restrict); +size_t fwrite(const void *restrict, size_t, size_t, FILE *restrict); + +int fgetc(FILE *); +int getc(FILE *); +int getchar(void); +int ungetc(int, FILE *); + +int fputc(int, FILE *); +int putc(int, FILE *); +int putchar(int); + +char *fgets(char *restrict, int, FILE *restrict); + + + + +int fputs(const char *restrict, FILE *restrict); +int puts(const char *); + +int printf(const char *restrict, ...); +int fprintf(FILE *restrict, const char *restrict, ...); +int sprintf(char *restrict, const char *restrict, ...); +int snprintf(char *restrict, size_t, const char *restrict, ...); + +int vprintf(const char *restrict, __isoc_va_list); +int vfprintf(FILE *restrict, const char *restrict, __isoc_va_list); +int vsprintf(char *restrict, const char *restrict, __isoc_va_list); +int vsnprintf(char *restrict, size_t, const char *restrict, __isoc_va_list); + +int scanf(const char *restrict, ...); +int fscanf(FILE *restrict, const char *restrict, ...); +int sscanf(const char *restrict, const char *restrict, ...); +int vscanf(const char *restrict, __isoc_va_list); +int vfscanf(FILE *restrict, const char *restrict, __isoc_va_list); +int vsscanf(const char *restrict, const char *restrict, __isoc_va_list); + +void perror(const char *); + +int setvbuf(FILE *restrict, char *restrict, int, size_t); +void setbuf(FILE *restrict, char *restrict); + +char *tmpnam(char *); +FILE *tmpfile(void); + + + + +FILE *fmemopen(void *restrict, size_t, const char *restrict); +FILE *open_memstream(char **, size_t *); +FILE *fdopen(int, const char *); +FILE *popen(const char *, const char *); +int pclose(FILE *); +int fileno(FILE *); +int fseeko(FILE *, off_t, int); +off_t ftello(FILE *); +int dprintf(int, const char *restrict, ...); +int vdprintf(int, const char *restrict, __isoc_va_list); +void flockfile(FILE *); +int ftrylockfile(FILE *); +void funlockfile(FILE *); +int getc_unlocked(FILE *); +int getchar_unlocked(void); +int putc_unlocked(int, FILE *); +int putchar_unlocked(int); +ssize_t getdelim(char **restrict, size_t *restrict, int, FILE *restrict); +ssize_t getline(char **restrict, size_t *restrict, FILE *restrict); +int renameat(int, const char *, int, const char *); +char *ctermid(char *); + + + + + + + +char *tempnam(const char *, const char *); + + + + +char *cuserid(char *); +void setlinebuf(FILE *); +void setbuffer(FILE *, char *, size_t); +int fgetc_unlocked(FILE *); +int fputc_unlocked(int, FILE *); +int fflush_unlocked(FILE *); +size_t fread_unlocked(void *, size_t, size_t, FILE *); +size_t fwrite_unlocked(const void *, size_t, size_t, FILE *); +void clearerr_unlocked(FILE *); +int feof_unlocked(FILE *); +int ferror_unlocked(FILE *); +int fileno_unlocked(FILE *); +int getw(FILE *); +int putw(int, FILE *); +char *fgetln(FILE *, size_t *); +int asprintf(char **, const char *, ...); +int vasprintf(char **, const char *, __isoc_va_list); +# 3 "env1.c" 2 +# 1 "/usr/include/unistd.h" 1 3 4 +# 33 "/usr/include/unistd.h" 3 4 +# 1 "/usr/include/bits/alltypes.h" 1 3 4 +# 121 "/usr/include/bits/alltypes.h" 3 4 +typedef long intptr_t; +# 276 "/usr/include/bits/alltypes.h" 3 4 +typedef int pid_t; +# 286 "/usr/include/bits/alltypes.h" 3 4 +typedef unsigned uid_t; + + + + +typedef unsigned gid_t; +# 301 "/usr/include/bits/alltypes.h" 3 4 +typedef unsigned useconds_t; +# 34 "/usr/include/unistd.h" 2 3 4 + +int pipe(int [2]); +int pipe2(int [2], int); +int close(int); +int posix_close(int, int); +int dup(int); +int dup2(int, int); +int dup3(int, int, int); +off_t lseek(int, off_t, int); +int fsync(int); +int fdatasync(int); + +ssize_t read(int, void *, size_t); +ssize_t write(int, const void *, size_t); +ssize_t pread(int, void *, size_t, off_t); +ssize_t pwrite(int, const void *, size_t, off_t); + +int chown(const char *, uid_t, gid_t); +int fchown(int, uid_t, gid_t); +int lchown(const char *, uid_t, gid_t); +int fchownat(int, const char *, uid_t, gid_t, int); + +int link(const char *, const char *); +int linkat(int, const char *, int, const char *, int); +int symlink(const char *, const char *); +int symlinkat(const char *, int, const char *); +ssize_t readlink(const char *restrict, char *restrict, size_t); +ssize_t readlinkat(int, const char *restrict, char *restrict, size_t); +int unlink(const char *); +int unlinkat(int, const char *, int); +int rmdir(const char *); +int truncate(const char *, off_t); +int ftruncate(int, off_t); + + + + + + +int access(const char *, int); +int faccessat(int, const char *, int, int); + +int chdir(const char *); +int fchdir(int); +char *getcwd(char *, size_t); + +unsigned alarm(unsigned); +unsigned sleep(unsigned); +int pause(void); + +pid_t fork(void); +int execve(const char *, char *const [], char *const []); +int execv(const char *, char *const []); +int execle(const char *, const char *, ...); +int execl(const char *, const char *, ...); +int execvp(const char *, char *const []); +int execlp(const char *, const char *, ...); +int fexecve(int, char *const [], char *const []); +_Noreturn void _exit(int); + +pid_t getpid(void); +pid_t getppid(void); +pid_t getpgrp(void); +pid_t getpgid(pid_t); +int setpgid(pid_t, pid_t); +pid_t setsid(void); +pid_t getsid(pid_t); +char *ttyname(int); +int ttyname_r(int, char *, size_t); +int isatty(int); +pid_t tcgetpgrp(int); +int tcsetpgrp(int, pid_t); + +uid_t getuid(void); +uid_t geteuid(void); +gid_t getgid(void); +gid_t getegid(void); +int getgroups(int, gid_t []); +int setuid(uid_t); +int seteuid(uid_t); +int setgid(gid_t); +int setegid(gid_t); + +char *getlogin(void); +int getlogin_r(char *, size_t); +int gethostname(char *, size_t); +char *ctermid(char *); + +int getopt(int, char * const [], const char *); +extern char *optarg; +extern int optind, opterr, optopt; + +long pathconf(const char *, int); +long fpathconf(int, int); +long sysconf(int); +size_t confstr(int, char *, size_t); + + + + + + +int setreuid(uid_t, uid_t); +int setregid(gid_t, gid_t); +int lockf(int, int, off_t); +long gethostid(void); +int nice(int); +void sync(void); +pid_t setpgrp(void); +char *crypt(const char *, const char *); +void encrypt(char *, int); +void swab(const void *restrict, void *restrict, ssize_t); + + + + +int usleep(unsigned); +unsigned ualarm(unsigned, unsigned); + + + + + + +int brk(void *); +void *sbrk(intptr_t); +pid_t vfork(void); +int vhangup(void); +int chroot(const char *); +int getpagesize(void); +int getdtablesize(void); +int sethostname(const char *, size_t); +int getdomainname(char *, size_t); +int setdomainname(const char *, size_t); +int setgroups(size_t, const gid_t *); +char *getpass(const char *); +int daemon(int, int); +void setusershell(void); +void endusershell(void); +char *getusershell(void); +int acct(const char *); +long syscall(long, ...); +int execvpe(const char *, char *const [], char *const []); +int issetugid(void); +int getentropy(void *, size_t); +# 252 "/usr/include/unistd.h" 3 4 +# 1 "/usr/include/bits/posix.h" 1 3 4 +# 253 "/usr/include/unistd.h" 2 3 4 +# 4 "env1.c" 2 + + +# 5 "env1.c" +extern char **environ; +char **env ; +int main() +{ +env= environ; +while(*environ){ + puts(*environ); + environ++; +} + +char * p; +puts("----------------------\n"); +if((p=getenv("USER"))) +printf("USER =%s\n",p); +setenv("USER","test",1); +printf("USER=%s\n",getenv("USER")); + + +char * argv[]={"env2", +# 23 "env1.c" 3 4 + ((void*)0) +# 23 "env1.c" + }; +execve("./env2",argv,env); +return 0; +} diff --git a/testsuits_alpine/env1.o b/testsuits_alpine/env1.o new file mode 100644 index 0000000000000000000000000000000000000000..e7cf24bd077a1bb7a738c8bdabfc732b30b2f090 GIT binary patch literal 2608 zcmbtUO-vI}5S~*0M36!xLGe(d82n-7Cn_2tEoA8)DkMOo7qeN)A`NugbQgjq#sl%E zX-M?q&6^i*dN3hgBry>=n0Vx9VoXf*03Hkn6P($7uRLFOFFKpIGxN{Wj^~I0c>LBqvvS=68Ep6rQ7C7x%3C-er##}4Y-_RFms}~3e zo~ANSTV-9VpS2B@wb|y)f>61V8*$5NrE9x0T7RSa=}wIs*nHRRD-DpER43e5bgvITGq#e0De=z>2&e=rx`BS%}9LyA6WwbkTB0fiGPIoPXvCmz<(z3PcZ+v zg!8&D7*2iCx#Ru64B)>O_+p=LC4Lw4HwC`f=O>BZ%lt0_F7EG+fYUl(Wd1Lvss9!n zy#HppP*4bO#li6?+9b5^G|Hmbx3i8h4T|j)JUz#)g1KNQj=AiBGGjOfDATqLN+IVt z>0CBzS{So(j;SQZQr+%pMgpaobNXz-$eQIk|7k=qpFT~#fntb}@cYH{JTA9Mci^Bk ziQy2Xoj{ZuY*8A}raJr{Yo{Q}DIA2$H*boqH*rLf;d2&MX+ zMXrAtgM`t&Daunur1cSn=W{)bL2iq@SAL)m_d3Jm{?}OkfH*1IeEm5*frj7y<=KJY z`$YRkxjdiaR7S3i5NxyhADE^)m;OIFpD=mv5P~%Z^81i55;mRZ;G6zYzx+q6f1}Lw H3_1S~WGF`W literal 0 HcmV?d00001 diff --git a/testsuits_alpine/env1.s b/testsuits_alpine/env1.s new file mode 100644 index 0000000..bcc7724 --- /dev/null +++ b/testsuits_alpine/env1.s @@ -0,0 +1,94 @@ + .file "env1.c" + .text + .comm env,8,8 + .section .rodata +.LC0: + .string "----------------------\n" +.LC1: + .string "USER" +.LC2: + .string "USER =%s\n" +.LC3: + .string "test" +.LC4: + .string "USER=%s\n" +.LC5: + .string "env2" +.LC6: + .string "./env2" + .text + .globl main + .type main, @function +main: +.LFB0: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + subq $48, %rsp + movq %fs:40, %rax + movq %rax, -8(%rbp) + xorl %eax, %eax + movq environ(%rip), %rax + movq %rax, env(%rip) + jmp .L2 +.L3: + movq environ(%rip), %rax + movq (%rax), %rax + movq %rax, %rdi + call puts@PLT + movq environ(%rip), %rax + addq $8, %rax + movq %rax, environ(%rip) +.L2: + movq environ(%rip), %rax + movq (%rax), %rax + testq %rax, %rax + jne .L3 + leaq .LC0(%rip), %rdi + call puts@PLT + leaq .LC1(%rip), %rdi + call getenv@PLT + movq %rax, -40(%rbp) + cmpq $0, -40(%rbp) + je .L4 + movq -40(%rbp), %rax + movq %rax, %rsi + leaq .LC2(%rip), %rdi + movl $0, %eax + call printf@PLT +.L4: + movl $1, %edx + leaq .LC3(%rip), %rsi + leaq .LC1(%rip), %rdi + call setenv@PLT + leaq .LC1(%rip), %rdi + call getenv@PLT + movq %rax, %rsi + leaq .LC4(%rip), %rdi + movl $0, %eax + call printf@PLT + leaq .LC5(%rip), %rax + movq %rax, -32(%rbp) + movq $0, -24(%rbp) + movq env(%rip), %rdx + leaq -32(%rbp), %rax + movq %rax, %rsi + leaq .LC6(%rip), %rdi + call execve@PLT + movl $0, %eax + movq -8(%rbp), %rcx + xorq %fs:40, %rcx + je .L6 + call __stack_chk_fail@PLT +.L6: + leave + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE0: + .size main, .-main + .ident "GCC: (Alpine 8.2.0) 8.2.0" + .section .note.GNU-stack,"",@progbits diff --git a/testsuits_alpine/env2 b/testsuits_alpine/env2 new file mode 100755 index 0000000000000000000000000000000000000000..12cbcdebcf6fe11e0b8e347419a7a1cb44d894fc GIT binary patch literal 18760 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 literal 0 HcmV?d00001 diff --git a/testsuits_alpine/env2.c b/testsuits_alpine/env2.c new file mode 100644 index 0000000..9af5f6a --- /dev/null +++ b/testsuits_alpine/env2.c @@ -0,0 +1,25 @@ +#include +#include +#include + +//extern char **environ; +//char **env = environ; +int main(int argc, char * argv [] , char ** environ) +{ +puts("child, evn2----------------------\n"); +while(*environ){ + puts(*environ); + environ++; +} + +char * p; +puts("----------------------\n"); +if((p=getenv("USER"))) +printf("USER =%s\n",p); +setenv("USER","TEST",1); +printf("USER=%s\n",getenv("USER")); +unsetenv("USER"); +printf("USER=%s\n",getenv("USER")); +setenv("USER","TEST",1); +return 0; +} diff --git a/testsuits_alpine/env2.s b/testsuits_alpine/env2.s new file mode 100644 index 0000000..7de027f --- /dev/null +++ b/testsuits_alpine/env2.s @@ -0,0 +1,243 @@ + +env2: file format elf64-x86-64 + + +Disassembly of section .init: + +0000000000001000 <_init>: + 1000: 50 push %rax + 1001: e8 ad 01 00 00 callq 11b3 + 1006: e8 ce 02 00 00 callq 12d9 <__do_global_ctors_aux> + 100b: 58 pop %rax + 100c: c3 retq + +Disassembly of section .plt: + +0000000000001010 <.plt>: + 1010: ff 35 82 2f 00 00 pushq 0x2f82(%rip) # 3f98 <_GLOBAL_OFFSET_TABLE_+0x8> + 1016: ff 25 84 2f 00 00 jmpq *0x2f84(%rip) # 3fa0 <_GLOBAL_OFFSET_TABLE_+0x10> + 101c: 0f 1f 40 00 nopl 0x0(%rax) + +0000000000001020 : + 1020: ff 25 82 2f 00 00 jmpq *0x2f82(%rip) # 3fa8 + 1026: 68 00 00 00 00 pushq $0x0 + 102b: e9 e0 ff ff ff jmpq 1010 <.plt> + +0000000000001030 : + 1030: ff 25 7a 2f 00 00 jmpq *0x2f7a(%rip) # 3fb0 + 1036: 68 01 00 00 00 pushq $0x1 + 103b: e9 d0 ff ff ff jmpq 1010 <.plt> + +0000000000001040 : + 1040: ff 25 72 2f 00 00 jmpq *0x2f72(%rip) # 3fb8 + 1046: 68 02 00 00 00 pushq $0x2 + 104b: e9 c0 ff ff ff jmpq 1010 <.plt> + +0000000000001050 : + 1050: ff 25 6a 2f 00 00 jmpq *0x2f6a(%rip) # 3fc0 + 1056: 68 03 00 00 00 pushq $0x3 + 105b: e9 b0 ff ff ff jmpq 1010 <.plt> + +0000000000001060 : + 1060: ff 25 62 2f 00 00 jmpq *0x2f62(%rip) # 3fc8 + 1066: 68 04 00 00 00 pushq $0x4 + 106b: e9 a0 ff ff ff jmpq 1010 <.plt> + +0000000000001070 <__libc_start_main@plt>: + 1070: ff 25 5a 2f 00 00 jmpq *0x2f5a(%rip) # 3fd0 <__libc_start_main> + 1076: 68 05 00 00 00 pushq $0x5 + 107b: e9 90 ff ff ff jmpq 1010 <.plt> + +Disassembly of section .plt.got: + +0000000000001080 <__cxa_finalize@plt>: + 1080: ff 25 52 2f 00 00 jmpq *0x2f52(%rip) # 3fd8 <__cxa_finalize> + 1086: 66 90 xchg %ax,%ax + +0000000000001088 <__deregister_frame_info@plt>: + 1088: ff 25 52 2f 00 00 jmpq *0x2f52(%rip) # 3fe0 <__deregister_frame_info> + 108e: 66 90 xchg %ax,%ax + +0000000000001090 <__register_frame_info@plt>: + 1090: ff 25 62 2f 00 00 jmpq *0x2f62(%rip) # 3ff8 <__register_frame_info> + 1096: 66 90 xchg %ax,%ax + +Disassembly of section .text: + +0000000000001098 <_start>: + 1098: 48 31 ed xor %rbp,%rbp + 109b: 48 89 e7 mov %rsp,%rdi + 109e: 48 8d 35 6b 2d 00 00 lea 0x2d6b(%rip),%rsi # 3e10 <_DYNAMIC> + 10a5: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp + 10a9: e8 00 00 00 00 callq 10ae <_start_c> + +00000000000010ae <_start_c>: + 10ae: 50 push %rax + 10af: 48 8d 57 08 lea 0x8(%rdi),%rdx + 10b3: 48 8b 37 mov (%rdi),%rsi + 10b6: 45 31 c9 xor %r9d,%r9d + 10b9: 4c 8d 05 3b 02 00 00 lea 0x23b(%rip),%r8 # 12fb <_fini> + 10c0: 48 8d 0d 39 ff ff ff lea -0xc7(%rip),%rcx # 1000 <_init> + 10c7: 48 8d 3d 0c 01 00 00 lea 0x10c(%rip),%rdi # 11da
+ 10ce: e8 9d ff ff ff callq 1070 <__libc_start_main@plt> + +00000000000010d3 : + 10d3: 48 8d 3d 2e 2f 00 00 lea 0x2f2e(%rip),%rdi # 4008 <__TMC_END__> + 10da: 48 8d 05 27 2f 00 00 lea 0x2f27(%rip),%rax # 4008 <__TMC_END__> + 10e1: 48 39 f8 cmp %rdi,%rax + 10e4: 74 0e je 10f4 + 10e6: 48 8b 05 03 2f 00 00 mov 0x2f03(%rip),%rax # 3ff0 <_ITM_deregisterTMCloneTable> + 10ed: 48 85 c0 test %rax,%rax + 10f0: 74 02 je 10f4 + 10f2: ff e0 jmpq *%rax + 10f4: c3 retq + +00000000000010f5 : + 10f5: 48 8d 3d 0c 2f 00 00 lea 0x2f0c(%rip),%rdi # 4008 <__TMC_END__> + 10fc: 48 8d 35 05 2f 00 00 lea 0x2f05(%rip),%rsi # 4008 <__TMC_END__> + 1103: b9 02 00 00 00 mov $0x2,%ecx + 1108: 48 29 fe sub %rdi,%rsi + 110b: 48 c1 fe 03 sar $0x3,%rsi + 110f: 48 89 f0 mov %rsi,%rax + 1112: 48 99 cqto + 1114: 48 f7 f9 idiv %rcx + 1117: 48 89 c6 mov %rax,%rsi + 111a: 48 85 c0 test %rax,%rax + 111d: 74 0e je 112d + 111f: 48 8b 05 c2 2e 00 00 mov 0x2ec2(%rip),%rax # 3fe8 <_ITM_registerTMCloneTable> + 1126: 48 85 c0 test %rax,%rax + 1129: 74 02 je 112d + 112b: ff e0 jmpq *%rax + 112d: c3 retq + +000000000000112e <__do_global_dtors_aux>: + 112e: 80 3d eb 2e 00 00 00 cmpb $0x0,0x2eeb(%rip) # 4020 + 1135: 75 7b jne 11b2 <__do_global_dtors_aux+0x84> + 1137: 55 push %rbp + 1138: 48 83 3d 98 2e 00 00 cmpq $0x0,0x2e98(%rip) # 3fd8 <__cxa_finalize> + 113f: 00 + 1140: 48 89 e5 mov %rsp,%rbp + 1143: 41 54 push %r12 + 1145: 53 push %rbx + 1146: 74 0c je 1154 <__do_global_dtors_aux+0x26> + 1148: 48 8b 3d b1 2e 00 00 mov 0x2eb1(%rip),%rdi # 4000 <__dso_handle> + 114f: e8 2c ff ff ff callq 1080 <__cxa_finalize@plt> + 1154: 48 8d 05 a5 2c 00 00 lea 0x2ca5(%rip),%rax # 3e00 <__DTOR_LIST__> + 115b: 48 8d 1d a6 2c 00 00 lea 0x2ca6(%rip),%rbx # 3e08 <__DTOR_END__> + 1162: 48 29 c3 sub %rax,%rbx + 1165: 49 89 c4 mov %rax,%r12 + 1168: 48 c1 fb 03 sar $0x3,%rbx + 116c: 48 ff cb dec %rbx + 116f: 48 8b 05 b2 2e 00 00 mov 0x2eb2(%rip),%rax # 4028 + 1176: 48 39 d8 cmp %rbx,%rax + 1179: 73 10 jae 118b <__do_global_dtors_aux+0x5d> + 117b: 48 ff c0 inc %rax + 117e: 48 89 05 a3 2e 00 00 mov %rax,0x2ea3(%rip) # 4028 + 1185: 41 ff 14 c4 callq *(%r12,%rax,8) + 1189: eb e4 jmp 116f <__do_global_dtors_aux+0x41> + 118b: e8 43 ff ff ff callq 10d3 + 1190: 48 83 3d 48 2e 00 00 cmpq $0x0,0x2e48(%rip) # 3fe0 <__deregister_frame_info> + 1197: 00 + 1198: 74 0c je 11a6 <__do_global_dtors_aux+0x78> + 119a: 48 8d 3d 37 0f 00 00 lea 0xf37(%rip),%rdi # 20d8 <__EH_FRAME_BEGIN__> + 11a1: e8 e2 fe ff ff callq 1088 <__deregister_frame_info@plt> + 11a6: 5b pop %rbx + 11a7: 41 5c pop %r12 + 11a9: c6 05 70 2e 00 00 01 movb $0x1,0x2e70(%rip) # 4020 + 11b0: 5d pop %rbp + 11b1: c3 retq + 11b2: c3 retq + +00000000000011b3 : + 11b3: 48 83 3d 3d 2e 00 00 cmpq $0x0,0x2e3d(%rip) # 3ff8 <__register_frame_info> + 11ba: 00 + 11bb: 74 18 je 11d5 + 11bd: 55 push %rbp + 11be: 48 8d 35 7b 2e 00 00 lea 0x2e7b(%rip),%rsi # 4040 + 11c5: 48 8d 3d 0c 0f 00 00 lea 0xf0c(%rip),%rdi # 20d8 <__EH_FRAME_BEGIN__> + 11cc: 48 89 e5 mov %rsp,%rbp + 11cf: e8 bc fe ff ff callq 1090 <__register_frame_info@plt> + 11d4: 5d pop %rbp + 11d5: e9 1b ff ff ff jmpq 10f5 + +00000000000011da
: + 11da: 55 push %rbp + 11db: 48 89 e5 mov %rsp,%rbp + 11de: 48 83 ec 30 sub $0x30,%rsp + 11e2: 89 7d ec mov %edi,-0x14(%rbp) + 11e5: 48 89 75 e0 mov %rsi,-0x20(%rbp) + 11e9: 48 89 55 d8 mov %rdx,-0x28(%rbp) + 11ed: 48 8d 3d 0c 0e 00 00 lea 0xe0c(%rip),%rdi # 2000 <_fini+0xd05> + 11f4: e8 57 fe ff ff callq 1050 + 11f9: eb 14 jmp 120f + 11fb: 48 8b 45 d8 mov -0x28(%rbp),%rax + 11ff: 48 8b 00 mov (%rax),%rax + 1202: 48 89 c7 mov %rax,%rdi + 1205: e8 46 fe ff ff callq 1050 + 120a: 48 83 45 d8 08 addq $0x8,-0x28(%rbp) + 120f: 48 8b 45 d8 mov -0x28(%rbp),%rax + 1213: 48 8b 00 mov (%rax),%rax + 1216: 48 85 c0 test %rax,%rax + 1219: 75 e0 jne 11fb + 121b: 48 8d 3d 01 0e 00 00 lea 0xe01(%rip),%rdi # 2023 <_fini+0xd28> + 1222: e8 29 fe ff ff callq 1050 + 1227: 48 8d 3d 0d 0e 00 00 lea 0xe0d(%rip),%rdi # 203b <_fini+0xd40> + 122e: e8 0d fe ff ff callq 1040 + 1233: 48 89 45 f8 mov %rax,-0x8(%rbp) + 1237: 48 83 7d f8 00 cmpq $0x0,-0x8(%rbp) + 123c: 74 18 je 1256 + 123e: 48 8b 45 f8 mov -0x8(%rbp),%rax + 1242: 48 89 c6 mov %rax,%rsi + 1245: 48 8d 3d f4 0d 00 00 lea 0xdf4(%rip),%rdi # 2040 <_fini+0xd45> + 124c: b8 00 00 00 00 mov $0x0,%eax + 1251: e8 da fd ff ff callq 1030 + 1256: ba 01 00 00 00 mov $0x1,%edx + 125b: 48 8d 35 e8 0d 00 00 lea 0xde8(%rip),%rsi # 204a <_fini+0xd4f> + 1262: 48 8d 3d d2 0d 00 00 lea 0xdd2(%rip),%rdi # 203b <_fini+0xd40> + 1269: e8 f2 fd ff ff callq 1060 + 126e: 48 8d 3d c6 0d 00 00 lea 0xdc6(%rip),%rdi # 203b <_fini+0xd40> + 1275: e8 c6 fd ff ff callq 1040 + 127a: 48 89 c6 mov %rax,%rsi + 127d: 48 8d 3d cb 0d 00 00 lea 0xdcb(%rip),%rdi # 204f <_fini+0xd54> + 1284: b8 00 00 00 00 mov $0x0,%eax + 1289: e8 a2 fd ff ff callq 1030 + 128e: 48 8d 3d a6 0d 00 00 lea 0xda6(%rip),%rdi # 203b <_fini+0xd40> + 1295: e8 86 fd ff ff callq 1020 + 129a: 48 8d 3d 9a 0d 00 00 lea 0xd9a(%rip),%rdi # 203b <_fini+0xd40> + 12a1: e8 9a fd ff ff callq 1040 + 12a6: 48 89 c6 mov %rax,%rsi + 12a9: 48 8d 3d 9f 0d 00 00 lea 0xd9f(%rip),%rdi # 204f <_fini+0xd54> + 12b0: b8 00 00 00 00 mov $0x0,%eax + 12b5: e8 76 fd ff ff callq 1030 + 12ba: ba 01 00 00 00 mov $0x1,%edx + 12bf: 48 8d 35 84 0d 00 00 lea 0xd84(%rip),%rsi # 204a <_fini+0xd4f> + 12c6: 48 8d 3d 6e 0d 00 00 lea 0xd6e(%rip),%rdi # 203b <_fini+0xd40> + 12cd: e8 8e fd ff ff callq 1060 + 12d2: b8 00 00 00 00 mov $0x0,%eax + 12d7: c9 leaveq + 12d8: c3 retq + +00000000000012d9 <__do_global_ctors_aux>: + 12d9: 55 push %rbp + 12da: 48 89 e5 mov %rsp,%rbp + 12dd: 53 push %rbx + 12de: 48 8d 1d 0b 2b 00 00 lea 0x2b0b(%rip),%rbx # 3df0 <__CTOR_LIST__> + 12e5: 52 push %rdx + 12e6: 48 8b 03 mov (%rbx),%rax + 12e9: 48 83 f8 ff cmp $0xffffffffffffffff,%rax + 12ed: 74 08 je 12f7 <__do_global_ctors_aux+0x1e> + 12ef: ff d0 callq *%rax + 12f1: 48 83 eb 08 sub $0x8,%rbx + 12f5: eb ef jmp 12e6 <__do_global_ctors_aux+0xd> + 12f7: 58 pop %rax + 12f8: 5b pop %rbx + 12f9: 5d pop %rbp + 12fa: c3 retq + +Disassembly of section .fini: + +00000000000012fb <_fini>: + 12fb: 50 push %rax + 12fc: e8 2d fe ff ff callq 112e <__do_global_dtors_aux> + 1301: 58 pop %rax + 1302: c3 retq diff --git a/testsuits_alpine/func.c b/testsuits_alpine/func.c new file mode 100644 index 0000000..27d33c6 --- /dev/null +++ b/testsuits_alpine/func.c @@ -0,0 +1,5 @@ +#include "func.h" +void func() +{ + printf("Hello World!\n"); +} diff --git a/testsuits_alpine/func.h b/testsuits_alpine/func.h new file mode 100644 index 0000000..8f449e6 --- /dev/null +++ b/testsuits_alpine/func.h @@ -0,0 +1,5 @@ +#ifndef __FUNC_H +#define __FUNC_H +#include +void func(); +#endif diff --git a/testsuits_alpine/func.o b/testsuits_alpine/func.o new file mode 100644 index 0000000000000000000000000000000000000000..d91e5e0e7d621b779f915317c6848c0902927341 GIT binary patch literal 1520 zcmbtTOKTKC5U$zD!^f_ykAn~oBY_Y>n-woHpzMQv9F_#~ASW3on+XZd?u3~MBzn-3 z;6cbw@#x(@;U5U(>Rm|c+v!R=o!N`l(oL#)%&^K@01*eL>zicSDv6mKT212 zeQegLLS@?QeLL-ae*@$UpObgLdSMjB-d3DMJ5Pzat=6))*oY4HN1?Z*Ua8u%Tp^n1 zQLf1OxJJ%V)tM{L-a6p|o-mFDd5BNrUiE9KRhe1g0QeIGwNKHX^P+9H@Mc6V|BA%r zOhw|-bP>#1W+&jq6}vQZBOZ|tj5^16XRN}jdLx=>egaOrhogZSj1~Fa{%W()_g6ce z_4bCp(P;MDJ{=rp>1D+jFK+esJeRUQ3mv#?;GV`2Z#)Sil^zeXV4HQ8?K8SqBz z&es`(NWXJ0j};qwju(1T=XFhVGin;V!y4zvlwjH~r`F8zZG-t`+!j%3C zyv9b+{AxO(%n9=YSNMXX9{X&D=qElbo-P>wncKW Lq5^{p)8=0QvR7Zp literal 0 HcmV?d00001 diff --git a/testsuits_alpine/hello.go b/testsuits_alpine/hello.go new file mode 100644 index 0000000..f2482c1 --- /dev/null +++ b/testsuits_alpine/hello.go @@ -0,0 +1,5 @@ +package main +import "fmt" +func main() { + fmt.Println("hello world") +} diff --git a/testsuits_alpine/hello.py b/testsuits_alpine/hello.py new file mode 100644 index 0000000..18d9f87 --- /dev/null +++ b/testsuits_alpine/hello.py @@ -0,0 +1 @@ +print "Hello, World!" diff --git a/testsuits_alpine/libfunc.so b/testsuits_alpine/libfunc.so new file mode 100755 index 0000000000000000000000000000000000000000..113f06d9a5146d822ab9038ff890f1c051330bff GIT binary patch literal 17008 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 literal 0 HcmV?d00001 diff --git a/testsuits_alpine/main.rs b/testsuits_alpine/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/testsuits_alpine/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/testsuits_alpine/main_rs_static b/testsuits_alpine/main_rs_static new file mode 100755 index 0000000000000000000000000000000000000000..b02918174c4bb425569a138dc220b33d567a2781 GIT binary patch literal 239248 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

j)z+5o66#rlqSOXpfw}P9N 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 literal 0 HcmV?d00001 diff --git a/testsuits_alpine/map b/testsuits_alpine/map new file mode 100755 index 0000000000000000000000000000000000000000..4e7762f4e1b36c5fd7e6d5dd090202640f46e31c GIT binary patch literal 18792 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 +#include +int *temp[1024*1024]; +void test(int i) +{ +// char temp[1024*1024] = {0}; + char *loc; + temp[i]=malloc(1024*1024); + *temp[i] =i; + printf("%s %d num = %d!\r\n", __FUNCTION__, __LINE__, *temp[i]); + i++; + //if(i==10) return; + test(i++); +} +int main(void) +{ + test(0); + return 0; +} diff --git a/testsuits_alpine/readfile b/testsuits_alpine/readfile new file mode 100755 index 0000000000000000000000000000000000000000..49174b3a3ebd5f59d7371bffdd11ba058800b782 GIT binary patch literal 18808 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 JyBu7i_#YCIajyUX literal 0 HcmV?d00001 diff --git a/testsuits_alpine/readfile.c b/testsuits_alpine/readfile.c new file mode 100644 index 0000000..162817e --- /dev/null +++ b/testsuits_alpine/readfile.c @@ -0,0 +1,16 @@ +#include + +char a[4096]="\0"; +FILE *fp; +void main(int argc, char** argv){ + if (argc >1) { + fp = fopen(argv[1], "r"); + int i=0; + while (!feof(fp)) + { + fscanf(fp, "%c", &a[i]); + printf("%c",a[i]); + i++; + } + } +} diff --git a/testsuits_alpine/stack b/testsuits_alpine/stack new file mode 100755 index 0000000000000000000000000000000000000000..6f00e8242147d7221584a84f1f74c5a2f5f59415 GIT binary patch literal 18808 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 E01O0?`2YX_ literal 0 HcmV?d00001 diff --git a/testsuits_alpine/stack.c b/testsuits_alpine/stack.c new file mode 100644 index 0000000..c34f1ab --- /dev/null +++ b/testsuits_alpine/stack.c @@ -0,0 +1,16 @@ +#include +#include +void test(int i) +{ + char temp[1024*1024] = {0}; + + temp[0] = i; + temp[0] ++; + printf("%s %d num = %d!\r\n", __FUNCTION__, __LINE__, temp[0]); + test(temp[0]); +} +int main(void) +{ + test(0); + return 0; +} From f27309af533398f408c48453d4bb86bc07483ffd Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Mon, 22 Apr 2019 10:59:29 +0800 Subject: [PATCH 27/39] Enable redis static build --- redis/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redis/Makefile b/redis/Makefile index c25e3d2..53d7c88 100644 --- a/redis/Makefile +++ b/redis/Makefile @@ -32,7 +32,7 @@ $(redis_dir)/src/redis-server: $(redis_dir)/src/config.h # our accept does not have backlog sed -i 's/#define MAX_ACCEPTS_PER_CALL 1000/#define MAX_ACCEPTS_PER_CALL 1/' $(redis_dir)/src/networking.c # note: on some platforms gcc seems to forget linking with libatomic, fix it anyway - cd $(redis_dir) && make CC=$(cc) LDFLAGS="${LDFLAGS} -latomic" MALLOC=libc + cd $(redis_dir) && make CC=$(cc) LDFLAGS="${LDFLAGS} -latomic -static" MALLOC=libc $(bin_server_unstripped): $(redis_dir)/src/redis-server cp $(redis_dir)/src/redis-server $(bin_server_unstripped) From 532c7c25584ce07f0701d2fd68ddd72486314abf Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Mon, 22 Apr 2019 11:16:49 +0800 Subject: [PATCH 28/39] Fix redis building on mipsel --- redis/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/redis/Makefile b/redis/Makefile index 53d7c88..2e42614 100644 --- a/redis/Makefile +++ b/redis/Makefile @@ -32,7 +32,8 @@ $(redis_dir)/src/redis-server: $(redis_dir)/src/config.h # our accept does not have backlog sed -i 's/#define MAX_ACCEPTS_PER_CALL 1000/#define MAX_ACCEPTS_PER_CALL 1/' $(redis_dir)/src/networking.c # note: on some platforms gcc seems to forget linking with libatomic, fix it anyway - cd $(redis_dir) && make CC=$(cc) LDFLAGS="${LDFLAGS} -latomic -static" MALLOC=libc + sed -i 's/-ldl -pthread -lrt/-ldl -pthread -lrt -latomic/' $(redis_dir)/src/Makefile + cd $(redis_dir) && make CC=$(cc) LDFLAGS="${LDFLAGS} -static" MALLOC=libc $(bin_server_unstripped): $(redis_dir)/src/redis-server cp $(redis_dir)/src/redis-server $(bin_server_unstripped) From 8763df973dbd5848f8351108e527791525c88fc1 Mon Sep 17 00:00:00 2001 From: chyyuu Date: Fri, 26 Apr 2019 08:40:40 +0800 Subject: [PATCH 29/39] set 'busybox ash' dynamic-linked app from alpine linux as the default init shell in x86_64 environment --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index d961b32..afbaa96 100644 --- a/Makefile +++ b/Makefile @@ -13,8 +13,8 @@ ucore_bin_path := ucore/build/$(arch) biscuit_bin_path := biscuit/build/$(arch) busybox := $(out_dir)/busybox alpine_version_major := 3.9 -alpine_version_full := 3.9.2 -alpine_file := alpine-minirootfs-3.9.2-$(arch).tar.gz +alpine_version_full := 3.9.3 +alpine_file := alpine-minirootfs-3.9.3-$(arch).tar.gz alpine := alpine/$(alpine_file) rust_build_args := --target targets/$(arch)-rcore.json @@ -111,7 +111,8 @@ ifeq ($(arch), $(filter $(arch), x86_64 aarch64)) @cd $(out_dir) && tar xvf ../../$(alpine) endif -build: rust ucore biscuit $(busybox) nginx redis iperf3 +#build: rust ucore biscuit $(busybox) nginx redis iperf3 +build: rust alpine sfsimg: $(out_qcow2) From ffe790d91f120af1d672bc6100d94cdb14fc17ca Mon Sep 17 00:00:00 2001 From: chyyuu Date: Fri, 26 Apr 2019 08:43:58 +0800 Subject: [PATCH 30/39] add new hello world lua/py3/ruby apps --- testsuits_alpine/hello.lua | 1 + testsuits_alpine/hello.py3 | 1 + testsuits_alpine/hello.rb | 1 + 3 files changed, 3 insertions(+) create mode 100644 testsuits_alpine/hello.lua create mode 100644 testsuits_alpine/hello.py3 create mode 100644 testsuits_alpine/hello.rb diff --git a/testsuits_alpine/hello.lua b/testsuits_alpine/hello.lua new file mode 100644 index 0000000..ad35e5a --- /dev/null +++ b/testsuits_alpine/hello.lua @@ -0,0 +1 @@ +print("Hello World") diff --git a/testsuits_alpine/hello.py3 b/testsuits_alpine/hello.py3 new file mode 100644 index 0000000..7df869a --- /dev/null +++ b/testsuits_alpine/hello.py3 @@ -0,0 +1 @@ +print("Hello, World!") diff --git a/testsuits_alpine/hello.rb b/testsuits_alpine/hello.rb new file mode 100644 index 0000000..61e0260 --- /dev/null +++ b/testsuits_alpine/hello.rb @@ -0,0 +1 @@ +puts "Hello, world" From b1391f235dfce0c199ebedc0aa895e831b4d822a Mon Sep 17 00:00:00 2001 From: chyyuu Date: Fri, 26 Apr 2019 08:45:25 +0800 Subject: [PATCH 31/39] update env1 executive file --- testsuits_alpine/env1 | Bin 18888 -> 18904 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/testsuits_alpine/env1 b/testsuits_alpine/env1 index 650eabceb3e0179bfec1903e4bd7e275e4179fa3..613fd9214ca146d50c3b9fc0b5fe24ebc5116ac3 100755 GIT binary patch delta 179 zcmX>xneoPC#t9mXGd61e)R%O3cD7Q`aLg&l%u7|U&@nHd^eGNctH=BCD{l;-AEGUO*^r6!jE#Z4?Xzq0$s&S*0EqNVWUKW-|F4wDt# z?HNBzPIR~DWHVv_gQH;CJ?<)urzbxI%3heP=wZ*qVKO<%!;W$FvWaZ?Ap6UR3cRGat delta 163 zcmcaHneoJA#t9mX9UC=&>T@!{z-DWM8GPzy3@Ih~Me&&_6?$fd#uf}|MTxno@hPRb zxs?q0Nm;4MB|vc#i_O36{;@MkO@3%8JekK`h0$QLp}RffgUN;N_MG1gAx0hr%bo$s z?w Date: Fri, 26 Apr 2019 08:52:03 +0800 Subject: [PATCH 32/39] add hello.sh for testing shell --- testsuits_alpine/hello.sh | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuits_alpine/hello.sh diff --git a/testsuits_alpine/hello.sh b/testsuits_alpine/hello.sh new file mode 100644 index 0000000..b4286e3 --- /dev/null +++ b/testsuits_alpine/hello.sh @@ -0,0 +1 @@ +echo Hello World from shell From 05f0efd3fda084109e4b6da8ff30ecb1557a267f Mon Sep 17 00:00:00 2001 From: chyyuu Date: Fri, 26 Apr 2019 09:10:52 +0800 Subject: [PATCH 33/39] add some test parts for alpine linux x86_64 --- Makefile | 8 +++++++- README.md | 23 +++++++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index afbaa96..290b52c 100644 --- a/Makefile +++ b/Makefile @@ -111,7 +111,13 @@ ifeq ($(arch), $(filter $(arch), x86_64 aarch64)) @cd $(out_dir) && tar xvf ../../$(alpine) endif -#build: rust ucore biscuit $(busybox) nginx redis iperf3 +test: + @echo setup test DIR + @mkdir -p $(out_dir) + @cp -r testsuits_alpine $(out_dir)/ + @mv $(out_dir)/testsuits_alpine $(out_dir)/test + +#build: rust ucore biscuit $(busybox) nginx redis iperf3 test build: rust alpine sfsimg: $(out_qcow2) diff --git a/README.md b/README.md index a3029fe..4a10636 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ Then, build userspace programs for rCore: ```bash $ make {ucore,biscuit,rust,nginx,redis,all} arch={x86_64,aarch64,riscv32,riscv64,mipsel} $ make alpine arch={x86_64,aarch64} # if you want to use alpine rootfs +$ make test arch={x86_64} # test alpine real apps, e.g. python, gcc, rust, go, lua, etc.(need rootfs with these real apps) $ make sfsimg arch={x86_64,aarch64,riscv32,riscv64,mipsel} ``` @@ -61,7 +62,7 @@ A rootfs is created at `build/$(arch)` and converted to `qcow2`. | busybox | ✅ | ✅ | ✅ | ✅ | ✅ | | alpine rootfs | ✅ | ✅ | ❌ | ❌ | ❌ | | iperf3 | ✅ | ❌ | ❌ | ❌ | ❌ | - +| test | ✅ | ❌ | ❌ | ❌ | ❌ | Note: ❗ means workarounds are used so that they may not work properly. ❌ means failure in compiling or not existed on such platform. @@ -158,4 +159,22 @@ $ printf Built within rCore ``` -Note: the long linker args can be replaced by invoking gcc instead later when we fix the problem. If you encountered `rcore-fs-fuse` panicking, consider upgrading it to latest version. \ No newline at end of file +Note: the long linker args can be replaced by invoking gcc instead later when we fix the problem. If you encountered `rcore-fs-fuse` panicking, consider upgrading it to latest version. + + +### How to test real alpine apps +#### simple test for alpine minifs with little apps +```bash +1. make alpine arch=x86_64 +2. make test arch=x86_64 +3. make sfsimg arch=x86_64 +4. cd $(RCORE_ROOT)/kernel; make run arch=x86_64 mode=release +``` + +#### test gcc/go/python2/python3/ruby/lua/java/rust +```bash +1. download x86_64.qcow2.realapps.xz from cloud tsinghua +2. xz -d x86_64.qcow2.realapps.xz; mv x86_64.qcow2.realapps x86_64.qcow2 +3. mv x86_64.qcow2 $(RCORE_ROOT)/user/build +4. cd $(RCORE_ROOT)/kernel; make run arch=x86_64 mode=release +``` From aec8667eb056cb564e301d6c0937da1e4500a4d3 Mon Sep 17 00:00:00 2001 From: chyyuu Date: Mon, 29 Apr 2019 16:43:41 +0800 Subject: [PATCH 34/39] add exec fork readv test apps --- testsuits_alpine/exec | Bin 0 -> 13992 bytes testsuits_alpine/exec.c | 32 +++++++++++++++++++++ testsuits_alpine/exec.static | Bin 0 -> 22376 bytes testsuits_alpine/forktree | Bin 0 -> 18952 bytes testsuits_alpine/forktree.c | 38 +++++++++++++++++++++++++ testsuits_alpine/readv | Bin 0 -> 18952 bytes testsuits_alpine/readv.c | 52 +++++++++++++++++++++++++++++++++++ 7 files changed, 122 insertions(+) create mode 100755 testsuits_alpine/exec create mode 100644 testsuits_alpine/exec.c create mode 100755 testsuits_alpine/exec.static create mode 100755 testsuits_alpine/forktree create mode 100644 testsuits_alpine/forktree.c create mode 100755 testsuits_alpine/readv create mode 100644 testsuits_alpine/readv.c diff --git a/testsuits_alpine/exec b/testsuits_alpine/exec new file mode 100755 index 0000000000000000000000000000000000000000..64359b4995c9dcfb6439674caf633c5ca96cca8d GIT binary patch literal 13992 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 literal 0 HcmV?d00001 diff --git a/testsuits_alpine/exec.c b/testsuits_alpine/exec.c new file mode 100644 index 0000000..81f5128 --- /dev/null +++ b/testsuits_alpine/exec.c @@ -0,0 +1,32 @@ +#include +int main() +{ + int child, grandson; + char *sargs[] = { "/bin/echo", "Son ", "Hello", "World!", NULL}; + char *gargs[] = { "/bin/echo", "Grandson ", "Hello", "World!", NULL}; + + if (!(child = fork())) + { + /* child */ + printf("child:s1: pid %d: %d is my father\n", getpid(), getppid()); + if(!(grandson=fork())) + { + printf("grandson: pid %d: %d is my father\n", getpid(), getppid()); + execve("/bin/echo", gargs, NULL); + printf("pid %d: I am back, something is wrong!\n", getpid()); + }else{ + printf("child:s2: pid %d: %d is my father\n", getpid(), getppid()); + wait4(grandson, NULL, 0, NULL); + execve("/bin/echo", sargs, NULL); + printf("pid %d: I am back, something is wrong!\n", getpid()); + } + } + else + { + int myself = getpid(); + printf("parent: pid %d: %d is my son\n", myself, child); + wait4(child, NULL, 0, NULL); + printf("pid %d: done\n", myself); + } + return 0; +} diff --git a/testsuits_alpine/exec.static b/testsuits_alpine/exec.static new file mode 100755 index 0000000000000000000000000000000000000000..cc84df2aa5818b51d84e7abedee56bc5ac782418 GIT binary patch literal 22376 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 iyb*|zG4U6UgPZJ(O- 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 Y*XP_{e|o*GX8*OQvcKJD;A6#q0f5{e3;+NC literal 0 HcmV?d00001 diff --git a/testsuits_alpine/forktree.c b/testsuits_alpine/forktree.c new file mode 100644 index 0000000..0a27b6a --- /dev/null +++ b/testsuits_alpine/forktree.c @@ -0,0 +1,38 @@ +#include +#include + +#define DEPTH 4 +#define SLEEP_TIME 1 +void forktree(const char *cur); + +void +forkchild(const char *cur, char branch) { + char nxt[DEPTH + 1]; + + if (strlen(cur) >= DEPTH) + return; + + snprintf(nxt, DEPTH + 1, "%s%c", cur, branch); + if (fork() == 0) { + forktree(nxt); + //yield(); + exit(0); + } +} + +void +forktree(const char *cur) { + printf("%04x: I am '%s'\n", getpid(), cur); + + forkchild(cur, '0'); + forkchild(cur, '1'); +} + +int +main(void) { + printf("forktree process will sleep %d ticks\n",SLEEP_TIME); + sleep(SLEEP_TIME); + forktree(""); + return 0; +} + diff --git a/testsuits_alpine/readv b/testsuits_alpine/readv new file mode 100755 index 0000000000000000000000000000000000000000..393e6561adeed7bfed1b6e9ac5118f89725a4c40 GIT binary patch literal 18952 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 literal 0 HcmV?d00001 diff --git a/testsuits_alpine/readv.c b/testsuits_alpine/readv.c new file mode 100644 index 0000000..f808b4b --- /dev/null +++ b/testsuits_alpine/readv.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +char head[1024],foo[48], bar[51], baz[49]; +struct iovec iov[3]; +int main () +{ + + + ssize_t nr; + int fd, i; + + fd = open ("hello.sh", O_RDONLY); + if (fd==-1){ + perror ("open"); + return 1; + } + nr=read(fd, head, sizeof(head)); + if(nr==-1) { + perror("read"); + return 2; + } + + printf ("read size %d, head: %s\n", nr, (char *) head); + + /* set up our iovec structures */ + iov[0].iov_base = foo; + iov[0].iov_len = sizeof (foo); + iov[1].iov_base = bar; + iov[1].iov_len = sizeof (bar); + iov[2].iov_base = baz; + iov[2].iov_len = sizeof (baz); + + /* read into the structures with a single call */ + nr = readv (fd, iov, 3); + if (nr==-1) { + perror ("readv"); + return 1; + } + + for (i = 0; i < 3; i++) + printf ("IOV%d: size:%d %s\n", i, nr, (char *) iov[i].iov_base); + + if (close (fd)) { + perror ("close"); + return 1; + } + + return 0; +} From b6a347750531be125583107b6d0fc307366fdcc9 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Fri, 3 May 2019 00:31:46 +0800 Subject: [PATCH 35/39] bump rcore-fs-fuse version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 290b52c..026016f 100644 --- a/Makefile +++ b/Makefile @@ -133,7 +133,7 @@ $(out_qcow2): $(out_img) rcore-fs-fuse: ifeq ($(shell which rcore-fs-fuse),) @echo Installing rcore-fs-fuse - @cargo install rcore-fs-fuse --git https://github.com/rcore-os/rcore-fs --rev c611248 + @cargo install rcore-fs-fuse --git https://github.com/rcore-os/rcore-fs --rev 41ccb16 endif clean: From bb73d6ecce1ab0e6fae692c51e4335772b0335d4 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Fri, 3 May 2019 14:55:47 +0800 Subject: [PATCH 36/39] Implement rcore-fs-fuse version binding --- Makefile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 026016f..0a55e5a 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,8 @@ out_dir ?= build/$(arch) out_img ?= build/$(arch).img out_qcow2 ?= build/$(arch).qcow2 +rcore_fs_fuse_revision ?= 585eb61 + rust_src_dir := rust/src/bin rust_bin_path := rust/target/$(arch)-rcore/$(mode) rust_bins := $(patsubst $(rust_src_dir)/%.rs, $(rust_bin_path)/%, $(wildcard $(rust_src_dir)/*.rs)) @@ -118,7 +120,7 @@ test: @mv $(out_dir)/testsuits_alpine $(out_dir)/test #build: rust ucore biscuit $(busybox) nginx redis iperf3 test -build: rust alpine +build: rust alpine $(busybox) sfsimg: $(out_qcow2) @@ -131,9 +133,9 @@ $(out_qcow2): $(out_img) @qemu-img resize $@ +1G rcore-fs-fuse: -ifeq ($(shell which rcore-fs-fuse),) +ifneq ($(shell rcore-fs-fuse dir image git-version), $(rcore_fs_fuse_revision)) @echo Installing rcore-fs-fuse - @cargo install rcore-fs-fuse --git https://github.com/rcore-os/rcore-fs --rev 41ccb16 + @cargo install rcore-fs-fuse --git https://github.com/rcore-os/rcore-fs --rev $(rcore_fs_fuse_revision) --force endif clean: From 9fb1d459b50bc14c7ac56d9fd94b4b8485620730 Mon Sep 17 00:00:00 2001 From: chyyuu Date: Fri, 3 May 2019 15:53:02 +0800 Subject: [PATCH 37/39] add pthread testsuits --- testsuits_alpine/pthread-cond | Bin 0 -> 13992 bytes testsuits_alpine/pthread-cond.c | 77 ++++++++++++++++++++++++++++++ testsuits_alpine/pthread-create | Bin 0 -> 18976 bytes testsuits_alpine/pthread-create.c | 48 +++++++++++++++++++ testsuits_alpine/pthread-join | Bin 0 -> 19016 bytes testsuits_alpine/pthread-join.c | 37 ++++++++++++++ testsuits_alpine/pthread-mutex | Bin 0 -> 18960 bytes testsuits_alpine/pthread-mutex.c | 42 ++++++++++++++++ 8 files changed, 204 insertions(+) create mode 100755 testsuits_alpine/pthread-cond create mode 100644 testsuits_alpine/pthread-cond.c create mode 100755 testsuits_alpine/pthread-create create mode 100644 testsuits_alpine/pthread-create.c create mode 100755 testsuits_alpine/pthread-join create mode 100644 testsuits_alpine/pthread-join.c create mode 100755 testsuits_alpine/pthread-mutex create mode 100644 testsuits_alpine/pthread-mutex.c diff --git a/testsuits_alpine/pthread-cond b/testsuits_alpine/pthread-cond new file mode 100755 index 0000000000000000000000000000000000000000..f24440be05659d37b8d974d41873b3034719910a GIT binary patch literal 13992 zcmeHOYiu0V6~1e;;E>p{(ooW-z$)N2iO9wdc@eU(#&t3wK{6qsDc~;a-F3WlAJ*;| zHffcbS|FBXD+3Zr_<^FT(EMnmNEK32s@BLT4MM6yQ6&E;s#RfiSEh>T3nN-jzjNoD z$#|MYRfYO%t~B%A^PSh7Gjqo?p1VKj-M6bL5Kz*Z)!mAu3+*-&Wks!%JAkO#uCB-a zM)hTNE#zx7XX~RjKx?zhFR~$udtn8vDOmR6 zX&Mlkpy-`^A+1)*gMDOxCg}E~p-gSiYBd#Ej8c~n=M_IH2l>sj-#q&Xj&eRhsb}Ae znWVZTL)f8takEV;L8;*b@Z*xP#pi>RZ$Ia2bbM?1ybAKL)y7PEU}Gk^Av;pcY$$Et z8r!-#T+D~NBrBDp4IA0(ag9EO6CMo^w;UVge=qgh?78a4ZL{xRCi<%FX|OAA zjctXx&Y3@O*X?1=FIBI7$(DszIM0djf1KrEbEuGtCu7+WGgXR>G*c=z2&F^XfpnNuiF`Q0{U`fx6uQL$K}6sH*R zO!_FI#b}_hq8Trkv1}Ypu~;%yNF7cW%~T;aScqp+7|mc_#r7PyKPHL;_xEJ-xzvI9 zKn5{LbH!<~&T(+O1HUp4p!Mrl-AmmrK$jVz<%uG;;DFlmCH5ZpO$wi%V+`_zAW!fdjp zCt>}2ZL#GN;2a&Sv2MY5YoXaF&lx9-Pd+uu=gF8HUvxQ+M&5*^M!t8@7>f*1*C@|) zA9&DQW>g|iL9X4d2N3MX`<_v~={p4LCij%zHs1QI*|6S4ydP4$JEw~6hBaZ7gGGql z*2=eMKdkkT?^t9N#YMzwy?Cg| zruIu%_t#e=(m{yE*hitHQMsmLtsZLceAk3g?X8`I1g9JFfM4l;`8TyDctSZR$~WE0 znSVi9>8&}|o5{M;JLeF$f~W+u7!68SjhJ{DIZL5yufX-!x;KrU9#u7R31_u-hJseN zyhCTW8fk)S?KG%L@EhokO$5rpo6)HRsUSM&HYaGWc8&aq!hBo%{1x4?`6b7Gth4q{ za-s}b?A8|VX^W;~ODn`S+i>^!PBIm%s)Y=5_}bVop}cDAok(B z3rl#dB(Fc9UkM%|A7p;PmH9!O{5|WH+HX{vjj?&lY_TpHW3w%@mk&MCKiOCNIYy-C zCl$tTeg*sr_!aOg;8(z}fL{T>0)7Sj3iuWHUn;PRK7@r5`H`HtBh-;}KDG1^lPZLs zh-XGpp}~<{!c6CLn(cBMevaKHu?wtjzN-_1qnG}lUAC-!z0)7Sj3iuW9EAaoW06ysHCV9OweZZwAi0@T) z;|0F0EXumhzb{zy^-qn{$4@j_Yj}tkBgz`X3D(PtB2?koQ4ZQ%LJ+skLxo;Y&O)ysqgs&M0dOCBGo6)n}G{d>F2F{q%|~CSNGZdTwvf zuXFvkGVWr0h;fkd3C3p_UuJxr(Hpm+9JMvOdwO<+)^=xx)45b=dw5g0bDa&!qq)P@ z0F(+Bhl*ywj1QN zH+(pc4%P%?uh;j63;AT+jH_^Jh!@TdB@sj<6;7D>LJ`p!j^yImbON$=8Yn`Q$Y-;u z9Q~8w3utux(xoidWuxCKNGh3EBGdBdf8d%Df0;*usHSc*59In~THS;WjY0fno(Uf3 zgftzgEBmiTF2rBvncz74dB-pLx3T}dY$x+paLVOR z>*T%T?*>O>lKYJOUP4grR~*K +#include +#include + +pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER; + +void *functionCount1(); +void *functionCount2(); +int count = 0; +#define COUNT_DONE 10 +#define COUNT_HALT1 3 +#define COUNT_HALT2 6 + +main() +{ + pthread_t thread1, thread2; + + pthread_create( &thread1, NULL, &functionCount1, NULL); + pthread_create( &thread2, NULL, &functionCount2, NULL); + + pthread_join( thread1, NULL); + pthread_join( thread2, NULL); + + printf("Final count: %d\n",count); + + exit(EXIT_SUCCESS); +} + +// Write numbers 1-3 and 8-10 as permitted by functionCount2() + +void *functionCount1() +{ + for(;;) + { + // Lock mutex and then wait for signal to relase mutex + pthread_mutex_lock( &count_mutex ); + + // Wait while functionCount2() operates on count + // mutex unlocked if condition varialbe in functionCount2() signaled. + pthread_cond_wait( &condition_var, &count_mutex ); + count++; + printf("Counter value functionCount1: %d\n",count); + + pthread_mutex_unlock( &count_mutex ); + + if(count >= COUNT_DONE) return(NULL); + } +} + +// Write numbers 4-7 + +void *functionCount2() +{ + for(;;) + { + pthread_mutex_lock( &count_mutex ); + + if( count < COUNT_HALT1 || count > COUNT_HALT2 ) + { + // Condition of if statement has been met. + // Signal to free waiting thread by freeing the mutex. + // Note: functionCount1() is now permitted to modify "count". + pthread_cond_signal( &condition_var ); + } + else + { + count++; + printf("Counter value functionCount2: %d\n",count); + } + + pthread_mutex_unlock( &count_mutex ); + + if(count >= COUNT_DONE) return(NULL); + } + +} diff --git a/testsuits_alpine/pthread-create b/testsuits_alpine/pthread-create new file mode 100755 index 0000000000000000000000000000000000000000..d1fc403dabf3bd4c0ffd2f55931bdf5ae95f8fdb GIT binary patch literal 18976 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 +#include +#include + +void *print_message_function( void *ptr ); + +main() +{ + pthread_t thread1, thread2; + const char *message1 = "Thread 1"; + const char *message2 = "Thread 2"; + int iret1, iret2; + + /* Create independent threads each of which will execute function */ + + iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1); + if(iret1) + { + fprintf(stderr,"Error - pthread_create() return code: %d\n",iret1); + exit(EXIT_FAILURE); + } + + iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2); + if(iret2) + { + fprintf(stderr,"Error - pthread_create() return code: %d\n",iret2); + exit(EXIT_FAILURE); + } + + printf("pthread_create() for thread 1 returns: %d\n",iret1); + printf("pthread_create() for thread 2 returns: %d\n",iret2); + + /* Wait till threads are complete before main continues. Unless we */ + /* wait we run the risk of executing an exit which will terminate */ + /* the process and all threads before the threads have completed. */ + + pthread_join( thread1, NULL); + pthread_join( thread2, NULL); + + exit(EXIT_SUCCESS); +} + +void *print_message_function( void *ptr ) +{ + char *message; + message = (char *) ptr; + printf("%s \n", message); +} diff --git a/testsuits_alpine/pthread-join b/testsuits_alpine/pthread-join new file mode 100755 index 0000000000000000000000000000000000000000..bcf7f21bfdf3a73a23397c765ff95d64febd024b GIT binary patch literal 19016 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 GQT!(r#~POa literal 0 HcmV?d00001 diff --git a/testsuits_alpine/pthread-join.c b/testsuits_alpine/pthread-join.c new file mode 100644 index 0000000..056ff32 --- /dev/null +++ b/testsuits_alpine/pthread-join.c @@ -0,0 +1,37 @@ +#include +#include + +#define NTHREADS 10 +void *thread_function(void *); +pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; +int counter = 0; + +main() +{ + pthread_t thread_id[NTHREADS]; + int i, j; + + for(i=0; i < NTHREADS; i++) + { + pthread_create( &thread_id[i], NULL, thread_function, NULL ); + } + + for(j=0; j < NTHREADS; j++) + { + pthread_join( thread_id[j], NULL); + } + + /* Now that all threads are complete I can print the final result. */ + /* Without the join I could be printing a value before all the threads */ + /* have been completed. */ + + printf("Final counter value: %d\n", counter); +} + +void *thread_function(void *dummyPtr) +{ + printf("Thread number %ld\n", pthread_self()); + pthread_mutex_lock( &mutex1 ); + counter++; + pthread_mutex_unlock( &mutex1 ); +} diff --git a/testsuits_alpine/pthread-mutex b/testsuits_alpine/pthread-mutex new file mode 100755 index 0000000000000000000000000000000000000000..b21743aec0a3bd6275d89aff94061131e4cf2b8c GIT binary patch literal 18960 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 literal 0 HcmV?d00001 diff --git a/testsuits_alpine/pthread-mutex.c b/testsuits_alpine/pthread-mutex.c new file mode 100644 index 0000000..8394e87 --- /dev/null +++ b/testsuits_alpine/pthread-mutex.c @@ -0,0 +1,42 @@ +#include +#include +#include + +void *functionC(); +pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; +int counter = 0; + +main() +{ + int rc1, rc2; + pthread_t thread1, thread2; + + /* Create independent threads each of which will execute functionC */ + + if( (rc1=pthread_create( &thread1, NULL, &functionC, NULL)) ) + { + printf("Thread creation failed: %d\n", rc1); + } + + if( (rc2=pthread_create( &thread2, NULL, &functionC, NULL)) ) + { + printf("Thread creation failed: %d\n", rc2); + } + + /* Wait till threads are complete before main continues. Unless we */ + /* wait we run the risk of executing an exit which will terminate */ + /* the process and all threads before the threads have completed. */ + + pthread_join( thread1, NULL); + pthread_join( thread2, NULL); + + exit(EXIT_SUCCESS); +} + +void *functionC() +{ + pthread_mutex_lock( &mutex1 ); + counter++; + printf("Counter value: %d\n",counter); + pthread_mutex_unlock( &mutex1 ); +} From dca77ec5ec8bc43306f0d3b9ae3783d67d99fe7e Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Thu, 9 May 2019 11:00:08 +0800 Subject: [PATCH 38/39] Ignore errors when downloading alpine, run full build instead of selected ones Signed-off-by: Harry Chen --- Makefile | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 0a55e5a..5ef33f8 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ out_img ?= build/$(arch).img out_qcow2 ?= build/$(arch).qcow2 rcore_fs_fuse_revision ?= 585eb61 +endif rust_src_dir := rust/src/bin rust_bin_path := rust/target/$(arch)-rcore/$(mode) @@ -104,7 +105,7 @@ endif endif $(alpine): - wget "http://dl-cdn.alpinelinux.org/alpine/v3.9/releases/$(arch)/$(alpine_file)" -O $(alpine) + -wget "http://dl-cdn.alpinelinux.org/alpine/v3.9/releases/$(arch)/$(alpine_file)" -O $(alpine) alpine: $(alpine) ifeq ($(arch), $(filter $(arch), x86_64 aarch64)) @@ -114,13 +115,13 @@ ifeq ($(arch), $(filter $(arch), x86_64 aarch64)) endif test: +ifeq ($(arch), $(filter $(arch), x86_64 aarch64)) @echo setup test DIR @mkdir -p $(out_dir) - @cp -r testsuits_alpine $(out_dir)/ - @mv $(out_dir)/testsuits_alpine $(out_dir)/test + @cp -r testsuits_alpine $(out_dir)/test +endif -#build: rust ucore biscuit $(busybox) nginx redis iperf3 test -build: rust alpine $(busybox) +build: rust ucore biscuit $(busybox) nginx redis iperf3 test sfsimg: $(out_qcow2) From ad822e6d3b626b598874bb52a407e90f549c5ab9 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Thu, 9 May 2019 11:11:15 +0800 Subject: [PATCH 39/39] Fix Makefile (what stupid typo) Signed-off-by: Harry Chen --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 5ef33f8..37acd8c 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,6 @@ out_img ?= build/$(arch).img out_qcow2 ?= build/$(arch).qcow2 rcore_fs_fuse_revision ?= 585eb61 -endif rust_src_dir := rust/src/bin rust_bin_path := rust/target/$(arch)-rcore/$(mode)