1
0
Fork 0
mirror of https://github.com/hermitcore/libhermit.git synced 2025-03-09 00:00:03 +01:00

Merge branch 'path2rs' into proxy_rs

This commit is contained in:
Stefan Lankes 2017-09-03 00:14:34 +02:00
commit bd585ae180
31 changed files with 1808 additions and 46 deletions

3
.gitmodules vendored
View file

@ -6,3 +6,6 @@
path = usr/libomp
url = https://github.com/RWTH-OS/libomp_oss.git
branch = hermit
[submodule "librs/rust"]
path = librs/rust
url = https://github.com/RWTH-OS/rust.git

View file

@ -1,27 +1,102 @@
sudo: required
dist: trusty
language: c
git:
submodules: true
env:
global:
- PATH=$PATH:~/.cargo/bin
language: c
compiler:
- clang
- gcc
matrix:
include:
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.9
env:
- COMPILERCXX=g++-4.9
- COMPILERC=gcc-4.9
- DEPLOY=true
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
env:
- COMPILERCXX=g++-5
- COMPILERC=gcc-5
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
env:
- COMPILERCXX=g++-6
- COMPILERC=gcc-6
- compiler: clang
env:
- COMPILERC=clang
- COMPILERCXX=clang++
- CLANGV=3.8.1
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
- compiler: clang
env:
- COMPILERC=clang
- COMPILERCXX=clang++
- CLANGV=3.9.1
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
- compiler: clang
env:
- COMPILERC=clang
- COMPILERCXX=clang++
- CLANGV=4.0.1
- RUNCLANGTIDY=TRUE
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
before_install:
- echo "deb https://dl.bintray.com/rwth-os/hermitcore vivid main" | sudo tee -a /etc/apt/sources.list
- travis_retry sudo apt-get -qq update
- travis_retry sudo apt-get install -y curl wget qemu-system-x86 nasm texinfo libmpfr-dev libmpc-dev libgmp-dev libisl-dev flex bison packaging-dev rpm g++-multilib
- travis_retry sudo apt-get install -y --force-yes binutils-hermit libhermit newlib-hermit pthread-embedded-hermit gcc-hermit
- git submodule update --init lwip usr/libomp
# download clang
- mkdir $HOME/clang+llvm
- export PATH=$HOME/clang+llvm/bin:$PATH
- if [ -n "$CLANGV" ]; then wget http://llvm.org/releases/$CLANGV/clang+llvm-$CLANGV-x86_64-linux-gnu-debian8.tar.xz -O $HOME/clang+llvm.tar.xz; fi
- if [ -n "$CLANGV" ]; then tar xf $HOME/clang+llvm.tar.xz -C $HOME/clang+llvm --strip-components 1; fi
script:
- curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly
- source cmake/local-cmake.sh
- cd librs
- make runtime
- cd -
- mkdir build
- cd build
- cmake ..
- make -j1 package
- cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=true ..
- CC=$COMPILERC CXX=$COMPILERCXX make -j1 package
- cd $TRAVIS_BUILD_DIR
# - ./tests.sh
@ -29,9 +104,9 @@ notifications:
slack: hermitcore:UtcfeEXkbpx3WyIDK2Wm2beS
deploy:
on:
on:
branch: master
condition: "$CC = gcc"
condition: $DEPLOY = true
provider: bintray
file: .bintray_descriptor.json
user:

View file

@ -66,6 +66,53 @@ set_target_properties(hermit-bootstrap PROPERTIES
# dependency makes sure that this is done before hermit is linked
add_dependencies(hermit-bootstrap ${X86_KERNEL_TARGET})
# add external project hermit-rs
ExternalProject_Add(
objmv
DOWNLOAD_COMMAND ""
CONFIGURE_COMMAND ""
BUILD_COMMAND cargo build --release
BINARY_DIR "${CMAKE_SOURCE_DIR}/objmv"
INSTALL_COMMAND ""
LOG_BUILD ON)
# add external project hermit-rs
ExternalProject_Add(
hermit-rs
DOWNLOAD_COMMAND ""
CONFIGURE_COMMAND ""
BUILD_COMMAND make all
BINARY_DIR "${CMAKE_SOURCE_DIR}/librs"
INSTALL_COMMAND ""
LOG_BUILD ON)
# Create dependency of hermit-rs objmv
add_dependencies(hermit-rs objmv)
# Create dependency of hermit-boostrap hermit-rs
add_dependencies(hermit-bootstrap hermit-rs)
add_custom_command(
TARGET
hermit-rs POST_BUILD
# rename sections in rust library
COMMAND
${CMAKE_SOURCE_DIR}/objmv/target/release/objmv
${CMAKE_SOURCE_DIR}/librs/target/x86_64-hermit/release/libhermit_rs.a
# convert rust library to hermitcore's osabi
COMMAND
${CMAKE_ELFEDIT} --output-osabi HermitCore ${CMAKE_SOURCE_DIR}/librs/target/x86_64-hermit/release/libhermit_rs.a
# copy libhermit_rs.a into local prefix directory so that all subsequent
# targets can link against the freshly built version (as opposed to
# linking against the one supplied by the toolchain)
COMMAND
${CMAKE_COMMAND} -E make_directory ${LOCAL_PREFIX_ARCH_LIB_DIR}
COMMAND
${CMAKE_COMMAND} -E copy_if_different
${CMAKE_SOURCE_DIR}/librs/target/x86_64-hermit/release/libhermit_rs.a
${LOCAL_PREFIX_ARCH_LIB_DIR}/)
add_custom_command(
TARGET
hermit-bootstrap POST_BUILD
@ -76,6 +123,18 @@ add_custom_command(
--rename-section .data=.kdata
$<TARGET_FILE:hermit-bootstrap>
# merge libhermit.a and libhermit_rs.a
COMMAND
${CMAKE_AR} x ${CMAKE_SOURCE_DIR}/librs/target/x86_64-hermit/release/libhermit_rs.a
COMMAND
${CMAKE_AR} rcs $<TARGET_FILE:hermit-bootstrap> *.o
COMMAND
${CMAKE_COMMAND} -E remove *.o
# redefine _Unwind_Resume to avoid collision with libgcc.a
COMMAND
${CMAKE_OBJCOPY} --redefine-sym _Unwind_Resume=_Unwind_Resume_rs $<TARGET_FILE:hermit-bootstrap>
# copy libhermit.a into local prefix directory so that all subsequent
# targets can link against the freshly built version (as opposed to
# linking against the one supplied by the toolchain)

View file

@ -41,6 +41,7 @@ the HermitCore kernel and applications you need:
* Netwide Assember (NASM)
* recent host compiler such as GCC
* HermitCore cross-toolchain, i.e. Binutils, GCC, newlib, pthreads
* [Rust compiler (nightly release)](https://www.rust-lang.org/en-US/install.html)
### HermitCore cross-toolchain

View file

@ -111,7 +111,7 @@ typedef struct {
} __attribute__ ((packed)) gdt_ptr_t;
// a TSS descriptor is twice larger than a code/data descriptor
#define GDT_ENTRIES (6+MAX_CORES*2)
#define GDT_ENTRIES (7+MAX_CORES*2)
#if GDT_ENTRIES > 8192
#error Too many GDT entries!

View file

@ -48,11 +48,11 @@
#define PAGE_SIZE ( 1L << PAGE_BITS)
/// Mask the page address without page map flags and XD flag
#if 0
#define PAGE_MASK ((~0L) << PAGE_BITS)
#define PAGE_2M_MASK (~0L) << PAGE_2M_BITS)
#define PAGE_MASK ((~0UL) << PAGE_BITS)
#define PAGE_2M_MASK (~0UL) << PAGE_2M_BITS)
#else
#define PAGE_MASK (((~0L) << PAGE_BITS) & ~PG_XD)
#define PAGE_2M_MASK (((~0L) << PAGE_2M_BITS) & ~PG_XD)
#define PAGE_MASK (((~0UL) << PAGE_BITS) & ~PG_XD)
#define PAGE_2M_MASK (((~0UL) << PAGE_2M_BITS) & ~PG_XD)
#endif
#if 0

View file

@ -141,6 +141,7 @@ start64:
; store pointer to the multiboot information
mov [mb_info], QWORD rdx
;
; relocate page tables
mov rdi, boot_pml4
mov rax, QWORD [rdi]
@ -256,31 +257,6 @@ Lsmp_main:
jmp $
%endif
ALIGN 64
global gdt_flush
extern gp
; This will set up our new segment registers and is declared in
; C as 'extern void gdt_flush();'
gdt_flush:
lgdt [gp]
; reload the segment descriptors
mov eax, 0x10
mov ds, eax
mov es, eax
mov ss, eax
xor eax, eax
mov fs, eax
mov gs, eax
; create pseudo interrupt to set cs
push QWORD 0x10 ; SS
push rsp ; RSP
add QWORD [rsp], 0x08 ; => value of rsp before the creation of a pseudo interrupt
pushfq ; RFLAGS
push QWORD 0x08 ; CS
push QWORD rollback ; RIP
iretq
; The first 32 interrupt service routines (ISR) entries correspond to exceptions.
; Some exceptions will push an error code onto the stack which is specific to
; the exception caused. To decrease the complexity, we handle this by pushing a

View file

@ -35,6 +35,7 @@
#include <asm/tss.h>
#include <asm/page.h>
#if 0
#define MAX_IST 3
gdt_ptr_t gp;
@ -117,7 +118,7 @@ void gdt_install(void)
* this entry's access byte says it's a Data Segment
*/
gdt_set_gate(num++, 0, 0,
GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, 0);
GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, GDT_FLAG_64_BIT);
/*
* Create code segment for 32bit user-space applications (ring 3)
@ -141,7 +142,7 @@ void gdt_install(void)
* Create data segment for 64bit user-space applications (ring 3)
*/
gdt_set_gate(num++, 0, 0,
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, 0);
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, GDT_FLAG_64_BIT);
/*
* Create TSS for each core (we use these segments for task switching)
@ -160,3 +161,4 @@ void gdt_install(void)
/* Flush out the old GDT and install the new changes! */
gdt_flush();
}
#endif

View file

@ -37,9 +37,9 @@
#define PAGE_SIZE ( 1L << PAGE_BITS)
/// Mask the page address without page map flags and XD flag
#ifdef CONFIG_X86_32
#define PAGE_MASK (-1L << PAGE_BITS)
#define PAGE_MASK (~0UL << PAGE_BITS)
#elif defined(CONFIG_X86_64)
#define PAGE_MASK ((-1L << PAGE_BITS) & ~PG_XD)
#define PAGE_MASK ((~0UL << PAGE_BITS) & ~PG_XD)
#endif
#ifdef CONFIG_X86_32

View file

@ -98,7 +98,9 @@ extern volatile int libc_sd;
islelock_t* rcce_lock = NULL;
rcce_mpb_t* rcce_mpb = NULL;
extern void signal_init();
extern void signal_init(void);
extern void rust_main(void);
extern void rust_init(void);
static int hermit_init(void)
{
@ -113,6 +115,7 @@ static int hermit_init(void)
memcpy((char*) &percore_start + i*sz, (char*) &percore_start, sz);
koutput_init();
rust_init();
system_init();
irq_init();
timer_init();
@ -539,6 +542,8 @@ int hermit_main(void)
LOG_INFO("Kernel cmdline: %s\n", (char*) (size_t) mb_info->cmdline);
if (hbmem_base)
LOG_INFO("Found high bandwidth memory at 0x%zx (size 0x%zx)\n", hbmem_base, hbmem_size);
LOG_INFO("rust_main at %p\n", rust_main);
rust_main();
#if 0
print_pci_adapters();

58
libkern/muloti4.c Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2017, Stefan Lankes, RWTH Aachen University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/* HermitCore prelude */
#include <hermit/stddef.h>
#include <hermit/ctype.h>
#include <asm/limits.h>
typedef int ti_int;
/*
* Workarount for the LLVM bug https://llvm.org/bugs/show_bug.cgi?id=16404
*
* rustc based on LLVM and uses this builtin function, which isn't part of
* libgcc.
*/
ti_int
__muloti4(ti_int a, ti_int b, int* overflow)
{
size_t flags;
ti_int result;
*overflow = 0;
result = a * b;
asm volatile("pushf; pop %0": "=r"(flags) : : "memory");
if (flags & (1ULL << 11))
*overflow = 1;
return result;
}

2
librs/.gitignore vendored Normal file
View file

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

42
librs/Cargo.toml Normal file
View file

@ -0,0 +1,42 @@
[package]
name = "hermit-rs"
version = "0.2.2"
authors = [
"Stefan Lankes <slankes@eonerc.rwth-aachen.de>",
]
[lib]
crate-type = ["staticlib"]
[dependencies]
rlibc = "1.0.0" # Low-level functions like memcpy.
spin = "0.4.5" # Spinlocks.
raw-cpuid = "3.0.0"
#[dependencies.lazy_static]
#version = "0.2.8"
#features = ["spin_no_std"]
[dependencies.x86]
version = "0.7"
default-features = false
# The development profile, used for `cargo build`.
[profile.dev]
opt-level = 0 # controls the `--opt-level` the compiler builds with
debug = true # controls whether the compiler passes `-C debuginfo`
# a value of `true` is equivalent to `2`
rpath = false # controls whether the compiler passes `-C rpath`
lto = false # controls `-C lto` for binaries and staticlibs
debug-assertions = true # controls whether debug assertions are enabled
codegen-units = 1 # controls whether the compiler passes `-C codegen-units`
# `codegen-units` is ignored when `lto = true`
# The release profile, used for `cargo build --release`.
[profile.release]
opt-level = 3
debug = false
rpath = false
lto = true
debug-assertions = false
codegen-units = 1

51
librs/Makefile Normal file
View file

@ -0,0 +1,51 @@
# derived from http://blog.phil-opp.com/rust-os/multiboot-kernel.html
arch ?= x86_64
target ?= $(arch)-hermit
rust_os := target/$(target)/release/libhermit_rs.a
.PHONY: all lib default clean cargo
default: lib
lib: cargo $(rust_os)
all: runtime lib
clean:
@cargo clean --target $(target)
cargo:
@echo CARGO
@cargo build --target $(target) --release
#==========================================================================
# Building the Rust runtime for our bare-metal target
# Where to put our compiled runtime libraries for this platform.
installed_target_libs := \
$(shell rustup which rustc | \
sed s,bin/rustc,lib/rustlib/$(target)/lib,)
runtime_rlibs := \
$(installed_target_libs)/libcore.rlib \
$(installed_target_libs)/libstd_unicode.rlib \
$(installed_target_libs)/liballoc.rlib \
$(installed_target_libs)/libcollections.rlib
RUSTC := \
rustc --verbose --target $(target) \
-Z no-landing-pads \
--out-dir $(installed_target_libs)
.PHONY: runtime
runtime: $(runtime_rlibs)
$(installed_target_libs):
@mkdir -p $(installed_target_libs)
$(installed_target_libs)/%.rlib: rust/src/%/lib.rs $(installed_target_libs)
@echo RUSTC $<
@$(RUSTC) $<
@echo Check $(installed_target_libs)

1
librs/rust Submodule

@ -0,0 +1 @@
Subproject commit 230a379a452e5a2bcdfd0a956b259e0a1d83b512

30
librs/src/arch/mod.rs Normal file
View file

@ -0,0 +1,30 @@
// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// Export our platform-specific modules.
#[cfg(target_arch="x86_64")]
pub use self::x86_64::{processor, gdt};
// Implementations for x86_64.
#[cfg(target_arch="x86_64")]
pub mod x86_64;

View file

@ -0,0 +1,291 @@
// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#![allow(dead_code)]
#![allow(private_no_mangle_fns)]
use consts::*;
use spin;
use x86::dtables::{self, DescriptorTablePointer};
use x86::segmentation::{self, SegmentSelector};
use core::mem::size_of;
const GDT_NULL: usize = 0;
const GDT_KERNEL_CODE: usize = 1;
const GDT_KERNEL_DATA: usize = 2;
// This segment is a data segment
const GDT_FLAG_DATASEG: u8 = 0x02;
/// This segment is a code segment
const GDT_FLAG_CODESEG: u8 = 0x0a;
const GDT_FLAG_TSS: u8 = 0x09;
const GDT_FLAG_TSS_BUSY: u8 = 0x02;
const GDT_FLAG_SEGMENT: u8 = 0x10;
/// Privilege level: Ring 0
const GDT_FLAG_RING0: u8 = 0x00;
/// Privilege level: Ring 1
const GDT_FLAG_RING1: u8 = 0x20;
/// Privilege level: Ring 2
const GDT_FLAG_RING2: u8 = 0x40;
/// Privilege level: Ring 3
const GDT_FLAG_RING3: u8 = 0x60;
/// Segment is present
const GDT_FLAG_PRESENT: u8 = 0x80;
/// Segment was accessed
const GDT_FLAG_ACCESSED: u8 = 0x01;
/// Granularity of segment limit
/// - set: segment limit unit is 4 KB (page size)
/// - not set: unit is bytes
const GDT_FLAG_4K_GRAN: u8 = 0x80;
/// Default operand size
/// - set: 32 bit
/// - not set: 16 bit
const GDT_FLAG_16_BIT: u8 = 0x00;
const GDT_FLAG_32_BIT: u8 = 0x40;
const GDT_FLAG_64_BIT: u8 = 0x20;
// a TSS descriptor is twice larger than a code/data descriptor
const GDT_ENTRIES: usize = (7+MAX_CORES*2);
const MAX_IST: usize = 3;
// thread_local on a static mut, signals that the value of this static may
// change depending on the current thread.
static mut GDT: [GdtEntry; GDT_ENTRIES] = [GdtEntry::new(0, 0, 0, 0); GDT_ENTRIES];
static mut GDTR: DescriptorTablePointer = DescriptorTablePointer { limit: 0, base: 0 };
static mut TSS_BUFFER: TssBuffer = TssBuffer::new();
static STACK_TABLE: [[IrqStack; MAX_IST]; MAX_CORES] = [[IrqStack::new(); MAX_IST]; MAX_CORES];
static GDT_INIT: spin::Once<()> = spin::Once::new();
extern "C" {
static boot_stack: [u8; MAX_CORES*KERNEL_STACK_SIZE];
}
#[derive(Copy, Clone)]
#[repr(C, packed)]
struct GdtEntry {
/// Lower 16 bits of limit range
limit_low: u16,
/// Lower 16 bits of base address
base_low: u16,
/// middle 8 bits of base address
base_middle: u8,
/// Access bits
access: u8,
/// Granularity bits
granularity: u8,
/// Higher 8 bits of base address
base_high: u8
}
impl GdtEntry {
pub const fn new(base: u32, limit: u32, access: u8, gran: u8) -> Self {
GdtEntry {
limit_low: (limit & 0xFFFF) as u16,
base_low: (base & 0xFFFF) as u16,
base_middle: ((base >> 16) & 0xFF) as u8,
access: access,
granularity: (gran & 0xF0) as u8 | ((limit >> 16) & 0x0F) as u8,
base_high: ((base >> 24) & 0xFF) as u8
}
}
}
#[derive(Copy, Clone)]
#[repr(C, packed)]
struct TaskStateSegment {
reserved: u32,
/// The full 64-bit canonical forms of the stack pointers (RSP) for privilege levels 0-2.
rsp: [u64; 3],
reserved2: u64,
/// The full 64-bit canonical forms of the interrupt stack table (IST) pointers.
ist: [u64; 7],
reserved3: u64,
reserved4: u16,
/// The 16-bit offset to the I/O permission bit map from the 64-bit TSS base.
iomap_base: u16,
}
impl TaskStateSegment {
const fn new() -> TaskStateSegment {
TaskStateSegment {
reserved: 0,
rsp: [0; 3],
reserved2: 0,
ist: [0; 7],
reserved3: 0,
reserved4: 0,
iomap_base: 0,
}
}
}
// workaround to use th enew repr(align) feature
// currently, it is only supported by structs
// => map all TSS in a struct
#[repr(align(4096))]
struct TssBuffer {
tss: [TaskStateSegment; MAX_CORES],
}
impl TssBuffer {
const fn new() -> TssBuffer {
TssBuffer {
tss: [TaskStateSegment::new(); MAX_CORES],
}
}
}
// workaround to use th enew repr(align) feature
// currently, it is only supported by structs
// => map stacks in a struct
#[derive(Copy)]
#[repr(C, align(4096))]
struct IrqStack {
buffer: [u8; KERNEL_STACK_SIZE],
}
impl Clone for IrqStack {
fn clone(&self) -> IrqStack
{
*self
}
}
impl IrqStack {
pub const fn new() -> IrqStack {
IrqStack {
buffer: [0; KERNEL_STACK_SIZE],
}
}
}
/// This will setup the special GDT
/// pointer, set up the entries in our GDT, and then
/// finally to load the new GDT and to update the
/// new segment registers
#[no_mangle]
pub unsafe fn gdt_install()
{
GDT_INIT.call_once(|| {
let mut num: usize = 0;
GDTR.limit = (size_of::<GdtEntry>() * GDT.len() - 1) as u16;
GDTR.base = GDT.as_ptr() as u64;
/* Our NULL descriptor */
GDT[num] = GdtEntry::new(0, 0, 0, 0);
num += 1;
/*
* The second entry is our Code Segment. The base address
* is 0, the limit is 4 GByte, it uses 4KByte granularity,
* and is a Code Segment descriptor.
*/
GDT[num] = GdtEntry::new(0, 0,
GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT, GDT_FLAG_64_BIT);
num += 1;
/*
* The third entry is our Data Segment. It's EXACTLY the
* same as our code segment, but the descriptor type in
* this entry's access byte says it's a Data Segment
*/
GDT[num] = GdtEntry::new(0, 0,
GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, GDT_FLAG_64_BIT);
num += 1;
/*
* Create code segment for 32bit user-space applications (ring 3)
*/
GDT[num] = GdtEntry::new(0, 0xFFFFFFFF,
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT,
GDT_FLAG_32_BIT | GDT_FLAG_4K_GRAN);
num += 1;
/*
* Create data segment for 32bit user-space applications (ring 3)
*/
GDT[num] = GdtEntry::new(0, 0xFFFFFFFF,
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT,
GDT_FLAG_32_BIT | GDT_FLAG_4K_GRAN);
num += 1;
/*
* Create code segment for 64bit user-space applications (ring 3)
*/
GDT[num] = GdtEntry::new(0, 0,
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT,
GDT_FLAG_64_BIT);
num += 1;
/*
* Create data segment for 64bit user-space applications (ring 3)
*/
GDT[num] = GdtEntry::new(0, 0,
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, GDT_FLAG_64_BIT);
num += 1;
/*
* Create TSS for each core (we use these segments for task switching)
*/
for i in 0..MAX_CORES {
TSS_BUFFER.tss[i].rsp[0] = (&(boot_stack[0]) as *const _) as u64;
TSS_BUFFER.tss[i].rsp[0] += ((i+1) * KERNEL_STACK_SIZE - 0x10) as u64;
TSS_BUFFER.tss[i].ist[0] = 0; // ist will created per task
TSS_BUFFER.tss[i].ist[1] = (&(STACK_TABLE[i][2 /*IST number */ - 2]) as *const _) as u64;
TSS_BUFFER.tss[i].ist[1] += (KERNEL_STACK_SIZE - 0x10) as u64;
TSS_BUFFER.tss[i].ist[2] = (&(STACK_TABLE[i][3 /*IST number */ - 2]) as *const _) as u64;
TSS_BUFFER.tss[i].ist[2] += (KERNEL_STACK_SIZE - 0x10) as u64;
TSS_BUFFER.tss[i].ist[3] = (&(STACK_TABLE[i][4 /*IST number */ - 2]) as *const _) as u64;
TSS_BUFFER.tss[i].ist[3] += (KERNEL_STACK_SIZE - 0x10) as u64;
let tss_ptr = &(TSS_BUFFER.tss[i]) as *const TaskStateSegment;
GDT[num+i*2] = GdtEntry::new(tss_ptr as u32, size_of::<TaskStateSegment>() as u32,
GDT_FLAG_PRESENT | GDT_FLAG_TSS | GDT_FLAG_RING0, 0);
}
});
gdt_flush();
}
#[no_mangle]
pub unsafe fn set_tss(rsp: u64, ist: u64)
{
TSS_BUFFER.tss[core_id!()].rsp[0] = rsp;
TSS_BUFFER.tss[core_id!()].ist[0] = ist;
}
#[no_mangle]
pub unsafe fn gdt_flush()
{
dtables::lgdt(&GDTR);
// Reload the segment descriptors
segmentation::load_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16));
segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16));
segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16));
segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16));
//segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_DATA as u16));
//segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16));
}

