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:
commit
bd585ae180
31 changed files with 1808 additions and 46 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -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
|
||||
|
|
91
.travis.yml
91
.travis.yml
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
58
libkern/muloti4.c
Normal 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
2
librs/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
target
|
||||
Cargo.lock
|
42
librs/Cargo.toml
Normal file
42
librs/Cargo.toml
Normal 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
51
librs/Makefile
Normal 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
1
librs/rust
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 230a379a452e5a2bcdfd0a956b259e0a1d83b512
|
30
librs/src/arch/mod.rs
Normal file
30
librs/src/arch/mod.rs
Normal 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;
|
291
librs/src/arch/x86_64/gdt.rs
Normal file
291
librs/src/arch/x86_64/gdt.rs
Normal 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));
|
||||
}
|
25
librs/src/arch/x86_64/mod.rs
Normal file
25
librs/src/arch/x86_64/mod.rs
Normal 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;
|
602
librs/src/arch/x86_64/processor.rs
Normal file
602
librs/src/arch/x86_64/processor.rs
Normal 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
56
librs/src/console.rs
Normal 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
30
librs/src/consts.rs
Normal 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
65
librs/src/lib.rs
Normal 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
137
librs/src/logging.rs
Normal 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
46
librs/src/macros.rs
Normal 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
46
librs/src/runtime_glue.rs
Normal 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
20
librs/x86_64-hermit.json
Normal 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
2
objmv/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
target
|
||||
Cargo.lock
|
9
objmv/Cargo.toml
Normal file
9
objmv/Cargo.toml
Normal 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
92
objmv/src/main.rs
Normal 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);
|
||||
}
|
||||
}
|
2
tests.sh
2
tests.sh
|
@ -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 &
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue