...
 
......@@ -67,18 +67,18 @@ fn main() {
.flag("-O3")
.flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("src/runtime/runtime_x64_sel4_rumprun_sysv.c")
.file("src/runtime/runtime_c_x64_sel4_rumprun_sysv.c")
.compile("libruntime_c.a");
gcc::Build::new()
.flag("-O3")
.flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("src/runtime/runtime_asm_x64_sel4_rumprun_sysv.S")
.file("src/runtime/runtime_asm_x64_sysv.S")
.compile("libruntime_asm.a");
gcc::Build::new()
.flag("-O3")
.flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("zebu_c_helpers.c")
.file("src/runtime/zebu_c_helpers.c")
.compile("libzebu_c_helpers.a");
}
#!/usr/bin/env bash
mkdir ../rumprun-sel4
cd ../rumprun-sel4
repo init -u https://github.com/SEL4PROJ/rumprun-sel4-demoapps.git
repo sync
repo forall -c git reset --hard 98dcffbb44bfef5d997f22fcacefdb57d81da940
source scripts/init-all.sh
cd apps/
git clone git@gitlab.anu.edu.au:mu/zebu_rumprun_sel4_runtime.git
mv zebu_rumprun_sel4_runtime ./zebu_rt
cd zebu_rt/
cp workshop/Kbuild_apps ../Kbuild
cp workshop/Kconfig_apps ../Kconfig
cp workshop/dot_config ../../configs/zebu_rt-x86_64-x86_64_qemu_defconfig
cp workshop/clean_and_build.sh ../../clean_and_build.sh
cd ../../
make zebu_rt-x86_64-x86_64_qemu_defconfig
#might be enough, but should be tested step by step
\ No newline at end of file
......@@ -3918,12 +3918,7 @@ pub fn emit_sym_table(vm: &VM) {
fn mangle_all(name_vec: &mut Vec<String>) {
for i in 0..name_vec.len() {
name_vec[i] = name_vec[i]
.replace('.', "Zd")
.replace('-', "Zh")
.replace(':', "Zc")
.replace('#', "Za");
name_vec[i] = "__mu_".to_string() + &name_vec[i];
name_vec[i] = mangle_name(name_vec[i].clone());
}
}
......@@ -3932,6 +3927,7 @@ pub fn emit_sym_table(vm: &VM) {
use std::path;
use std::io::Write;
use compiler::backend::AOT_EMIT_SYM_TABLE_FILE;
// Here goes the code to generate an asm file to resolve symbol addresses at link time
// in this stage, a single sym_file is generated for the test
......
......@@ -406,13 +406,13 @@ pub fn run_test(vm: &VM, test_name: &str, tester_name: &str) {
use std::fs::File;
// emit/add.s
let test_asm_file = "emit/".to_string() + test_name + ".S";
let test_asm_file = vm.vm_options.flag_aot_emit_dir.clone() + "/" + test_name + ".S";
// emit/add_test1.s
let tester_asm_file = "emit/".to_string() + tester_name + ".S";
let tester_asm_file = vm.vm_options.flag_aot_emit_dir.clone() + "/" + tester_name + ".S";
// emit/context.s
let context_asm_file = "emit/".to_string() + "context.S";
let context_asm_file = vm.vm_options.flag_aot_emit_dir.clone() + "/" + "context.S";
// emit/mu_sym_table.s
let mu_sym_table_asm_file = "emit/".to_string() + "mu_sym_table.S";
let mu_sym_table_asm_file = vm.vm_options.flag_aot_emit_dir.clone() + "/" + "mu_sym_table.S";
// clean the destination first
let destination_prefix = "../rumprun-sel4/apps/zebu_rt/src/emit/";
......@@ -488,7 +488,7 @@ pub fn run_test(vm: &VM, test_name: &str, tester_name: &str) {
use std::os::unix::io::FromRawFd;
use std::os::unix::io::AsRawFd;
use std::process::Stdio;
let output = Command::new("rm")
.arg("outputs.txt")
......@@ -563,8 +563,14 @@ pub fn run_test(vm: &VM, test_name: &str, tester_name: &str) {
} else if file_content.contains("@#$%FAILED%$#@") {
test_succeeded = 0;
} else {
panic!("Invalid test outcome!");
panic!("\n*_*_*_*_*_Invalid test outcome!*_*_*_*_*_*\n");
}
} else if file_content.contains("assertion failed") {
println!("\n*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_");
panic!(
"\n*_*_*_*_*_Panic due to assertion failure \
(Check output.txt for log)!*_*_*_*_*_*\n"
);
} else {
continue;
}
......@@ -671,15 +677,15 @@ pub fn run_test_2f(vm: &VM, test_name: &str, dep_name: &str, tester_name: &str)
use std::fs::File;
// emit/add.s
let test_asm_file = "emit/".to_string() + test_name + ".S";
let test_asm_file = vm.vm_options.flag_aot_emit_dir.clone() + "/" + test_name + ".S";
// emit/add_test1.s
let tester_asm_file = "emit/".to_string() + tester_name + ".S";
let tester_asm_file = vm.vm_options.flag_aot_emit_dir.clone() + "/" + tester_name + ".S";
// emit/context.s
let context_asm_file = "emit/".to_string() + "context.S";
let context_asm_file = vm.vm_options.flag_aot_emit_dir.clone() + "/" + "context.S";
// emit/mu_sym_table.s
let mu_sym_table_asm_file = "emit/".to_string() + "mu_sym_table.S";
let mu_sym_table_asm_file = vm.vm_options.flag_aot_emit_dir.clone() + "/" + "mu_sym_table.S";
// something like emit/dummy_call.s
let dep_asm_file = "emit/".to_string() + dep_name + ".S";
let dep_asm_file = vm.vm_options.flag_aot_emit_dir.clone() + "/" + dep_name + ".S";
// clean the destination first
let destination_prefix = "../rumprun-sel4/apps/zebu_rt/src/emit/";
......@@ -763,7 +769,7 @@ pub fn run_test_2f(vm: &VM, test_name: &str, dep_name: &str, tester_name: &str)
use std::os::unix::io::FromRawFd;
use std::os::unix::io::AsRawFd;
use std::process::Stdio;
let output = Command::new("rm")
.arg("outputs.txt")
......
......@@ -119,5 +119,5 @@ pub fn get_dylib_name(name: &'static str) -> String {
/// Must not be used for sel4-rumprun
#[cfg(feature = "sel4-rumprun")]
pub fn get_dylib_name(name: &'static str) -> String {
format!("lib{}.UNKNOWN", name)
unreachable!();
}
......@@ -45,8 +45,24 @@ CNAME(\n):
.macro end_func n
.endm
#elif defined (__NetBSD__)
#define CNAME(n) n
.macro begin_func n
.text
.globl CNAME(\n)
.type CNAME(\n),@function
.balign 16
CNAME(\n):
.endm
.macro end_func n
.size CNAME(\n), .-CNAME(\n)
.endm
#else
#error "Only Linux and OSX are supported."
#error "Only Linux, OSX and Rumprun-NetBSD are supported."
#endif
; vim: ft=asm
# Copyright 2017 The Australian National University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
// This file provides a template so that we can define functions in ASM and also
// let the symbols be recognised in both Linux and OSX
#define CNAME(n) n
.macro begin_func n
.text
.globl CNAME(\n)
.type CNAME(\n),@function
.balign 16
CNAME(\n):
.endm
.macro end_func n
.size CNAME(\n), .-CNAME(\n)
.endm
; vim: ft=asm
# Copyright 2017 The Australian National University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#include "asm_common_x64_sel4_rumprun.S.inc"
# swap_stack_to(new_sp: Address, entry: Address, old_sp_loc: Address)
# %rdi %rsi %rdx
begin_func swap_to_mu_stack
# -- on old stack --
# C calling convention
pushq %rbp
movq %rsp, %rbp
# other callee-saved registers
pushq %rbx
pushq %r12
pushq %r13
pushq %r14
pushq %r15
# save sp to %rbx
movq %rsp, 0(%rdx)
# switch to new stack
movq %rdi, %rsp
# save entry function in %rax
movq %rsi, %rax
# -- on new stack --
# arguments (reverse order of thread.rs - runtime_load_args)
popq %r9
popq %r8
popq %rcx
popq %rdx
popq %rsi
popq %rdi
movsd 0(%rsp), %xmm7
movsd 8(%rsp), %xmm6
movsd 16(%rsp), %xmm5
movsd 24(%rsp), %xmm4
movsd 32(%rsp), %xmm3
movsd 40(%rsp), %xmm2
movsd 48(%rsp), %xmm1
movsd 56(%rsp), %xmm0
add $64, %rsp
# at this point new stack is clean (no intermediate values)
movq %rsp, %rbp
# push an empty pointer to stack, if entry fucntion tries to return, it causes a segfault
pushq $0
# push entry function and start it
pushq %rax
ret
end_func swap_to_mu_stack
# _swap_back_to_native_stack(sp_loc: Address)
# %rdi
begin_func muentry_swap_back_to_native_stack
movq 0(%rdi), %rsp
popq %r15
popq %r14
popq %r13
popq %r12
popq %rbx
popq %rbp
ret
end_func muentry_swap_back_to_native_stack
# _get_current_frame_bp() -> Address
begin_func get_current_frame_bp
movq %rbp, %rax
ret
end_func get_current_frame_bp
# muentry_throw_exception(obj: Address)
# %rdi
begin_func muentry_throw_exception
# save all callee-saved
pushq %rbp
movq %rsp, %rbp
pushq %rbx
pushq %r12
pushq %r13
pushq %r14
pushq %r15
# %rsp points to %rbx, pass this as 2nd argument
movq %rbp, %rsi
# _exception_restore(dest: Address, callee_saved: *const Word, rsp: Address) -> !
# %rdi %rsi %rdx
# callee_saved: [rbx, rbp, r12, r13, r14, r15]
begin_func exception_restore
movq 0(%rsi), %rbp
movq -8(%rsi),%rbx
movq -16(%rsi),%r12
movq -24(%rsi),%r13
movq -32(%rsi),%r14
movq -40(%rsi),%r15
movq %rdx, %rsp
jmpq *%rdi
end_func exception_restore
\ No newline at end of file
......@@ -105,8 +105,10 @@ begin_func muentry_throw_exception
jmp CNAME(throw_exception_internal@PLT)
#elif defined (__APPLE__)
jmp CNAME(throw_exception_internal)
#elif defined (__NetBSD__)
jmp CNAME(throw_exception_internal@PLT)
#else
#error "Only Linux and OSX are supported. "
#error "Only Linux, OSX and Rumprun-NetBSD are supported. "
#endif
# won't return
......
......@@ -28,15 +28,23 @@ int tls_initialized = 0;
static pthread_key_t mu_tls;
void set_thread_local(void* thread) {
if(tls_initialized == 0){
tls_initialized = 1;
int result = pthread_key_create(&mu_tls, NULL);
if(result != 0){
printf("Set_Thread_Local(): PThread key create failed with error code = %d\n", result);
assert(0);
}
void c_initialize_mu_tls(){
int result = pthread_key_create(&mu_tls, NULL);
if(result != 0){
printf("Set_Thread_Local(): PThread key create failed with error code = %d\n", result);
assert(0);
}
}
void set_thread_local(void* thread) {
// if(tls_initialized == 0){
// tls_initialized = 1;
// int result = pthread_key_create(&mu_tls, NULL);
// if(result != 0){
// printf("Set_Thread_Local(): PThread key create failed with error code = %d\n", result);
// assert(0);
// }
// }
int result = pthread_setspecific(mu_tls, thread);
if(result != 0){
printf("Set_Thread_Local(): PThread set specific failed with error code = %d\n", result);
......@@ -45,10 +53,10 @@ void set_thread_local(void* thread) {
}
void* muentry_get_thread_local() {
if(tls_initialized == 0){
printf("Get_Thread_Local(): PThread key MUST be initialized before first use!!\n");
assert(0);
}
// if(tls_initialized == 0){
// printf("Get_Thread_Local(): PThread key MUST be initialized before first use!!\n");
// assert(0);
// }
void * result = pthread_getspecific(mu_tls);
if(result == NULL){
printf("Get_Thread_Local(): NO pthread key found for current thread!!\n");
......
# Copyright 2017 The Australian National University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#include "asm_common_x64_sel4_rumprun.S.inc"
# swap_stack_to(new_sp: Address, entry: Address, old_sp_loc: Address)
# %rdi %rsi %rdx
begin_func swap_to_mu_stack
# -- on old stack --
# C calling convention
pushq %rbp
movq %rsp, %rbp
# other callee-saved registers
pushq %rbx
pushq %r12
pushq %r13
pushq %r14
pushq %r15
# save sp to %rbx
movq %rsp, 0(%rdx)
# switch to new stack
movq %rdi, %rsp
# save entry function in %rax
movq %rsi, %rax
# -- on new stack --
# arguments (reverse order of thread.rs - runtime_load_args)
popq %r9
popq %r8
popq %rcx
popq %rdx
popq %rsi
popq %rdi
movsd 0(%rsp), %xmm7
movsd 8(%rsp), %xmm6
movsd 16(%rsp), %xmm5
movsd 24(%rsp), %xmm4
movsd 32(%rsp), %xmm3
movsd 40(%rsp), %xmm2
movsd 48(%rsp), %xmm1
movsd 56(%rsp), %xmm0
add $64, %rsp
# at this point new stack is clean (no intermediate values)
movq %rsp, %rbp
# push an empty pointer to stack, if entry fucntion tries to return, it causes a segfault
pushq $0
# push entry function and start it
pushq %rax
ret
end_func swap_to_mu_stack
# _swap_back_to_native_stack(sp_loc: Address)
# %rdi
begin_func muentry_swap_back_to_native_stack
movq 0(%rdi), %rsp
popq %r15
popq %r14
popq %r13
popq %r12
popq %rbx
popq %rbp
ret
end_func muentry_swap_back_to_native_stack
# _get_current_frame_rbp() -> Address
begin_func get_current_frame_rbp
movq %rbp, %rax
ret
end_func get_current_frame_rbp
# muentry_throw_exception(obj: Address)
# %rdi
begin_func muentry_throw_exception
# save all callee-saved
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbp
pushq %rbx
# %rsp points to %rbx, pass this as 2nd argument
movq %rsp, %rsi
jmp CNAME(throw_exception_internal@PLT)
# won't return
# _exception_restore(dest: Address, callee_saved: *const Word, rsp: Address) -> !
# %rdi %rsi %rdx
# callee_saved: [rbx, rbp, r12, r13, r14, r15]
begin_func exception_restore
movq 0(%rsi), %rbx
movq 8(%rsi), %rbp
movq 16(%rsi),%r12
movq 24(%rsi),%r13
movq 32(%rsi),%r14
movq 40(%rsi),%r15
movq %rdx, %rsp
jmpq *%rdi
end_func exception_restore
# fake_swap_mu_thread(old_sp_loc: Address)
# %rdi
# (we do not actually swap stack, but we make the stack the same
# as if they are native stack that have been swapped out, so that
# when THREADEXIT (swap_back_to_native_stack) is called, we won't panic
# this function is untested!!!
begin_func fake_swap_mu_thread
# save return address
movq (%rsp), %rax
pushq %rbp
movq %rsp, %rbp
pushq %rbx
pushq %r12
pushq %r13
pushq %r14
pushq %r15
# save old sp to thread field
movq %rsp, 0(%rdi)
# return to caller, but preserve those pushed values (since THREADEXIT will pick them up)
pushq %rax
ret
\ No newline at end of file
......@@ -435,6 +435,7 @@ extern "C" {
pub fn muentry_get_thread_local() -> Address;
pub fn muentry_set_retval(val: u32);
fn c_check_result() -> c_int;
pub fn c_initialize_mu_tls();
}
/// a Rust wrapper for the C function which returns the last set result
......@@ -443,6 +444,19 @@ pub fn check_result() -> c_int {
result
}
/// a Rust wrapper for the C function which initializes pthread local storage for runtime
/// currently just needed on sel4-rumprun
#[cfg(features = "sel4-rumprun-target-side")]
pub fn initialize_mu_tls() {
unsafe { c_initialize_mu_tls() };
}
/// this one should never be called
#[cfg(not(features = "sel4-rumprun-target-side"))]
pub fn initialize_mu_tls() {
unreachable!();
}
impl MuThread {
/// creates a new Mu thread with normal execution
pub fn new_thread_normal(
......
......@@ -211,7 +211,7 @@ impl<'a> VM {
}
/// internal function to create a VM with options
#[cfg(not(feature = "sel4-rumprun"))]
// #[cfg(not(feature = "sel4-rumprun"))]
fn new_internal(options: VMOptions) -> VM {
VM::start_logging(options.flag_log_level);
......@@ -259,56 +259,55 @@ impl<'a> VM {
/// internal function to create a VM with options for sel4-rumprun
/// default memory sizes are different from other platforms
#[cfg(feature = "sel4-rumprun")]
fn new_internal(options: VMOptions) -> VM {
VM::start_logging(options.flag_log_level);
let mut ret = VM {
next_id: ATOMIC_USIZE_INIT,
vm_options: options,
id_name_map: RwLock::new(HashMap::new()),
name_id_map: RwLock::new(HashMap::new()),
constants: RwLock::new(HashMap::new()),
types: RwLock::new(HashMap::new()),
backend_type_info: RwLock::new(HashMap::new()),
globals: RwLock::new(HashMap::new()),
global_locations: RwLock::new(hashmap!{}),
func_sigs: RwLock::new(HashMap::new()),
func_vers: RwLock::new(HashMap::new()),
funcs: RwLock::new(HashMap::new()),
compiled_funcs: RwLock::new(HashMap::new()),
callsite_table: RwLock::new(HashMap::new()),
primordial: RwLock::new(None),
aot_pending_funcref_store: RwLock::new(HashMap::new()),
compiled_callsite_table: RwLock::new(HashMap::new()),
callsite_count: ATOMIC_USIZE_INIT
};
// currently, the default sizes don't work on sel4-rumprun platform
// this is due to memory allocation size limitations
ret.vm_options.flag_gc_immixspace_size = 1 << 19;
ret.vm_options.flag_gc_lospace_size = 1 << 19;
// insert all internal types
{
let mut types = ret.types.write().unwrap();
for ty in INTERNAL_TYPES.iter() {
types.insert(ty.id(), ty.clone());
}
}
// starts allocating ID from USER_ID_START
ret.next_id.store(USER_ID_START, Ordering::Relaxed);
// init types
types::init_types();
// init runtime
ret.init_runtime();
ret
}
// #[cfg(feature = "sel4-rumprun")]
// fn new_internal(options: VMOptions) -> VM {
// VM::start_logging(options.flag_log_level);
//
// let mut ret = VM {
// next_id: ATOMIC_USIZE_INIT,
// vm_options: options,
// id_name_map: RwLock::new(HashMap::new()),
// name_id_map: RwLock::new(HashMap::new()),
// constants: RwLock::new(HashMap::new()),
// types: RwLock::new(HashMap::new()),
// backend_type_info: RwLock::new(HashMap::new()),
// globals: RwLock::new(HashMap::new()),
// global_locations: RwLock::new(hashmap!{}),
// func_sigs: RwLock::new(HashMap::new()),
// func_vers: RwLock::new(HashMap::new()),
// funcs: RwLock::new(HashMap::new()),
// compiled_funcs: RwLock::new(HashMap::new()),
// callsite_table: RwLock::new(HashMap::new()),
// primordial: RwLock::new(None),
// aot_pending_funcref_store: RwLock::new(HashMap::new()),
// compiled_callsite_table: RwLock::new(HashMap::new()),
// callsite_count: ATOMIC_USIZE_INIT
// };
//
// // currently, the default sizes don't work on sel4-rumprun platform
// // this is due to memory allocation size limitations
// ret.vm_options.flag_gc_immixspace_size = 1 << 19;
// ret.vm_options.flag_gc_lospace_size = 1 << 19;
//
// // insert all internal types
// {
// let mut types = ret.types.write().unwrap();
// for ty in INTERNAL_TYPES.iter() {
// types.insert(ty.id(), ty.clone());
// }
// }
//
// // starts allocating ID from USER_ID_START
// ret.next_id.store(USER_ID_START, Ordering::Relaxed);
//
// // init types
// types::init_types();
//
// // init runtime
// ret.init_runtime();
//
// ret
// }
/// initializes runtime
fn init_runtime(&self) {
// init gc
......@@ -321,6 +320,11 @@ impl<'a> VM {
!options.flag_gc_disable_collection
);
}
// initializes pthread local storage
// This is currently just needed for sel4-rumprun
if cfg!(feature = "sel4-rumprun-target-side") {
initialize_mu_tls();
}
}
/// starts logging based on MuLogLevel flag
......
......@@ -135,6 +135,19 @@ impl VMOptions {
// always disable register validation
// register validation is buggy. See Issue #19
ret.flag_disable_regalloc_validate = true;
// TODO
if cfg!(feature = "sel4-rumprun") {
if ret.flag_gc_immixspace_size > (1 << 19) {
ret.flag_gc_immixspace_size = 1 << 19;
warn!("Could not satisfy the user requested gc_immixspace_size \
(down-scaled it to 512KB)");
}
if ret.flag_gc_lospace_size > (1 << 19) {
ret.flag_gc_lospace_size = 1 << 19;
warn!("Could not satisfy the user requested gc_lospace_size \
(down-scaled it to 512KB)");
}
}
ret
}
......