View file

@ -0,0 +1,25 @@
// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
pub mod processor;
pub mod gdt;

View file

@ -0,0 +1,602 @@
// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#![allow(dead_code)]
use logging::*;
use spin;
use raw_cpuid::*;
// feature list 0x00000001 (ebx)
const CPU_FEATURE_FPU : u32 = (1 << 0);
const CPU_FEATURE_PSE : u32 = (1 << 3);
const CPU_FEATURE_MSR : u32 = (1 << 5);
const CPU_FEATURE_PAE : u32 = (1 << 6);
const CPU_FEATURE_APIC : u32 = (1 << 9);
const CPU_FEATURE_SEP : u32 = (1 << 11);
const CPU_FEATURE_PGE : u32 = (1 << 13);
const CPU_FEATURE_PAT : u32 = (1 << 16);
const CPU_FEATURE_PSE36 : u32 = (1 << 17);
const CPU_FEATURE_CLFLUSH : u32 = (1 << 19);
const CPU_FEATURE_MMX : u32 = (1 << 23);
const CPU_FEATURE_FXSR : u32 = (1 << 24);
const CPU_FEATURE_SSE : u32 = (1 << 25);
const CPU_FEATURE_SSE2 : u32 = (1 << 26);
// feature list 0x00000001 (ecx)
const CPU_FEATURE_MWAIT : u32 = (1 << 3);
const CPU_FEATURE_VMX : u32 = (1 << 5);
const CPU_FEATURE_EST : u32 = (1 << 7);
const CPU_FEATURE_SSE3 : u32 = (1 << 9);
const CPU_FEATURE_FMA : u32 = (1 << 12);
const CPU_FEATURE_DCA : u32 = (1 << 18);
const CPU_FEATURE_SSE4_1 : u32 = (1 << 19);
const CPU_FEATURE_SSE4_2 : u32 = (1 << 20);
const CPU_FEATURE_X2APIC : u32 = (1 << 21);
const CPU_FEATURE_MOVBE : u32 = (1 << 22);
const CPU_FEATURE_XSAVE : u32 = (1 << 26);
const CPU_FEATURE_OSXSAVE : u32 = (1 << 27);
const CPU_FEATURE_AVX : u32 = (1 << 28);
const CPU_FEATURE_RDRAND : u32 = (1 << 30);
const CPU_FEATURE_HYPERVISOR : u32 = (1 << 31);
// const.80000001H:EDX feature list
const CPU_FEATURE_SYSCALL : u32 = (1 << 11);
const CPU_FEATURE_NX : u32 = (1 << 20);
const CPU_FEATURE_1GBHP : u32 = (1 << 26);
const CPU_FEATURE_RDTSCP : u32 = (1 << 27);
const CPU_FEATURE_LM : u32 = (1 << 29);
// feature list 0x00000007:0
const CPU_FEATURE_FSGSBASE : u32 = (1 << 0);
const CPU_FEATURE_TSC_ADJUST : u32 = (1 << 1);
const CPU_FEATURE_BMI1 : u32 = (1 << 3);
const CPU_FEATURE_HLE : u32 = (1 << 4);
const CPU_FEATURE_AVX2 : u32 = (1 << 5);
const CPU_FEATURE_SMEP : u32 = (1 << 7);
const CPU_FEATURE_BMI2 : u32 = (1 << 8);
const CPU_FEATURE_ERMS : u32 = (1 << 9);
const CPU_FEATURE_INVPCID : u32 = (1 << 10);
const CPU_FEATURE_RTM : u32 = (1 << 11);
const CPU_FEATURE_CQM : u32 = (1 << 12);
const CPU_FEATURE_MPX : u32 = (1 << 14);
const CPU_FEATURE_AVX512F : u32 = (1 << 16);
const CPU_FEATURE_RDSEED : u32 = (1 << 18);
const CPU_FEATURE_ADX : u32 = (1 << 19);
const CPU_FEATURE_SMAP : u32 = (1 << 20);
const CPU_FEATURE_PCOMMIT : u32 = (1 << 22);
const CPU_FEATURE_CLFLUSHOPT : u32 = (1 << 23);
const CPU_FEATURE_CLWB : u32 = (1 << 24);
const CPU_FEATURE_AVX512PF : u32 = (1 << 26);
const CPU_FEATURE_AVX512ER : u32 = (1 << 27);
const CPU_FEATURE_AVX512CD : u32 = (1 << 28);
const CPU_FEATURE_SHA_NI : u32 = (1 << 29);
// feature list 0x00000006
const CPU_FEATURE_IDA : u32 = (1 << 0);
const CPU_FEATURE_EPB : u32 = (1 << 3);
const CPU_FEATURE_HWP : u32 = (1 << 10);
/*
* EFLAGS bits
*/
const EFLAGS_CF : u32 = (1 << 0); /* Carry Flag */
const EFLAGS_FIXED : u32 = (1 << 1); /* Bit 1 - always on */
const EFLAGS_PF : u32 = (1 << 2); /* Parity Flag */
const EFLAGS_AF : u32 = (1 << 4); /* Auxiliary carry Flag */
const EFLAGS_ZF : u32 = (1 << 6); /* Zero Flag */
const EFLAGS_SF : u32 = (1 << 7); /* Sign Flag */
const EFLAGS_TF : u32 = (1 << 8); /* Trap Flag */
const EFLAGS_IF : u32 = (1 << 9); /* Interrupt Flag */
const EFLAGS_DF : u32 = (1 << 10); /* Direction Flag */
const EFLAGS_OF : u32 = (1 << 11); /* Overflow Flag */
const EFLAGS_IOPL : u32 = (1 << 12); /* I/O Privilege Level (2 bits) */
const EFLAGS_NT : u32 = (1 << 14); /* Nested Task */
const EFLAGS_RF : u32 = (1 << 16); /* Resume Flag */
const EFLAGS_VM : u32 = (1 << 17); /* Virtual Mode */
const EFLAGS_AC : u32 = (1 << 18); /* Alignment Check/Access Control */
const EFLAGS_VIF : u32 = (1 << 19); /* Virtual Interrupt Flag */
const EFLAGS_VIP : u32 = (1 << 20); /* Virtual Interrupt Pending */
const EFLAGS_ID : u32 = (1 << 21); /* const detection */
// x86 control registers
/// Protected Mode Enable
const CR0_PE : u32 = (1 << 0);
/// Monitor coprocessor
const CR0_MP : u32 = (1 << 1);
/// Enable FPU emulation
const CR0_EM : u32 = (1 << 2);
/// Task switched
const CR0_TS : u32 = (1 << 3);
/// Extension type of coprocessor
const CR0_ET : u32 = (1 << 4);
/// Enable FPU error reporting
const CR0_NE : u32 = (1 << 5);
/// Enable write protected pages
const CR0_WP : u32 = (1 << 16);
/// Enable alignment checks
const CR0_AM : u32 = (1 << 18);
/// Globally enables/disable write-back caching
const CR0_NW : u32 = (1 << 29);
/// Globally disable memory caching
const CR0_CD : u32 = (1 << 30);
/// Enable paging
const CR0_PG : u32 = (1 << 31);
/// Virtual 8086 Mode Extensions
const CR4_VME: u32 = (1 << 0);
/// Protected-mode Virtual Interrupts
const CR4_PVI : u32 = (1 << 1);
/// Disable Time Stamp Counter register (rdtsc instruction)
const CR4_TSD : u32 = (1 << 2);
/// Enable debug extensions
const CR4_DE : u32 = (1 << 3);
/// Enable hugepage support
const CR4_PSE : u32 = (1 << 4);
/// Enable physical address extension
const CR4_PAE : u32 = (1 << 5);
/// Enable machine check exceptions
const CR4_MCE : u32 = (1 << 6);
/// Enable global pages
const CR4_PGE : u32 = (1 << 7);
/// Enable Performance-Monitoring Counter
const CR4_PCE : u32 = (1 << 8);
/// Enable Operating system support for FXSAVE and FXRSTOR instructions
const CR4_OSFXSR : u32 = (1 << 9);
/// Enable Operating System Support for Unmasked SIMD Floating-Point Exceptions
const CR4_OSXMMEXCPT : u32 = (1 << 10);
/// Enable Virtual Machine Extensions, see Intel VT-x
const CR4_VMXE : u32 = (1 << 13);
/// Enable Safer Mode Extensions, see Trusted Execution Technology (TXT)
const CR4_SMXE : u32 = (1 << 14);
/// Enables the instructions RDFSBASE, RDGSBASE, WRFSBASE, and WRGSBASE
const CR4_FSGSBASE : u32 = (1 << 16);
/// Enables process-context identifiers
const CR4_PCIDE : u32 = (1 << 17);
/// Enable XSAVE and Processor Extended States
const CR4_OSXSAVE : u32 = (1 << 18);
/// Enable Supervisor Mode Execution Protection
const CR4_SMEP : u32 = (1 << 20);
/// Enable Supervisor Mode Access Protection
const CR4_SMAP : u32 = (1 << 21);
// x86-64 specific MSRs
/// APIC register
const MSR_APIC_BASE : u32 = 0x0000001B;
/// extended feature register
const MSR_EFER : u32 = 0xc0000080;
/// legacy mode SYSCALL target
const MSR_STAR : u32 = 0xc0000081;
/// long mode SYSCALL target
const MSR_LSTAR : u32 = 0xc0000082;
/// compat mode SYSCALL target
const MSR_CSTAR : u32 = 0xc0000083;
/// EFLAGS mask for syscall
const MSR_SYSCALL_MASK : u32 = 0xc0000084;
/// 64bit FS base
const MSR_FS_BASE : u32 = 0xc0000100;
/// 64bit GS base
const MSR_GS_BASE : u32 = 0xc0000101;
/// SwapGS GS shadow
const MSR_KERNEL_GS_BASE : u32 = 0xc0000102;
const MSR_XAPIC_ENABLE : u32 = (1 << 11);
const MSR_X2APIC_ENABLE : u32 = (1 << 10);
const MSR_IA32_PLATFORM_ID : u32 = 0x00000017;
const MSR_IA32_PERFCTR0 : u32 = 0x000000c1;
const MSR_IA32_PERFCTR1 : u32 = 0x000000c2;
const MSR_FSB_FREQ : u32 = 0x000000cd;
const MSR_PLATFORM_INFO : u32 = 0x000000ce;
const MSR_IA32_MPERF : u32 = 0x000000e7;
const MSR_IA32_APERF : u32 = 0x000000e8;
const MSR_IA32_MISC_ENABLE : u32 = 0x000001a0;
const MSR_IA32_FEATURE_CONTROL : u32 = 0x0000003a;
const MSR_IA32_ENERGY_PERF_BIAS : u32 = 0x000001b0;
const MSR_IA32_PERF_STATUS : u32 = 0x00000198;
const MSR_IA32_PERF_CTL : u32 = 0x00000199;
const MSR_IA32_CR_PAT : u32 = 0x00000277;
const MSR_MTRRDEFTYPE : u32 = 0x000002ff;
const MSR_PPERF : u32 = 0x0000064e;
const MSR_PERF_LIMIT_REASONS : u32 = 0x0000064f;
const MSR_PM_ENABLE : u32 = 0x00000770;
const MSR_HWP_CAPABILITIES : u32 = 0x00000771;
const MSR_HWP_REQUEST_PKG : u32 = 0x00000772;
const MSR_HWP_INTERRUPT : u32 = 0x00000773;
const MSR_HWP_REQUEST : u32 = 0x00000774;
const MSR_HWP_STATUS : u32 = 0x00000777;
const MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP : u64 = (1 << 16);
const MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK : u64 = (1 << 20);
const MSR_IA32_MISC_ENABLE_TURBO_DISABLE : u64 = (1 << 38);
const MSR_MTRRFIX64K_00000 : u32 = 0x00000250;
const MSR_MTRRFIX16K_80000 : u32 = 0x00000258;
const MSR_MTRRFIX16K_A0000 : u32 = 0x00000259;
const MSR_MTRRFIX4K_C0000 : u32 = 0x00000268;
const MSR_MTRRFIX4K_C8000 : u32 = 0x00000269;
const MSR_MTRRFIX4K_D0000 : u32 = 0x0000026a;
const MSR_MTRRFIX4K_D8000 : u32 = 0x0000026b;
const MSR_MTRRFIX4K_E0000 : u32 = 0x0000026c;
const MSR_MTRRFIX4K_E8000 : u32 = 0x0000026d;
const MSR_MTRRFIX4K_F0000 : u32 = 0x0000026e;
const MSR_MTRRFIX4K_F8000 : u32 = 0x0000026f;
const MSR_OFFCORE_RSP_0 : u32 = 0x000001a6;
const MSR_OFFCORE_RSP_1 : u32 = 0x000001a7;
const MSR_NHM_TURBO_RATIO_LIMIT : u32 = 0x000001ad;
const MSR_IVT_TURBO_RATIO_LIMIT : u32 = 0x000001ae;
const MSR_TURBO_RATIO_LIMIT : u32 = 0x000001ad;
const MSR_TURBO_RATIO_LIMIT1 : u32 = 0x000001ae;
const MSR_TURBO_RATIO_LIMIT2 : u32 = 0x000001af;
// MSR EFER bits
const EFER_SCE : u32 = (1 << 0);
const EFER_LME : u32 = (1 << 8);
const EFER_LMA : u32 = (1 << 10);
const EFER_NXE : u32 = (1 << 11);
const EFER_SVME : u32 = (1 << 12);
const EFER_LMSLE : u32 = (1 << 13);
const EFER_FFXSR : u32 = (1 << 14);
const EFER_TCE : u32 = (1 << 15);
pub struct CpuInfo {
feature1 : u32,
feature2 : u32,
feature3 : u32,
feature4 : u32,
addr_width : u32
}
/// Execute CPUID instruction with eax, ebx, ecx and edx register set.
/// Note: This is a low-level function to query cpuid directly.
#[warn(unused_assignments)]
fn cpuid4(mut eax: u32, mut ebx: u32, mut ecx: u32, mut edx: u32) -> CpuIdResult {
unsafe {
asm!("cpuid" : "+{eax}"(eax) "+{ebx}"(ebx) "+{ecx}"(ecx) "+{edx}"(edx) ::: "volatile");
}
CpuIdResult { eax: eax, ebx: ebx, ecx: ecx, edx: edx }
}
impl CpuInfo {
fn new() -> Self {
let mut cpuid: CpuIdResult = cpuid4(0, 0, 0, 0);
let level: u32 = cpuid.ebx;
cpuid = cpuid4(1, 0, 0, 0);
let mut f1: u32 = cpuid.edx;
let f2: u32 = cpuid.ecx;
let family: u32 = (cpuid.eax & 0x00000F00u32) >> 8;
let model: u32 = (cpuid.eax & 0x000000F0u32) >> 4;
let stepping: u32 = cpuid.eax & 0x0000000Fu32;
if (family == 6) && (model < 3) && (stepping < 3) {
f1 &= 0 ^ CPU_FEATURE_SEP;
}
cpuid = cpuid4(0x80000000u32, 0, 0, 0);
let extended: u32 = cpuid.eax;
let mut f3: u32 = 0;
if extended >= 0x80000001u32 {
cpuid = cpuid4(0x80000001u32, 0, 0, 0);
f3 = cpuid.edx;
}
let mut width: u32 = 0;
if extended >= 0x80000008u32 {
cpuid = cpuid4(0x80000008u32, 0, 0, 0);
width = cpuid.eax;
}
let mut f4: u32 = 0;
/* Additional Intel-defined flags: level 0x00000007 */
if level >= 0x00000007u32 {
cpuid = cpuid4(0x7u32, 0, 0, 0);
f4 = cpuid.ebx;
}
CpuInfo{
feature1 : f1,
feature2 : f2,
feature3 : f3,
feature4 : f4,
addr_width : width
}
}
#[inline(always)]
pub const fn has_fpu(&self) -> bool {
(self.feature1 & CPU_FEATURE_FPU) != 0
}
#[inline(always)]
pub const fn has_msr(&self) -> bool {
(self.feature1 & CPU_FEATURE_MSR) != 0
}
#[inline(always)]
pub const fn has_apic(&self) -> bool {
(self.feature1 & CPU_FEATURE_APIC) != 0
}
#[inline(always)]
pub const fn has_fxsr(&self) -> bool {
(self.feature1 & CPU_FEATURE_FXSR) != 0
}
#[inline(always)]
pub const fn has_clflush(&self) -> bool {
(self.feature1 & CPU_FEATURE_CLFLUSH) != 0
}
#[inline(always)]
pub const fn has_sse(&self) -> bool {
(self.feature1 & CPU_FEATURE_SSE) != 0
}
#[inline(always)]
pub const fn has_pat(&self) -> bool {
(self.feature1 & CPU_FEATURE_PAT) != 0
}
#[inline(always)]
pub const fn has_sse2(&self) -> bool {
(self.feature1 & CPU_FEATURE_SSE2) != 0
}
#[inline(always)]
pub const fn has_pge(&self) -> bool {
(self.feature1 & CPU_FEATURE_PGE) != 0
}
#[inline(always)]
pub const fn has_sep(&self) -> bool {
(self.feature1 & CPU_FEATURE_SEP) != 0
}
#[inline(always)]
pub const fn has_movbe(&self) -> bool {
(self.feature2 & CPU_FEATURE_MOVBE) != 0
}
#[inline(always)]
pub const fn has_fma(&self) -> bool {
(self.feature2 & CPU_FEATURE_FMA) != 0
}
#[inline(always)]
pub const fn has_mwait(&self) -> bool {
(self.feature2 & CPU_FEATURE_MWAIT) != 0
}
#[inline(always)]
pub const fn has_vmx(&self) -> bool {
(self.feature2 & CPU_FEATURE_VMX) != 0
}
#[inline(always)]
pub const fn has_est(&self) -> bool {
(self.feature2 & CPU_FEATURE_EST) != 0
}
#[inline(always)]
pub const fn has_sse3(&self) -> bool {
(self.feature2 & CPU_FEATURE_SSE3) != 0
}
#[inline(always)]
pub const fn has_dca(&self) -> bool {
(self.feature2 & CPU_FEATURE_DCA) != 0
}
#[inline(always)]
pub const fn has_sse4_1(&self) -> bool {
(self.feature2 & CPU_FEATURE_SSE4_1) != 0
}
#[inline(always)]
pub const fn has_sse4_2(&self) -> bool {
(self.feature2 & CPU_FEATURE_SSE4_2) != 0
}
#[inline(always)]
pub const fn has_x2apic(&self) -> bool {
(self.feature2 & CPU_FEATURE_X2APIC) != 0
}
#[inline(always)]
pub const fn has_xsave(&self) -> bool {
(self.feature2 & CPU_FEATURE_XSAVE) != 0
}
#[inline(always)]
pub const fn has_osxsave(&self) -> bool {
(self.feature2 & CPU_FEATURE_OSXSAVE) != 0
}
#[inline(always)]
pub const fn has_avx(&self) -> bool {
(self.feature2 & CPU_FEATURE_AVX) != 0
}
#[inline(always)]
pub const fn has_rdrand(&self) -> bool {
(self.feature2 & CPU_FEATURE_RDRAND) != 0
}
#[inline(always)]
pub const fn on_hypervisor(&self) -> bool {
(self.feature2 & CPU_FEATURE_HYPERVISOR) != 0
}
#[inline(always)]
pub const fn has_nx(&self) -> bool {
(self.feature3 & CPU_FEATURE_NX) != 0
}
#[inline(always)]
pub const fn has_fsgsbase(&self) -> bool {
(self.feature4 & CPU_FEATURE_FSGSBASE) != 0
}
#[inline(always)]
pub const fn has_avx2(&self) -> bool {
(self.feature4 & CPU_FEATURE_AVX2) != 0
}
#[inline(always)]
pub const fn has_bmi1(&self) -> bool {
(self.feature4 & CPU_FEATURE_BMI1) != 0
}
#[inline(always)]
pub const fn has_bmi2(&self) -> bool {
(self.feature4 & CPU_FEATURE_BMI2) != 0
}
#[inline(always)]
pub const fn has_hle(&self) -> bool {
(self.feature4 & CPU_FEATURE_HLE) != 0
}
#[inline(always)]
pub const fn has_cqm(&self) -> bool {
(self.feature4 & CPU_FEATURE_CQM) != 0
}
#[inline(always)]
pub const fn has_rtm(&self) -> bool {
(self.feature4 & CPU_FEATURE_RTM) != 0
}
#[inline(always)]
pub const fn has_avx512f(&self) -> bool {
(self.feature4 & CPU_FEATURE_AVX512F) != 0
}
#[inline(always)]
pub const fn has_avx512pf(&self) -> bool {
(self.feature4 & CPU_FEATURE_AVX512PF) != 0
}
#[inline(always)]
pub const fn has_avx512er(&self) -> bool {
(self.feature4 & CPU_FEATURE_AVX512ER) != 0
}
#[inline(always)]
pub const fn has_avx512cd(&self) -> bool {
(self.feature4 & CPU_FEATURE_AVX512CD) != 0
}
#[inline(always)]
pub const fn has_rdtscp(&self) -> bool {
(self.feature3 & CPU_FEATURE_RDTSCP) != 0
}
fn print_infos(&self) {
info!("CPU features: {}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
if self.has_sse() { "SSE " } else { "" },
if self.has_sse2() { "SSE2 " } else { "" },
if self.has_sse3() { "SSE3 " } else { "" },
if self.has_sse4_1() { "SSE4.1 " } else { "" },
if self.has_sse4_2() { "SSE4.2 " } else { "" },
if self.has_avx() { "AVX " } else { "" },
if self.has_avx2() { "AVX2 " } else { "" },
if self.has_rdrand() { "RDRAND " } else { "" },
if self.has_fma() { "FMA " } else { "" },
if self.has_movbe() { "MOVBE " } else { "" },
if self.has_x2apic() { "X2APIC " } else { "" },
if self.has_fpu() { "FPU " } else { "" },
if self.has_fxsr() { "FXSR " } else { "" },
if self.has_xsave() { "XSAVE " } else { "" },
if self.has_osxsave() { "OSXSAVE " } else { "" },
if self.has_vmx() { "VMX " } else { "" },
if self.has_rdtscp() { "RDTSCP " } else { "" },
if self.has_fsgsbase() { "FSGSBASE " } else { "" },
if self.has_mwait() { "MWAIT " } else { "" },
if self.has_clflush() { "CLFLUSH " } else { "" },
if self.has_bmi1() { "BMI1 " } else { "" },
if self.has_bmi2() { "BMI2 " } else { "" },
if self.has_dca() { "DCA " } else { "" },
if self.has_rtm() { "RTM " } else { "" },
if self.has_hle() { "HLE " } else { "" },
if self.has_cqm() { "CQM " } else { "" },
if self.has_avx512f() { "AVX512F " } else { "" },
if self.has_avx512cd() { "AVX512CD " } else { "" },
if self.has_avx512pf() { "AVX512PF " } else { "" },
if self.has_avx512er() == true { "AVX512ER " } else { "" });
info!("Paging features: {}{}{}{}{}{}{}{}",
if (self.feature1 & CPU_FEATURE_PSE) != 0 { "PSE (2/4Mb) " } else { "" },
if (self.feature1 & CPU_FEATURE_PAE) != 0 { "PAE " } else { "" },
if (self.feature1 & CPU_FEATURE_PGE) != 0 { "PGE " } else { "" },
if (self.feature1 & CPU_FEATURE_PAT) != 0 { "PAT " } else { "" },
if (self.feature1 & CPU_FEATURE_PSE36) != 0 { "PSE36 " } else { "" },
if (self.feature3 & CPU_FEATURE_NX) != 0 { "NX " } else { "" },
if (self.feature3 & CPU_FEATURE_1GBHP) != 0 { "PSE (1Gb) " } else { "" },
if (self.feature3 & CPU_FEATURE_LM) != 0 { "LM" } else { "" });
info!("Physical adress-width: {} bits", self.addr_width & 0xff);
info!("Linear adress-width: {} bits", (self.addr_width >> 8) & 0xff);
info!("Sysenter instruction: {}", if (self.feature1 & CPU_FEATURE_SEP) != 0 { "available" } else { "unavailable" });
info!("Syscall instruction: {}", if (self.feature3 & CPU_FEATURE_SYSCALL) != 0 { "available" } else { "unavailable" });
}
}
static mut CPU_INFO : CpuInfo = CpuInfo {
feature1 : 0,
feature2 : 0,
feature3 : 0,
feature4 : 0,
addr_width : 0
};
static CPU_INIT: spin::Once<()> = spin::Once::new();
/// Returns a reference to CpuInfo, which describes all CPU features.
/// The return value is only valid if cpu_detection is already called an initialized
/// the system.
pub fn get_cpuinfo() -> &'static CpuInfo {
unsafe {
&CPU_INFO
}
}
/// Determine CPU features and activates all by HermitCore supported features
pub fn cpu_detection() {
// A synchronization primitive which can be used to run a one-time global initialization.
CPU_INIT.call_once(|| {
unsafe {
CPU_INFO = CpuInfo::new();
}
});
let cpu_info = get_cpuinfo();
cpu_info.print_infos();
}

