Port ucore, rust, biscuit to mipsel

Signed-off-by: Harry Chen <i@harrychen.xyz>
master
Harry Chen 6 years ago
parent b1e7a2d07e
commit 60bc1a54d2

1
.gitignore vendored

@ -1,3 +1,4 @@
build/
target/
.DS_Store
.vscode

@ -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

@ -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

@ -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 ()

@ -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
}

@ -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
}

@ -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
}

@ -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 ()

@ -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

@ -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__ */

@ -0,0 +1,10 @@
#include <regdef.h>
.text
.globl _start
_start:
# call user-program function
lw a0, 0(sp)
addiu a1, sp, 8
b umain
nop

@ -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 */

@ -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

@ -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

Loading…
Cancel
Save