56
librs/src/console.rs Normal file
View file

@ -0,0 +1,56 @@
// Copyright (c) 2017, Stefan Lankes, RWTH Aachen University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the University nor the names of its contributors
// may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use core::fmt;
use spin::Mutex;
extern {
pub fn kputchar(c: u8) -> i32;
}
pub struct Console;
/// A collection of methods that are required to format
/// a message to HermitCore's console.
impl fmt::Write for Console {
/// print character to the screen
fn write_char(&mut self, c: char) -> fmt::Result {
let out: u8 = c as u8;
unsafe {
kputchar(out);
}
Ok(())
}
/// print string as kernel message.
fn write_str(&mut self, s: &str) -> fmt::Result {
for chars in s.chars() {
self.write_char(chars).unwrap();
}
Ok(())
}
}
pub static CONSOLE: Mutex<Console> = Mutex::new(Console);

30
librs/src/consts.rs Normal file
View file

@ -0,0 +1,30 @@
// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#![allow(dead_code)]
pub const MAX_CORES : usize = 512;
pub const KERNEL_STACK_SIZE : usize = 8192;
#[cfg(target_arch="x86_64")]
pub const PAGE_SIZE : usize = 4096;

65
librs/src/lib.rs Normal file
View file

@ -0,0 +1,65 @@
// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/*
* First version is derived and adapted for HermitCore from
* Philipp Oppermann's excellent series of blog posts (http://blog.phil-opp.com/)
* and Eric Kidd's toy OS (https://github.com/emk/toyos-rs).
*/
#![feature(asm, const_fn, lang_items, repr_align, attr_literals)]
#![no_std]
extern crate rlibc;
extern crate spin;
extern crate x86;
extern crate raw_cpuid;
// These need to be visible to the linker, so we need to export them.
pub use runtime_glue::*;
pub use logging::*;
pub use consts::*;
#[cfg(target_arch="x86_64")]
pub use arch::gdt::*;
#[macro_use]
mod macros;
#[macro_use]
mod logging;
mod runtime_glue;
mod console;
mod arch;
mod consts;
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
#[no_mangle]
pub extern "C" fn rust_init() {
info!("HermitCore's Rust runtime! v{}", VERSION);
}
#[no_mangle]
pub extern "C" fn rust_main() {
arch::processor::cpu_detection();
}

137
librs/src/logging.rs Normal file
View file

@ -0,0 +1,137 @@
// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#![allow(unused_macros)]
/// An enum representing the available verbosity levels of the logger.
#[derive(Copy, Clone)]
pub enum LogLevel {
/// Disable all our put messages
///
/// Designates without information
DISABLED = 0,
/// The "error" level.
///
/// Designates very serious errors.
ERROR,
/// The "warn" level.
///
/// Designates hazardous situations.
WARNING,
/// The "info" level.
///
/// Designates useful information.
INFO,
// The "debug" level.
///
/// Designates lower priority information.
DEBUG
}
/// Data structures to filter kernel messages
pub struct KernelLogger {
pub log_level: LogLevel,
}
/// default logger to handle kernel messages
pub static LOGGER: KernelLogger = KernelLogger { log_level: LogLevel::INFO };
/// Print formatted info text to our console, followed by a newline.
macro_rules! info {
($fmt:expr) => ({
let current_level = LOGGER.log_level as u8;
let cmp_level = LogLevel::INFO as u8;
if current_level >= cmp_level {
println!(concat!("[INFO] ", $fmt));
}
});
($fmt:expr, $($arg:tt)*) => ({
let current_level = LOGGER.log_level as u8;
let cmp_level = LogLevel::INFO as u8;
if current_level >= cmp_level {
println!(concat!("[INFO] ", $fmt), $($arg)*);
}
});
}
/// Print formatted warnings to our console, followed by a newline.
macro_rules! warn {
($fmt:expr) => ({
let current_level = LOGGER.log_level as u8;
let cmp_level = LogLevel::WARNING as u8;
if current_level >= cmp_level {
println!(concat!("[WARNING] ", $fmt));
}
});
($fmt:expr, $($arg:tt)*) => ({
let current_level = LOGGER.log_level as u8;
let cmp_level = LogLevel::WARNING as u8;
if current_level >= cmp_level {
println!(concat!("[WARNING] ", $fmt), $($arg)*);
}
});
}
/// Print formatted warnings to our console, followed by a newline.
macro_rules! error {
($fmt:expr) => ({
let current_level = LOGGER.log_level as u8;
let cmp_level = LogLevel::ERROR as u8;
if current_level >= cmp_level {
println!(concat!("[ERROR] ", $fmt));
}
});
($fmt:expr, $($arg:tt)*) => ({
let current_level = LOGGER.log_level as u8;
let cmp_level = LogLevel::ERROR as u8;
if current_level >= cmp_level {
println!(concat!("[ERROR] ", $fmt), $($arg)*);
}
});
}
/// Print formatted debuf messages to our console, followed by a newline.
macro_rules! debug {
($fmt:expr) => ({
let current_level = LOGGER.log_level as u8;
let cmp_level = LogLevel::DEBUG as u8;
if current_level >= cmp_level {
println!(concat!("[DEBUG] ", $fmt));
}
});
($fmt:expr, $($arg:tt)*) => ({
let current_level = LOGGER.log_level as u8;
let cmp_level = LogLevel::DEBUG as u8;
if current_level >= cmp_level {
println!(concat!("[DEBUG] ", $fmt), $($arg)*);
}
});
}

46
librs/src/macros.rs Normal file
View file

@ -0,0 +1,46 @@
// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/// Determin the Id of the current CPU
macro_rules! core_id {
() => ( 0 );
}
/// Print formatted text to our console.
///
/// From http://blog.phil-opp.com/rust-os/printing-to-screen.html, but tweaked
/// for HermitCore.
macro_rules! print {
($($arg:tt)*) => ({
use core::fmt::Write;
$crate::console::CONSOLE.lock().write_fmt(format_args!($($arg)*)).unwrap();
});
}
/// Print formatted text to our console, followed by a newline.
///
/// From https://doc.rust-lang.org/nightly/std/macro.println!.html
macro_rules! println {
($fmt:expr) => (print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}

46
librs/src/runtime_glue.rs Normal file
View file

@ -0,0 +1,46 @@
// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//! Minor functions that Rust really expects to be defined by the compiler,
//! but which we need to provide manually because we're on bare metal.
#![allow(private_no_mangle_fns)]
#[lang = "eh_personality"]
extern "C" fn eh_personality() {
}
#[lang = "panic_fmt"] #[no_mangle]
extern "C" fn panic_fmt(args: ::core::fmt::Arguments, file: &str, line: usize) -> !
{
println!("PANIC: {}:{}: {}", file, line, args);
loop {}
}
#[no_mangle]
#[allow(non_snake_case)]
pub fn _Unwind_Resume()
{
println!("UNWIND!");
loop {}
}

20
librs/x86_64-hermit.json Normal file
View file

@ -0,0 +1,20 @@
{
"llvm-target": "x86_64-unknown-none-gnu",
"linker-flavor": "gcc",
"target-endian": "little",
"target-pointer-width": "64",
"os": "none",
"arch": "x86_64",
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"pre-link-args": [ "-m64" ],
"cpu": "x86-64",
"features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float",
"disable-redzone": true,
"eliminate-frame-pointer": true,
"linker-is-gnu": true,
"no-compiler-rt": true,
"archive-format": "gnu",
"code-model": "kernel",
"relocation-model": "static",
"panic-strategy": "abort"
}

2
objmv/.gitignore vendored Normal file
View file

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

9
objmv/Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
[package]
name = "objmv"
version = "0.1.0"
authors = [
"Stefan Lankes <slankes@eonerc.rwth-aachen.de>",
]
[dependencies]
regex = "0.*"

92
objmv/src/main.rs Normal file
View file

@ -0,0 +1,92 @@
// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#![feature(rustc_private)]
extern crate regex;
#[macro_use]
extern crate log;
use regex::RegexSet;
use std::str;
use std::env;
use std::process::Command;
use std::vec::Vec;
fn rename_sections(fname: String)
{
let output = Command::new("objdump")
.arg("-h")
.arg(fname.to_string())
.output()
.expect("objdump failed to start");
if output.status.success() {
let mut args: Vec<String> = Vec::new();
let re = RegexSet::new(&[r"^.text", r"^.data", r"^.bss"]).unwrap();
let output_string = String::from_utf8_lossy(&output.stdout);
let substrings = output_string.split_whitespace();
for old_name in substrings {
if re.is_match(old_name) {
let mut new_name: String = ".k".to_owned();
new_name.push_str(old_name.trim_left_matches('.'));
//println!("{} {}", old_name, new_name);
let mut cmd: String = String::new();
cmd.push_str(old_name);
cmd.push('=');
cmd.push_str(&new_name);
//println!("{}", cmd);
args.push("--rename-section".to_string());
args.push(cmd);
}
}
if args.len() > 0 {
let status = Command::new("objcopy")
.args(args)
.arg(fname.to_string())
.status()
.expect("objcopy failed to start");
if !status.success() {
warn!("Unable to rename sections in {}", fname);
}
}
} else {
warn!("Unable to determine section names in {}", fname);
}
}
fn main() {
let mut arguments: Vec<String> = env::args().collect();
// remove unneeded programm name
arguments.remove(0);
for arg in arguments {
rename_sections(arg);
}
}

View file

@ -9,7 +9,7 @@ PROXY=build/local_prefix/opt/hermit/bin/proxy
for f in $FILES; do echo "check $f..."; HERMIT_ISLE=qemu HERMIT_CPUS=1 HERMIT_KVM=0 HERMIT_VERBOSE=1 timeout --kill-after=5m 5m $PROXY $f || exit 1; done
for f in $FILES; do echo "check $f..."; HERMIT_ISLE=qemu HERMIT_CPUS=2 HERMIT_KVM=0 HERMIT_VERBOSE=1 timeout --kill-after=5m 5m $PROXY $f || exit 1; done
#for f in $FILES; do echo "check $f..."; HERMIT_ISLE=qemu HERMIT_CPUS=2 HERMIT_KVM=0 HERMIT_VERBOSE=1 timeout --kill-after=5m 5m $PROXY $f || exit 1; done
# test echo server at port 8000
HERMIT_ISLE=qemu HERMIT_CPUS=1 HERMIT_KVM=0 HERMIT_VERBOSE=1 HERMIT_APP_PORT=8000 $PROXY $TDIR/tests/server &

View file

@ -100,8 +100,8 @@
#define PAGE_MASK ((~0L) << PAGE_BITS)
#define PAGE_2M_MASK (~0L) << PAGE_2M_BITS)
#else
#define PAGE_MASK (((~0L) << PAGE_BITS) & ~PG_XD)
#define PAGE_2M_MASK (((~0L) << PAGE_2M_BITS) & ~PG_XD)
#define PAGE_MASK (((~0UL) << PAGE_BITS) & ~PG_XD)
#define PAGE_2M_MASK (((~0UL) << PAGE_2M_BITS) & ~PG_XD)
#endif
// Page is present
@ -517,6 +517,17 @@ static int load_checkpoint(uint8_t* mem, char* path)
return 0;
}
static size_t virt2phys(size_t addr)
{
struct kvm_translation trans;
// determine guest physical address of the current rsp
trans.linear_address = addr;
kvm_ioctl(vcpufd, KVM_TRANSLATE, &trans);
return trans.physical_address;
}
static inline void show_dtable(const char *name, struct kvm_dtable *dtable)
{
fprintf(stderr, " %s %016zx %08hx\n", name, (size_t) dtable->base, (uint16_t) dtable->limit);
@ -589,6 +600,29 @@ static void show_registers(int id, struct kvm_regs* regs, struct kvm_sregs* sreg
for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++)
fprintf(stderr, " %016zx", (size_t) sregs->interrupt_bitmap[i]);
fprintf(stderr, "\n");
fprintf(stderr, "\n Last values on the stack:\n");
// determine guest physical address of the current rsp
size_t rsp_phys = virt2phys(regs->rsp);
for (i=7; i>=0; i--)
fprintf(stderr, " [0x%llx] = 0x%zx\n", regs->rsp+i*sizeof(size_t),
*((size_t*)(guest_mem+rsp_phys+i*sizeof(size_t))));
size_t tr_phys = virt2phys(sregs->tr.base);
for(i=0; i<7; i++) {
size_t vaddr = *((size_t*) (guest_mem+tr_phys+9*4+i*sizeof(size_t)));
if (vaddr) {
fprintf(stderr, "\n Last values on IST%d (at 0x%zx):\n", i, vaddr);
size_t paddr = virt2phys(vaddr);
for(int j=0; j<8; j++)
fprintf(stderr, " [0x%zx] = 0x%zx\n", vaddr-j*sizeof(size_t),
*((size_t*) (guest_mem+paddr-j*sizeof(size_t))));
}
}
}
static void print_registers(void)
@ -836,11 +870,13 @@ static int vcpu_loop(void)
break;
case KVM_EXIT_SHUTDOWN:
print_registers();
err(1, "KVM: receive shutdown command\n");
break;
case KVM_EXIT_DEBUG:
print_registers();
default:
fprintf(stderr, "KVM: unhandled exit: exit_reason = 0x%x\n", run->exit_reason);
exit(EXIT_FAILURE);