mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
Merge branch 'master' of github.com:RWTH-OS/HermitCore
This commit is contained in:
commit
6a865b679f
170 changed files with 6496 additions and 24431 deletions
|
@ -5,7 +5,7 @@
|
|||
"subject": "rwth-os",
|
||||
"website_url": "http://www.hermitcore.org",
|
||||
"issue_tracker_url": "https://github.com/RWTH-OS/HermitCore/issues",
|
||||
"vcs_url": "https://github.com/RWTH-OS/pthread-embedded.git",
|
||||
"vcs_url": "https://github.com/RWTH-OS/HermitCore.git",
|
||||
"github_release_notes_file": "RELEASE",
|
||||
"licenses": ["Revised BSD"],
|
||||
"public_download_numbers": false,
|
||||
|
@ -13,19 +13,23 @@
|
|||
},
|
||||
|
||||
"version": {
|
||||
"name": "0.1",
|
||||
"name": "0.2",
|
||||
"desc": "HermitCore's kernel as libOS",
|
||||
"gpgSign": false
|
||||
},
|
||||
|
||||
"files":
|
||||
[{
|
||||
"includePattern": "../(libhermit[^/]*deb$)", "uploadPattern": "$1",
|
||||
[
|
||||
{
|
||||
"includePattern": "build/(libhermit[^/]*deb$)", "uploadPattern": "$1",
|
||||
"matrixParams": {
|
||||
"deb_distribution": "vivid",
|
||||
"deb_component": "main",
|
||||
"deb_architecture": "amd64",
|
||||
"override": 1}
|
||||
}],
|
||||
"override": 1}
|
||||
},
|
||||
{"includePattern": "build/(libhermit[^/]*rpm$)", "uploadPattern": "$1", "override": 1},
|
||||
{"includePattern": "build/(libhermit[^/]*tar.bz2$)", "uploadPattern": "$1", "override": 1}
|
||||
],
|
||||
"publish": true
|
||||
}
|
||||
|
|
49
.gitignore
vendored
49
.gitignore
vendored
|
@ -1,54 +1,15 @@
|
|||
config.log
|
||||
config.status
|
||||
autom4te.cache
|
||||
/Makefile
|
||||
*.pcap
|
||||
*.config
|
||||
*.creator
|
||||
*.creator.user
|
||||
*.user
|
||||
*.files
|
||||
*.includes
|
||||
*.pyc
|
||||
*.callgrind
|
||||
*.xray
|
||||
*.o
|
||||
*.a
|
||||
*.dep
|
||||
*~
|
||||
*.elf
|
||||
*.elf32
|
||||
*.sym
|
||||
*.bin
|
||||
*.ko
|
||||
**/build/*
|
||||
.idea/*
|
||||
qemu-vlan0.pcap
|
||||
autom4te.cache
|
||||
documentation/html/
|
||||
include/hermit/config.inc
|
||||
include/hermit/config.h
|
||||
tools/proxy
|
||||
usr/tests/hello
|
||||
usr/tests/hello++
|
||||
usr/tests/hellof
|
||||
usr/tests/jacobi
|
||||
usr/tests/thr_hello
|
||||
usr/tests/pi
|
||||
usr/tests/RCCE_minimum
|
||||
usr/tests/signals
|
||||
usr/tests/server
|
||||
usr/benchmarks/RCCE_pingping
|
||||
usr/benchmarks/RCCE_pingpong
|
||||
usr/benchmarks/stream
|
||||
usr/benchmarks/hg
|
||||
usr/benchmarks/netio
|
||||
usr/benchmarks/basic
|
||||
usr/openmpbench/schedbench
|
||||
usr/openmpbench/syncbench
|
||||
usr/openmpbench/taskbench
|
||||
usr/tmp/
|
||||
usr/binutils/
|
||||
usr/gcc/
|
||||
usr/newlib/
|
||||
usr/pte/
|
||||
tools/Makefile
|
||||
usr/ircce/Makefile
|
||||
usr/xray/Makefile
|
||||
arch/x86/kernel/boot.h
|
||||
cmake/cmake-3.7.2-Linux-x86_64/*
|
||||
|
|
36
.travis.yml
36
.travis.yml
|
@ -1,26 +1,27 @@
|
|||
sudo: required
|
||||
dist: trusty
|
||||
git:
|
||||
submodules: false
|
||||
submodules: true
|
||||
language: c
|
||||
compiler: gcc
|
||||
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 qemu-system-x86 nasm texinfo libmpfr-dev libmpc-dev libgmp-dev libisl-dev flex bison packaging-dev
|
||||
#- sudo apt-get install -y --force-yes binutils-hermit gcc-hermit-bootstrap
|
||||
- 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
|
||||
- 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
|
||||
|
||||
script:
|
||||
- cd ..
|
||||
- mv HermitCore libhermit-0.1
|
||||
- tar -czf libhermit_0.1.orig.tar.gz libhermit-0.1 --exclude=.git
|
||||
- cd libhermit-0.1
|
||||
- debuild -e PATH -e CFLAGS_FOR_TARGET -e GOFLAGS_FOR_TARGET -e FCFLAGS_FOR_TARGET -e FFLAGS_FOR_TARGET -e CXXFLAGS_FOR_TARGET -us -uc -j2
|
||||
- sudo dpkg -i ../libhermit*_amd64.deb
|
||||
- make -j2 examples
|
||||
- if [ "$TRAVIS_BRANCH" != "master" ]; then make test; fi
|
||||
- source cmake/local-cmake.sh
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
- make -j1 package
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
- ./tests.sh
|
||||
|
||||
notifications:
|
||||
slack: hermitcore:UtcfeEXkbpx3WyIDK2Wm2beS
|
||||
|
||||
deploy:
|
||||
on: master
|
||||
|
@ -30,16 +31,3 @@ deploy:
|
|||
secure: wo0yLY7xhGZYDqdB05UE+IOXXgYhAwj+zvtZh3ET2253hy35y74cDKMBNGfynH0aauPk8EFmN/LJoYaV/T9QF6pc1bilbqSg1/LJuL7hjAVVFaBSjwlE/Wbbb+EHNX5CR3qmC42SUvbrU+0WNvRu7WJBpZIoH9EtPv2Cj7uRV9+7Mtp/O3Ykl3E5LgkF5iA6Lo03TN+bZ1Vog5MbuJagDTpNa18vJ3jVYaed5gqOkghYYDpc5U9yxN3debS7/8MCl3u9V9uanMAyjc6wtbvJLotVkUwdXK8u9FohuWQ4pTEQ/QspLDDBuxaS3kLNWtzBMNQn6rcYIOWWKyD3uqvIhqjcErX7WChf3oGS1XPFfTHebNrHyV4KGvzkMAJUR/1qC5f4nZCsvgPv/35d702nky3Di2/WZsjD5zUR9g3+vPO8mnM3z8eA6ShVJcxezZ73Co3p0ZnBaF3J438bAKiT4nlrbIVpRzZzo/5nYTx//SefXSAmYCILr/y7xTYBqjfjMQHQZEMZSvJYRPbtP7eVCfWGEa2tG4rQndegUtwS+n1r8atcESL9eeUUM6sa1QzZYDYVseOc9GWcB7SIJzPOm8QTuTlkISHMGJ8FY+KHorP15VkVlr0EZ5c7KY0cBIbWoZGNQTg9+nSgChyf7ElNbAxPiCZsR0zafjMDhfcnzco=
|
||||
key:
|
||||
secure: JfsqEUO3Z60yGfuK5RSzwMoWZtaYflZtW7QE6R1DVMPEQ+CytzEdV2JaTpY14xz4yz1YpBBuQ0P3Q3e2rf/ORp8N8j7/5m3gfiDi8bRH3gX10r6vCQaUBilj0pz3amWUacxwBUEYR/f1029OnJ1qug30f4ARk7DWyuAePt0OboDXZ3j4JOi8xfXKTzofyKGugU4EuzhmKAbpHaBoX97g8z+gETC+wsBEYio8iD2h0ZOe/qZ0S+JGYkphIKcxpQazKdi3YrmWm0BUZsQRtkgoH7KUZm8vqfOUyVOrK+UGOTz4vXqCWHZ+wG1QRrGPUv8ehLrB26y2o02mmaDWQhM+I3RtllL06JDvDw40xjRImYtzg6xr7Mvl0OTQHprXrkN8gw2IbIivV8v31O46Ov+KIaN3CCx1IncnllBWjEXAIs4zPtvNj2Ad338JTkI/opHmPG0DI0DKE36r8wPZYTs/pHVpc3xEzwKYDklJkICjMLUakUGKppS7eKzKGRMjWvbT0vM/U7hHUcz0lA+BUoXedNmJQ1wBT85Ud8uobuKS4C8QmlgIuF1PI2+6LJr5LsCGZRvg7Pl1SPc3ZQLPHX4ggoLAnZZJiV/0ZPCn7XCLiUS1qws37l0uZT1zJQMFLsw9MGuP58tpT7WDuYYAwma/pL+OKC/JKoDhuJwM1I7wB4s=
|
||||
env:
|
||||
global:
|
||||
- PATH=$PATH:/opt/hermit/bin/
|
||||
- HERMIT_ISLE=qemu
|
||||
- HERMIT_CPUS=1
|
||||
- HERMIT_MEM="512M"
|
||||
- HERMIT_KVM="0"
|
||||
- HERMIT_VERBOSE="1"
|
||||
- CFLAGS_FOR_TARGET="-m64 -mtls-direct-seg-refs -O2 -ftree-vectorize"
|
||||
- GOFLAGS_FOR_TARGET"=-m64 -mtls-direct-seg-refs -O2 -ftree-vectorize"
|
||||
- FCFLAGS_FOR_TARGET"=-m64 -mtls-direct-seg-refs -O2 -ftree-vectorize"
|
||||
- FFLAGS_FOR_TARGET="-m64 -mtls-direct-seg-refs -O2 -ftree-vectorize"
|
||||
- CXXFLAGS_FOR_TARGET="-m64 -mtls-direct-seg-refs -O2 -ftree-vectorize"
|
||||
|
|
220
CMakeLists.txt
Normal file
220
CMakeLists.txt
Normal file
|
@ -0,0 +1,220 @@
|
|||
cmake_minimum_required(VERSION 3.7)
|
||||
|
||||
include(ExternalProject)
|
||||
include(cmake/HermitCore.cmake)
|
||||
|
||||
project (HermitCore)
|
||||
|
||||
### Kernel
|
||||
|
||||
# generate config files
|
||||
add_subdirectory(include/hermit)
|
||||
|
||||
add_kernel_module_sources("kernel" "kernel/*.c")
|
||||
add_kernel_module_sources("libkern" "libkern/*.c")
|
||||
add_kernel_module_sources("mm" "mm/*.c")
|
||||
add_kernel_module_sources("drivers" "drivers/net/*.c")
|
||||
|
||||
set(LWIP_SRC lwip/src)
|
||||
add_kernel_module_sources("lwip" "${LWIP_SRC}/api/*.c")
|
||||
add_kernel_module_sources("lwip" "${LWIP_SRC}/arch/*.c")
|
||||
add_kernel_module_sources("lwip" "${LWIP_SRC}/core/*.c")
|
||||
add_kernel_module_sources("lwip" "${LWIP_SRC}/core/ipv4/*.c")
|
||||
add_kernel_module_sources("lwip" "${LWIP_SRC}/core/ipv6/*.c")
|
||||
add_kernel_module_sources("lwip" "${LWIP_SRC}/netif/*.c")
|
||||
|
||||
get_kernel_modules(KERNEL_MODULES)
|
||||
foreach(MODULE ${KERNEL_MODULES})
|
||||
get_kernel_module_sources(SOURCES ${MODULE})
|
||||
|
||||
# maintain list of all objects that will end up in libhermit.a
|
||||
list(APPEND KERNEL_OBJECTS $<TARGET_OBJECTS:${MODULE}>)
|
||||
|
||||
add_library(${MODULE} OBJECT ${SOURCES})
|
||||
|
||||
# this is kernel code
|
||||
target_compile_definitions(${MODULE}
|
||||
PRIVATE -D__KERNEL__)
|
||||
|
||||
target_compile_options(${MODULE}
|
||||
PRIVATE ${HERMIT_KERNEL_FLAGS})
|
||||
|
||||
target_include_directories(${MODULE}
|
||||
PUBLIC ${HERMIT_KERNEL_INCLUDES})
|
||||
|
||||
# suppress all LwIP compiler warnings. Not our code, so we cannot fix
|
||||
if("${MODULE}" STREQUAL "lwip")
|
||||
target_compile_options(${MODULE}
|
||||
PRIVATE -w)
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
|
||||
# add arch/x86 and its objects
|
||||
# TODO: make this conditional when new architectures are implemented
|
||||
add_subdirectory(arch/x86)
|
||||
list(APPEND KERNEL_OBJECTS
|
||||
$<TARGET_OBJECTS:${X86_KERNEL_ASM_TARGET}>
|
||||
$<TARGET_OBJECTS:${X86_KERNEL_C_TARGET}>)
|
||||
|
||||
# finally build libhermit.a
|
||||
add_library(hermit-bootstrap STATIC ${KERNEL_OBJECTS})
|
||||
set_target_properties(hermit-bootstrap PROPERTIES
|
||||
ARCHIVE_OUTPUT_NAME hermit)
|
||||
|
||||
# after compiling ASM sources, we need to post-process them. Adding this
|
||||
# dependency makes sure that this is done before hermit is linked
|
||||
add_dependencies(hermit-bootstrap ${X86_KERNEL_TARGET})
|
||||
|
||||
add_custom_command(
|
||||
TARGET
|
||||
hermit-bootstrap POST_BUILD
|
||||
# rename sections in final library
|
||||
COMMAND
|
||||
${CMAKE_OBJCOPY} --rename-section .bss=.kbss
|
||||
--rename-section .text=.ktext
|
||||
--rename-section .data=.kdata
|
||||
$<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)
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E make_directory ${LOCAL_PREFIX_ARCH_LIB_DIR}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:hermit-bootstrap>
|
||||
${LOCAL_PREFIX_ARCH_LIB_DIR}/
|
||||
|
||||
# and also copy headers into local prefix
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E make_directory ${LOCAL_PREFIX_ARCH_INCLUDE_DIR}/hermit
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different
|
||||
${CMAKE_BINARY_DIR}/include/hermit/*.h
|
||||
${LOCAL_PREFIX_ARCH_INCLUDE_DIR}/hermit/
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different
|
||||
${CMAKE_BINARY_DIR}/include/hermit/*.asm
|
||||
${LOCAL_PREFIX_ARCH_INCLUDE_DIR}/hermit/)
|
||||
|
||||
|
||||
# deploy libhermit.a and headers for package creation
|
||||
install(TARGETS hermit-bootstrap
|
||||
DESTINATION ${TARGET_ARCH}/lib
|
||||
COMPONENT bootstrap)
|
||||
|
||||
install(DIRECTORY include/hermit
|
||||
DESTINATION ${TARGET_ARCH}/include/
|
||||
COMPONENT bootstrap
|
||||
FILES_MATCHING
|
||||
PATTERN *.h)
|
||||
|
||||
# provide custom target to only install libhermit without its runtimes which is
|
||||
# needed during the compilation of the cross toolchain
|
||||
add_custom_target(hermit-bootstrap-install
|
||||
DEPENDS
|
||||
hermit-bootstrap
|
||||
COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
-DCMAKE_INSTALL_COMPONENT=bootstrap
|
||||
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
|
||||
-P cmake_install.cmake)
|
||||
|
||||
# The target 'hermit' includes the HermitCore kernel and several runtimes.
|
||||
# Applications should depend on this target if they link against HermitCore.
|
||||
add_custom_target(hermit
|
||||
DEPENDS hermit-bootstrap)
|
||||
|
||||
|
||||
### External projects
|
||||
#
|
||||
# Build projects externally and deploy into temporary common prefix, will later
|
||||
# be relocated for installation
|
||||
|
||||
## HermitCore's own tools such as Qemu/KVM proxy
|
||||
build_external(tools ${HERMIT_ROOT}/tools "")
|
||||
build_external(arch_x86_loader ${HERMIT_ROOT}/arch/x86/loader "")
|
||||
|
||||
## Intel's OpenMP runtime for x86 (libomp)
|
||||
build_external(libiomp ${HERMIT_ROOT}/usr/libomp ""
|
||||
-DHERMIT=1
|
||||
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
|
||||
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}/${TARGET_ARCH})
|
||||
|
||||
# libomp is part of HermitCore's runtime and should be available before any
|
||||
# application will link
|
||||
add_dependencies(hermit libiomp)
|
||||
|
||||
## iRCCE
|
||||
build_external(ircce ${HERMIT_ROOT}/usr/ircce "")
|
||||
add_dependencies(hermit ircce)
|
||||
|
||||
## XRay profiler
|
||||
build_external(xray ${HERMIT_ROOT}/usr/xray "")
|
||||
add_dependencies(hermit xray)
|
||||
|
||||
## Tests and benchmarks
|
||||
build_external(tests ${HERMIT_ROOT}/usr/tests hermit)
|
||||
build_external(benchmarks ${HERMIT_ROOT}/usr/benchmarks hermit)
|
||||
build_external(openmpbench ${HERMIT_ROOT}/usr/openmpbench hermit)
|
||||
|
||||
## relocate the local prefix to our install destination
|
||||
install(DIRECTORY ${LOCAL_PREFIX_DIR}/
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/
|
||||
USE_SOURCE_PERMISSIONS)
|
||||
|
||||
|
||||
### QEmu
|
||||
# Start HermitCore as multi-kernel in a QEmu VM
|
||||
|
||||
add_custom_target(qemu
|
||||
COMMAND
|
||||
qemu-system-x86_64
|
||||
-machine accel=kvm -cpu host
|
||||
-smp 10 -m 8G -numa node,nodeid=0,cpus=0-4 -numa node,nodeid=1,cpus=5-9
|
||||
-kernel ${HERMIT_ROOT}/config/bzImage
|
||||
-append "root=/dev/ram0 rootfstype=ramfs init=init console=ttyS0"
|
||||
-net nic,model=rtl8139 -net user -net dump
|
||||
-nographic -monitor telnet:127.0.0.1:1235,server,nowait
|
||||
-fsdev local,security_model=none,id=fsdev0,path=${LOCAL_PREFIX_DIR}
|
||||
-device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hermit
|
||||
-s
|
||||
USES_TERMINAL VERBATIM)
|
||||
|
||||
# create a QEmu target that depends on everything
|
||||
get_property(_TARGETS
|
||||
DIRECTORY .
|
||||
PROPERTY BUILDSYSTEM_TARGETS)
|
||||
|
||||
add_custom_target(qemu-dep
|
||||
DEPENDS
|
||||
${_TARGETS} qemu)
|
||||
|
||||
|
||||
### Packaging
|
||||
|
||||
set(CPACK_PACKAGE_NAME libhermit)
|
||||
set(CPACK_SYSTEM_NAME all)
|
||||
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR 0)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 2)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||
|
||||
set(CPACK_PACKAGE_CONTACT "Stefan Lankes <slankes@eonerc.rwth-aachen.de>")
|
||||
|
||||
# build .deb, .rpm and .tar.bz2 packages
|
||||
set(CPACK_GENERATOR DEB;RPM;TBZ2)
|
||||
|
||||
# needed in order for tests and bechmark to use correct install prefix
|
||||
set(CPACK_SET_DESTDIR on)
|
||||
|
||||
## Debian specific
|
||||
# not dependent on Debian system architecture
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE all)
|
||||
|
||||
## RPM specific
|
||||
# libhermit is currently not relocatable
|
||||
set(CPACK_PACKAGE_RELOCATABLE FALSE)
|
||||
|
||||
include(CPack)
|
29
LICENSE
Normal file
29
LICENSE
Normal file
|
@ -0,0 +1,29 @@
|
|||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2010-2017, RWTH Aachen University, Germany
|
||||
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 copyright holder 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 COPYRIGHT HOLDER 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.
|
278
Makefile.in
278
Makefile.in
|
@ -1,278 +0,0 @@
|
|||
TERM = xterm
|
||||
TOPDIR := $(shell pwd)
|
||||
ARCH = x86
|
||||
NAME = libhermit.a
|
||||
DRIVERDIRS = drivers/net
|
||||
LWIPDIRS = lwip/src/arch lwip/src/api lwip/src/core lwip/src/core/ipv4 lwip/src/core/ipv6 lwip/src/netif
|
||||
KERNDIRS = kernel mm libkern arch/$(ARCH)/kernel arch/$(ARCH)/mm $(LWIPDIRS) $(DRIVERDIRS)
|
||||
SUBDIRS = $(KERNDIRS)
|
||||
TODAY := $(shell date +'%Y%m%d')
|
||||
QEMU = @QEMU@ -machine accel=kvm -cpu host
|
||||
CROSSDIR = @prefix@/bin
|
||||
JOBS = $(shell nproc)
|
||||
ARCH_OPT = @ARCH_OPT@
|
||||
TOOLCHAIN = @TOOLCHAIN@
|
||||
ifeq ($(TOOLCHAIN),0)
|
||||
BUILD_BOOTSTRAP =
|
||||
BUILD_TOOLCHAIN =
|
||||
INSTALL_LIBHERMIT =
|
||||
else
|
||||
BUILD_BOOTSTRAP = bootstrap
|
||||
BUILD_TOOLCHAIN = toolchain
|
||||
INSTALL_LIBHERMIT = install_libhermit
|
||||
endif
|
||||
|
||||
prefix = @prefix@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
# add path to the cross toolchain
|
||||
PATH:=$(PATH):$(CROSSDIR)
|
||||
|
||||
# Set your own cross compiler tool chain prefix here
|
||||
CROSSCOMPREFIX = x86_64-hermit
|
||||
STACKPROT = -fno-stack-protector
|
||||
|
||||
FC_FOR_TARGET = $(CROSSCOMPREFIX)-gfortran
|
||||
CC_FOR_TARGET = $(CROSSCOMPREFIX)-gcc
|
||||
GO_FOR_TARGET = $(CROSSCOMPREFIX)-gccgo
|
||||
CXX_FOR_TARGET = $(CROSSCOMPREFIX)-g++
|
||||
GCC_FOR_TARGET = $(CROSSCOMPREFIX)-gcc
|
||||
CPP_FOR_TARGET = $(CROSSCOMPREFIX)-cpp
|
||||
AR_FOR_TARGET = $(CROSSCOMPREFIX)-ar
|
||||
AS_FOR_TARGET = $(CROSSCOMPREFIX)-as
|
||||
LD_FOR_TARGET = $(CROSSCOMPREFIX)-ld
|
||||
NM_FOR_TARGET = $(CROSSCOMPREFIX)-nm
|
||||
OBJDUMP_FOR_TARGET = $(CROSSCOMPREFIX)-objdump
|
||||
OBJCOPY_FOR_TARGET = $(CROSSCOMPREFIX)-objcopy
|
||||
RANLIB_FOR_TARGET = $(CROSSCOMPREFIX)-ranlib
|
||||
STRIP_FOR_TARGET = $(CROSSCOMPREFIX)-strip
|
||||
READELF_FOR_TARGET = $(CROSSCOMPREFIX)-readelf
|
||||
ELFEDIT_FOR_TARGET = $(CROSSCOMPREFIX)-elfedit
|
||||
|
||||
MAKE = make
|
||||
NASM = nasm
|
||||
NASMFLAGS = -felf64 -g -i$(TOPDIR)/include/hermit/
|
||||
|
||||
INCLUDE = -I$(TOPDIR)/include -I$(TOPDIR)/arch/$(ARCH)/include -I$(TOPDIR)/lwip/src/include -I$(TOPDIR)/drivers
|
||||
CFLAGS = -g -m64 -Wall -O2 -mno-red-zone -fno-var-tracking-assignments -fstrength-reduce -fomit-frame-pointer -finline-functions -ffreestanding -nostdinc -fno-stack-protector -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -fno-delete-null-pointer-checks -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mskip-rax-setup -fno-common -Wframe-larger-than=1024 -fno-strict-aliasing -fno-asynchronous-unwind-tables -fno-strict-overflow -maccumulate-outgoing-args $(INCLUDE)
|
||||
AR = ar
|
||||
ARFLAGS = rsv
|
||||
RM = rm -rf
|
||||
OUTPUT_FORMAT = -O elf64-x86-64-hermit
|
||||
|
||||
# Additional flags for profiling using Xray
|
||||
PROFILING_LDFLAGS =
|
||||
PROFILING_CFLAGS =
|
||||
|
||||
ifdef PROFILING
|
||||
PROFILING_LDFLAGS = -lxray
|
||||
|
||||
PROFILING_CFLAGS = -falign-functions=32 -finstrument-functions
|
||||
PROFILING_CFLAGS += -finstrument-functions-exclude-function-list=_mm_pause,_mm_setcsr,_mm_getcsr # we need this for libiomp to work
|
||||
PROFILING_CFLAGS += -DXRAY -DXRAY_DISABLE_BROWSER_INTEGRATION -DXRAY_NO_DEMANGLE
|
||||
PROFILING_CFLAGS += -DXRAY_ANNOTATE
|
||||
endif
|
||||
|
||||
CFLAGS_FOR_NEWLIB = -m64 -mtls-direct-seg-refs -O3 -ftree-vectorize $(ARCH_OPT) #$(STACKPROT)
|
||||
GOFLAGS_FOR_NEWLIB = -m64 -mtls-direct-seg-refs -O3 -ftree-vectorize $(ARCH_OPT)
|
||||
FCFLAGS_FOR_NEWLIB = -m64 -mtls-direct-seg-refs -O3 -ftree-vectorize $(ARCH_OPT)
|
||||
FFLAGS_FOR_NEWLIB = -m64 -mtls-direct-seg-refs -O3 -ftree-vectorize $(ARCH_OPT)
|
||||
CXXFLAGS_FOR_NEWLIB = -m64 -mtls-direct-seg-refs -O3 -ftree-vectorize $(ARCH_OPT)
|
||||
LDFLAGS_FOR_NEWLIB =
|
||||
NASMFLAGS_FOR_NEWLIB = -felf64
|
||||
CFLAGS_FOR_TOOLS = -O2 -Wall -std=gnu99
|
||||
LDFLAGS_FOR_TOOLS =
|
||||
|
||||
# Prettify output
|
||||
V = 1
|
||||
ifeq ($V,0)
|
||||
Q = @
|
||||
P = > /dev/null
|
||||
endif
|
||||
|
||||
|
||||
default: all
|
||||
|
||||
all: arch/x86/kernel/boot.h $(BUILD_BOOTSTRAP) $(NAME) $(BUILD_TOOLCHAIN) tools loader
|
||||
|
||||
toolchain: $(INSTALL_LIBHERMIT)
|
||||
$Q$(MAKE) ARCH=$(ARCH) PREFIX=$(prefix) \
|
||||
LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_NEWLIB)" \
|
||||
GOFLAGS_FOR_TARGET="$(GOFLAGS_FOR_NEWLIB)" \
|
||||
CFLAGS_FOR_TARGET="$(CFLAGS_FOR_NEWLIB)" \
|
||||
FFLAGS_FOR_TARGET="$(FFLAGS_FOR_NEWLIB)" \
|
||||
FCFLAGS_FOR_TARGET="$(FCFLAGS_FOR_NEWLIB)" \
|
||||
FCFLAGS="$(FCFLAGS_FOR_NEWLIB)" \
|
||||
CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_NEWLIB)" \
|
||||
NASMFLAGS="$(NASMFLAGS_FOR_NEWLIB)" \
|
||||
CC_FOR_TARGET=$(CC_FOR_TARGET) \
|
||||
GO_FOR_TARGET=$(GO_FOR_TARGET) \
|
||||
FC_FOR_TARGET=$(FC_FOR_TARGET) \
|
||||
CXX_FOR_TARGET=$(CXX_FOR_TARGET) \
|
||||
GCC_FOR_TARGET=$(GCC_FOR_TARGET) \
|
||||
AR_FOR_TARGET=$(AR_FOR_TARGET) \
|
||||
AS_FOR_TARGET=$(AS_FOR_TARGET) \
|
||||
LD_FOR_TARGET=$(LD_FOR_TARGET) \
|
||||
NM_FOR_TARGET=$(NM_FOR_TARGET) \
|
||||
OBJDUMP_FOR_TARGET=$(OBJDUMP_FOR_TARGET) \
|
||||
OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) \
|
||||
RANLIB_FOR_TARGET=$(RANLIB_FOR_TARGET) \
|
||||
STRIP_FOR_TARGET=$(STRIP_FOR_TARGET) \
|
||||
ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) \
|
||||
READELF_FOR_TARGET=$(READELF_FOR_TARGET) \
|
||||
PROFILING_CFLAGS="$(PROFILING_CFLAGS)" \
|
||||
PROFILING_LDFLAGS="$(PROFILING_LDFLAGS)" -C usr toolchain
|
||||
|
||||
libs:
|
||||
$Q$(MAKE) ARCH=$(ARCH) PREFIX=$(prefix) \
|
||||
LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_NEWLIB)" \
|
||||
GOFLAGS_FOR_TARGET="$(GOFLAGS_FOR_NEWLIB)" \
|
||||
CFLAGS_FOR_TARGET="$(CFLAGS_FOR_NEWLIB)" \
|
||||
FFLAGS_FOR_TARGET="$(FFLAGS_FOR_NEWLIB)" \
|
||||
FCFLAGS_FOR_TARGET="$(FCFLAGS_FOR_NEWLIB)" \
|
||||
FCFLAGS="$(FCFLAGS_FOR_NEWLIB)" \
|
||||
CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_NEWLIB)" \
|
||||
NASMFLAGS="$(NASMFLAGS_FOR_NEWLIB)" \
|
||||
CC_FOR_TARGET=$(CC_FOR_TARGET) \
|
||||
GO_FOR_TARGET=$(GO_FOR_TARGET) \
|
||||
FC_FOR_TARGET=$(FC_FOR_TARGET) \
|
||||
CXX_FOR_TARGET=$(CXX_FOR_TARGET) \
|
||||
GCC_FOR_TARGET=$(GCC_FOR_TARGET) \
|
||||
AR_FOR_TARGET=$(AR_FOR_TARGET) \
|
||||
AS_FOR_TARGET=$(AS_FOR_TARGET) \
|
||||
LD_FOR_TARGET=$(LD_FOR_TARGET) \
|
||||
NM_FOR_TARGET=$(NM_FOR_TARGET) \
|
||||
OBJDUMP_FOR_TARGET=$(OBJDUMP_FOR_TARGET) \
|
||||
OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) \
|
||||
RANLIB_FOR_TARGET=$(RANLIB_FOR_TARGET) \
|
||||
STRIP_FOR_TARGET=$(STRIP_FOR_TARGET) \
|
||||
ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) \
|
||||
READELF_FOR_TARGET=$(READELF_FOR_TARGET) \
|
||||
PROFILING_CFLAGS="$(PROFILING_CFLAGS)" \
|
||||
PROFILING_LDFLAGS="$(PROFILING_LDFLAGS)" -C usr libs
|
||||
|
||||
bootstrap:
|
||||
$Q$(MAKE) ARCH=$(ARCH) PREFIX=$(prefix) CFLAGS="" LDFLAGS="" -C usr bootstrap
|
||||
|
||||
tools:
|
||||
$Q$(MAKE) ARCH=$(ARCH) PREFIX=$(prefix) CFLAGS="$(CFLAGS_FOR_TOOLS)" LDFLAGS="$(LDFLAGS_FOR_TOOLS)" -C tools
|
||||
|
||||
loader:
|
||||
$Q$(MAKE) -C arch/$(ARCH)/loader
|
||||
|
||||
$(NAME):
|
||||
@echo [AR] $(NAME)
|
||||
$Q$(AR_FOR_TARGET) $(ARFLAGS) -o $(NAME) $^
|
||||
$Q$(OBJCOPY_FOR_TARGET) --rename-section .bss=.kbss --rename-section .text=.ktext --rename-section .data=.kdata $(NAME)
|
||||
|
||||
examples:
|
||||
$Q$(MAKE) ARCH=$(ARCH) PREFIX=$(prefix) \
|
||||
LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_NEWLIB)" \
|
||||
GOFLAGS_FOR_TARGET="$(GOFLAGS_FOR_NEWLIB)" \
|
||||
CFLAGS_FOR_TARGET="$(CFLAGS_FOR_NEWLIB)" \
|
||||
FFLAGS_FOR_TARGET="$(FFLAGS_FOR_NEWLIB)" \
|
||||
FCFLAGS_FOR_TARGET="$(FCFLAGS_FOR_NEWLIB)" \
|
||||
FCFLAGS="$(FCFLAGS_FOR_NEWLIB)" \
|
||||
CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_NEWLIB)" \
|
||||
NASMFLAGS="$(NASMFLAGS_FOR_NEWLIB)" \
|
||||
CC_FOR_TARGET=$(CC_FOR_TARGET) \
|
||||
GO_FOR_TARGET=$(GO_FOR_TARGET) \
|
||||
FC_FOR_TARGET=$(FC_FOR_TARGET) \
|
||||
CXX_FOR_TARGET=$(CXX_FOR_TARGET) \
|
||||
GCC_FOR_TARGET=$(GCC_FOR_TARGET) \
|
||||
AR_FOR_TARGET=$(AR_FOR_TARGET) \
|
||||
AS_FOR_TARGET=$(AS_FOR_TARGET) \
|
||||
LD_FOR_TARGET=$(LD_FOR_TARGET) \
|
||||
NM_FOR_TARGET=$(NM_FOR_TARGET) \
|
||||
OBJDUMP_FOR_TARGET=$(OBJDUMP_FOR_TARGET) \
|
||||
OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) \
|
||||
RANLIB_FOR_TARGET=$(RANLIB_FOR_TARGET) \
|
||||
STRIP_FOR_TARGET=$(STRIP_FOR_TARGET) \
|
||||
ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) \
|
||||
READELF_FOR_TARGET=$(READELF_FOR_TARGET) \
|
||||
PROFILING_CFLAGS="$(PROFILING_CFLAGS)" \
|
||||
PROFILING_LDFLAGS="$(PROFILING_LDFLAGS)" -C usr examples
|
||||
|
||||
test:
|
||||
. ./test.sh
|
||||
|
||||
qemu:
|
||||
$(QEMU) -smp 10 -m 8G -numa node,nodeid=0,cpus=0-4 -numa node,nodeid=1,cpus=5-9 \
|
||||
-kernel config/bzImage \
|
||||
-append "root=/dev/ram0 rootfstype=ramfs init=init console=ttyS0" \
|
||||
-net nic,model=rtl8139 -net user -net dump \
|
||||
-nographic -monitor telnet:127.0.0.1:1235,server,nowait \
|
||||
-fsdev local,security_model=none,id=fsdev0,path=$(shell realpath .) \
|
||||
-device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hermit \
|
||||
-s
|
||||
|
||||
install_libhermit:
|
||||
$Q$(INSTALL_PROGRAM) -d $(prefix)/$(CROSSCOMPREFIX)/lib/
|
||||
$Q$(INSTALL_DATA) $(NAME) $(prefix)/$(CROSSCOMPREFIX)/lib/
|
||||
$Q$(INSTALL_PROGRAM) -d $(prefix)/$(CROSSCOMPREFIX)/include/hermit/
|
||||
$Q$(INSTALL_DATA) include/hermit/* $(prefix)/$(CROSSCOMPREFIX)/include/hermit/
|
||||
|
||||
install: install_libhermit
|
||||
$Q$(MAKE) PREFIX=$(prefix) -C usr install
|
||||
$Q$(MAKE) PREFIX=$(prefix) -C tools install
|
||||
|
||||
clean:
|
||||
$Q$(RM) $(NAME) $(NAME).sym $(NAME).bin *~
|
||||
$Q$(MAKE) -C tools clean
|
||||
$Q$(MAKE) -C usr clean
|
||||
$Q$(MAKE) -C arch/$(ARCH)/loader clean
|
||||
@echo Cleaned.
|
||||
|
||||
veryclean: clean
|
||||
$Q$(RM) qemu-vlan0.pcap include/hermit/config.inc
|
||||
$Q$(MAKE) -C tools veryclean
|
||||
$Q$(MAKE) -C usr veryclean
|
||||
$Q$(MAKE) -C arch/$(ARCH)/loader veryclean
|
||||
@echo Very cleaned
|
||||
|
||||
doc:
|
||||
@echo Create documentation...
|
||||
@doxygen
|
||||
|
||||
%.o : %.c
|
||||
@echo [CC] $@
|
||||
$Q$(CC_FOR_TARGET) -c -D__KERNEL__ $(CFLAGS) -o $@ $<
|
||||
@echo [DEP] $*.dep
|
||||
$Q$(CC_FOR_TARGET) -MF $*.dep -MT $*.o -MM $(CFLAGS) $<
|
||||
|
||||
arch/x86/kernel/boot.bin: arch/x86/kernel/boot.asm
|
||||
@echo " NASM $@"
|
||||
$Q$(NASM) -fbin -o $@ $<
|
||||
|
||||
arch/x86/kernel/boot.h: arch/x86/kernel/boot.bin
|
||||
@echo " HEXDUMP $@"
|
||||
$Qecho "static const uint8_t boot_code[] = { \
|
||||
$(shell hexdump -v -e '"0x" 1/1 "%02X" ", "' $<) \
|
||||
};" > $@
|
||||
|
||||
include/hermit/config.inc: include/hermit/config.h
|
||||
@echo "; This file is generated automatically from the config.h file." > include/hermit/config.inc
|
||||
@echo "; Before editing this, you should consider editing config.h." >> include/hermit/config.inc
|
||||
@awk '/^#define MAX_CORES/{ print "%define MAX_CORES", $$3 }' include/hermit/config.h >> include/hermit/config.inc
|
||||
@awk '/^#define KERNEL_STACK_SIZE/{ print "%define KERNEL_STACK_SIZE", $$3 }' include/hermit/config.h >> include/hermit/config.inc
|
||||
@awk '/^#define VIDEO_MEM_ADDR/{ print "%define VIDEO_MEM_ADDR", $$3 }' include/hermit/config.h >> include/hermit/config.inc
|
||||
@awk '/^#define CONFIG_VGA/{ print "%define CONFIG_VGA", $$3 }' include/hermit/config.h >> include/hermit/config.inc
|
||||
@awk '/^#define DYNAMIC_TICKS/{ print "%define DYNAMIC_TICKS", $$3 }' include/hermit/config.h >> include/hermit/config.inc
|
||||
@awk '/^#define SAVE_FPU/{ print "%define SAVE_FPU", $$3 }' include/hermit/config.h >> include/hermit/config.inc
|
||||
|
||||
%.o : %.asm include/hermit/config.inc
|
||||
@echo [ASM] $@
|
||||
$Q$(NASM) $(NASMFLAGS) -o $@ $<
|
||||
$Q$(ELFEDIT_FOR_TARGET) --output-osabi HermitCore $@
|
||||
#$Q$(OBJCOPY_FOR_TARGET) $(OUTPUT_FORMAT) $@
|
||||
|
||||
%.o : %.S
|
||||
@echo [GCC-ASM] $@
|
||||
$Q$(CC_FOR_TARGET) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
.PHONY: default all clean qemu gdb usr test toolchain tools examples libs
|
||||
|
||||
include $(addsuffix /Makefile,$(SUBDIRS))
|
20
Makefile.inc
20
Makefile.inc
|
@ -1,20 +0,0 @@
|
|||
C_source-$(MODULE) := $(addprefix $(subst _,/,$(MODULE))/,$(filter %.c,$(C_source)))
|
||||
ASM_source-$(MODULE) := $(addprefix $(subst _,/,$(MODULE))/,$(filter %.asm,$(ASM_source)))
|
||||
C_source :=
|
||||
ASM_source :=
|
||||
|
||||
OBJS-$(MODULE) := $(C_source-$(MODULE):.c=.o)
|
||||
OBJS-$(MODULE) += $(ASM_source-$(MODULE):.asm=.o)
|
||||
|
||||
$(MODULE): $(OBJS-$(MODULE))
|
||||
|
||||
$(NAME): $(OBJS-$(MODULE))
|
||||
|
||||
clean: clean-$(MODULE)
|
||||
clean-$(MODULE): clean-% :
|
||||
@echo Cleaning $(subst _,/,$*)
|
||||
$Q$(RM) $(OBJS-$*) $(C_source-$*:.c=.dep)
|
||||
|
||||
.PHONY: clean-$(MODULE) $(MODULE)
|
||||
|
||||
-include $(C_source-$(MODULE):.c=.dep)
|
449
README.md
449
README.md
|
@ -1,91 +1,291 @@
|
|||
<img width="100" align="right" src="img/hermitcore_logo.png" />
|
||||
|
||||
|
||||
# HermitCore - A lightweight unikernel for a scalable and predictable runtime behavior
|
||||
|
||||
The project [HermitCore](http://www.hermitcore.org) is new [unikernel](http://unikernel.org) targeting at a scalable and predictable runtime for high-performance and cloud computing.
|
||||
HermitCore extends the multi-kernel approach (like [McKernel](http://www-sys-aics.riken.jp/ResearchTopics/os/mckernel.html)) with unikernel features for a better programmability and scalability for hierarchical systems.
|
||||
On the startup of HermitCore applications, cores are isolated from the Linux system enabling the bare-metal of the applications on these cores.
|
||||
This approach achieves lower OS jitter and a better scalability compared to full-weight kernels.
|
||||
Inter-kernel communication between HermitCore applications and the Linux system is realized by means of an IP interface.
|
||||
[](https://travis-ci.org/RWTH-OS/HermitCore)
|
||||
[](https://radiant-ridge-95061.herokuapp.com)
|
||||
|
||||
In addition to the multi-kernel approach described above, HermitCore can be used as classical standalone unikernel as well.
|
||||
In this case HermitCore runs a single-kernel exclusively on the hardware or within a virtual machine.
|
||||
This reduces the resource demand and improves the boot time which is critical for cloud computing applications.
|
||||
It is the result of a research project at RWTH Aachen University and is currently an experimental approach, i.e., not production ready.
|
||||
Please use it with caution.
|
||||
The project [HermitCore]( http://www.hermitcore.org ) is a new
|
||||
[unikernel](http://unikernel.org) targeting a scalable and predictable runtime
|
||||
for high-performance and cloud computing. HermitCore extends the multi-kernel
|
||||
approach (like
|
||||
[McKernel](http://www-sys-aics.riken.jp/ResearchTopics/os/mckernel.html)) with
|
||||
unikernel features for a better programmability and scalability for hierarchical
|
||||
systems.
|
||||
|
||||

|
||||
|
||||
On the startup of HermitCore applications, cores are isolated from the Linux
|
||||
system enabling bare-metal execution of on these cores. This approach achieves
|
||||
lower OS jitter and a better scalability compared to full-weight kernels.
|
||||
Inter-kernel communication between HermitCore applications and the Linux system
|
||||
is realized by means of an IP interface.
|
||||
|
||||
In addition to the multi-kernel approach described above, HermitCore can be used
|
||||
as a classical standalone unikernel as well. In this case, HermitCore runs a
|
||||
single-kernel exclusively on the hardware or within a virtual machine. This
|
||||
reduces the resource demand and loweres the boot time which is critical for
|
||||
cloud computing applications. It is the result of a research project at RWTH
|
||||
Aachen University and is currently an experimental approach, i.e., not
|
||||
production ready. Please use it with caution.
|
||||
|
||||
## Contributing
|
||||
|
||||
HermitCore is being developed on [GitHub](https://github.com/RWTH-OS/HermitCore).
|
||||
Create your own fork, send us a pull request, and chat with us on [Slack](https://radiant-ridge-95061.herokuapp.com).
|
||||
|
||||
## Requirements
|
||||
|
||||
The build process works currently only on **x86-based Linux** systems. The following software packets are required to build HermitCore on a Linux system:
|
||||
The build process works currently only on **x86-based Linux** systems. To build
|
||||
the HermitCore kernel and applications you need:
|
||||
|
||||
* Netwide Assembler (NASM)
|
||||
* GNU Make, GNU Binutils
|
||||
* Tools and libraries to build *linux*, *binutils* and *gcc* (e.g. flex, bison, MPFR library, GMP library, MPC library, ISL library)
|
||||
* texinfo
|
||||
* Qemu
|
||||
* CMake
|
||||
* Netwide Assember (NASM)
|
||||
* recent host compiler such as GCC
|
||||
* HermitCore cross-toolchain, i.e. Binutils, GCC, newlib, pthreads
|
||||
|
||||
On Debian-based systems the packets can be installed by executing:
|
||||
```
|
||||
sudo apt-get install qemu-system-x86 nasm texinfo libmpfr-dev libmpc-dev libgmp-dev libisl-dev flex bison
|
||||
### HermitCore cross-toolchain
|
||||
|
||||
We provide prebuilt packages (currently Debian-based only) of the HermitCore
|
||||
toolchain, which can be installed as follows:
|
||||
|
||||
```bash
|
||||
$ echo "deb [trusted=yes] https://dl.bintray.com/rwth-os/hermitcore vivid main" | sudo tee -a /etc/apt/sources.list
|
||||
$ sudo apt-get -qq update
|
||||
$ sudo apt-get install binutils-hermit newlib-hermit pthread-embedded-hermit gcc-hermit libhermit
|
||||
```
|
||||
|
||||
## Installing HermitCore with by using debian packets
|
||||
If you want to build the toolchain yourself, have a look at the repository [hermit-toolchain](https://github.com/RWTH-OS/hermit-toolchain), which contains scripts to build the whole toolchain.
|
||||
|
||||
We provide binary packets for debian-based systems containing the complete HermitCore toolchain including a cross-compiler.
|
||||
To install the packets you have to execute the following commands:
|
||||
Depending on how you want to use HermitCore, you might need additional packages
|
||||
such as:
|
||||
|
||||
* QEMU (`apt-get install qemu-system-x86`)
|
||||
|
||||
## Building HermitCore
|
||||
|
||||
### Preliminary work
|
||||
|
||||
To build HermitCore from source (without compiler), the repository with its submodules has to be cloned.
|
||||
|
||||
```bash
|
||||
$ git clone git@github.com:RWTH-OS/HermitCore.git
|
||||
$ cd HermitCore
|
||||
$ git submodule init
|
||||
$ git submodule update
|
||||
```
|
||||
echo "deb [trusted=yes] https://dl.bintray.com/rwth-os/hermitcore vivid main" | sudo tee -a /etc/apt/sources.list
|
||||
sudo apt-get -qq update
|
||||
sudo apt-get install binutils-hermit newlib-hermit pthread-embedded-hermit gcc-hermit libhermit
|
||||
|
||||
We require a fairly recent version of CMake (`3.7`) which is not yet present in
|
||||
most Linux distributions. We therefore provide a helper script that fetches the
|
||||
required CMake binaries from the upstream project and stores them locally, so
|
||||
you only need to download it once.
|
||||
|
||||
```bash
|
||||
$ . cmake/local-cmake.sh
|
||||
-- Downloading CMake
|
||||
--2017-03-28 16:13:37-- https://cmake.org/files/v3.7/cmake-3.7.2-Linux-x86_64.tar.gz
|
||||
Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'
|
||||
Resolving cmake.org... 66.194.253.19
|
||||
Connecting to cmake.org|66.194.253.19|:443... connected.
|
||||
HTTP request sent, awaiting response... 200 OK
|
||||
Length: 30681434 (29M) [application/x-gzip]
|
||||
Saving to: ‘cmake-3.7.2-Linux-x86_64.tar.gz’
|
||||
|
||||
cmake-3.7.2-Linux-x86_64.tar.gz 100%[===================>] 29,26M 3,74MB/s in 12s
|
||||
|
||||
2017-03-28 16:13:50 (2,48 MB/s) - ‘cmake-3.7.2-Linux-x86_64.tar.gz’ saved [30681434/30681434]
|
||||
|
||||
-- Unpacking CMake
|
||||
-- Local CMake v3.7.2 installed to cmake/cmake-3.7.2-Linux-x86_64
|
||||
-- Next time you source this script, no download will be neccessary
|
||||
```
|
||||
This toolchain is able to build applications for [classical unikernel](#building-and-testing-hermitcore-as-classical-standalone-unikernel) environments within virtual machines or bare-metal in a multi-kernel environment.
|
||||
For the latter, you have to install the modified Linux kernel.
|
||||
An introduction to this execution mode is provided in section [Building and testing HermitCore as multi-kernel on a real machine](#building-and-testing-hermitcore-as-multi-kernel-on a-real-machine).
|
||||
|
||||
## Building and testing HermitCore as multi-kernel within a virtual machine
|
||||
So before you build HermitCore you have to source the `local-cmake.sh` script
|
||||
everytime you open a new terminal.
|
||||
|
||||
1. Please make sure that you cloned this repository and all its submodules.
|
||||
2. To configure the system, run the *configure* script in the directory, which contains this *README*.
|
||||
With the flag `--with-toolchain`, the HermitCore's complete cross toolchain (cross compiler, binutils, etc.) will be downloaded and built.
|
||||
**NOTE**: This requires write access to the installation directory, which is specified by the flag `--prefix`.
|
||||
At the end of this *README* in section *Tips* you find hints to enable optimization for the target.
|
||||
3. The command `make all` build the the HermitCore kernel and depending on the configuration flags the cross toolchain.
|
||||
4. Install the kernel with `make install`.
|
||||
5. Build all example applications with `make examples`.
|
||||
6. To start a virtual machine and to boot a small Linux version use the command `make qemu`.
|
||||
Per default, the virtual machine has 10 cores, 2 NUMA nodes, and 8 GiB RAM.
|
||||
To increase or to decrease the machine size, the label `qemu` in the Makefile has to be modified accordingly.
|
||||
7. Inside the VM runs a small Linux system, which already includes the patches for HermitCore.
|
||||
Per NUMA node (= HermitCore isle) there is a directory called `isleX` under `/sys/hermit` , where `X` represents the NUMA node ID.
|
||||
The demo applications are located in the directories `/hermit/usr/{tests,benchmarks}`.
|
||||
A HermitCore loader is already registered.
|
||||
By starting a HermitCore application, a proxy will be executed on the Linux system, while the HermitCore binary will be started on isle 0 with cpu 1.
|
||||
To change the default behavior, the environment variable `HERMIT_ISLE` is used to specify the (memory) location of the isle, while the environment variable `HERMIT_CPUS` is used to specify the cores.
|
||||
For instance, `HERMIT_ISLE=1 HERMIT_CPUS="3-5" /hermit/usr/tests/hello` starts a HelloWorld demo on the HermitCore isle 1, which uses the cores 3 to 5.
|
||||
The output messages are forwarded to the Linux proxy and printed on the Linux system.
|
||||
8. HermitCore's kernel messages of `isleX` are available via `cat /sys/hermit/isleX/log`.
|
||||
9. There is a virtual IP device for the communication between the HermitCore isles and the Linux system (see output of `ifconfig`).
|
||||
Per default, the Linux system has the IP address `192.168.28.1`.
|
||||
The HermitCore isles starts with the IP address `192.168.28.2` for isle 0 and is increased by one for every isle.
|
||||
10. More HermitCore applications are available at `/hermit/usr/{tests,benchmarks}` which is a shared directory between the host and QEmu.
|
||||
### Building the library perating systems and its examples
|
||||
|
||||
## Building and testing HermitCore as multi-kernel on a real machine
|
||||
To build HermitCore go to the directory with the source code, create a `build` directory and call `cmake` followed by `make`.
|
||||
|
||||
```bash
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake ..
|
||||
$ make
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
If your toolchain is not located in `/opt/hermit/bin` then you have to supply
|
||||
its location to the `cmake` command above like so:
|
||||
|
||||
```bash
|
||||
$ cmake -DTOOLCHAIN_BIN_DIR=/home/user/hermit/bin ..
|
||||
```
|
||||
|
||||
assuming that binaries like `x86_64-hermit-gcc` and friends are located in that
|
||||
directory. To install your new version in the same directory, you have to set the installation path and to install HermitCore as follows:
|
||||
|
||||
```bash
|
||||
$ cmake -DTOOLCHAIN_BIN_DIR=/home/user/hermit/bin -DCMAKE_INSTALL_PREFIX=/home/user/hermit ..
|
||||
$ make
|
||||
$ make install
|
||||
```
|
||||
|
||||
**Note:** If you use the cross compiler outside of this repository, the compiler uses per default the library operating systems located by the toolchain (e.g. `/opt/hermit/x86_64-hermit/lib/libhermit.a`).
|
||||
|
||||
## Testing
|
||||
|
||||
### As multi-kernel within a virtual machine
|
||||
|
||||
```bash
|
||||
$ cd build
|
||||
$ make qemu
|
||||
$ # or 'make qemu-dep' to build HermitCore dependencies before
|
||||
```
|
||||
|
||||
Within the QEMU session you can start HermitCore application just the same as
|
||||
traditional Linux programs:
|
||||
|
||||
```bash
|
||||
(QEMU) $ /hermit/x86_64-hermit/extra/tests/hello
|
||||
smpboot: CPU 1 is now offline
|
||||
Hello World!!!
|
||||
argv[0] = /hermit/x86_64-hermit/extra/tests/hello
|
||||
Receive signal with number 30
|
||||
Hostname: hermit.localdomain
|
||||
x86: Booting SMP configuration:
|
||||
smpboot: Booting Node 0 Processor 1 APIC 0x1
|
||||
```
|
||||
|
||||
Per default, the virtual machine has 10 cores, 2 NUMA nodes, and 8 GiB RAM.
|
||||
Inside the VM runs a small Linux system, which already includes the patches for
|
||||
HermitCore. Per NUMA node (= HermitCore isle) there is a directory called
|
||||
`isleX` under `/sys/hermit` , where `X` represents the NUMA node ID.
|
||||
|
||||
The demo applications are located in the directories
|
||||
`/hermit/x86_64-hermit/extra/{tests,benchmarks}`. A HermitCore loader is already registered.
|
||||
By starting a HermitCore application, a proxy will be executed on the Linux
|
||||
system, while the HermitCore binary will be started on isle 0 with cpu 1. To
|
||||
change the default behavior, the environment variable `HERMIT_ISLE` is used to
|
||||
specify the (memory) location of the isle, while the environment variable
|
||||
`HERMIT_CPUS` is used to specify the cores.
|
||||
|
||||
For instance, `HERMIT_ISLE=1 HERMIT_CPUS="3-5" /hermit/x86_64-hermit/extra/tests/hello` starts
|
||||
a HelloWorld demo on the HermitCore isle 1, which uses the cores 3 to 5. The
|
||||
output messages are forwarded to the Linux proxy and printed on the Linux
|
||||
system.
|
||||
|
||||
HermitCore's kernel messages of `isleX` are available via `cat
|
||||
/sys/hermit/isleX/log`.
|
||||
|
||||
There is a virtual IP device for the communication between the HermitCore isles
|
||||
and the Linux system (see output of `ifconfig`). Per default, the Linux system
|
||||
has the IP address `192.168.28.1`. The HermitCore isles starts with the IP
|
||||
address `192.168.28.2` for isle 0 and is increased by one for every isle.
|
||||
|
||||
More HermitCore applications are available at `/hermit/usr/{tests,benchmarks}`
|
||||
which is a shared directory between the host and QEMU.
|
||||
|
||||
|
||||
### As classical standalone unikernel within a virtual machine
|
||||
|
||||
HermitCore applications can be directly started as standalone kernel within a
|
||||
virtual machine. In this case,
|
||||
[iRCCE](http://www.lfbs.rwth-aachen.de/publications/files/iRCCE.pdf ) is not
|
||||
supported.
|
||||
|
||||
```bash
|
||||
$ cd build
|
||||
$ make install DESTDIR=~/hermit-build
|
||||
$ cd ~/hermit-build/opt/hermit
|
||||
$ # using QEMU
|
||||
$ HERMIT_ISLE=qemu bin/proxy x86_64-hermit/extra/tests/hello
|
||||
$ # using uHyve
|
||||
$ HERMIT_ISLE=uhyve bin/proxy x86_64-hermit/extra/tests/hello
|
||||
```
|
||||
|
||||
With `HERMIT_ISLE=qemu`, the application will be started within a QEMU VM.
|
||||
Please note that the loader requires QEMU and uses per default *KVM*.
|
||||
Furthermore, it expects that the executable is called `qemu-system-x86_64`.
|
||||
|
||||
With `HERMIT_ISLE=hyve`, the application will be started within a thin
|
||||
hypervisor powered by Linux's KVM API and therefore requires *KVM* support.
|
||||
uHyve has a considerably smaller startup time than QEMU, but lacks some features
|
||||
such as GDB debugging.
|
||||
|
||||
In this context, the environment variable `HERMIT_CPUS` specifies the number of
|
||||
cpus (and no longer a range of core ids). Furthermore, the variable `HERMIT_MEM`
|
||||
defines the memory size of the virtual machine. The suffix of *M* or *G* can be
|
||||
used to specify a value in megabytes or gigabytes respectively. Per default, the
|
||||
loader initializes a system with one core and 2 GiB RAM.
|
||||
|
||||
The virtual machine opens two TCP/IP ports. One is used for the communication
|
||||
between HermitCore application and its proxy. The second port is used to create
|
||||
a connection via telnet to QEMU's system monitor. With the environment variable
|
||||
`HERMIT_PORT`, the default port (18766) can be changed for the communication
|
||||
between the HermitCore application and its proxy. The connection to the system
|
||||
monitor used automatically `HERMIT_PORT+1`, i.e., the default port is 18767.
|
||||
|
||||
The following command starts the stream benchmark in a virtual machine, which
|
||||
has 4 cores and 6GB memory.
|
||||
|
||||
```bash
|
||||
$ HERMIT_ISLE=qemu HERMIT_CPUS=4 HERMIT_MEM=6G bin/proxy x86_64-hermit/extra/benchmarks/stream
|
||||
```
|
||||
|
||||
|
||||
### As multi-kernel on a real machine
|
||||
|
||||
*Note*: to launch HermitCore applications, root privileges are required.
|
||||
|
||||
1. In principle you have to follow the tutorial above.
|
||||
After the configuration, building of the cross-compilers and all example application (Step 5 in the [above tutorial](#building-and-testing-hermitcore-within-a-virtual-machine)), a modified Linux kernel has to be installed.
|
||||
Please clone the repository with the [modified Linux kernel](https://github.com/RWTH-OS/linux).
|
||||
Afterwards switch to the branch `hermit` for a relative new vanilla kernel or to `centos`, which is compatible to the current CentOS 7 kernel.
|
||||
Configure the kernel with `make menuconfig` for your system.
|
||||
Be sure, that the option `CONFIG_HERMIT_CORE` in `Processor type and features` is enabled.
|
||||
2. Install the Linux kernel and its initial ramdisk on your system (see descriptions of your Linux distribution).
|
||||
We recommend to disable Linux NO_HZ feature by setting the kernel parameter `nohz=off`.
|
||||
3. After a reboot of the system, register the HermitCore loader at your system with following command: `echo ":hermit:M:7:\\x42::/path2proyxy/proxy:" > /proc/sys/fs/binfmt_misc/register`, in which `path2proxy` defines the path to the loader.
|
||||
You find the loader `proxy` after building the HermiCore sources in the subdirectory `tools` of the directory, which contains this *README*.
|
||||
4. The IP device between HermitCore and Linux currently does not support IPv6.
|
||||
Consequently, disable IPv6 by adding following line to `/etc/sysctl.conf`: `net.ipv6.conf.mmnif.disable_ipv6 = 1`.
|
||||
5. Per default, the IP device uses a static IP address range.
|
||||
Linux has to use `162.168.28.1`, where HermitCore isles start with `192.168.28.2` (isle 0).
|
||||
The network manager must be configured accordingly and therefore the file `/etc/sysconfig/network-scripts/ifcfg-mmnif` must be created with the following content:
|
||||
A [modified Linux kernel](https://github.com/RWTH-OS/linux) has to be installed.
|
||||
Afterwards switch to the branch `hermit` for a relative new vanilla kernel or to
|
||||
`centos`, which is compatible to the current CentOS 7 kernel. Configure the
|
||||
kernel with `make menuconfig` for your system. Be sure, that the option
|
||||
`CONFIG_HERMIT_CORE` in `Processor type and features` is enabled.
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/RWTH-OS/linux
|
||||
$ cd linux
|
||||
$ # see comments above
|
||||
$ git checkout hermit
|
||||
$ make menuconfig
|
||||
$ make
|
||||
```
|
||||
|
||||
Install the Linux kernel and its initial ramdisk on your system (see
|
||||
descriptions of your Linux distribution). We recommend to disable Linux NO_HZ
|
||||
feature by setting the kernel parameter `nohz=off`.
|
||||
|
||||
Install HermitCore to your system (by default to `/opt/hermit`):
|
||||
|
||||
```bash
|
||||
$ cd build
|
||||
$ sudo make install
|
||||
$ ls -l /opt/hermit
|
||||
```
|
||||
|
||||
After a reboot of the system, register the HermitCore loader at your system with
|
||||
following command:
|
||||
|
||||
```bash
|
||||
$ sudo -c sh 'echo ":hermit:M:7:\\x42::/opt/hermit/bin/proxy:" > /proc/sys/fs/binfmt_misc/register'
|
||||
```
|
||||
|
||||
The IP device between HermitCore and Linux currently does not support IPv6.
|
||||
Consequently, disable it (might be slightly different on your distribution):
|
||||
|
||||
```bash
|
||||
$ echo 'net.ipv6.conf.mmnif.disable_ipv6 = 1' | sudo tee /etc/sysctl.conf
|
||||
```
|
||||
|
||||
Per default, the IP device uses a static IP address range. Linux has to use
|
||||
`162.168.28.1`, where HermitCore isles start with `192.168.28.2` (isle 0). The
|
||||
interface is `mmnif`.
|
||||
|
||||
Please configure your network accordingly. For CentOS, you have to create the
|
||||
file `/etc/sysconfig/network-scripts/ifcfg-mmnif`:
|
||||
|
||||
```
|
||||
DEVICE=mmnif
|
||||
|
@ -96,63 +296,76 @@ NETMASK=255.255.255.0
|
|||
IPADDR=192.168.28.1
|
||||
NM_CONTROLLED=yes
|
||||
```
|
||||
Finally, follow the [above tutorial](#building-and-testing-hermitcore-within-a-virtual-machine) from Step 5.
|
||||
The demo applications are located in their subdirectories `usr/{tests,benchmarks}`.
|
||||
|
||||
## Building and testing HermitCore as classical standalone unikernel
|
||||
You can now start applications the same way as from within a virtual machine
|
||||
(see description above).
|
||||
|
||||
HermitCore applications can be directly started as standalone kernel within a virtual machine.
|
||||
In this case, [iRCCE](http://www.lfbs.rwth-aachen.de/publications/files/iRCCE.pdf) is not supported.
|
||||
Please build HermitCore and register the loader in the same way as done for the multi-kernel version (see [Building and testing HermitCore on a real machine](#building-and-testing-hermitcore-on-a-real-machine)).
|
||||
If the environment variable `HERMIT_ISLE` is set to `qemu`, the application will be started within a VM.
|
||||
Please note that the loader requires QEMU and uses per default *KVM*.
|
||||
Furthermore, it expects that the executable is called `qemu-system-x86_64`.
|
||||
You can adapt the name by setting the environment variable `HERMIT_QEMU`.
|
||||
|
||||
In this context, the environment variable `HERMIT_CPUS` specifies the number of cpus (and no longer a range of core ids).
|
||||
Furthermore, the variable `HERMIT_MEM` defines the memory size of the virtual machine.
|
||||
The suffix of *M* or *G* can be used to specify a value in megabytes or gigabytes respectively.
|
||||
Per default, the loader initializes a system with one core and 2 GiB RAM.
|
||||
## Building your own HermitCore applications
|
||||
|
||||
The virtual machine opens two TCP/IP ports.
|
||||
One is used for the communication between HermitCore application and its proxy.
|
||||
The second port is used to create a connection via telnet to QEMU's system monitor.
|
||||
With the environment variable `HERMIT_PORT`, the default port (18766) can be changed for the communication between the HermitCore application and its proxy.
|
||||
The connection to the system monitor used automatically `HERMIT_PORT+1`, i.e., the default port is 18767.
|
||||
You can take `usr/tests` as a starting point to build your own applications. All
|
||||
that is required is that you include
|
||||
`[...]/HermitCore/cmake/HermitCore-Application.cmake` in your application's
|
||||
`CMakeLists.txt`. It doesn't have to reside inside the HermitCore repository.
|
||||
Other than that, it should behave like normal CMake.
|
||||
|
||||
|
||||
## Profiling
|
||||
|
||||
We provide profiling support via the XRay profiler. See `usr/xray/README.md` for
|
||||
more information on how to use it.
|
||||
|
||||
|
||||
## Debugging
|
||||
|
||||
If the application is started via `make qemu`, debugging via GDB is enabled by
|
||||
default on port 1234. When run via proxy (`HERMIT_ISLE=qemu`), set
|
||||
`HERMIT_DEBUG=1`.
|
||||
|
||||
The following example starts the stream benchmark in a virtual machine, which has 4 cores and 6GB memory.
|
||||
```
|
||||
HERMIT_ISLE=qemu HERMIT_CPUS=4 HERMIT_MEM=6G usr/benchmarks/stream
|
||||
$ gdb x86_64-hermit/extra/tests/hello
|
||||
(gdb) target extended-remote :1234
|
||||
Remote debugging using :1234
|
||||
0xffffffff8100b542 in ?? ()
|
||||
```
|
||||
|
||||
## Building HermitCore applications
|
||||
|
||||
After successful building of HermitCore and its demo applications (see above), HermitCore’s cross toolchain (*gcc*, *g++*, *gfortran*, *gccgo*, *objdump*, etc.) is located at the subdiretory `usr/x86` of the directory, which contains this *README*.
|
||||
To use these tools, add `usr/x86/bin` to your environment variable `PATH`.
|
||||
As with any other cross toolchain, the tool names begin with the target architecture (*x86_64*) and the name of the operating system (*hermit*).
|
||||
For instance, `x86_64-hermit-gcc` stands for the GNU C compiler, which is able to build HermitCore applications.
|
||||
|
||||
All tools can be used as the well-known GNU tools. Only the Go compiler works different to the typical workflow.
|
||||
Instead of building Go application like
|
||||
```
|
||||
go build main.go
|
||||
```
|
||||
you have to use the compiler as follows
|
||||
```
|
||||
x86_64-hermit-gccgo -pthread -Wall -o main main.go
|
||||
```
|
||||
For network support, you have to link the Go application with the flag `-lnetgo`.
|
||||
|
||||
## Tips
|
||||
|
||||
1. The configuration flag `--with-mtune=name` specifies the name of the target processor for which GCC should tune the performance of the code.
|
||||
You can use any architecture name, which is supported by GCC.
|
||||
For instance, `--with-mtune=native` optimzes the code for the host system.
|
||||
Please note, if the applications is started within a VM, the hypervisor has to support the specified architecture name.
|
||||
Per default the system will be accelerated by KVM and the host architecture will be used as target processor.
|
||||
2. If Qemu is started by our proxy and the environment variable `HERMIT_KVM` is set to `0`, the virtual machine will be not accelerated by KVM.
|
||||
In this case, the configuration flag `--with-mtune=name` should be avoided.
|
||||
With the environment variable `HERMIT_APP_PORT`, an additional port can be open to establish an TCP/IP connection with your application.
|
||||
3. By setting the environment variable `HERMIT_VERBOSE` to `1`, the proxy prints at termination the kernel log messages onto the screen.
|
||||
4. If `HERMIT_DEBUG` is set to `1`, Qemu will establish an gdbserver, which will be listen port 1234.
|
||||
Afterwards you are able debug HermitCore applications remotely.
|
||||
### Optimization
|
||||
|
||||
You can configure the `-mtune=name` compiler flag by adding `-DMTUNE=name` to
|
||||
the `cmake` command when configuring the project.
|
||||
|
||||
Please note, if the applications is started within a VM, the hypervisor has to
|
||||
support the specified architecture name.
|
||||
|
||||
If QEMU is started by our proxy and the environment variable `HERMIT_KVM` is set
|
||||
to `0`, the virtual machine will be not accelerated by KVM. In this case, the
|
||||
`-mtune` flag should be avoided.
|
||||
|
||||
### TCP connections
|
||||
|
||||
With the environment variable `HERMIT_APP_PORT`, an additional port can be open
|
||||
to establish an TCP/IP connection with your application.
|
||||
|
||||
### Dumping the kernel log
|
||||
|
||||
By setting the environment variable `HERMIT_VERBOSE` to `1`, the proxy prints at
|
||||
termination the kernel log messages onto the screen.
|
||||
|
||||
### Network tracing
|
||||
|
||||
By setting the environment variable `HERMIT_CAPTURE_NET` to `1` and
|
||||
`HERMIT_ISLE` to `qemu`, QEMU captures the network traffic and creates the trace
|
||||
file *qemu-vlan0.pcap*. For instance with [Wireshark](https://www.wireshark.org)
|
||||
you are able to analyze the file.
|
||||
|
||||
### Monitor
|
||||
|
||||
If `HERMIT_MONITOR` is set to `1` and `HERMIT_ISLE` to `qemu`, QEMU establishes
|
||||
a monitor which is available via telnet at port 18767.
|
||||
|
||||
## Credits
|
||||
|
||||
HermitCore's Emoji is provided free by [EmojiOne](https://www.gfxmag.com/crab-emoji-vector-icon/).
|
||||
|
|
88
arch/x86/CMakeLists.txt
Normal file
88
arch/x86/CMakeLists.txt
Normal file
|
@ -0,0 +1,88 @@
|
|||
cmake_minimum_required(VERSION 3.7)
|
||||
include(../../cmake/HermitCore.cmake)
|
||||
|
||||
project(arch_x86_kernel C ASM_NASM)
|
||||
|
||||
set_parent(X86_KERNEL_TARGET ${PROJECT_NAME})
|
||||
set_parent(X86_KERNEL_ASM_TARGET ${X86_KERNEL_TARGET}_asm)
|
||||
set_parent(X86_KERNEL_C_TARGET ${X86_KERNEL_TARGET}_c)
|
||||
|
||||
add_custom_target(${X86_KERNEL_TARGET})
|
||||
|
||||
# compiling kernel code here
|
||||
add_definitions(-D__KERNEL__)
|
||||
|
||||
|
||||
### ASM sources ###
|
||||
|
||||
add_library(${X86_KERNEL_ASM_TARGET} OBJECT
|
||||
kernel/entry.asm
|
||||
libkern/string.asm)
|
||||
|
||||
# HACK: We need to post-process the objects by running elfedit on them, but
|
||||
# there is currently no way to get the list of objects out of CMake
|
||||
# except for $<TARGET_OBJECTS:tgt>, which only works with add_library()
|
||||
# and add_executable().
|
||||
# So predict path to objects and add custom commands that depend on
|
||||
# the asm target.
|
||||
#
|
||||
# Upstream issue: https://gitlab.kitware.com/cmake/cmake/issues/15226
|
||||
#
|
||||
set(_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}")
|
||||
set(_BUILD_DIR "${_BUILD_DIR}/${X86_KERNEL_ASM_TARGET}.dir")
|
||||
|
||||
get_target_property(ASM_SOURCES ${X86_KERNEL_ASM_TARGET} SOURCES)
|
||||
foreach(SOURCE ${ASM_SOURCES})
|
||||
set(OBJECT "${SOURCE}.obj")
|
||||
set(OBJECT_PATH "${_BUILD_DIR}/${OBJECT}")
|
||||
|
||||
# slash (/) not allowed in target names
|
||||
string(REPLACE "/" "-"
|
||||
OBJECT_TARGET_NAME
|
||||
"${OBJECT}")
|
||||
|
||||
add_custom_target("${OBJECT_TARGET_NAME}"
|
||||
COMMAND
|
||||
${CMAKE_ELFEDIT} --output-osabi HermitCore ${OBJECT_PATH}
|
||||
DEPENDS
|
||||
${X86_KERNEL_ASM_TARGET})
|
||||
|
||||
# make main target depend on this
|
||||
add_dependencies(${PROJECT_NAME} ${OBJECT_TARGET_NAME})
|
||||
endforeach()
|
||||
|
||||
|
||||
### C sources ###
|
||||
|
||||
file(GLOB KERNEL_SOURCES "kernel/*.c")
|
||||
file(GLOB MM_SOURCES "mm/*.c")
|
||||
|
||||
# add boot.h as source to mark dependency boot.asm -> boot.h -> apic.c
|
||||
add_library(${X86_KERNEL_C_TARGET} OBJECT
|
||||
${KERNEL_SOURCES} ${MM_SOURCES}
|
||||
${GENERATED_CONFIG_DIR}/hermit/boot.h)
|
||||
|
||||
target_include_directories(${X86_KERNEL_C_TARGET} BEFORE
|
||||
PUBLIC ${HERMIT_KERNEL_INCLUDES}
|
||||
PRIVATE ${GENERATED_CONFIG_DIR})
|
||||
|
||||
target_compile_options(${X86_KERNEL_C_TARGET}
|
||||
PRIVATE ${HERMIT_KERNEL_FLAGS})
|
||||
|
||||
# assemble boot.asm and dump to C-array in boot.h
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${GENERATED_CONFIG_DIR}/hermit/boot.h
|
||||
DEPENDS
|
||||
kernel/boot.asm
|
||||
COMMAND
|
||||
echo "static const uint8_t boot_code[] = {" > boot.h
|
||||
COMMAND
|
||||
nasm -f bin -o boot.bin ${CMAKE_CURRENT_LIST_DIR}/kernel/boot.asm
|
||||
COMMAND
|
||||
hexdump -v -e "7/1 \"0x%02X, \" 1/1 \" 0x%02X,\\n\"" boot.bin >> boot.h
|
||||
COMMAND
|
||||
echo "};" >> boot.h
|
||||
WORKING_DIRECTORY
|
||||
${GENERATED_CONFIG_DIR}/hermit/
|
||||
VERBATIM USES_TERMINAL)
|
|
@ -52,8 +52,8 @@ typedef struct { volatile int32_t counter; } atomic_int32_t;
|
|||
* This function will atomically exchange the value of an atomic variable and
|
||||
* return its old value. Is used in locking-operations.\n
|
||||
* \n
|
||||
* Intel manuals: If a memory operand is referenced, the processor's locking
|
||||
* protocol is automatically implemented for the duration of the exchange
|
||||
* Intel manuals: If a memory operand is referenced, the processor's locking
|
||||
* protocol is automatically implemented for the duration of the exchange
|
||||
* operation, regardless of the presence or absence of the LOCK prefix.
|
||||
*
|
||||
* @param d Pointer to the atomic_int_32_t with the value you want to exchange
|
||||
|
@ -79,7 +79,7 @@ inline static int32_t atomic_int32_test_and_set(atomic_int32_t* d, int32_t ret)
|
|||
inline static int32_t atomic_int32_add(atomic_int32_t *d, int32_t i)
|
||||
{
|
||||
int32_t res = i;
|
||||
asm volatile(LOCK "xaddl %0, %1" : "=r"(i) : "m"(d->counter), "0"(i) : "memory", "cc");
|
||||
asm volatile(LOCK "xaddl %0, %1" : "+r"(i), "+m"(d->counter) : : "memory", "cc");
|
||||
return res+i;
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ inline static int32_t atomic_int32_add(atomic_int32_t *d, int32_t i)
|
|||
*/
|
||||
inline static int32_t atomic_int32_sub(atomic_int32_t *d, int32_t i)
|
||||
{
|
||||
return atomic_int32_add(d, -i);
|
||||
return atomic_int32_add(d, -i);
|
||||
}
|
||||
|
||||
/** @brief Atomic increment by one
|
||||
|
@ -105,7 +105,9 @@ inline static int32_t atomic_int32_sub(atomic_int32_t *d, int32_t i)
|
|||
* @param d The atomic_int32_t var you want to increment
|
||||
*/
|
||||
inline static int32_t atomic_int32_inc(atomic_int32_t* d) {
|
||||
return atomic_int32_add(d, 1);
|
||||
int32_t res = 1;
|
||||
asm volatile(LOCK "xaddl %0, %1" : "+r"(res), "+m"(d->counter) : : "memory", "cc");
|
||||
return ++res;
|
||||
}
|
||||
|
||||
/** @brief Atomic decrement by one
|
||||
|
@ -115,7 +117,9 @@ inline static int32_t atomic_int32_inc(atomic_int32_t* d) {
|
|||
* @param d The atomic_int32_t var you want to decrement
|
||||
*/
|
||||
inline static int32_t atomic_int32_dec(atomic_int32_t* d) {
|
||||
return atomic_int32_add(d, -1);
|
||||
int32_t res = -1;
|
||||
asm volatile(LOCK "xaddl %0, %1" : "+r"(res), "+m"(d->counter) : : "memory", "cc");
|
||||
return --res;
|
||||
}
|
||||
|
||||
/** @brief Read out an atomic_int32_t var
|
||||
|
@ -132,7 +136,7 @@ inline static int32_t atomic_int32_read(atomic_int32_t *d) {
|
|||
|
||||
/** @brief Set the value of an atomic_int32_t var
|
||||
*
|
||||
* This function is for convenience: It sets the internal value of
|
||||
* This function is for convenience: It sets the internal value of
|
||||
* an atomic_int32_t var for you.
|
||||
*
|
||||
* @param d Pointer to the atomic_int32_t var you want to set
|
||||
|
|
|
@ -52,8 +52,8 @@ typedef struct { volatile int64_t counter; } atomic_int64_t;
|
|||
* This function will atomically exchange the value of an atomic variable and
|
||||
* return its old value. Is used in locking-operations.\n
|
||||
* \n
|
||||
* Intel manuals: If a memory operand is referenced, the processor's locking
|
||||
* protocol is automatically implemented for the duration of the exchange
|
||||
* Intel manuals: If a memory operand is referenced, the processor's locking
|
||||
* protocol is automatically implemented for the duration of the exchange
|
||||
* operation, regardless of the presence or absence of the LOCK prefix.
|
||||
*
|
||||
* @param d Pointer to the atomic_int_64_t with the value you want to exchange
|
||||
|
@ -79,7 +79,7 @@ inline static int64_t atomic_int64_test_and_set(atomic_int64_t* d, int64_t ret)
|
|||
inline static int64_t atomic_int64_add(atomic_int64_t *d, int64_t i)
|
||||
{
|
||||
int64_t res = i;
|
||||
asm volatile(LOCK "xaddq %0, %1" : "=r"(i) : "m"(d->counter), "0"(i) : "memory", "cc");
|
||||
asm volatile(LOCK "xaddq %0, %1" : "+r"(i), "+m"(d->counter) : : "memory", "cc");
|
||||
return res+i;
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ inline static int64_t atomic_int64_add(atomic_int64_t *d, int64_t i)
|
|||
*/
|
||||
inline static int64_t atomic_int64_sub(atomic_int64_t *d, int64_t i)
|
||||
{
|
||||
return atomic_int64_add(d, -i);
|
||||
return atomic_int64_add(d, -i);
|
||||
}
|
||||
|
||||
/** @brief Atomic increment by one
|
||||
|
@ -105,7 +105,9 @@ inline static int64_t atomic_int64_sub(atomic_int64_t *d, int64_t i)
|
|||
* @param d The atomic_int64_t var you want to increment
|
||||
*/
|
||||
inline static int64_t atomic_int64_inc(atomic_int64_t* d) {
|
||||
return atomic_int64_add(d, 1);
|
||||
int64_t res = 1;
|
||||
asm volatile(LOCK "xaddq %0, %1" : "+r"(res), "+m"(d->counter) : : "memory", "cc");
|
||||
return ++res;
|
||||
}
|
||||
|
||||
/** @brief Atomic decrement by one
|
||||
|
@ -115,7 +117,9 @@ inline static int64_t atomic_int64_inc(atomic_int64_t* d) {
|
|||
* @param d The atomic_int64_t var you want to decrement
|
||||
*/
|
||||
inline static int64_t atomic_int64_dec(atomic_int64_t* d) {
|
||||
return atomic_int64_add(d, -1);
|
||||
int64_t res = -1;
|
||||
asm volatile(LOCK "xaddq %0, %1" : "+r"(res), "+m"(d->counter) : : "memory", "cc");
|
||||
return --res;
|
||||
}
|
||||
|
||||
/** @brief Read out an atomic_int64_t var
|
||||
|
@ -132,7 +136,7 @@ inline static int64_t atomic_int64_read(atomic_int64_t *d) {
|
|||
|
||||
/** @brief Set the value of an atomic_int64_t var
|
||||
*
|
||||
* This function is for convenience: It sets the internal value of
|
||||
* This function is for convenience: It sets the internal value of
|
||||
* an atomic_int64_t var for you.
|
||||
*
|
||||
* @param d Pointer to the atomic_int64_t var you want to set
|
||||
|
|
|
@ -143,6 +143,8 @@ typedef struct multiboot_mod_list multiboot_module_t;
|
|||
|
||||
/// Pointer to multiboot structure
|
||||
/// This pointer is declared at set by entry.asm
|
||||
extern multiboot_info_t* mb_info;
|
||||
extern const multiboot_info_t* const mb_info;
|
||||
extern char* cmdline;
|
||||
extern size_t cmdsize;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,19 +36,23 @@
|
|||
|
||||
#include <hermit/stddef.h>
|
||||
#include <hermit/stdlib.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#ifndef __PAGE_H__
|
||||
#define __PAGE_H__
|
||||
|
||||
/// Page offset bits
|
||||
#define PAGE_BITS 12
|
||||
#define PAGE_2M_BITS 21
|
||||
/// The size of a single page in bytes
|
||||
#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)
|
||||
#else
|
||||
#define PAGE_MASK (((~0L) << PAGE_BITS) & ~PG_XD)
|
||||
#define PAGE_2M_MASK (((~0L) << PAGE_2M_BITS) & ~PG_XD)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
@ -141,6 +145,8 @@ static inline size_t sign_extend(ssize_t addr, int bits)
|
|||
/// Disable execution for this page
|
||||
#define PG_XD (1L << 63)
|
||||
|
||||
#define PG_NX (has_nx() ? PG_XD : 0)
|
||||
|
||||
/** @brief Converts a virtual address to a physical
|
||||
*
|
||||
* A non mapped virtual address causes a pagefault!
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
*/
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file arch/x86/include/asm/pci.h
|
||||
* @brief functions related to PCI initialization and information
|
||||
|
@ -48,6 +48,8 @@ typedef struct {
|
|||
uint32_t irq;
|
||||
} pci_info_t;
|
||||
|
||||
#define PCI_IGNORE_SUBID (0)
|
||||
|
||||
/** @brief Initialize the PCI environment
|
||||
*/
|
||||
int pci_init(void);
|
||||
|
@ -55,15 +57,16 @@ int pci_init(void);
|
|||
/** @brief Determine the IObase address and the interrupt number of a specific device
|
||||
*
|
||||
* @param vendor_id The device's vendor ID
|
||||
* @param device_id the device's ID
|
||||
* @param device_id The device's ID
|
||||
* @param subystem_id The subsystem DI
|
||||
* @param info Pointer to the record pci_info_t where among other the IObase address will be stored
|
||||
* @param enable_bus_master If true, the bus mastering will be enabled.
|
||||
*
|
||||
* @return
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
int pci_get_device_info(uint32_t vendor_id, uint32_t device_id, pci_info_t* info, int8_t enble_bus_master);
|
||||
int pci_get_device_info(uint32_t vendor_id, uint32_t device_id, uint32_t subsystem_id, pci_info_t* info, int8_t enble_bus_master);
|
||||
|
||||
/** @brief Print information of existing pci adapters
|
||||
*
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <asm/apic.h>
|
||||
#include <asm/irqflags.h>
|
||||
#include <asm/pci.h>
|
||||
#include <asm/tss.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -89,6 +90,7 @@ extern "C" {
|
|||
// feature list 0x00000007:0
|
||||
#define CPU_FEATURE_FSGSBASE (1 << 0)
|
||||
#define CPU_FEATURE_TSC_ADJUST (1 << 1)
|
||||
#define CPU_FEATURE_SGX (1 << 2)
|
||||
#define CPU_FEATURE_BMI1 (1 << 3)
|
||||
#define CPU_FEATURE_HLE (1 << 4)
|
||||
#define CPU_FEATURE_AVX2 (1 << 5)
|
||||
|
@ -110,6 +112,8 @@ extern "C" {
|
|||
#define CPU_FEATURE_AVX512ER (1 << 27)
|
||||
#define CPU_FEATURE_AVX512CD (1 << 28)
|
||||
#define CPU_FEATURE_SHA_NI (1 << 29)
|
||||
#define CPU_FEATURE_AVX512BW (1 << 30)
|
||||
#define CPU_FEATURE_AVX512VL (1 <<31)
|
||||
|
||||
// feature list 0x00000006
|
||||
#define CPU_FEATURE_IDA (1 << 0)
|
||||
|
@ -407,6 +411,10 @@ inline static uint32_t has_fsgsbase(void) {
|
|||
return (cpu_info.feature4 & CPU_FEATURE_FSGSBASE);
|
||||
}
|
||||
|
||||
inline static uint32_t has_sgx(void) {
|
||||
return (cpu_info.feature4 & CPU_FEATURE_SGX);
|
||||
}
|
||||
|
||||
inline static uint32_t has_avx2(void) {
|
||||
return (cpu_info.feature4 & CPU_FEATURE_AVX2);
|
||||
}
|
||||
|
@ -431,6 +439,14 @@ inline static uint32_t has_rtm(void) {
|
|||
return (cpu_info.feature4 & CPU_FEATURE_RTM);
|
||||
}
|
||||
|
||||
inline static uint32_t has_clflushopt(void) {
|
||||
return (cpu_info.feature4 & CPU_FEATURE_CLFLUSHOPT);
|
||||
}
|
||||
|
||||
inline static uint32_t has_clwb(void) {
|
||||
return (cpu_info.feature4 & CPU_FEATURE_CLWB);
|
||||
}
|
||||
|
||||
inline static uint32_t has_avx512f(void) {
|
||||
return (cpu_info.feature4 & CPU_FEATURE_AVX512F);
|
||||
}
|
||||
|
@ -447,6 +463,14 @@ inline static uint32_t has_avx512cd(void) {
|
|||
return (cpu_info.feature4 & CPU_FEATURE_AVX512CD);
|
||||
}
|
||||
|
||||
inline static uint32_t has_avx512bw(void) {
|
||||
return (cpu_info.feature4 & CPU_FEATURE_AVX512BW);
|
||||
}
|
||||
|
||||
inline static uint32_t has_avx512vl(void) {
|
||||
return (cpu_info.feature4 & CPU_FEATURE_AVX512VL);
|
||||
}
|
||||
|
||||
inline static uint32_t has_rdtscp(void) {
|
||||
return (cpu_info.feature3 & CPU_FEATURE_RDTSCP);
|
||||
}
|
||||
|
@ -722,6 +746,16 @@ static inline void clflush(volatile void *addr)
|
|||
asm volatile("clflush %0" : "+m" (*(volatile char *)addr));
|
||||
}
|
||||
|
||||
static inline void clwb(volatile void *addr)
|
||||
{
|
||||
asm volatile("clwb %0" : "+m" (*(volatile char *)addr));
|
||||
}
|
||||
|
||||
static inline void clflushopt(volatile void *addr)
|
||||
{
|
||||
asm volatile("clflushopt %0" : "+m" (*(volatile char *)addr));
|
||||
}
|
||||
|
||||
#if 0
|
||||
// the old way to serialize the store and load operations
|
||||
static inline void mb(void) { asm volatile ("lock; addl $0,0(%%esp)" ::: "memory", "cc"); }
|
||||
|
@ -791,6 +825,66 @@ static inline uint64_t read_rflags(void)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall
|
||||
* instruction. The hypervisor may replace it with something else but only the
|
||||
* instructions are guaranteed to be supported.
|
||||
*
|
||||
* Up to four arguments may be passed in rbx, rcx, rdx, and rsi respectively.
|
||||
* The hypercall number should be placed in rax and the return value will be
|
||||
* placed in rax. No other registers will be clobbered unless explicitly
|
||||
* noted by the particular hypercall.
|
||||
*/
|
||||
|
||||
inline static size_t vmcall0(int nr)
|
||||
{
|
||||
size_t res;
|
||||
|
||||
asm volatile ("vmcall" : "=a" (res): "a" (nr)
|
||||
: "memory");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
inline static size_t vmcall1(int nr, size_t arg0)
|
||||
{
|
||||
size_t res;
|
||||
|
||||
asm volatile ("vmcall" : "=a" (res): "a" (nr), "b"(arg0)
|
||||
: "memory");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
inline static size_t vmcall2(int nr, size_t arg0, size_t arg1)
|
||||
{
|
||||
size_t res;
|
||||
|
||||
asm volatile ("vmcall" : "=a" (res): "a" (nr), "b"(arg0), "c"(arg1)
|
||||
: "memory");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
inline static size_t vmcall3(int nr, size_t arg0, size_t arg1, size_t arg2)
|
||||
{
|
||||
size_t res;
|
||||
|
||||
asm volatile ("vmcall" : "=a" (res): "a" (nr), "b"(arg0), "c"(arg1), "d"(arg2)
|
||||
: "memory");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
inline static size_t vmcall4(int nr, size_t arg0, size_t arg1, size_t arg2, size_t arg3)
|
||||
{
|
||||
size_t res;
|
||||
|
||||
asm volatile ("vmcall" : "=a" (res): "a" (nr), "b"(arg0), "c"(arg1), "d"(arg2), "S"(arg3)
|
||||
: "memory");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/** @brief search the first most significant bit
|
||||
*
|
||||
* @param i source operand
|
||||
|
@ -894,7 +988,7 @@ inline static int system_calibration(void)
|
|||
size_t cr0;
|
||||
|
||||
apic_init();
|
||||
if (is_single_kernel())
|
||||
if (is_single_kernel() && !is_uhyve())
|
||||
pci_init();
|
||||
register_task();
|
||||
|
||||
|
|
|
@ -205,6 +205,7 @@ typedef struct {
|
|||
size_t ss_size; /* Stack size. */
|
||||
} stack_t;
|
||||
|
||||
const int32_t is_uhyve(void);
|
||||
const int32_t is_single_kernel(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARCH_MEMCPY
|
||||
#if HAVE_ARCH_MEMCPY
|
||||
/** @brief Copy a byte range from source to dest
|
||||
*
|
||||
* @param dest Destination address
|
||||
|
@ -52,7 +52,7 @@ inline static void *memcpy(void* dest, const void *src, size_t count)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARCH_MEMSET
|
||||
#if HAVE_ARCH_MEMSET
|
||||
/** @brief Repeated write of a value to a whole range of bytes
|
||||
*
|
||||
* @param dest Destination address
|
||||
|
@ -84,7 +84,7 @@ inline static void *memset(void* dest, int val, size_t count)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARCH_STRLEN
|
||||
#if HAVE_ARCH_STRLEN
|
||||
/** @brief Standard string length
|
||||
*
|
||||
* This function computed the length of the given null terminated string
|
||||
|
@ -111,7 +111,7 @@ inline static size_t strlen(const char* str)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARCH_STRNCPY
|
||||
#if HAVE_ARCH_STRNCPY
|
||||
/** @brief Copy string with maximum of n byte length
|
||||
*
|
||||
* @param dest Destination string pointer
|
||||
|
@ -121,7 +121,7 @@ inline static size_t strlen(const char* str)
|
|||
char* strncpy(char* dest, const char* src, size_t n);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARCH_STRCPY
|
||||
#if HAVE_ARCH_STRCPY
|
||||
/** @brief Copy string
|
||||
*
|
||||
* Note that there is another safer variant of this function: strncpy.\n
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* @file arch/x86/include/asm/tasks.h
|
||||
* @brief Task related structure definitions
|
||||
*
|
||||
* This file contains the task_t structure definition
|
||||
* This file contains the task_t structure definition
|
||||
* and task state define constants
|
||||
*/
|
||||
|
||||
|
@ -55,7 +55,7 @@ void switch_context(size_t** stack);
|
|||
* @param task Pointer to the task structure
|
||||
* @param ep The entry point for code execution
|
||||
* @param arg Arguments list pointer for the task's stack
|
||||
* @param core_id Id of the core, which is firstly used by the task
|
||||
* @param core_id Id of the core, which is firstly used by the task
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
|
@ -77,6 +77,13 @@ static inline int jump_to_user_code(size_t ep, size_t stack)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Architecture dependent initialize routine
|
||||
*/
|
||||
static inline void arch_init_task(task_t* task)
|
||||
{
|
||||
set_tss((size_t) task->stack + KERNEL_STACK_SIZE - 0x10, (size_t) task->ist_addr + KERNEL_STACK_SIZE - 0x10);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* Copyright (c) 2017, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,34 +25,26 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __VGA_H__
|
||||
#define __VGA_H__
|
||||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file arch/x86/include/asm/string.h
|
||||
* @brief Time related functions
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#ifndef __ARCH_TIME_H__
|
||||
#define __ARCH_TIME_H__
|
||||
|
||||
#include <asm/apic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Initialize VGA output and clear the screen */
|
||||
void vga_init(void);
|
||||
static inline int timer_deadline(uint32_t t) { return apic_timer_deadline(t); }
|
||||
|
||||
/** @brief Simple string output on screen.
|
||||
*
|
||||
* If you want a new line you will have to "\\n".
|
||||
*
|
||||
* @return Length of output in bytes
|
||||
*/
|
||||
int vga_puts(const char *text);
|
||||
static inline void timer_disable(void) { apic_disable_timer(); }
|
||||
|
||||
/** @brief Simple character output on screen.
|
||||
*
|
||||
* @return The original input character casted to int
|
||||
*/
|
||||
int vga_putchar(unsigned char c);
|
||||
|
||||
/** @brief Clear the screen */
|
||||
void vga_cls(void);
|
||||
static inline int timer_is_running(void) { return apic_timer_is_running(); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
|
@ -40,12 +40,6 @@ extern "C" {
|
|||
*/
|
||||
int uart_init(void);
|
||||
|
||||
/** @brief Initialize UART output without a device check
|
||||
*
|
||||
* @return Returns 0 on success
|
||||
*/
|
||||
int uart_early_init(char*);
|
||||
|
||||
/** @brief Simple string output on a serial device.
|
||||
*
|
||||
* If you want a new line you will have to "\\n".
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* Copyright (c) 2017, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,34 +25,26 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __VGA_H__
|
||||
#define __VGA_H__
|
||||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file arch/x86/include/asm/uhyve.h
|
||||
* @brief interface to our machine monitor
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_UHYVE_H__
|
||||
#define __ARCH_UHYVE_H__
|
||||
|
||||
#include <hermit/stddef.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Initialize VGA output and clear the screen */
|
||||
void vga_init(void);
|
||||
|
||||
/** @brief Simple string output on screen.
|
||||
*
|
||||
* If you want a new line you will have to "\\n".
|
||||
*
|
||||
* @return Length of output in bytes
|
||||
*/
|
||||
int vga_puts(const char *text);
|
||||
|
||||
/** @brief Simple character output on screen.
|
||||
*
|
||||
* @return The original input character casted to int
|
||||
*/
|
||||
int vga_putchar(unsigned char c);
|
||||
|
||||
/** @brief Clear the screen */
|
||||
void vga_cls(void);
|
||||
inline static void uhyve_send(unsigned short _port, unsigned int _data)
|
||||
{
|
||||
outportl(_port, _data);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
C_source := irq.c idt.c isrs.c gdt.c processor.c timer.c tasks.c apic.c pci.c vga.c uart.c syscall.c
|
||||
ASM_source := entry.asm string.asm
|
||||
MODULE := arch_x86_kernel
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
|
@ -42,7 +42,7 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/apic.h>
|
||||
#include "boot.h"
|
||||
#include <hermit/boot.h>
|
||||
|
||||
/*
|
||||
* Note that linker symbols are not variables, they have no memory allocated for
|
||||
|
@ -408,6 +408,7 @@ static apic_mp_t* search_mptable(size_t base, size_t limit) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static size_t search_ebda(void) {
|
||||
size_t ptr=PAGE_CEIL(0x400), vptr=0xF0000;
|
||||
size_t flags = PG_GLOBAL | PG_RW | PG_PCD;
|
||||
|
@ -421,12 +422,13 @@ static size_t search_ebda(void) {
|
|||
|
||||
uint16_t addr = *((uint16_t*) (vptr+0x40E));
|
||||
LOG_INFO("Found EBDA at 0x%x!\n", (uint32_t)addr);
|
||||
|
||||
|
||||
// unmap page via mapping a zero page
|
||||
page_unmap(vptr, 1);
|
||||
|
||||
return (size_t) addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lapic_reset(void)
|
||||
{
|
||||
|
@ -454,8 +456,8 @@ static int lapic_reset(void)
|
|||
lapic_write(APIC_LVT_TSR, 0x10000); // disable thermal sensor interrupt
|
||||
if (max_lvt >= 5)
|
||||
lapic_write(APIC_LVT_PMC, 0x10000); // disable performance counter interrupt
|
||||
lapic_write(APIC_LINT0, 0x7C); // connect LINT0 to idt entry 124
|
||||
lapic_write(APIC_LINT1, 0x7D); // connect LINT1 to idt entry 125
|
||||
lapic_write(APIC_LINT0, 0x00010000); // disable LINT0
|
||||
lapic_write(APIC_LINT1, 0x00010000); // disable LINT1
|
||||
lapic_write(APIC_LVT_ER, 0x7E); // connect error to idt entry 126
|
||||
|
||||
return 0;
|
||||
|
@ -479,7 +481,7 @@ static int wakeup_ap(uint32_t start_eip, uint32_t id)
|
|||
reset_vector = (char*) vma_alloc(PAGE_SIZE, VMA_READ|VMA_WRITE);
|
||||
page_map((size_t)reset_vector, 0x00, 1, PG_RW|PG_GLOBAL|PG_PCD);
|
||||
reset_vector += 0x467; // add base address of the reset vector
|
||||
LOG_INFO("Map reset vector to %p\n", reset_vector);
|
||||
LOG_DEBUG("Map reset vector to %p\n", reset_vector);
|
||||
}
|
||||
|
||||
*((volatile unsigned short *) (reset_vector+2)) = start_eip >> 4;
|
||||
|
@ -546,7 +548,7 @@ static int wakeup_ap(uint32_t start_eip, uint32_t id)
|
|||
set_ipi_dest(id);
|
||||
lapic_write(APIC_ICR1, APIC_DM_STARTUP|(start_eip >> 12));
|
||||
if (traditional_delay)
|
||||
udelay(200);
|
||||
udelay(200);
|
||||
else
|
||||
udelay(10);
|
||||
|
||||
|
@ -568,7 +570,7 @@ int smp_init(void)
|
|||
if (ncores <= 1)
|
||||
return -EINVAL;
|
||||
|
||||
LOG_INFO("CR0 of core %u: 0x%x\n", apic_cpu_id(), read_cr0());
|
||||
LOG_DEBUG("CR0 of core %u: 0x%x\n", apic_cpu_id(), read_cr0());
|
||||
|
||||
/*
|
||||
* dirty hack: Reserve memory for the bootup code.
|
||||
|
@ -609,7 +611,7 @@ int smp_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
LOG_INFO("%d cores online\n", atomic_int32_read(&cpu_online));
|
||||
LOG_DEBUG("%d cores online\n", atomic_int32_read(&cpu_online));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -664,7 +666,8 @@ int apic_calibration(void)
|
|||
apic_initialized = 1;
|
||||
atomic_int32_inc(&cpu_online);
|
||||
|
||||
if(is_single_kernel()) {
|
||||
if (is_single_kernel()) {
|
||||
LOG_INFO("Disable PIC\n");
|
||||
// Now, HermitCore is able to use the APIC => Therefore, we disable the PIC
|
||||
outportb(0xA1, 0xFF);
|
||||
outportb(0x21, 0xFF);
|
||||
|
@ -681,6 +684,7 @@ int apic_calibration(void)
|
|||
}
|
||||
|
||||
// now, we don't longer need the IOAPIC timer and turn it off
|
||||
LOG_INFO("Disable IOAPIC timer\n");
|
||||
ioapic_intoff(2, apic_processors[boot_processor]->id);
|
||||
}
|
||||
|
||||
|
@ -694,7 +698,7 @@ int apic_calibration(void)
|
|||
|
||||
static int apic_probe(void)
|
||||
{
|
||||
size_t addr, ebda;
|
||||
size_t addr;
|
||||
uint32_t i, j, count;
|
||||
int isa_bus = -1;
|
||||
size_t flags = PG_GLOBAL | PG_RW | PG_PCD;
|
||||
|
@ -703,10 +707,12 @@ static int apic_probe(void)
|
|||
if (has_nx())
|
||||
flags |= PG_XD;
|
||||
|
||||
ebda = search_ebda();
|
||||
#if 0
|
||||
size_t ebda = search_ebda();
|
||||
apic_mp = search_mptable(ebda, ebda+0x400);
|
||||
if (apic_mp)
|
||||
goto found_mp;
|
||||
#endif
|
||||
|
||||
apic_mp = search_mptable(0xF0000, 0x100000);
|
||||
if (apic_mp)
|
||||
|
@ -717,7 +723,7 @@ static int apic_probe(void)
|
|||
|
||||
found_mp:
|
||||
if (!apic_mp) {
|
||||
LOG_ERROR("Didn't find MP config table\n");
|
||||
LOG_INFO("Didn't find MP config table\n");
|
||||
goto no_mp;
|
||||
}
|
||||
|
||||
|
@ -887,7 +893,8 @@ no_mp:
|
|||
boot_processor = 0;
|
||||
apic_mp = NULL;
|
||||
apic_config = NULL;
|
||||
ncores = 1;
|
||||
if (!is_uhyve())
|
||||
ncores = 1;
|
||||
goto check_lapic;
|
||||
}
|
||||
|
||||
|
@ -903,7 +910,7 @@ int smp_start(void)
|
|||
// reset APIC and set id
|
||||
lapic_reset();
|
||||
|
||||
LOG_INFO("Processor %d (local id %d) is entering its idle task\n", apic_cpu_id(), atomic_int32_read(¤t_boot_id));
|
||||
LOG_DEBUG("Processor %d (local id %d) is entering its idle task\n", apic_cpu_id(), atomic_int32_read(¤t_boot_id));
|
||||
|
||||
// use the same gdt like the boot processors
|
||||
gdt_flush();
|
||||
|
@ -911,12 +918,6 @@ int smp_start(void)
|
|||
// install IDT
|
||||
idt_install();
|
||||
|
||||
/*
|
||||
* we turned on paging
|
||||
* => now, we are able to register our task
|
||||
*/
|
||||
register_task();
|
||||
|
||||
// enable additional cpu features
|
||||
cpu_detection();
|
||||
|
||||
|
@ -931,6 +932,12 @@ int smp_start(void)
|
|||
|
||||
set_idle_task();
|
||||
|
||||
/*
|
||||
* TSS is set, pagining is enabled
|
||||
* => now, we are able to register our task
|
||||
*/
|
||||
register_task();
|
||||
|
||||
irq_enable();
|
||||
|
||||
atomic_int32_inc(&cpu_online);
|
||||
|
@ -1077,19 +1084,16 @@ void shutdown_system(void)
|
|||
}
|
||||
}
|
||||
|
||||
volatile uint32_t go_down = 0;
|
||||
|
||||
static void apic_shutdown(struct state * s)
|
||||
static void apic_shutdown(struct state* s)
|
||||
{
|
||||
go_down = 1;
|
||||
|
||||
LOG_DEBUG("Receive shutdown interrupt\n");
|
||||
}
|
||||
|
||||
static void apic_lint0(struct state * s)
|
||||
static void apic_wakeup(struct state* s)
|
||||
{
|
||||
// Currently nothing to do
|
||||
LOG_INFO("Receive LINT0 interrupt\n");
|
||||
LOG_DEBUG("Receive wakeup interrupt\n");
|
||||
}
|
||||
|
||||
int apic_init(void)
|
||||
|
@ -1101,12 +1105,12 @@ int apic_init(void)
|
|||
return ret;
|
||||
|
||||
// set APIC error handler
|
||||
irq_install_handler(121, apic_wakeup);
|
||||
irq_install_handler(126, apic_err_handler);
|
||||
#if MAX_CORES > 1
|
||||
irq_install_handler(80+32, apic_tlb_handler);
|
||||
#endif
|
||||
irq_install_handler(81+32, apic_shutdown);
|
||||
irq_install_handler(124, apic_lint0);
|
||||
if (apic_processors[boot_processor])
|
||||
LOG_INFO("Boot processor %u (ID %u)\n", boot_processor, apic_processors[boot_processor]->id);
|
||||
else
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
; Copyright (c) 2010-2015, Stefan Lankes, RWTH Aachen University
|
||||
; All rights reserved.
|
||||
;
|
||||
|
@ -29,12 +28,11 @@
|
|||
; perhaps setting up the GDT and segments. Please note that interrupts
|
||||
; are disabled at this point: More on interrupts later!
|
||||
|
||||
%include "config.inc"
|
||||
%include "hermit/config.asm"
|
||||
|
||||
[BITS 64]
|
||||
|
||||
extern kernel_start ; defined in linker script
|
||||
extern kernel_end
|
||||
|
||||
MSR_FS_BASE equ 0xc0000100
|
||||
MSR_GS_BASE equ 0xc0000101
|
||||
|
@ -69,6 +67,11 @@ align 4
|
|||
global mb_info
|
||||
global hbmem_base
|
||||
global hbmem_size
|
||||
global uhyve
|
||||
global image_size
|
||||
global uartport
|
||||
global cmdline
|
||||
global cmdsize
|
||||
base dq 0
|
||||
limit dq 0
|
||||
cpu_freq dd 0
|
||||
|
@ -92,6 +95,10 @@ align 4
|
|||
mb_info dq 0
|
||||
hbmem_base dq 0
|
||||
hbmem_size dq 0
|
||||
uhyve dd 0
|
||||
uartport dq 0
|
||||
cmdline dq 0
|
||||
cmdsize dq 0
|
||||
|
||||
; Bootstrap page tables are used during the initialization.
|
||||
align 4096
|
||||
|
@ -113,9 +120,6 @@ boot_pgt:
|
|||
SECTION .ktext
|
||||
align 4
|
||||
start64:
|
||||
; store pointer to the multiboot information
|
||||
mov [mb_info], QWORD rdx
|
||||
|
||||
; reset registers to kill any stale realmode selectors
|
||||
xor eax, eax
|
||||
mov ds, eax
|
||||
|
@ -133,10 +137,8 @@ start64:
|
|||
cmp eax, 0
|
||||
jne Lno_pml4_init
|
||||
|
||||
; determine full image size
|
||||
mov rax, kernel_end
|
||||
sub rax, kernel_start
|
||||
mov QWORD [image_size], rax
|
||||
; store pointer to the multiboot information
|
||||
mov [mb_info], QWORD rdx
|
||||
|
||||
; relocate page tables
|
||||
mov rdi, boot_pml4
|
||||
|
@ -172,16 +174,6 @@ start64:
|
|||
add rax, [base]
|
||||
mov QWORD [rdi+511*8], rax
|
||||
|
||||
%ifdef CONFIG_VGA
|
||||
; map vga 1:1
|
||||
mov rax, VIDEO_MEM_ADDR ; map vga
|
||||
and rax, ~0xFFF ; page align lower half
|
||||
mov rdi, rax
|
||||
shr rdi, 9 ; (edi >> 12) * 8 (index for boot_pgt)
|
||||
add rdi, boot_pgt
|
||||
or rax, 0x113 ; set present, global, writable and cache disable bits
|
||||
mov QWORD [rdi], rax
|
||||
%endif
|
||||
; map multiboot info
|
||||
mov rax, QWORD [mb_info]
|
||||
and rax, ~0xFFF ; page align lower half
|
||||
|
@ -190,7 +182,7 @@ start64:
|
|||
mov rdi, rax
|
||||
shr rdi, 9 ; (edi >> 12) * 8 (index for boot_pgt)
|
||||
add rdi, boot_pgt
|
||||
or rax, 0x103 ; set present, global and writable bits
|
||||
or rax, 0x23 ; set present, accessed and writable bits
|
||||
mov QWORD [rdi], rax
|
||||
Lno_mbinfo:
|
||||
; remap kernel
|
||||
|
@ -198,13 +190,18 @@ Lno_mbinfo:
|
|||
shr rdi, 18 ; (edi >> 21) * 8 (index for boot_pgd)
|
||||
add rdi, boot_pgd
|
||||
mov rax, [base]
|
||||
or rax, 0x83 ; PG_GLOBAL isn't required because HermitCore is a single-address space OS
|
||||
or rax, 0xA3 ; PG_GLOBAL isn't required because HermitCore is a single-address space OS
|
||||
xor rcx, rcx
|
||||
mov rsi, 510*0x200000
|
||||
sub rsi, kernel_start
|
||||
Lremap:
|
||||
mov QWORD [rdi], rax
|
||||
add rax, 0x200000
|
||||
add rcx, 0x200000
|
||||
add rdi, 8
|
||||
; note: the whole code segement muust fit in the first pgd
|
||||
cmp rcx, rsi
|
||||
jnb Lno_pml4_init
|
||||
cmp rcx, QWORD [image_size]
|
||||
jb Lremap
|
||||
|
||||
|
@ -609,7 +606,7 @@ common_switch:
|
|||
call get_current_stack ; get new rsp
|
||||
mov rsp, rax
|
||||
|
||||
%ifdef SAVE_FPU
|
||||
%ifidn SAVE_FPU,ON
|
||||
; set task switched flag
|
||||
mov rax, cr0
|
||||
or rax, 8
|
||||
|
@ -666,6 +663,12 @@ Lgo3:
|
|||
add rsp, 16
|
||||
iretq
|
||||
|
||||
global is_uhyve
|
||||
align 64
|
||||
is_uhyve:
|
||||
mov eax, DWORD [uhyve]
|
||||
ret
|
||||
|
||||
global is_single_kernel
|
||||
align 64
|
||||
is_single_kernel:
|
||||
|
|
|
@ -82,10 +82,11 @@ extern void isr29(void);
|
|||
extern void isr30(void);
|
||||
extern void isr31(void);
|
||||
|
||||
static void fault_handler(struct state *s);
|
||||
extern void fpu_handler(struct state *s);
|
||||
static void arch_fault_handler(struct state *s);
|
||||
static void arch_fpu_handler(struct state *s);
|
||||
extern void fpu_handler(void);
|
||||
|
||||
/*
|
||||
/*
|
||||
* This is a very repetitive function... it's not hard, it's
|
||||
* just annoying. As you can see, we set the first 32 entries
|
||||
* in the IDT to the first 32 ISRs. We can't use a for loop
|
||||
|
@ -94,7 +95,7 @@ extern void fpu_handler(struct state *s);
|
|||
* flags to 0x8E. This means that the entry is present, is
|
||||
* running in ring 0 (kernel level), and has the lower 5 bits
|
||||
* set to the required '14', which is represented by 'E' in
|
||||
* hex.
|
||||
* hex.
|
||||
*/
|
||||
void isrs_install(void)
|
||||
{
|
||||
|
@ -174,11 +175,11 @@ void isrs_install(void)
|
|||
|
||||
// install the default handler
|
||||
for(i=0; i<32; i++)
|
||||
irq_install_handler(i, fault_handler);
|
||||
irq_install_handler(i, arch_fault_handler);
|
||||
|
||||
// set hanlder for fpu exceptions
|
||||
irq_uninstall_handler(7);
|
||||
irq_install_handler(7, fpu_handler);
|
||||
irq_install_handler(7, arch_fpu_handler);
|
||||
}
|
||||
|
||||
/** @brief Exception messages
|
||||
|
@ -186,35 +187,45 @@ void isrs_install(void)
|
|||
* This is a simple string array. It contains the message that
|
||||
* corresponds to each and every exception. We get the correct
|
||||
* message by accessing it like this:
|
||||
* exception_message[interrupt_number]
|
||||
* exception_message[interrupt_number]
|
||||
*/
|
||||
static const char *exception_messages[] = {
|
||||
"Division By Zero", "Debug", "Non Maskable Interrupt",
|
||||
static const char *exception_messages[] = {
|
||||
"Division By Zero", "Debug", "Non Maskable Interrupt",
|
||||
"Breakpoint", "Into Detected Overflow", "Out of Bounds", "Invalid Opcode",
|
||||
"No Coprocessor", "Double Fault", "Coprocessor Segment Overrun", "Bad TSS",
|
||||
"Segment Not Present", "Stack Fault", "General Protection Fault", "Page Fault",
|
||||
"Unknown Interrupt", "Coprocessor Fault", "Alignment Check", "Machine Check",
|
||||
"No Coprocessor", "Double Fault", "Coprocessor Segment Overrun", "Bad TSS",
|
||||
"Segment Not Present", "Stack Fault", "General Protection Fault", "Page Fault",
|
||||
"Unknown Interrupt", "Coprocessor Fault", "Alignment Check", "Machine Check",
|
||||
"SIMD Floating-Point", "Virtualization", "Reserved", "Reserved", "Reserved",
|
||||
"Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved",
|
||||
"Reserved", "Reserved" };
|
||||
|
||||
/*
|
||||
/* interrupt handler to save / restore the FPU context */
|
||||
static void arch_fpu_handler(struct state *s)
|
||||
{
|
||||
(void) s;
|
||||
|
||||
clts(); // clear the TS flag of cr0
|
||||
|
||||
fpu_handler();
|
||||
}
|
||||
|
||||
/*
|
||||
* All of our Exception handling Interrupt Service Routines will
|
||||
* point to this function. This will tell us what exception has
|
||||
* occured! Right now, we simply abort the current task.
|
||||
* occured! Right now, we simply abort the current task.
|
||||
* All ISRs disable interrupts while they are being
|
||||
* serviced as a 'locking' mechanism to prevent an IRQ from
|
||||
* happening and messing up kernel data structures
|
||||
*/
|
||||
static void fault_handler(struct state *s)
|
||||
static void arch_fault_handler(struct state *s)
|
||||
{
|
||||
|
||||
|
||||
if (s->int_no < 32)
|
||||
LOG_INFO("%s", exception_messages[s->int_no]);
|
||||
else
|
||||
LOG_WARNING("Unknown exception %d", s->int_no);
|
||||
|
||||
LOG_ERROR(" Exception (%d) on core %d at %#x:%#lx, fs = %#lx, gs = %#lx, error code = 0x%#lx, task id = %u, rflags = %#x\n",
|
||||
LOG_ERROR(" Exception (%d) on core %d at %#x:%#lx, fs = %#lx, gs = %#lx, error code = %#lx, task id = %u, rflags = %#x\n",
|
||||
s->int_no, CORE_ID, s->cs, s->rip, s->fs, s->gs, s->error, per_core(current_task)->id, s->rflags);
|
||||
LOG_ERROR("rax %#lx, rbx %#lx, rcx %#lx, rdx %#lx, rbp, %#lx, rsp %#lx rdi %#lx, rsi %#lx, r8 %#lx, r9 %#lx, r10 %#lx, r11 %#lx, r12 %#lx, r13 %#lx, r14 %#lx, r15 %#lx\n",
|
||||
s->rax, s->rbx, s->rcx, s->rdx, s->rbp, s->rsp, s->rdi, s->rsi, s->r8, s->r9, s->r10, s->r11, s->r12, s->r13, s->r14, s->r15);
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#define PCI_CFRV 0x08 /* Configuration Revision */
|
||||
#define PCI_CFLT 0x0c /* Configuration Latency Timer */
|
||||
#define PCI_CBIO 0x10 /* Configuration Base IO Address */
|
||||
#define PCI_CSID 0x2C /* Configuration Subsystem Id & Subsystem Vendor Id */
|
||||
#define PCI_CFIT 0x3c /* Configuration Interrupt */
|
||||
#define PCI_CFDA 0x40 /* Configuration Driver Area */
|
||||
|
||||
|
@ -101,6 +102,11 @@ static uint32_t pci_conf_read(uint32_t bus, uint32_t slot, uint32_t off)
|
|||
return data;
|
||||
}
|
||||
|
||||
static inline uint32_t pci_subid(uint32_t bus, uint32_t slot)
|
||||
{
|
||||
return pci_conf_read(bus, slot, PCI_CSID);
|
||||
}
|
||||
|
||||
static inline uint32_t pci_what_irq(uint32_t bus, uint32_t slot)
|
||||
{
|
||||
return pci_conf_read(bus, slot, PCI_CFIT) & 0xFF;
|
||||
|
@ -139,29 +145,30 @@ static inline uint32_t pci_what_size(uint32_t bus, uint32_t slot, uint32_t nr)
|
|||
int pci_init(void)
|
||||
{
|
||||
uint32_t slot, bus;
|
||||
|
||||
|
||||
for (bus = 0; bus < MAX_BUS; bus++)
|
||||
for (slot = 0; slot < MAX_SLOTS; slot++)
|
||||
adapters[bus][slot] = pci_conf_read(bus, slot, PCI_CFID);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pci_get_device_info(uint32_t vendor_id, uint32_t device_id, pci_info_t* info, int8_t bus_master)
|
||||
int pci_get_device_info(uint32_t vendor_id, uint32_t device_id, uint32_t subsystem_id, pci_info_t* info, int8_t bus_master)
|
||||
{
|
||||
uint32_t slot, bus, i;
|
||||
|
||||
if (!info)
|
||||
return -EINVAL;
|
||||
|
||||
if (!mechanism)
|
||||
if (!mechanism && !is_uhyve())
|
||||
pci_init();
|
||||
|
||||
for (bus = 0; bus < MAX_BUS; bus++) {
|
||||
for (slot = 0; slot < MAX_SLOTS; slot++) {
|
||||
if (adapters[bus][slot] != -1) {
|
||||
if (((adapters[bus][slot] & 0xffff) == vendor_id) &&
|
||||
(((adapters[bus][slot] & 0xffff0000) >> 16) == device_id)) {
|
||||
if (((adapters[bus][slot] & 0xffff) == vendor_id) &&
|
||||
(((adapters[bus][slot] & 0xffff0000) >> 16) == device_id) &&
|
||||
(((pci_subid(bus, slot) >> 16) & subsystem_id) == subsystem_id)) {
|
||||
for(i=0; i<6; i++) {
|
||||
info->base[i] = pci_what_iobase(bus, slot, i);
|
||||
info->size[i] = (info->base[i]) ? pci_what_size(bus, slot, i) : 0;
|
||||
|
@ -195,7 +202,7 @@ int print_pci_adapters(void)
|
|||
if (adapters[bus][slot] != -1) {
|
||||
counter++;
|
||||
LOG_INFO("%d) Vendor ID: 0x%x Device Id: 0x%x\n",
|
||||
counter, adapters[bus][slot] & 0xffff,
|
||||
counter, adapters[bus][slot] & 0xffff,
|
||||
(adapters[bus][slot] & 0xffff0000) >> 16);
|
||||
|
||||
#ifdef WITH_PCI_IDS
|
||||
|
|
|
@ -49,6 +49,8 @@ extern atomic_int32_t current_boot_id;
|
|||
extern void isrsyscall(void);
|
||||
|
||||
cpu_info_t cpu_info = { 0, 0, 0, 0, 0};
|
||||
static char cpu_vendor[13] = {[0 ... 12] = 0};
|
||||
static char cpu_brand[4*3*sizeof(uint32_t)+1] = {[0 ... 4*3*sizeof(uint32_t)] = 0};
|
||||
extern uint32_t cpu_freq;
|
||||
|
||||
static void default_save_fpu_state(union fpu_state* state)
|
||||
|
@ -170,17 +172,16 @@ static void fpu_init_xsave(union fpu_state* fpu)
|
|||
|
||||
static uint32_t get_frequency_from_mbinfo(void)
|
||||
{
|
||||
#if 0
|
||||
if (mb_info && (mb_info->flags & MULTIBOOT_INFO_CMDLINE))
|
||||
if (mb_info && (mb_info->flags & MULTIBOOT_INFO_CMDLINE) && (cmdline))
|
||||
{
|
||||
// search in the command line for cpu frequency
|
||||
char* found = strstr((char*) mb_info->cmdline, "-freq");
|
||||
char* found = strstr((char*) (size_t)cmdline, "-freq");
|
||||
if (!found)
|
||||
return 0;
|
||||
|
||||
return atoi(found+strlen("-freq"));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -189,52 +190,37 @@ static uint32_t get_frequency_from_mbinfo(void)
|
|||
// Identification and the CPUID Instruction".
|
||||
static uint32_t get_frequency_from_brand(void)
|
||||
{
|
||||
char brand[4*3*sizeof(uint32_t)+1];
|
||||
uint32_t eax = 0, ebx = 0;
|
||||
uint32_t ecx = 0, edx = 0;
|
||||
uint32_t index, multiplier = 0;
|
||||
uint32_t* bint = (uint32_t*) brand;
|
||||
|
||||
memset(brand, 0x00, sizeof(brand));
|
||||
|
||||
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
|
||||
if (eax >= 0x80000004)
|
||||
for(index=0; index<sizeof(cpu_brand)-2; index++)
|
||||
{
|
||||
cpuid(0x80000002, bint+0, bint+1, bint+2, bint+3);
|
||||
cpuid(0x80000003, bint+4, bint+5, bint+6, bint+7);
|
||||
cpuid(0x80000004, bint+8, bint+9, bint+10, bint+11);
|
||||
LOG_INFO("Processor: %s\n", brand);
|
||||
|
||||
for(index=0; index<sizeof(brand)-2; index++)
|
||||
if ((cpu_brand[index+1] == 'H') && (cpu_brand[index+2] == 'z'))
|
||||
{
|
||||
if ((brand[index+1] == 'H') && (brand[index+2] == 'z'))
|
||||
{
|
||||
if (brand[index] == 'M')
|
||||
multiplier = 1;
|
||||
else if (brand[index] == 'G')
|
||||
multiplier = 1000;
|
||||
else if (brand[index] == 'T')
|
||||
multiplier = 1000000;
|
||||
if (cpu_brand[index] == 'M')
|
||||
multiplier = 1;
|
||||
else if (cpu_brand[index] == 'G')
|
||||
multiplier = 1000;
|
||||
else if (cpu_brand[index] == 'T')
|
||||
multiplier = 1000000;
|
||||
}
|
||||
|
||||
if (multiplier > 0) {
|
||||
uint32_t freq;
|
||||
|
||||
// Compute frequency (in MHz) from brand string
|
||||
if (cpu_brand[index-3] == '.') { // If format is “x.xx”
|
||||
freq = (uint32_t)(cpu_brand[index-4] - '0') * multiplier;
|
||||
freq += (uint32_t)(cpu_brand[index-2] - '0') * (multiplier / 10);
|
||||
freq += (uint32_t)(cpu_brand[index-1] - '0') * (multiplier / 100);
|
||||
} else { // If format is xxxx
|
||||
freq = (uint32_t)(cpu_brand[index-4] - '0') * 1000;
|
||||
freq += (uint32_t)(cpu_brand[index-3] - '0') * 100;
|
||||
freq += (uint32_t)(cpu_brand[index-2] - '0') * 10;
|
||||
freq += (uint32_t)(cpu_brand[index-1] - '0');
|
||||
freq *= multiplier;
|
||||
}
|
||||
|
||||
if (multiplier > 0) {
|
||||
uint32_t freq;
|
||||
|
||||
// Compute frequency (in MHz) from brand string
|
||||
if (brand[index-3] == '.') { // If format is “x.xx”
|
||||
freq = (uint32_t)(brand[index-4] - '0') * multiplier;
|
||||
freq += (uint32_t)(brand[index-2] - '0') * (multiplier / 10);
|
||||
freq += (uint32_t)(brand[index-1] - '0') * (multiplier / 100);
|
||||
} else { // If format is xxxx
|
||||
freq = (uint32_t)(brand[index-4] - '0') * 1000;
|
||||
freq += (uint32_t)(brand[index-3] - '0') * 100;
|
||||
freq += (uint32_t)(brand[index-2] - '0') * 10;
|
||||
freq += (uint32_t)(brand[index-1] - '0');
|
||||
freq *= multiplier;
|
||||
}
|
||||
|
||||
return freq;
|
||||
}
|
||||
return freq;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -407,7 +393,7 @@ static void check_est(uint8_t out)
|
|||
|
||||
int cpu_detection(void) {
|
||||
uint64_t xcr0;
|
||||
uint32_t a=0, b=0, c=0, d=0, level = 0;
|
||||
uint32_t a=0, b=0, c=0, d=0, level = 0, extended = 0;
|
||||
uint32_t family, model, stepping;
|
||||
size_t cr0, cr4;
|
||||
uint8_t first_time = 0;
|
||||
|
@ -415,10 +401,10 @@ int cpu_detection(void) {
|
|||
if (!cpu_info.feature1) {
|
||||
first_time = 1;
|
||||
|
||||
cpuid(0, &level, &b, &c, &d);
|
||||
LOG_INFO("cpuid level %d\n", level);
|
||||
cpuid(0, &level, (uint32_t*) cpu_vendor, (uint32_t*)(cpu_vendor+8), (uint32_t*)(cpu_vendor+4));
|
||||
kprintf("cpuid level %d\n", level);
|
||||
kprintf("CPU vendor: %s\n", cpu_vendor);
|
||||
|
||||
a = b = c = d = 0;
|
||||
cpuid(1, &a, &b, &cpu_info.feature2, &cpu_info.feature1);
|
||||
|
||||
family = (a & 0x00000F00) >> 8;
|
||||
|
@ -427,18 +413,29 @@ int cpu_detection(void) {
|
|||
if ((family == 6) && (model < 3) && (stepping < 3))
|
||||
cpu_info.feature1 &= ~CPU_FEATURE_SEP;
|
||||
|
||||
cpuid(0x80000001, &a, &b, &c, &cpu_info.feature3);
|
||||
cpuid(0x80000008, &cpu_info.addr_width, &b, &c, &d);
|
||||
cpuid(0x80000000, &extended, &b, &c, &d);
|
||||
if (extended >= 0x80000001)
|
||||
cpuid(0x80000001, &a, &b, &c, &cpu_info.feature3);
|
||||
if (extended >= 0x80000008) {
|
||||
uint32_t* bint = (uint32_t*) cpu_brand;
|
||||
|
||||
cpuid(0x80000002, bint+0, bint+1, bint+2, bint+3);
|
||||
cpuid(0x80000003, bint+4, bint+5, bint+6, bint+7);
|
||||
cpuid(0x80000004, bint+8, bint+9, bint+10, bint+11);
|
||||
kprintf("Processor: %s\n", cpu_brand);
|
||||
}
|
||||
if (extended >= 0x80000008)
|
||||
cpuid(0x80000008, &cpu_info.addr_width, &b, &c, &d);
|
||||
|
||||
/* Additional Intel-defined flags: level 0x00000007 */
|
||||
if (level >= 0x00000007) {
|
||||
if (level >= 0x00000007) {
|
||||
a = b = c = d = 0;
|
||||
cpuid(7, &a, &cpu_info.feature4, &c, &d);
|
||||
}
|
||||
}
|
||||
|
||||
if (first_time) {
|
||||
LOG_INFO("Paging features: %s%s%s%s%s%s%s%s\n",
|
||||
kprintf("Paging features: %s%s%s%s%s%s%s%s\n",
|
||||
(cpu_info.feature1 & CPU_FEATURE_PSE) ? "PSE (2/4Mb) " : "",
|
||||
(cpu_info.feature1 & CPU_FEATURE_PAE) ? "PAE " : "",
|
||||
(cpu_info.feature1 & CPU_FEATURE_PGE) ? "PGE " : "",
|
||||
|
@ -448,10 +445,10 @@ int cpu_detection(void) {
|
|||
(cpu_info.feature3 & CPU_FEATURE_1GBHP) ? "PSE (1Gb) " : "",
|
||||
(cpu_info.feature3 & CPU_FEATURE_LM) ? "LM" : "");
|
||||
|
||||
LOG_INFO("Physical adress-width: %u bits\n", cpu_info.addr_width & 0xff);
|
||||
LOG_INFO("Linear adress-width: %u bits\n", (cpu_info.addr_width >> 8) & 0xff);
|
||||
LOG_INFO("Sysenter instruction: %s\n", (cpu_info.feature1 & CPU_FEATURE_SEP) ? "available" : "unavailable");
|
||||
LOG_INFO("Syscall instruction: %s\n", (cpu_info.feature3 & CPU_FEATURE_SYSCALL) ? "available" : "unavailable");
|
||||
kprintf("Physical adress-width: %u bits\n", cpu_info.addr_width & 0xff);
|
||||
kprintf("Linear adress-width: %u bits\n", (cpu_info.addr_width >> 8) & 0xff);
|
||||
kprintf("Sysenter instruction: %s\n", (cpu_info.feature1 & CPU_FEATURE_SEP) ? "available" : "unavailable");
|
||||
kprintf("Syscall instruction: %s\n", (cpu_info.feature3 & CPU_FEATURE_SYSCALL) ? "available" : "unavailable");
|
||||
}
|
||||
|
||||
//TODO: add check for SMEP and SMAP
|
||||
|
@ -509,7 +506,8 @@ int cpu_detection(void) {
|
|||
xcr0 |= 0xE0;
|
||||
xsetbv(0, xcr0);
|
||||
|
||||
LOG_INFO("Set XCR0 to 0x%llx\n", xgetbv(0));
|
||||
if (first_time)
|
||||
kprintf("Set XCR0 to 0x%llx\n", xgetbv(0));
|
||||
}
|
||||
|
||||
// libos => currently no support of syscalls
|
||||
|
@ -520,7 +518,7 @@ int cpu_detection(void) {
|
|||
wrmsr(MSR_LSTAR, (size_t) &isrsyscall);
|
||||
// clear IF flag during an interrupt
|
||||
wrmsr(MSR_SYSCALL_MASK, EFLAGS_TF|EFLAGS_DF|EFLAGS_IF|EFLAGS_AC|EFLAGS_NT);
|
||||
} else LOG_INFO("Processor doesn't support syscalls\n");
|
||||
} else kprintf("Processor doesn't support syscalls\n");
|
||||
#endif
|
||||
|
||||
if (has_nx())
|
||||
|
@ -554,7 +552,7 @@ int cpu_detection(void) {
|
|||
a = b = c = d = 0;
|
||||
cpuid(1, &a, &b, &cpu_info.feature2, &cpu_info.feature1);
|
||||
|
||||
LOG_INFO("CPU features: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
LOG_INFO("CPU features: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
has_sse() ? "SSE " : "",
|
||||
has_sse2() ? "SSE2 " : "",
|
||||
has_sse3() ? "SSE3 " : "",
|
||||
|
@ -573,6 +571,7 @@ int cpu_detection(void) {
|
|||
has_vmx() ? "VMX " : "",
|
||||
has_rdtscp() ? "RDTSCP " : "",
|
||||
has_fsgsbase() ? "FSGSBASE " : "",
|
||||
has_sgx() ? "SGX " : "",
|
||||
has_mwait() ? "MWAIT " : "",
|
||||
has_clflush() ? "CLFLUSH " : "",
|
||||
has_bmi1() ? "BMI1 " : "",
|
||||
|
@ -581,10 +580,14 @@ int cpu_detection(void) {
|
|||
has_rtm() ? "RTM " : "",
|
||||
has_hle() ? "HLE " : "",
|
||||
has_cqm() ? "CQM " : "",
|
||||
has_clflushopt() ? "CLFLUSHOPT " : "",
|
||||
has_clwb() ? "CLWB " : "",
|
||||
has_avx512f() ? "AVX512F " : "",
|
||||
has_avx512cd() ? "AVX512CD " : "",
|
||||
has_avx512pf() ? "AVX512PF " : "",
|
||||
has_avx512er() ? "AVX512ER " : "");
|
||||
has_avx512er() ? "AVX512ER " : "",
|
||||
has_avx512vl() ? "AVX512VL " : "",
|
||||
has_avx512bw() ? "AVX512BW " : "");
|
||||
}
|
||||
|
||||
if (first_time && has_osxsave()) {
|
||||
|
@ -616,15 +619,11 @@ int cpu_detection(void) {
|
|||
check_est(first_time);
|
||||
|
||||
if (first_time && on_hypervisor()) {
|
||||
uint32_t c, d;
|
||||
char vendor_id[13];
|
||||
|
||||
LOG_INFO("HermitCore is running on a hypervisor!\n");
|
||||
|
||||
cpuid(0x40000000, &a, &b, &c, &d);
|
||||
memcpy(vendor_id, &b, 4);
|
||||
memcpy(vendor_id + 4, &c, 4);
|
||||
memcpy(vendor_id + 8, &d, 4);
|
||||
cpuid(0x40000000, &a, (uint32_t*)vendor_id, (uint32_t*)(vendor_id+4), (uint32_t*)(vendor_id+8));
|
||||
vendor_id[12] = '\0';
|
||||
|
||||
LOG_INFO("Hypervisor Vendor Id: %s\n", vendor_id);
|
||||
|
|
|
@ -1,3 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Daniel Krebs, 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.
|
||||
*/
|
||||
#include <hermit/signal.h>
|
||||
#include <hermit/stddef.h>
|
||||
#include <hermit/spinlock.h>
|
||||
|
@ -186,7 +212,7 @@ int hermit_kill(tid_t dest, int signum)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void signal_init()
|
||||
void signal_init(void)
|
||||
{
|
||||
// initialize per-core signal queue
|
||||
for(int i = 0; i < MAX_CORES; i++) {
|
||||
|
@ -196,4 +222,3 @@ void signal_init()
|
|||
|
||||
irq_install_handler(SIGNAL_IRQ, _signal_irq_handler);
|
||||
}
|
||||
|
|
@ -37,16 +37,55 @@
|
|||
#include <hermit/logging.h>
|
||||
#include <asm/tss.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/multiboot.h>
|
||||
|
||||
#define TLS_ALIGNBITS 5
|
||||
#define TLS_ALIGNSIZE (1L << TLS_ALIGNBITS)
|
||||
#define TSL_ALIGNMASK ((~0L) << TLS_ALIGNBITS)
|
||||
#define TLS_FLOOR(addr) ((((size_t)addr) + TLS_ALIGNSIZE - 1) & TSL_ALIGNMASK)
|
||||
|
||||
/*
|
||||
* Note that linker symbols are not variables, they have no memory allocated for
|
||||
* maintaining a value, rather their address is their value.
|
||||
*/
|
||||
extern const void tls_start;
|
||||
extern const void tls_end;
|
||||
extern const void percore_start;
|
||||
extern const void percore_end0;
|
||||
|
||||
extern uint64_t base;
|
||||
|
||||
static int init_tls(void)
|
||||
{
|
||||
task_t* curr_task = per_core(current_task);
|
||||
|
||||
// do we have a thread local storage?
|
||||
if (((size_t) &tls_end - (size_t) &tls_start) > 0) {
|
||||
char* tls_addr = NULL;
|
||||
size_t fs;
|
||||
|
||||
curr_task->tls_addr = (size_t) &tls_start;
|
||||
curr_task->tls_size = (size_t) &tls_end - (size_t) &tls_start;
|
||||
|
||||
tls_addr = kmalloc(curr_task->tls_size + TLS_ALIGNSIZE + sizeof(size_t));
|
||||
if (BUILTIN_EXPECT(!tls_addr, 0)) {
|
||||
LOG_ERROR("load_task: heap is missing!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(tls_addr, 0x00, TLS_ALIGNSIZE);
|
||||
memcpy((void*) TLS_FLOOR(tls_addr), (void*) curr_task->tls_addr, curr_task->tls_size);
|
||||
fs = (size_t) TLS_FLOOR(tls_addr) + curr_task->tls_size;
|
||||
*((size_t*)fs) = fs;
|
||||
|
||||
// set fs register to the TLS segment
|
||||
set_tls(fs);
|
||||
LOG_INFO("TLS of task %d on core %d starts at 0x%zx (size 0x%zx)\n", curr_task->id, CORE_ID, TLS_FLOOR(tls_addr), curr_task->tls_size);
|
||||
} else set_tls(0); // no TLS => clear fs register
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int thread_entry(void* arg, size_t ep)
|
||||
{
|
||||
|
||||
|
@ -61,6 +100,22 @@ static int thread_entry(void* arg, size_t ep)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int is_proxy(void)
|
||||
{
|
||||
if (is_uhyve())
|
||||
return 0;
|
||||
if (!is_single_kernel())
|
||||
return 1;
|
||||
if (mb_info && (mb_info->flags & MULTIBOOT_INFO_CMDLINE) && (cmdline))
|
||||
{
|
||||
// search in the command line for the "proxy" hint
|
||||
char* found = strstr((char*) (size_t) cmdline, "-proxy");
|
||||
if (found)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t* get_current_stack(void)
|
||||
{
|
||||
task_t* curr_task = per_core(current_task);
|
||||
|
@ -141,7 +196,7 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg, uint32_t cor
|
|||
void wait_for_task(void)
|
||||
{
|
||||
if (!has_mwait()) {
|
||||
PAUSE;
|
||||
HALT;
|
||||
} else {
|
||||
void* queue = get_readyqueue();
|
||||
|
||||
|
@ -152,3 +207,17 @@ void wait_for_task(void)
|
|||
mwait(0x2 /* 0x2 = c3, 0xF = c0 */, 1 /* break on interrupt flag */);
|
||||
}
|
||||
}
|
||||
|
||||
void wakeup_core(uint32_t core_id)
|
||||
{
|
||||
// if mwait is available, an IPI isn't required to wakeup the core
|
||||
if (has_mwait())
|
||||
return;
|
||||
|
||||
// no self IPI required
|
||||
if (core_id == CORE_ID)
|
||||
return;
|
||||
|
||||
LOG_DEBUG("wakeup core %d\n", core_id);
|
||||
apic_send_ipi(core_id, 121);
|
||||
}
|
||||
|
|
|
@ -41,8 +41,6 @@
|
|||
#include <asm/pci.h>
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_VGA
|
||||
|
||||
/*
|
||||
* This implementation based on following tutorial:
|
||||
* http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming
|
||||
|
@ -99,40 +97,40 @@
|
|||
#define UART_MCR_RTS 0x02 /* RTS complement */
|
||||
#define UART_MCR_DTR 0x01 /* DTR complement */
|
||||
|
||||
static uint8_t mmio = 0;
|
||||
static size_t iobase = 0;
|
||||
#define DEFAULT_UART_PORT 0xc110
|
||||
|
||||
extern size_t uartport;
|
||||
|
||||
static inline unsigned char read_from_uart(uint32_t off)
|
||||
{
|
||||
uint8_t c = 0;
|
||||
|
||||
if (mmio)
|
||||
c = *((const volatile unsigned char*) (iobase + off));
|
||||
else if (iobase)
|
||||
c = inportb(iobase + off);
|
||||
if (uartport)
|
||||
c = inportb(uartport + off);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static void write_to_uart(uint32_t off, unsigned char c)
|
||||
static inline int is_transmit_empty(void)
|
||||
{
|
||||
if (mmio)
|
||||
*((volatile unsigned char*) (iobase + off)) = c;
|
||||
else if (iobase)
|
||||
outportb(iobase + off, c);
|
||||
if (uartport)
|
||||
return inportb(uartport + UART_LSR) & 0x20;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Get a single character on a serial device */
|
||||
static unsigned char uart_getchar(void)
|
||||
static inline void write_to_uart(uint32_t off, unsigned char c)
|
||||
{
|
||||
return read_from_uart(UART_RX);
|
||||
while (is_transmit_empty() == 0) { PAUSE; }
|
||||
|
||||
if (uartport)
|
||||
outportb(uartport + off, c);
|
||||
}
|
||||
|
||||
/* Puts a single character on a serial device */
|
||||
int uart_putchar(unsigned char c)
|
||||
{
|
||||
if (!iobase && !mmio)
|
||||
if (!uartport)
|
||||
return 0;
|
||||
|
||||
write_to_uart(UART_TX, c);
|
||||
|
@ -145,7 +143,7 @@ int uart_puts(const char *text)
|
|||
{
|
||||
size_t i, len = strlen(text);
|
||||
|
||||
if (!iobase && !mmio)
|
||||
if (!uartport)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
|
@ -154,54 +152,14 @@ int uart_puts(const char *text)
|
|||
return len;
|
||||
}
|
||||
|
||||
/* Handles all UART's interrupt */
|
||||
static void uart_handler(struct state *s)
|
||||
{
|
||||
unsigned char c = read_from_uart(UART_IIR);
|
||||
|
||||
while (!(c & UART_IIR_NO_INT)) {
|
||||
if (c & UART_IIR_RDI) {
|
||||
c = uart_getchar();
|
||||
|
||||
//TODO: handle input messages
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(c & UART_IIR_THRI) {
|
||||
// acknowledge interrupt
|
||||
c = read_from_uart(UART_IIR);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(c & UART_IIR_RLSI) {
|
||||
// acknowledge interrupt
|
||||
c = read_from_uart(UART_LSR);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
c = read_from_uart(UART_IIR);
|
||||
}
|
||||
}
|
||||
|
||||
static int uart_config(void)
|
||||
{
|
||||
/*
|
||||
* enable FIFOs
|
||||
* clear RX and TX FIFO
|
||||
* set irq trigger to 8 bytes
|
||||
*/
|
||||
write_to_uart(UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_1);
|
||||
if (!uartport)
|
||||
return 0;
|
||||
|
||||
/* disable interrupts */
|
||||
write_to_uart(UART_IER, 0);
|
||||
|
||||
/* DTR + RTS */
|
||||
write_to_uart(UART_MCR, UART_MCR_DTR|UART_MCR_RTS);
|
||||
|
||||
/*
|
||||
* 8bit word length
|
||||
* 1 stop bit
|
||||
|
@ -214,116 +172,60 @@ static int uart_config(void)
|
|||
write_to_uart(UART_LCR, lcr);
|
||||
|
||||
/*
|
||||
* set baudrate to 115200
|
||||
* set baudrate to 38400
|
||||
*/
|
||||
uint32_t divisor = 1843200 / 115200;
|
||||
write_to_uart(UART_DLL, divisor & 0xff);
|
||||
write_to_uart(UART_DLM, (divisor >> 8) & 0xff);
|
||||
write_to_uart(UART_DLL, 0x03);
|
||||
write_to_uart(UART_DLM, 0x00);
|
||||
|
||||
/* set DLAB=0 */
|
||||
write_to_uart(UART_LCR, lcr & (~UART_LCR_DLAB));
|
||||
|
||||
/*
|
||||
* enable FIFOs
|
||||
* clear RX and TX FIFO
|
||||
* set irq trigger to 8 bytes
|
||||
*/
|
||||
write_to_uart(UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern const void kernel_start;
|
||||
|
||||
int uart_early_init(char* cmdline)
|
||||
{
|
||||
#if 1
|
||||
// default value of our QEMU configuration
|
||||
iobase = 0xc110;
|
||||
#else
|
||||
if (BUILTIN_EXPECT(!cmdline, 0))
|
||||
return -EINVAL;
|
||||
|
||||
char* str = strstr(cmdline, "uart=");
|
||||
if (!str)
|
||||
return -EINVAL;
|
||||
|
||||
if (strncmp(str, "uart=io:", 8) == 0) {
|
||||
iobase = strtol(str+8, (char **)NULL, 16);
|
||||
if (!iobase)
|
||||
return -EINVAL;
|
||||
mmio = 0;
|
||||
} else if (strncmp(str, "uart=mmio:", 10) == 0) {
|
||||
iobase = strtol(str+10, (char **)NULL, 16);
|
||||
if (!iobase)
|
||||
return -EINVAL;
|
||||
if (iobase >= PAGE_MAP_ENTRIES*PAGE_SIZE) {
|
||||
/* at this point we use the boot page table
|
||||
* => IO address is not mapped
|
||||
* => dirty hack, map device before the kernel
|
||||
*/
|
||||
int err;
|
||||
size_t newaddr = ((size_t) &kernel_start - PAGE_SIZE);
|
||||
|
||||
err = page_map_bootmap(newaddr & PAGE_MASK, iobase & PAGE_MASK, PG_GLOBAL | PG_ACCESSED | PG_DIRTY | PG_RW | PG_PCD);
|
||||
if (BUILTIN_EXPECT(err, 0)) {
|
||||
iobase = 0;
|
||||
return err;
|
||||
}
|
||||
iobase = newaddr;
|
||||
}
|
||||
mmio = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// configure uart
|
||||
return uart_config();
|
||||
}
|
||||
|
||||
int uart_init(void)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
if (is_uhyve())
|
||||
return 0;
|
||||
|
||||
if (uartport)
|
||||
return uart_config();
|
||||
|
||||
pci_info_t pci_info;
|
||||
uint32_t bar = 0;
|
||||
|
||||
// Searching for Intel's UART device
|
||||
if (pci_get_device_info(0x8086, 0x0936, iobase, &pci_info) == 0)
|
||||
if (pci_get_device_info(0x8086, 0x0936, PCI_IGNORE_SUBID, &pci_info, 1) == 0)
|
||||
goto Lsuccess;
|
||||
// Searching for Qemu's UART device
|
||||
if (pci_get_device_info(0x1b36, 0x0002, iobase, &pci_info) == 0)
|
||||
// Searching for Qemu's UART device
|
||||
if (pci_get_device_info(0x1b36, 0x0002, PCI_IGNORE_SUBID, &pci_info, 1) == 0)
|
||||
goto Lsuccess;
|
||||
// Searching for Qemu's 2x UART device (pci-serial-2x)
|
||||
if (pci_get_device_info(0x1b36, 0x0003, iobase, &pci_info) == 0)
|
||||
if (pci_get_device_info(0x1b36, 0x0003, PCI_IGNORE_SUBID, &pci_info, 1) == 0)
|
||||
goto Lsuccess;
|
||||
// Searching for Qemu's 4x UART device (pci-serial-4x)
|
||||
if (pci_get_device_info(0x1b36, 0x0004, iobase, &pci_info) == 0)
|
||||
if (pci_get_device_info(0x1b36, 0x0004, PCI_IGNORE_SUBID, &pci_info, 1) == 0)
|
||||
goto Lsuccess;
|
||||
|
||||
return -1;
|
||||
// default value of our QEMU configuration
|
||||
uartport = DEFAULT_UART_PORT;
|
||||
|
||||
// configure uart
|
||||
return uart_config();
|
||||
|
||||
Lsuccess:
|
||||
iobase = pci_info.base[bar];
|
||||
irq_install_handler(32+pci_info.irq, uart_handler);
|
||||
if (pci_info.type[0]) {
|
||||
mmio = 0;
|
||||
LOG_INFO("UART uses io address 0x%x\n", iobase);
|
||||
} else {
|
||||
mmio = 1;
|
||||
page_map(iobase & PAGE_MASK, iobase & PAGE_MASK, 1, PG_GLOBAL | PG_ACCESSED | PG_DIRTY | PG_RW | PG_PCD);
|
||||
LOG_INFO("UART uses mmio address 0x%x\n", iobase);
|
||||
vma_add(iobase, iobase + PAGE_SIZE, VMA_READ|VMA_WRITE);
|
||||
}
|
||||
uartport = pci_info.base[bar];
|
||||
|
||||
//irq_install_handler(32+pci_info.irq, uart_handler);
|
||||
kprintf("UART uses io address 0x%x\n", uartport);
|
||||
|
||||
// configure uart
|
||||
return uart_config();
|
||||
#else
|
||||
// per default we use COM1...
|
||||
if (!iobase)
|
||||
iobase = 0x3F8;
|
||||
mmio = 0;
|
||||
if ((iobase == 0x3F8) || (iobase == 0x3E8))
|
||||
irq_install_handler(32+4, uart_handler);
|
||||
else if ((iobase == 0x2F8) || (iobase == 0x2E8))
|
||||
irq_install_handler(32+3, uart_handler);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
// configure uart
|
||||
return uart_config();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,240 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010, 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.
|
||||
*/
|
||||
|
||||
#include <hermit/string.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/vga.h>
|
||||
|
||||
#ifdef CONFIG_VGA
|
||||
|
||||
/*
|
||||
* These define our textpointer, our background and foreground
|
||||
* colors (attributes), and x and y cursor coordinates
|
||||
*/
|
||||
static unsigned short *textmemptr;
|
||||
static int attrib = 0x0F;
|
||||
static int csr_x = 0, csr_y = 0;
|
||||
|
||||
inline static unsigned short *memsetw(unsigned short *dest, unsigned short val, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (BUILTIN_EXPECT(!dest, 0))
|
||||
return dest;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
dest[i] = val;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Scrolls the screen */
|
||||
static void scroll(void)
|
||||
{
|
||||
unsigned blank, temp;
|
||||
|
||||
/*
|
||||
* A blank is defined as a space... we need to give it
|
||||
* backcolor too
|
||||
*/
|
||||
blank = 0x20 | (attrib << 8);
|
||||
|
||||
/* Row 25 is the end, this means we need to scroll up */
|
||||
if (csr_y >= 25) {
|
||||
|
||||
/*
|
||||
* Move the current text chunk that makes up the screen
|
||||
*
|
||||
* back in the buffer by one line
|
||||
*/
|
||||
temp = csr_y - 25 + 1;
|
||||
memcpy(textmemptr, textmemptr + temp * 80,
|
||||
(25 - temp) * 80 * 2);
|
||||
|
||||
/*
|
||||
* Finally, we set the chunk of memory that occupies
|
||||
* the last line of text to our 'blank' character
|
||||
*/
|
||||
memsetw(textmemptr + (25 - temp) * 80, blank, 80);
|
||||
csr_y = 25 - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates the hardware cursor: the little blinking line
|
||||
* on the screen under the last character pressed!
|
||||
*/
|
||||
static void move_csr(void)
|
||||
{
|
||||
unsigned temp;
|
||||
|
||||
/*
|
||||
* The equation for finding the index in a linear
|
||||
* chunk of memory can be represented by:
|
||||
* Index = [(y * width) + x] */
|
||||
temp = csr_y * 80 + csr_x;
|
||||
|
||||
/*
|
||||
* This sends a command to indicies 14 and 15 in the
|
||||
* CRT Control Register of the VGA controller. These
|
||||
* are the high and low bytes of the index that show
|
||||
* where the hardware cursor is to be 'blinking'. To
|
||||
* learn more, you should look up some VGA specific
|
||||
* programming documents. A great start to graphics:
|
||||
* http://www.brackeen.com/home/vga
|
||||
*/
|
||||
outportb(0x3D4, 14);
|
||||
outportb(0x3D5, temp >> 8);
|
||||
outportb(0x3D4, 15);
|
||||
outportb(0x3D5, temp);
|
||||
}
|
||||
|
||||
/* Clears the screen */
|
||||
void vga_clear(void)
|
||||
{
|
||||
unsigned blank;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Again, we need the 'short' that will be used to
|
||||
* represent a space with color
|
||||
*/
|
||||
blank = 0x20 | (attrib << 8);
|
||||
|
||||
/*
|
||||
* Fills the entire screen with spaces in our current
|
||||
* color
|
||||
**/
|
||||
for (i = 0; i < 25; i++)
|
||||
memsetw(textmemptr + i * 80, blank, 80);
|
||||
|
||||
/*
|
||||
* Update out virtual cursor, and then move the
|
||||
* hardware cursor
|
||||
*/
|
||||
csr_x = 0;
|
||||
csr_y = 0;
|
||||
move_csr();
|
||||
}
|
||||
|
||||
/* Puts a single character on the screen */
|
||||
int vga_putchar(unsigned char c)
|
||||
{
|
||||
unsigned short *where;
|
||||
unsigned att = attrib << 8;
|
||||
|
||||
/* Handle a backspace by moving the cursor back one space */
|
||||
if (c == 0x08) {
|
||||
if (csr_x != 0)
|
||||
csr_x--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles a tab by incrementing the cursor's x, but only
|
||||
* to a point that will make it divisible by 8
|
||||
*/
|
||||
else if (c == 0x09) {
|
||||
csr_x = (csr_x + 8) & ~(8 - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles a 'Carriage Return', which simply brings the
|
||||
* cursor back to the margin
|
||||
*/
|
||||
else if (c == '\r') {
|
||||
csr_x = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We handle our newlines the way DOS and BIOS do: we
|
||||
* treat it as if a 'CR' was there also, so we bring the
|
||||
* cursor to the margin and increment the 'y' value
|
||||
*/
|
||||
else if (c == '\n') {
|
||||
csr_x = 0;
|
||||
csr_y++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Any character greater than and including the space is a
|
||||
* printable character. The equation for finding the index
|
||||
* in a linear chunk of memory can be represented by:
|
||||
* Index = [(y * width) + x]
|
||||
*/
|
||||
else if (c >= ' ') {
|
||||
where = textmemptr + (csr_y * 80 + csr_x);
|
||||
*where = c | att; /* Character AND attributes: color */
|
||||
csr_x++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the cursor has reached the edge of the screen's width, we
|
||||
* insert a new line in there
|
||||
*/
|
||||
if (csr_x >= 80) {
|
||||
csr_x = 0;
|
||||
csr_y++;
|
||||
}
|
||||
|
||||
/* Scroll the screen if needed, and finally move the cursor */
|
||||
scroll();
|
||||
move_csr();
|
||||
|
||||
return (int) c;
|
||||
}
|
||||
|
||||
/* Uses the routine above to output a string... */
|
||||
int vga_puts(const char *text)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < strlen(text); i++)
|
||||
vga_putchar(text[i]);
|
||||
|
||||
return i-1;
|
||||
}
|
||||
|
||||
/* Sets the forecolor and backcolor we will use */
|
||||
//void settextcolor(unsigned char forecolor, unsigned char backcolor)
|
||||
//{
|
||||
|
||||
/*
|
||||
* Top 4 bytes are the background, bottom 4 bytes
|
||||
* are the foreground color
|
||||
*/
|
||||
// attrib = (backcolor << 4) | (forecolor & 0x0F);
|
||||
//}
|
||||
|
||||
/* Sets our text-mode VGA pointer, then clears the screen for us */
|
||||
void vga_init(void)
|
||||
{
|
||||
textmemptr = (unsigned short *)VIDEO_MEM_ADDR;
|
||||
// our bootloader already cleared the screen
|
||||
vga_clear();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -8,7 +8,7 @@
|
|||
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
;
|
||||
|
||||
%include "config.inc"
|
||||
%include "hermit/config.asm"
|
||||
|
||||
%ifdef CONFIG_X86_32
|
||||
[BITS 32]
|
50
arch/x86/loader/CMakeLists.txt
Normal file
50
arch/x86/loader/CMakeLists.txt
Normal file
|
@ -0,0 +1,50 @@
|
|||
cmake_minimum_required(VERSION 3.7)
|
||||
|
||||
project(arch_x86_loader C ASM_NASM)
|
||||
|
||||
## ASM sources
|
||||
|
||||
file(GLOB ASM_SOURCES *.asm)
|
||||
add_library(arch_x86_loader_asm STATIC ${ASM_SOURCES})
|
||||
|
||||
## C sources
|
||||
|
||||
file(GLOB C_SOURCES *.c)
|
||||
add_executable(arch_x86_loader ${C_SOURCES})
|
||||
|
||||
target_include_directories(arch_x86_loader
|
||||
PRIVATE include/)
|
||||
|
||||
target_compile_options(arch_x86_loader
|
||||
PRIVATE -O2 -Wall -m64 -std=gnu99 -ffreestanding -mno-red-zone
|
||||
-fstrength-reduce -fomit-frame-pointer -finline-functions)
|
||||
|
||||
target_link_libraries(arch_x86_loader
|
||||
arch_x86_loader_asm
|
||||
"-T ${CMAKE_CURRENT_LIST_DIR}/link.ld"
|
||||
"-z max-page-size=4096"
|
||||
-Wl,--build-id=none # required because CMake links with gcc, not ld
|
||||
-nostdlib)
|
||||
|
||||
# tools/proxy looks for `ldhermit.elf`
|
||||
set_target_properties(arch_x86_loader PROPERTIES
|
||||
OUTPUT_NAME ldhermit.elf)
|
||||
|
||||
add_custom_command(
|
||||
TARGET arch_x86_loader POST_BUILD
|
||||
# Split debug symbols into seperate file
|
||||
COMMAND
|
||||
${CMAKE_OBJCOPY} --only-keep-debug
|
||||
$<TARGET_FILE:arch_x86_loader>
|
||||
$<TARGET_FILE:arch_x86_loader>.sym
|
||||
# Qemu requires 32-bit ELF
|
||||
COMMAND
|
||||
${CMAKE_OBJCOPY} -O elf32-i386 --strip-debug
|
||||
$<TARGET_FILE:arch_x86_loader>)
|
||||
|
||||
install(TARGETS arch_x86_loader
|
||||
DESTINATION bin)
|
||||
|
||||
# Show include files in IDE
|
||||
file(GLOB_RECURSE ARCH_X86_LOADER_INCLUDES "include/*")
|
||||
add_custom_target(arch_x86_loader_includes_ide SOURCES ${ARCH_X86_LOADER_INCLUDES})
|
|
@ -1,69 +0,0 @@
|
|||
MAKE = make
|
||||
QEMU = qemu-system-x86_64 -machine accel=kvm -cpu host
|
||||
OBJDUMP = objdump
|
||||
OBJCOPY = objcopy
|
||||
CC = gcc
|
||||
CFLAGS = -O2 -Wall -m64 -std=gnu99 -ffreestanding -mno-red-zone -fstrength-reduce -fomit-frame-pointer -finline-functions -Iinclude
|
||||
NASM = nasm
|
||||
NASMFLAGS = -felf64 -g
|
||||
LD = ld
|
||||
LDFLAGS = -T link.ld -z max-page-size=4096
|
||||
STRIP_DEBUG = --strip-debug
|
||||
KEEP_DEBUG = --only-keep-debug
|
||||
OUTPUT_FORMAT = -O elf32-i386
|
||||
NAME = ldhermit
|
||||
TTY := $(shell tty)
|
||||
|
||||
C_source := main.c printf.c string.c stdio.c vga.c uart.c page.c
|
||||
ASM_source := entry.asm
|
||||
|
||||
OBJS := $(C_source:.c=.o)
|
||||
OBJS += $(ASM_source:.asm=.o)
|
||||
|
||||
# Prettify output
|
||||
V = 0
|
||||
ifeq ($V,0)
|
||||
Q = @
|
||||
P = > /dev/null
|
||||
endif
|
||||
|
||||
# other implicit rules
|
||||
%.o : %.c
|
||||
@echo [CC] $@
|
||||
$Q$(CC) -c $(CFLAGS) -o $@ $<
|
||||
@echo [DEP] $*.dep
|
||||
$Q$(CC) -MF $*.dep -MT $*.o -MM $(CFLAGS) $<
|
||||
|
||||
%.o : %.asm
|
||||
@echo [ASM] $@
|
||||
$Q$(NASM) $(NASMFLAGS) -o $@ $<
|
||||
|
||||
all: ldhermit.elf
|
||||
|
||||
$(NAME).elf: $(OBJS)
|
||||
@echo [LD] $@
|
||||
$Q$(LD) $(LDFLAGS) -o $@ $(OBJS)
|
||||
@echo [OBJCOPY] $(NAME).sym
|
||||
$Q$(OBJCOPY) $(KEEP_DEBUG) $(NAME).elf $(NAME).sym
|
||||
@echo [OBJCOPY] $(NAME).elf
|
||||
$Q$(OBJCOPY) $(STRIP_DEBUG) $(OUTPUT_FORMAT) $(NAME).elf
|
||||
|
||||
#qemu:
|
||||
# @echo "Do you already start netcat (nc -l 4555)?"
|
||||
# $(QEMU) -smp 4 -m 4G -kernel $(NAME).elf -initrd ../../../usr/benchmarks/stream \
|
||||
-net nic,model=rtl8139 -net user -net dump \
|
||||
-chardev socket,host=127.0.0.1,port=4555,id=gnc0 \
|
||||
-device pci-serial,chardev=gnc0 \
|
||||
-monitor telnet:127.0.0.1:1235,server,nowait -nographic
|
||||
|
||||
clean:
|
||||
@echo Cleaning loader
|
||||
$Q$(RM) -rf *.o *~ *.bin *.obj
|
||||
|
||||
veryclean: clean
|
||||
|
||||
depend:
|
||||
$(CC) -MM $(CFLAGS) *.c > Makefile.dep
|
||||
|
||||
-include -include $(C_source:.c=.dep)
|
||||
# DO NOT DELETE
|
|
@ -99,32 +99,24 @@ stublet:
|
|||
; Interpret multiboot information
|
||||
mov DWORD [mb_info], ebx
|
||||
|
||||
; Initialize CPU features
|
||||
call cpu_init
|
||||
|
||||
pop ebx ; restore pointer to multiboot structure
|
||||
lgdt [GDT64.Pointer] ; Load the 64-bit global descriptor table.
|
||||
jmp GDT64.Code:start64 ; Set the code segment and enter 64-bit long mode.
|
||||
|
||||
; This will set up the x86 control registers:
|
||||
; Caching and the floating point unit are enabled
|
||||
; Bootstrap page tables are loaded and page size
|
||||
; extensions (huge pages) enabled.
|
||||
global cpu_init
|
||||
cpu_init:
|
||||
|
||||
; initialize page tables
|
||||
|
||||
; map vga 1:1
|
||||
push edi
|
||||
mov eax, VIDEO_MEM_ADDR ; map vga
|
||||
and eax, 0xFFFFF000 ; page align lower half
|
||||
mov edi, eax
|
||||
shr edi, 9 ; (edi >> 12) * 8 (index for boot_pgt)
|
||||
add edi, boot_pgt
|
||||
or eax, 0x113 ; set present, global, writable and cache disable bits
|
||||
mov DWORD [edi], eax
|
||||
pop edi
|
||||
; push edi
|
||||
; mov eax, VIDEO_MEM_ADDR ; map vga
|
||||
; and eax, 0xFFFFF000 ; page align lower half
|
||||
; mov edi, eax
|
||||
; shr edi, 9 ; (edi >> 12) * 8 (index for boot_pgt)
|
||||
; add edi, boot_pgt
|
||||
; or eax, 0x13 ; set present, writable and cache disable bits
|
||||
; mov DWORD [edi], eax
|
||||
; pop edi
|
||||
|
||||
; map multiboot info 1:1
|
||||
push edi
|
||||
|
@ -133,7 +125,7 @@ cpu_init:
|
|||
mov edi, eax
|
||||
shr edi, 9 ; (edi >> 12) * 8 (index for boot_pgt)
|
||||
add edi, boot_pgt
|
||||
or eax, 0x101 ; set present and global bits
|
||||
or eax, 0x3 ; set present and writable bits
|
||||
mov DWORD [edi], eax
|
||||
pop edi
|
||||
|
||||
|
@ -151,7 +143,7 @@ L0: cmp ecx, ebx
|
|||
mov edi, eax
|
||||
shr edi, 9 ; (edi >> 12) * 8 (index for boot_pgt)
|
||||
add edi, boot_pgt
|
||||
or eax, 0x103 ; set present, global and writable bits
|
||||
or eax, 0x3 ; set present and writable bits
|
||||
mov DWORD [edi], eax
|
||||
add ecx, 0x1000
|
||||
jmp L0
|
||||
|
@ -188,23 +180,22 @@ L1:
|
|||
test edx, 1 << 29 ; Test if the LM-bit, which is bit 29, is set in the D-register.
|
||||
jz Linvalid ; They aren't, there is no long mode.
|
||||
|
||||
; Set CR3
|
||||
mov eax, boot_pml4
|
||||
;or eax, (1 << 0) ; set present bit
|
||||
mov cr3, eax
|
||||
|
||||
; we need to enable PAE modus
|
||||
; we need to enable PAE modus
|
||||
mov eax, cr4
|
||||
or eax, 1 << 5
|
||||
mov cr4, eax
|
||||
|
||||
; switch to the compatibility mode (which is part of long mode)
|
||||
; switch to the compatibility mode (which is part of long mode)
|
||||
mov ecx, 0xC0000080
|
||||
rdmsr
|
||||
or eax, 1 << 8
|
||||
wrmsr
|
||||
|
||||
; Set CR3
|
||||
mov eax, boot_pml4
|
||||
or eax, (1 << 0) ; set present bit
|
||||
mov cr3, eax
|
||||
|
||||
; Set CR4
|
||||
mov eax, cr4
|
||||
and eax, 0xfffbf9ff ; disable SSE
|
||||
|
@ -221,7 +212,9 @@ L1:
|
|||
or eax, (1 << 31) ; enable paging
|
||||
mov cr0, eax
|
||||
|
||||
ret
|
||||
;pop ebx ; restore pointer to multiboot structure
|
||||
lgdt [GDT64.Pointer] ; Load the 64-bit global descriptor table.
|
||||
jmp GDT64.Code:start64 ; Set the code segment and enter 64-bit long mode.
|
||||
|
||||
; there is no long mode
|
||||
Linvalid:
|
||||
|
@ -244,7 +237,7 @@ start64:
|
|||
|
||||
; jump to the boot processors's C code
|
||||
extern main
|
||||
call main
|
||||
jmp main
|
||||
jmp $
|
||||
|
||||
SECTION .data
|
||||
|
@ -262,17 +255,17 @@ boot_stack:
|
|||
; Bootstrap page tables are used during the initialization.
|
||||
ALIGN 4096
|
||||
boot_pml4:
|
||||
DQ boot_pdpt + 0x107 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_USER
|
||||
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
|
||||
DQ boot_pml4 + 0x303 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_SELF (self-reference)
|
||||
DQ boot_pdpt + 0x7 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_USER
|
||||
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
|
||||
DQ boot_pml4 + 0x3 ; PG_PRESENT | PG_GLOBAL | PG_RW
|
||||
boot_pdpt:
|
||||
DQ boot_pgd + 0x107 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_USER
|
||||
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
|
||||
DQ boot_pml4 + 0x303 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_SELF (self-reference)
|
||||
DQ boot_pgd + 0x7 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_USER
|
||||
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
|
||||
DQ boot_pml4 + 0x3 ; PG_PRESENT | PG_GLOBAL | PG_RW
|
||||
boot_pgd:
|
||||
DQ boot_pgt + 0x107 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_USER
|
||||
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
|
||||
DQ boot_pml4 + 0x303 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_SELF (self-reference)
|
||||
DQ boot_pgt + 0x7 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_USER
|
||||
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
|
||||
DQ boot_pml4 + 0x3 ; PG_PRESENT | PG_GLOBAL | PG_RW
|
||||
boot_pgt:
|
||||
times 512 DQ 0
|
||||
|
||||
|
|
129
arch/x86/loader/include/ctype.h
Normal file
129
arch/x86/loader/include/ctype.h
Normal file
|
@ -0,0 +1,129 @@
|
|||
/****************************************************************************************
|
||||
*
|
||||
* Author: Stefan Lankes
|
||||
* Chair for Operating Systems, RWTH Aachen University
|
||||
* Date: 24/03/2011
|
||||
*
|
||||
****************************************************************************************
|
||||
*
|
||||
* Written by the Chair for Operating Systems, RWTH Aachen University
|
||||
*
|
||||
* NO Copyright (C) 2010, Stefan Lankes,
|
||||
* consider these trivial functions to be public domain.
|
||||
*
|
||||
* These functions are distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file include/ctype.h
|
||||
* @brief Functions related to alphanumerical character values
|
||||
*
|
||||
* This file contains functions helping to determine
|
||||
* the type of alphanumerical character values.
|
||||
*/
|
||||
|
||||
#ifndef __CTYPE_H_
|
||||
#define __CYTPE_H_
|
||||
|
||||
/** Returns true if the value of 'c' is an ASCII-charater */
|
||||
static inline int isascii(int c)
|
||||
{
|
||||
return (((unsigned char)(c))<=0x7f);
|
||||
}
|
||||
|
||||
/** Applies an and-operation to
|
||||
* push the value of 'c' into the ASCII-range */
|
||||
static inline int toascii(int c)
|
||||
{
|
||||
return (((unsigned char)(c))&0x7f);
|
||||
}
|
||||
|
||||
/** Returns true if the value of 'c' is the
|
||||
* space character or a control character */
|
||||
static inline int isspace(int c)
|
||||
{
|
||||
if (!isascii(c))
|
||||
return 0;
|
||||
|
||||
if (' ' == (unsigned char) c)
|
||||
return 1;
|
||||
if ('\n' == (unsigned char) c)
|
||||
return 1;
|
||||
if ('\r' == (unsigned char) c)
|
||||
return 1;
|
||||
if ('\t' == (unsigned char) c)
|
||||
return 1;
|
||||
if ('\v' == (unsigned char) c)
|
||||
return 1;
|
||||
if ('\f' == (unsigned char) c)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Returns true if the value of 'c' is a number */
|
||||
static inline int isdigit(int c)
|
||||
{
|
||||
if (!isascii(c))
|
||||
return 0;
|
||||
|
||||
if (((unsigned char) c >= '0') && ((unsigned char) c <= '9'))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Returns true if the value of 'c' is a lower case letter */
|
||||
static inline int islower(int c)
|
||||
{
|
||||
if (!isascii(c))
|
||||
return 0;
|
||||
|
||||
if (((unsigned char) c >= 'a') && ((unsigned char) c <= 'z'))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Returns true if the value of 'c' is an upper case letter */
|
||||
static inline int isupper(int c)
|
||||
{
|
||||
if (!isascii(c))
|
||||
return 0;
|
||||
|
||||
if (((unsigned char) c >= 'A') && ((unsigned char) c <= 'Z'))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Returns true if the value of 'c' is an alphabetic character */
|
||||
static inline int isalpha(int c)
|
||||
{
|
||||
if (isupper(c) || islower(c))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Makes the input character lower case.\n Will do nothing if it
|
||||
* was something different than an upper case letter before. */
|
||||
static inline unsigned char tolower(unsigned char c)
|
||||
{
|
||||
if (isupper(c))
|
||||
c -= 'A'-'a';
|
||||
return c;
|
||||
}
|
||||
|
||||
/** Makes the input character upper case.\n Will do nothing if it
|
||||
* was something different than a lower case letter before. */
|
||||
static inline unsigned char toupper(unsigned char c)
|
||||
{
|
||||
if (islower(c))
|
||||
c -= 'a'-'A';
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif
|
87
arch/x86/loader/include/limits.h
Normal file
87
arch/x86/loader/include/limits.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2010, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* author Stefan Lankes
|
||||
* @file include/limits.h
|
||||
* @brief Define constants related to numerical value-ranges of variable types
|
||||
*
|
||||
* This file contains define constants for the numerical
|
||||
* ranges of the most typical variable types.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_LIMITS_H__
|
||||
#define __ARCH_LIMITS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Number of bits in a char */
|
||||
#define CHAR_BIT 8
|
||||
|
||||
/** Maximum value for a signed char */
|
||||
#define SCHAR_MAX 0x7f
|
||||
/** Minimum value for a signed char */
|
||||
#define SCHAR_MIN (-0x7f - 1)
|
||||
|
||||
/** Maximum value for an unsigned char */
|
||||
#define UCHAR_MAX 0xff
|
||||
|
||||
/** Maximum value for an unsigned short */
|
||||
#define USHRT_MAX 0xffff
|
||||
/** Maximum value for a short */
|
||||
#define SHRT_MAX 0x7fff
|
||||
/** Minimum value for a short */
|
||||
#define SHRT_MIN (-0x7fff - 1)
|
||||
|
||||
/** Maximum value for an unsigned int */
|
||||
#define UINT_MAX 0xffffffffU
|
||||
/** Maximum value for an int */
|
||||
#define INT_MAX 0x7fffffff
|
||||
/** Minimum value for an int */
|
||||
#define INT_MIN (-0x7fffffff - 1)
|
||||
|
||||
/** Maximum value for an unsigned long */
|
||||
#define ULONG_MAX 0xffffffffUL
|
||||
/** Maximum value for a long */
|
||||
#define LONG_MAX 0x7fffffffL
|
||||
/** Minimum value for a long */
|
||||
#define LONG_MIN (-0x7fffffffL - 1)
|
||||
|
||||
/** Maximum value for an unsigned long long */
|
||||
#define ULLONG_MAX 0xffffffffffffffffULL
|
||||
/** Maximum value for a long long */
|
||||
#define LLONG_MAX 0x7fffffffffffffffLL
|
||||
/** Minimum value for a long long */
|
||||
#define LLONG_MIN (-0x7fffffffffffffffLL - 1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -85,6 +85,14 @@ typedef char int8_t;
|
|||
/// 16 bit wide char type
|
||||
typedef unsigned short wchar_t;
|
||||
|
||||
/** @brief String to long
|
||||
*
|
||||
* @return Long value of the parsed numerical string
|
||||
*/
|
||||
long _strtol(const char* str, char** endptr, int base);
|
||||
|
||||
#define strtol(str, endptr, base) _strtol((str), (endptr), (base))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -41,7 +41,9 @@ char *strncpy(char *dest, const char *src, size_t n);
|
|||
char *strcpy(char *dest, const char *src);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
int strncmp(const char *s1, const char *s2, size_t n);
|
||||
char *strstr(const char *s, const char *find);
|
||||
char *_strstr(const char *s, const char *find);
|
||||
|
||||
#define strstr(s, find) _strstr((s), (find))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -34,17 +34,11 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Initialize UART output
|
||||
*
|
||||
* @return Returns 0 on success
|
||||
*/
|
||||
int uart_init(void);
|
||||
|
||||
/** @brief Initialize UART output without a device check
|
||||
*
|
||||
* @return Returns 0 on success
|
||||
*/
|
||||
int uart_early_init(char*);
|
||||
int uart_init(const char*);
|
||||
|
||||
/** @brief Simple string output on a serial device.
|
||||
*
|
||||
|
@ -56,7 +50,7 @@ int uart_puts(const char *text);
|
|||
|
||||
/** @brief Simple character output on a serial device.
|
||||
*
|
||||
* @return The original input character casted to int
|
||||
* @return The original input character casted to int
|
||||
*/
|
||||
int uart_putchar(unsigned char c);
|
||||
|
||||
|
|
|
@ -42,11 +42,56 @@ extern const void kernel_start;
|
|||
extern const void kernel_end;
|
||||
extern const void bss_start;
|
||||
extern const void bss_end;
|
||||
extern size_t uartport;
|
||||
|
||||
static int load_code(size_t viraddr, size_t phyaddr, size_t limit, uint32_t file_size, size_t mem_size, size_t cmdline, size_t cmdsize)
|
||||
{
|
||||
const size_t displacement = 0x200000ULL - (phyaddr & 0x1FFFFFULL);
|
||||
|
||||
kprintf("Found program segment at 0x%zx-0x%zx (viraddr 0x%zx-0x%zx)\n", phyaddr, phyaddr+file_size-1, viraddr, viraddr+file_size-1);
|
||||
|
||||
uint32_t npages = (file_size >> PAGE_BITS);
|
||||
if (file_size & (PAGE_SIZE-1))
|
||||
npages++;
|
||||
|
||||
kprintf("Map %u pages from physical start address 0x%zx linear to 0x%zx\n", npages + (displacement >> PAGE_BITS), phyaddr, viraddr);
|
||||
int ret = page_map(viraddr, phyaddr, npages + (displacement >> PAGE_BITS), PG_GLOBAL|PG_RW);
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
phyaddr += displacement;
|
||||
*((uint64_t*) (viraddr + 0x08)) = phyaddr; // physical start address
|
||||
*((uint64_t*) (viraddr + 0x10)) = limit; // physical limit
|
||||
*((uint32_t*) (viraddr + 0x24)) = 1; // number of used cpus
|
||||
*((uint32_t*) (viraddr + 0x30)) = 0; // apicid
|
||||
*((uint64_t*) (viraddr + 0x38)) = mem_size;
|
||||
*((uint32_t*) (viraddr + 0x60)) = 1; // numa nodes
|
||||
*((uint64_t*) (viraddr + 0x98)) = uartport;
|
||||
*((uint64_t*) (viraddr + 0xA0)) = cmdline;
|
||||
*((uint64_t*) (viraddr + 0xA8)) = cmdsize;
|
||||
|
||||
// move file to a 2 MB boundary
|
||||
for(size_t va = viraddr+(npages << PAGE_BITS)+displacement-sizeof(uint8_t); va >= viraddr+displacement; va-=sizeof(uint8_t))
|
||||
*((uint8_t*) va) = *((uint8_t*) (va-displacement));
|
||||
|
||||
kprintf("Remap %u pages from physical start address 0x%zx linear to 0x%zx\n", npages, phyaddr, viraddr);
|
||||
ret = page_map(viraddr, phyaddr, npages, PG_GLOBAL|PG_RW);
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
size_t limit = 0;
|
||||
size_t viraddr = 0;
|
||||
size_t phyaddr = 0;
|
||||
elf_header_t* header = NULL;
|
||||
uint32_t file_size = 0;
|
||||
size_t mem_size = 0;
|
||||
size_t cmdline_size = 0;
|
||||
size_t cmdline = 0;
|
||||
|
||||
// initialize .bss section
|
||||
memset((void*)&bss_start, 0x00, ((size_t) &bss_end - (size_t) &bss_start));
|
||||
|
@ -56,6 +101,12 @@ void main(void)
|
|||
kprintf("Loader starts at %p and ends at %p\n", &kernel_start, &kernel_end);
|
||||
kprintf("Found mb_info at %p\n", mb_info);
|
||||
|
||||
if (mb_info && mb_info->cmdline) {
|
||||
cmdline = (size_t) mb_info->cmdline;
|
||||
cmdline_size = strlen((char*)cmdline);
|
||||
}
|
||||
|
||||
// enable paging
|
||||
page_init();
|
||||
|
||||
if (mb_info) {
|
||||
|
@ -128,35 +179,12 @@ void main(void)
|
|||
switch(prog_header->type)
|
||||
{
|
||||
case ELF_PT_LOAD: { // load program segment
|
||||
size_t viraddr = prog_header->virt_addr;
|
||||
size_t phyaddr = prog_header->offset + (size_t)header;
|
||||
const size_t displacement = 0x200000ULL - (phyaddr & 0x1FFFFFULL);
|
||||
|
||||
uint32_t npages = (prog_header->file_size >> PAGE_BITS);
|
||||
if (prog_header->file_size & (PAGE_SIZE-1))
|
||||
npages++;
|
||||
|
||||
kprintf("Map %u pages from physical start address 0x%zx linear to 0x%zx\n", npages + (displacement >> PAGE_BITS), phyaddr, viraddr);
|
||||
int ret = page_map(viraddr, phyaddr, npages + (displacement >> PAGE_BITS), PG_GLOBAL|PG_RW);
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
phyaddr += displacement;
|
||||
*((uint64_t*) (viraddr + 0x08)) = phyaddr; // physical start address
|
||||
*((uint64_t*) (viraddr + 0x10)) = limit; // physical limit
|
||||
*((uint32_t*) (viraddr + 0x24)) = 1; // number of used cpus
|
||||
*((uint32_t*) (viraddr + 0x30)) = 0; // apicid
|
||||
*((uint64_t*) (viraddr + 0x38)) = prog_header->file_size;
|
||||
*((uint32_t*) (viraddr + 0x60)) = 1; // numa nodes
|
||||
|
||||
// move file to a 2 MB boundary
|
||||
for(size_t va = viraddr+(npages << PAGE_BITS)+displacement-sizeof(uint8_t); va >= viraddr+displacement; va-=sizeof(uint8_t))
|
||||
*((uint8_t*) va) = *((uint8_t*) (va-displacement));
|
||||
|
||||
kprintf("Remap %u pages from physical start address 0x%zx linear to 0x%zx\n", npages, phyaddr, viraddr);
|
||||
ret = page_map(viraddr, phyaddr, npages, PG_GLOBAL|PG_RW);
|
||||
if (ret)
|
||||
goto failed;
|
||||
if (!viraddr)
|
||||
viraddr = prog_header->virt_addr;
|
||||
if (!phyaddr)
|
||||
phyaddr = prog_header->offset + (size_t)header;
|
||||
file_size = prog_header->virt_addr + PAGE_FLOOR(prog_header->file_size) - viraddr;
|
||||
mem_size += prog_header->mem_size;
|
||||
}
|
||||
break;
|
||||
case ELF_PT_GNU_STACK: // Indicates stack executability => nothing to do
|
||||
|
@ -168,6 +196,9 @@ void main(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (BUILTIN_EXPECT(load_code(viraddr, phyaddr, limit, file_size, mem_size, cmdline, cmdline_size), 0))
|
||||
goto failed;
|
||||
|
||||
kprintf("Entry point: 0x%zx\n", header->entry);
|
||||
// jump to the HermitCore app
|
||||
asm volatile ("jmp *%0" :: "r"(header->entry), "d"(mb_info) : "memory");
|
||||
|
|
|
@ -27,27 +27,18 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <multiboot.h>
|
||||
#include <vga.h>
|
||||
#include <uart.h>
|
||||
|
||||
int koutput_init(void)
|
||||
{
|
||||
#ifdef CONFIG_VGA
|
||||
vga_init();
|
||||
#else
|
||||
uart_early_init((char*) mb_info->cmdline);
|
||||
#endif
|
||||
uart_init((const char*) (size_t)mb_info->cmdline);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kputchar(int c)
|
||||
{
|
||||
#ifdef CONFIG_VGA
|
||||
vga_putchar(c);
|
||||
#else
|
||||
uart_putchar(c);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
73
arch/x86/loader/strstr.c
Normal file
73
arch/x86/loader/strstr.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
/* $NetBSD: strstr.c,v 1.1 2005/12/20 19:28:52 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Chris Torek.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code has been taken from NetBSD (sys/libkern/strstr.c) and is consequently
|
||||
* BSD-licensed. Unnecessary functions have been removed and all typedefs required
|
||||
* have been added.
|
||||
*/
|
||||
|
||||
/* HermiCore prelude */
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
/*
|
||||
* Find the first occurrence of find in s.
|
||||
*/
|
||||
char *
|
||||
_strstr(s, find)
|
||||
const char *s, *find;
|
||||
{
|
||||
char c, sc;
|
||||
size_t len;
|
||||
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return NULL;
|
||||
if (BUILTIN_EXPECT(!find, 0))
|
||||
return NULL;
|
||||
|
||||
if ((c = *find++) != 0) {
|
||||
len = strlen(find);
|
||||
do {
|
||||
do {
|
||||
if ((sc = *s++) == 0)
|
||||
return (NULL);
|
||||
} while (sc != c);
|
||||
} while (strncmp(s, find, len) != 0);
|
||||
s--;
|
||||
}
|
||||
return ((char *) s);
|
||||
}
|
132
arch/x86/loader/strtol.c
Normal file
132
arch/x86/loader/strtol.c
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Chris Torek.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 4. 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.
|
||||
*
|
||||
* From: @(#)strtol.c 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code has been taken from FreeBSD (sys/libkern/strtol.c) and is consequently
|
||||
* BSD-licensed. Unnecessary functions have been removed and all typedefs required
|
||||
* have been added.
|
||||
*/
|
||||
|
||||
/* HermitCore prelude */
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
/*
|
||||
* Convert a string to a long integer.
|
||||
*
|
||||
* Ignores `locale' stuff. Assumes that the upper and lower case
|
||||
* alphabets and digits are each contiguous.
|
||||
*/
|
||||
long
|
||||
_strtol(nptr, endptr, base)
|
||||
const char *nptr;
|
||||
char **endptr;
|
||||
int base;
|
||||
{
|
||||
const char *s = nptr;
|
||||
unsigned long acc;
|
||||
unsigned char c;
|
||||
unsigned long cutoff;
|
||||
int neg = 0, any, cutlim;
|
||||
|
||||
/*
|
||||
* Skip white space and pick up leading +/- sign if any.
|
||||
* If base is 0, allow 0x for hex and 0 for octal, else
|
||||
* assume decimal; if base is already 16, allow 0x.
|
||||
*/
|
||||
do {
|
||||
c = *s++;
|
||||
} while (isspace(c));
|
||||
if (c == '-') {
|
||||
neg = 1;
|
||||
c = *s++;
|
||||
} else if (c == '+')
|
||||
c = *s++;
|
||||
if ((base == 0 || base == 16) &&
|
||||
c == '0' && (*s == 'x' || *s == 'X')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
|
||||
/*
|
||||
* Compute the cutoff value between legal numbers and illegal
|
||||
* numbers. That is the largest legal value, divided by the
|
||||
* base. An input number that is greater than this value, if
|
||||
* followed by a legal input character, is too big. One that
|
||||
* is equal to this value may be valid or not; the limit
|
||||
* between valid and invalid numbers is then based on the last
|
||||
* digit. For instance, if the range for longs is
|
||||
* [-2147483648..2147483647] and the input base is 10,
|
||||
* cutoff will be set to 214748364 and cutlim to either
|
||||
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
|
||||
* a value > 214748364, or equal but the next digit is > 7 (or 8),
|
||||
* the number is too big, and we will return a range error.
|
||||
*
|
||||
* Set any if any `digits' consumed; make it negative to indicate
|
||||
* overflow.
|
||||
*/
|
||||
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
|
||||
cutlim = cutoff % (unsigned long)base;
|
||||
cutoff /= (unsigned long)base;
|
||||
for (acc = 0, any = 0;; c = *s++) {
|
||||
if (!isascii(c))
|
||||
break;
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (isalpha(c))
|
||||
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
||||
else
|
||||
break;
|
||||
if (c >= base)
|
||||
break;
|
||||
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
|
||||
any = -1;
|
||||
else {
|
||||
any = 1;
|
||||
acc *= base;
|
||||
acc += c;
|
||||
}
|
||||
}
|
||||
if (any < 0) {
|
||||
acc = neg ? LONG_MIN : LONG_MAX;
|
||||
} else if (neg)
|
||||
acc = -acc;
|
||||
if (endptr != 0)
|
||||
*((const char **)endptr) = any ? s - 1 : nptr;
|
||||
return (acc);
|
||||
}
|
|
@ -90,33 +90,40 @@
|
|||
#define UART_MCR_RTS 0x02 /* RTS complement */
|
||||
#define UART_MCR_DTR 0x01 /* DTR complement */
|
||||
|
||||
static uint8_t mmio = 0;
|
||||
static size_t iobase = 0;
|
||||
#define DEFAULT_UART_PORT 0 //0xc110
|
||||
|
||||
size_t uartport = 0;
|
||||
|
||||
static inline unsigned char read_from_uart(uint32_t off)
|
||||
{
|
||||
uint8_t c;
|
||||
|
||||
if (mmio)
|
||||
c = *((const volatile unsigned char*) (iobase + off));
|
||||
else
|
||||
c = inportb(iobase + off);
|
||||
if (uartport)
|
||||
c = inportb(uartport + off);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline int is_transmit_empty(void)
|
||||
{
|
||||
if (uartport)
|
||||
return inportb(uartport + UART_LSR) & 0x20;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void write_to_uart(uint32_t off, unsigned char c)
|
||||
{
|
||||
if (mmio)
|
||||
*((volatile unsigned char*) (iobase + off)) = c;
|
||||
else
|
||||
outportb(iobase + off, c);
|
||||
while (is_transmit_empty() == 0) ;
|
||||
|
||||
if (uartport)
|
||||
outportb(uartport + off, c);
|
||||
}
|
||||
|
||||
/* Puts a single character on a serial device */
|
||||
int uart_putchar(unsigned char c)
|
||||
{
|
||||
if (!iobase)
|
||||
if (!uartport)
|
||||
return 0;
|
||||
|
||||
write_to_uart(UART_TX, c);
|
||||
|
@ -129,7 +136,7 @@ int uart_puts(const char *text)
|
|||
{
|
||||
size_t i, len = strlen(text);
|
||||
|
||||
if (!iobase)
|
||||
if (!uartport)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
|
@ -140,19 +147,12 @@ int uart_puts(const char *text)
|
|||
|
||||
static int uart_config(void)
|
||||
{
|
||||
/*
|
||||
* enable FIFOs
|
||||
* clear RX and TX FIFO
|
||||
* set irq trigger to 8 bytes
|
||||
*/
|
||||
write_to_uart(UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_1);
|
||||
if (!uartport)
|
||||
return 0;
|
||||
|
||||
/* disable interrupts */
|
||||
write_to_uart(UART_IER, 0);
|
||||
|
||||
/* DTR + RTS */
|
||||
write_to_uart(UART_MCR, UART_MCR_DTR|UART_MCR_RTS);
|
||||
|
||||
/*
|
||||
* 8bit word length
|
||||
* 1 stop bit
|
||||
|
@ -165,110 +165,39 @@ static int uart_config(void)
|
|||
write_to_uart(UART_LCR, lcr);
|
||||
|
||||
/*
|
||||
* set baudrate to 115200
|
||||
* set baudrate to 38400
|
||||
*/
|
||||
uint32_t divisor = 1843200 / 115200;
|
||||
write_to_uart(UART_DLL, divisor & 0xff);
|
||||
write_to_uart(UART_DLM, (divisor >> 8) & 0xff);
|
||||
write_to_uart(UART_DLL, 0x03);
|
||||
write_to_uart(UART_DLM, 0x00);
|
||||
|
||||
/* set DLAB=0 */
|
||||
write_to_uart(UART_LCR, lcr & (~UART_LCR_DLAB));
|
||||
|
||||
/*
|
||||
* enable FIFOs
|
||||
* clear RX and TX FIFO
|
||||
* set irq trigger to 8 bytes
|
||||
*/
|
||||
write_to_uart(UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern const void kernel_start;
|
||||
|
||||
int uart_early_init(char* cmdline)
|
||||
int uart_init(const char* cmdline)
|
||||
{
|
||||
#if 1
|
||||
// default value of our QEMU configuration
|
||||
iobase = 0xc110;
|
||||
#else
|
||||
if (BUILTIN_EXPECT(!cmdline, 0))
|
||||
return -EINVAL;
|
||||
char* str;
|
||||
|
||||
char* str = strstr(cmdline, "uart=");
|
||||
if (!str)
|
||||
return -EINVAL;
|
||||
if (!uartport && cmdline && ((str = strstr(cmdline, "uart=io:")) != NULL))
|
||||
uartport = strtol(str+8, (char **)NULL, 16);
|
||||
|
||||
if (strncmp(str, "uart=io:", 8) == 0) {
|
||||
iobase = strtol(str+8, (char **)NULL, 16);
|
||||
if (!iobase)
|
||||
return -EINVAL;
|
||||
mmio = 0;
|
||||
} else if (strncmp(str, "uart=mmio:", 10) == 0) {
|
||||
iobase = strtol(str+10, (char **)NULL, 16);
|
||||
if (!iobase)
|
||||
return -EINVAL;
|
||||
if (iobase >= PAGE_MAP_ENTRIES*PAGE_SIZE) {
|
||||
/* at this point we use the boot page table
|
||||
* => IO address is not mapped
|
||||
* => dirty hack, map device before the kernel
|
||||
*/
|
||||
int err;
|
||||
size_t newaddr = ((size_t) &kernel_start - PAGE_SIZE);
|
||||
if (!uartport)
|
||||
uartport = DEFAULT_UART_PORT;
|
||||
|
||||
err = page_map_bootmap(newaddr & PAGE_MASK, iobase & PAGE_MASK, PG_GLOBAL | PG_ACCESSED | PG_DIRTY | PG_RW | PG_PCD);
|
||||
if (BUILTIN_EXPECT(err, 0)) {
|
||||
iobase = 0;
|
||||
return err;
|
||||
}
|
||||
iobase = newaddr;
|
||||
}
|
||||
mmio = 1;
|
||||
}
|
||||
#endif
|
||||
if (!uartport)
|
||||
return 0;
|
||||
|
||||
// configure uart
|
||||
return uart_config();
|
||||
}
|
||||
|
||||
int uart_init(void)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
pci_info_t pci_info;
|
||||
uint32_t bar = 0;
|
||||
|
||||
// Searching for Intel's UART device
|
||||
if (pci_get_device_info(0x8086, 0x0936, iobase, &pci_info) == 0)
|
||||
goto Lsuccess;
|
||||
// Searching for Qemu's UART device
|
||||
if (pci_get_device_info(0x1b36, 0x0002, iobase, &pci_info) == 0)
|
||||
goto Lsuccess;
|
||||
// Searching for Qemu's 2x UART device (pci-serial-2x)
|
||||
if (pci_get_device_info(0x1b36, 0x0003, iobase, &pci_info) == 0)
|
||||
goto Lsuccess;
|
||||
// Searching for Qemu's 4x UART device (pci-serial-4x)
|
||||
if (pci_get_device_info(0x1b36, 0x0004, iobase, &pci_info) == 0)
|
||||
goto Lsuccess;
|
||||
|
||||
return -1;
|
||||
|
||||
Lsuccess:
|
||||
iobase = pci_info.base[bar];
|
||||
//irq_install_handler(32+pci_info.irq, uart_handler);
|
||||
if (pci_info.type[0]) {
|
||||
mmio = 0;
|
||||
kprintf("UART uses io address 0x%x\n", iobase);
|
||||
} else {
|
||||
mmio = 1;
|
||||
page_map(iobase & PAGE_MASK, iobase & PAGE_MASK, 1, PG_GLOBAL | PG_ACCESSED | PG_DIRTY | PG_RW | PG_PCD);
|
||||
kprintf("UART uses mmio address 0x%x\n", iobase);
|
||||
vma_add(iobase, iobase + PAGE_SIZE, VMA_READ|VMA_WRITE);
|
||||
}
|
||||
|
||||
// configure uart
|
||||
return uart_config();
|
||||
#else
|
||||
// per default we use COM1...
|
||||
if (!iobase)
|
||||
iobase = 0x3F8;
|
||||
mmio = 0;
|
||||
|
||||
// configure uart
|
||||
return uart_config();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,241 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010, 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <io.h>
|
||||
#include <vga.h>
|
||||
|
||||
#ifdef CONFIG_UART
|
||||
|
||||
#define VIDEO_MEM_ADDR 0xB8000 /* the video memory address */
|
||||
|
||||
/*
|
||||
* These define our textpointer, our background and foreground
|
||||
* colors (attributes), and x and y cursor coordinates
|
||||
*/
|
||||
static unsigned short *textmemptr;
|
||||
static int attrib = 0x0F;
|
||||
static int csr_x = 0, csr_y = 0;
|
||||
|
||||
inline static unsigned short *memsetw(unsigned short *dest, unsigned short val, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (BUILTIN_EXPECT(!dest, 0))
|
||||
return dest;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
dest[i] = val;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Scrolls the screen */
|
||||
static void scroll(void)
|
||||
{
|
||||
unsigned blank, temp;
|
||||
|
||||
/*
|
||||
* A blank is defined as a space... we need to give it
|
||||
* backcolor too
|
||||
*/
|
||||
blank = 0x20 | (attrib << 8);
|
||||
|
||||
/* Row 25 is the end, this means we need to scroll up */
|
||||
if (csr_y >= 25) {
|
||||
|
||||
/*
|
||||
* Move the current text chunk that makes up the screen
|
||||
*
|
||||
* back in the buffer by one line
|
||||
*/
|
||||
temp = csr_y - 25 + 1;
|
||||
memcpy(textmemptr, textmemptr + temp * 80,
|
||||
(25 - temp) * 80 * 2);
|
||||
|
||||
/*
|
||||
* Finally, we set the chunk of memory that occupies
|
||||
* the last line of text to our 'blank' character
|
||||
*/
|
||||
memsetw(textmemptr + (25 - temp) * 80, blank, 80);
|
||||
csr_y = 25 - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates the hardware cursor: the little blinking line
|
||||
* on the screen under the last character pressed!
|
||||
*/
|
||||
static void move_csr(void)
|
||||
{
|
||||
unsigned temp;
|
||||
|
||||
/*
|
||||
* The equation for finding the index in a linear
|
||||
* chunk of memory can be represented by:
|
||||
* Index = [(y * width) + x] */
|
||||
temp = csr_y * 80 + csr_x;
|
||||
|
||||
/*
|
||||
* This sends a command to indicies 14 and 15 in the
|
||||
* CRT Control Register of the VGA controller. These
|
||||
* are the high and low bytes of the index that show
|
||||
* where the hardware cursor is to be 'blinking'. To
|
||||
* learn more, you should look up some VGA specific
|
||||
* programming documents. A great start to graphics:
|
||||
* http://www.brackeen.com/home/vga
|
||||
*/
|
||||
outportb(0x3D4, 14);
|
||||
outportb(0x3D5, temp >> 8);
|
||||
outportb(0x3D4, 15);
|
||||
outportb(0x3D5, temp);
|
||||
}
|
||||
|
||||
/* Clears the screen */
|
||||
void vga_clear(void)
|
||||
{
|
||||
unsigned blank;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Again, we need the 'short' that will be used to
|
||||
* represent a space with color
|
||||
*/
|
||||
blank = 0x20 | (attrib << 8);
|
||||
|
||||
/*
|
||||
* Fills the entire screen with spaces in our current
|
||||
* color
|
||||
**/
|
||||
for (i = 0; i < 25; i++)
|
||||
memsetw(textmemptr + i * 80, blank, 80);
|
||||
|
||||
/*
|
||||
* Update out virtual cursor, and then move the
|
||||
* hardware cursor
|
||||
*/
|
||||
csr_x = 0;
|
||||
csr_y = 0;
|
||||
move_csr();
|
||||
}
|
||||
|
||||
/* Puts a single character on the screen */
|
||||
int vga_putchar(unsigned char c)
|
||||
{
|
||||
unsigned short *where;
|
||||
unsigned att = attrib << 8;
|
||||
|
||||
/* Handle a backspace by moving the cursor back one space */
|
||||
if (c == 0x08) {
|
||||
if (csr_x != 0)
|
||||
csr_x--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles a tab by incrementing the cursor's x, but only
|
||||
* to a point that will make it divisible by 8
|
||||
*/
|
||||
else if (c == 0x09) {
|
||||
csr_x = (csr_x + 8) & ~(8 - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles a 'Carriage Return', which simply brings the
|
||||
* cursor back to the margin
|
||||
*/
|
||||
else if (c == '\r') {
|
||||
csr_x = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We handle our newlines the way DOS and BIOS do: we
|
||||
* treat it as if a 'CR' was there also, so we bring the
|
||||
* cursor to the margin and increment the 'y' value
|
||||
*/
|
||||
else if (c == '\n') {
|
||||
csr_x = 0;
|
||||
csr_y++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Any character greater than and including the space is a
|
||||
* printable character. The equation for finding the index
|
||||
* in a linear chunk of memory can be represented by:
|
||||
* Index = [(y * width) + x]
|
||||
*/
|
||||
else if (c >= ' ') {
|
||||
where = textmemptr + (csr_y * 80 + csr_x);
|
||||
*where = c | att; /* Character AND attributes: color */
|
||||
csr_x++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the cursor has reached the edge of the screen's width, we
|
||||
* insert a new line in there
|
||||
*/
|
||||
if (csr_x >= 80) {
|
||||
csr_x = 0;
|
||||
csr_y++;
|
||||
}
|
||||
|
||||
/* Scroll the screen if needed, and finally move the cursor */
|
||||
scroll();
|
||||
move_csr();
|
||||
|
||||
return (int) c;
|
||||
}
|
||||
|
||||
/* Uses the routine above to output a string... */
|
||||
int vga_puts(const char *text)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < strlen(text); i++)
|
||||
vga_putchar(text[i]);
|
||||
|
||||
return i-1;
|
||||
}
|
||||
|
||||
/* Sets the forecolor and backcolor we will use */
|
||||
//void settextcolor(unsigned char forecolor, unsigned char backcolor)
|
||||
//{
|
||||
|
||||
/*
|
||||
* Top 4 bytes are the background, bottom 4 bytes
|
||||
* are the foreground color
|
||||
*/
|
||||
// attrib = (backcolor << 4) | (forecolor & 0x0F);
|
||||
//}
|
||||
|
||||
/* Sets our text-mode VGA pointer, then clears the screen for us */
|
||||
void vga_init(void)
|
||||
{
|
||||
textmemptr = (unsigned short *)VIDEO_MEM_ADDR;
|
||||
vga_clear();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,4 +0,0 @@
|
|||
C_source := page.c
|
||||
MODULE := arch_x86_mm
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
|
@ -37,6 +37,8 @@
|
|||
#include <asm/page.h>
|
||||
#include <asm/multiboot.h>
|
||||
|
||||
#define GAP_BELOW 0x100000ULL
|
||||
|
||||
extern uint64_t base;
|
||||
extern uint64_t limit;
|
||||
|
||||
|
@ -51,7 +53,6 @@ typedef struct free_list {
|
|||
* maintaining a value, rather their address is their value.
|
||||
*/
|
||||
extern const void kernel_start;
|
||||
extern const void kernel_end;
|
||||
|
||||
static spinlock_t list_lock = SPINLOCK_INIT;
|
||||
|
||||
|
@ -245,7 +246,6 @@ void page_free(void* viraddr, size_t sz)
|
|||
|
||||
int memory_init(void)
|
||||
{
|
||||
size_t image_size = (size_t) &kernel_end - (size_t) &kernel_start;
|
||||
int ret = 0;
|
||||
|
||||
// enable paging and map Multiboot modules etc.
|
||||
|
@ -272,8 +272,8 @@ int memory_init(void)
|
|||
|
||||
LOG_INFO("Free region 0x%zx - 0x%zx\n", start_addr, end_addr);
|
||||
|
||||
if ((start_addr <= base) && (end_addr >= PAGE_2M_FLOOR(base+image_size))) {
|
||||
init_list.start = PAGE_2M_FLOOR(base+image_size);
|
||||
if ((start_addr <= base) && (end_addr >= PAGE_2M_FLOOR((size_t) &kernel_start + image_size))) {
|
||||
init_list.start = PAGE_2M_FLOOR((size_t) &kernel_start + image_size);
|
||||
init_list.end = end_addr;
|
||||
|
||||
LOG_INFO("Add region 0x%zx - 0x%zx\n", init_list.start, init_list.end);
|
||||
|
@ -295,7 +295,6 @@ int memory_init(void)
|
|||
atomic_int64_add(&total_pages, (limit-base) >> PAGE_BITS);
|
||||
atomic_int64_add(&total_available_pages, (limit-base) >> PAGE_BITS);
|
||||
|
||||
//initialize free list
|
||||
init_list.start = PAGE_2M_FLOOR(base + image_size);
|
||||
init_list.end = limit;
|
||||
}
|
||||
|
@ -332,8 +331,16 @@ int memory_init(void)
|
|||
end_addr = base;
|
||||
|
||||
// ignore everything below 1M => reserve for I/O devices
|
||||
if ((start_addr < (size_t) 0x100000))
|
||||
start_addr = 0x100000;
|
||||
if ((start_addr < GAP_BELOW))
|
||||
start_addr = GAP_BELOW;
|
||||
|
||||
if (start_addr < (size_t)mb_info)
|
||||
start_addr = PAGE_FLOOR((size_t)mb_info);
|
||||
|
||||
if ((mb_info->flags & MULTIBOOT_INFO_CMDLINE) && cmdline) {
|
||||
if (start_addr < (size_t) cmdline+cmdsize)
|
||||
start_addr = PAGE_FLOOR((size_t) cmdline+cmdsize);
|
||||
}
|
||||
|
||||
if (start_addr >= end_addr)
|
||||
continue;
|
||||
|
@ -351,8 +358,6 @@ int memory_init(void)
|
|||
last->end = end_addr;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: mb_info and mb_info->cmdline should be marked as reserevd
|
||||
}
|
||||
}
|
||||
|
|
@ -49,7 +49,6 @@
|
|||
/* Note that linker symbols are not variables, they have no memory
|
||||
* allocated for maintaining a value, rather their address is their value. */
|
||||
extern const void kernel_start;
|
||||
//extern const void kernel_end;
|
||||
|
||||
/// This page is reserved for copying
|
||||
#define PAGE_TMP (PAGE_FLOOR((size_t) &kernel_start) - PAGE_SIZE)
|
||||
|
@ -81,6 +80,7 @@ static size_t* const self[PAGE_LEVELS] = {
|
|||
(size_t *) 0xFFFFFFFFFFFFF000
|
||||
};
|
||||
|
||||
#if 0
|
||||
/** An other self-reference for page_map_copy() */
|
||||
static size_t * const other[PAGE_LEVELS] = {
|
||||
(size_t *) 0xFFFFFF0000000000,
|
||||
|
@ -89,17 +89,30 @@ static size_t * const other[PAGE_LEVELS] = {
|
|||
(size_t *) 0xFFFFFFFFFFFFE000
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static uint8_t expect_zeroed_pages = 0;
|
||||
|
||||
size_t virt_to_phys(size_t addr)
|
||||
{
|
||||
size_t vpn = addr >> PAGE_BITS; // virtual page number
|
||||
size_t entry = self[0][vpn]; // page table entry
|
||||
size_t off = addr & ~PAGE_MASK; // offset within page
|
||||
size_t phy = entry & PAGE_MASK; // physical page frame number
|
||||
if ((addr > (size_t) &kernel_start) &&
|
||||
(addr <= PAGE_2M_FLOOR((size_t) &kernel_start + image_size)))
|
||||
{
|
||||
size_t vpn = addr >> (PAGE_2M_BITS); // virtual page number
|
||||
size_t entry = self[1][vpn]; // page table entry
|
||||
size_t off = addr & ~PAGE_2M_MASK; // offset within page
|
||||
size_t phy = entry & PAGE_2M_MASK; // physical page frame number
|
||||
|
||||
return phy | off;
|
||||
return phy | off;
|
||||
|
||||
} else {
|
||||
size_t vpn = addr >> PAGE_BITS; // virtual page number
|
||||
size_t entry = self[0][vpn]; // page table entry
|
||||
size_t off = addr & ~PAGE_MASK; // offset within page
|
||||
size_t phy = entry & PAGE_MASK; // physical page frame number
|
||||
|
||||
return phy | off;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -141,15 +154,15 @@ int __page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits, uint8
|
|||
if (!(self[lvl][vpn] & PG_PRESENT)) {
|
||||
/* There's no table available which covers the region.
|
||||
* Therefore we need to create a new empty table. */
|
||||
size_t phyaddr = get_pages(1);
|
||||
if (BUILTIN_EXPECT(!phyaddr, 0))
|
||||
size_t paddr = get_pages(1);
|
||||
if (BUILTIN_EXPECT(!paddr, 0))
|
||||
goto out;
|
||||
|
||||
/* Reference the new table within its parent */
|
||||
#if 0
|
||||
self[lvl][vpn] = phyaddr | bits | PG_PRESENT | PG_USER | PG_RW | PG_ACCESSED;
|
||||
self[lvl][vpn] = paddr | bits | PG_PRESENT | PG_USER | PG_RW | PG_ACCESSED | PG_DIRTY;
|
||||
#else
|
||||
self[lvl][vpn] = (phyaddr | bits | PG_PRESENT | PG_USER | PG_RW | PG_ACCESSED) & ~PG_XD;
|
||||
self[lvl][vpn] = (paddr | bits | PG_PRESENT | PG_USER | PG_RW | PG_ACCESSED | PG_DIRTY) & ~PG_XD;
|
||||
#endif
|
||||
|
||||
/* Fill new table with zeros */
|
||||
|
@ -165,7 +178,7 @@ int __page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits, uint8
|
|||
send_ipi = flush = 1;
|
||||
}
|
||||
|
||||
self[lvl][vpn] = phyaddr | bits | PG_PRESENT | PG_ACCESSED;
|
||||
self[lvl][vpn] = phyaddr | bits | PG_PRESENT | PG_ACCESSED | PG_DIRTY;
|
||||
|
||||
if (flush)
|
||||
/* There's already a page mapped at this address.
|
||||
|
@ -312,10 +325,16 @@ int page_init(void)
|
|||
LOG_INFO("Detect Go runtime! Consequently, HermitCore zeroed heap.\n");
|
||||
}
|
||||
|
||||
if (mb_info && ((mb_info->cmdline & PAGE_MASK) != ((size_t) mb_info & PAGE_MASK))) {
|
||||
LOG_INFO("Map multiboot cmdline 0x%x into the virtual address space\n", mb_info->cmdline);
|
||||
page_map((size_t) mb_info->cmdline & PAGE_MASK, mb_info->cmdline & PAGE_MASK, 1, PG_GLOBAL|PG_RW|PG_PRESENT);
|
||||
}
|
||||
if (mb_info && (mb_info->flags & MULTIBOOT_INFO_CMDLINE) && (cmdline))
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
while(((size_t) cmdline + i) <= ((size_t) cmdline + cmdsize))
|
||||
{
|
||||
page_map(((size_t) cmdline + i) & PAGE_MASK, ((size_t) cmdline + i) & PAGE_MASK, 1, PG_GLOBAL|PG_RW|PG_PRESENT);
|
||||
i += PAGE_SIZE;
|
||||
}
|
||||
} else cmdline = 0;
|
||||
|
||||
/* Replace default pagefault handler */
|
||||
irq_uninstall_handler(14);
|
||||
|
|
61
arch/x86/mm/vma.c
Normal file
61
arch/x86/mm/vma.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Steffen Vogel, 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.
|
||||
*/
|
||||
|
||||
#include <hermit/stdio.h>
|
||||
#include <hermit/vma.h>
|
||||
#include <hermit/logging.h>
|
||||
#include <asm/multiboot.h>
|
||||
|
||||
int vma_arch_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (mb_info) {
|
||||
ret = vma_add((size_t)mb_info & PAGE_MASK, ((size_t)mb_info & PAGE_MASK) + PAGE_SIZE, VMA_READ|VMA_WRITE);
|
||||
if (BUILTIN_EXPECT(ret, 0))
|
||||
goto out;
|
||||
|
||||
if ((mb_info->flags & MULTIBOOT_INFO_CMDLINE) && cmdline) {
|
||||
LOG_INFO("vma_arch_init: map cmdline %p (size 0x%zd)", cmdline, cmdsize);
|
||||
|
||||
size_t i = 0;
|
||||
while(((size_t) cmdline + i) < ((size_t) cmdline + cmdsize))
|
||||
{
|
||||
if ((((size_t)cmdline + i) & PAGE_MASK) != ((size_t) mb_info & PAGE_MASK)) {
|
||||
ret = vma_add(((size_t)cmdline + i) & PAGE_MASK, (((size_t)cmdline + i) & PAGE_MASK) + PAGE_SIZE, VMA_READ|VMA_WRITE);
|
||||
if (BUILTIN_EXPECT(ret, 0))
|
||||
goto out;
|
||||
}
|
||||
|
||||
i += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
9
cmake/HermitCore-Application.cmake
Normal file
9
cmake/HermitCore-Application.cmake
Normal file
|
@ -0,0 +1,9 @@
|
|||
include(${CMAKE_CURRENT_LIST_DIR}/HermitCore.cmake)
|
||||
include_guard()
|
||||
|
||||
add_compile_options(${HERMIT_APP_FLAGS})
|
||||
|
||||
# link against and include locally built libraries instead of the ones
|
||||
# supplied with the toolchain, if built from top-level
|
||||
link_directories(${LOCAL_PREFIX_ARCH_LIB_DIR})
|
||||
include_directories(BEFORE ${LOCAL_PREFIX_ARCH_INCLUDE_DIR})
|
32
cmake/HermitCore-Configuration.cmake
Normal file
32
cmake/HermitCore-Configuration.cmake
Normal file
|
@ -0,0 +1,32 @@
|
|||
set(PACKAGE_VERSION "0.2" CACHE STRING
|
||||
"HermitCore current version")
|
||||
|
||||
set(MAX_CORES "512" CACHE STRING
|
||||
"Maximum number of cores that can be managed")
|
||||
|
||||
set(MAX_TASKS "((MAX_CORES * 2) + 2)" CACHE STRING
|
||||
"Maximum number of tasks")
|
||||
|
||||
set(MAX_ISLE "8" CACHE STRING
|
||||
"Maximum number of NUMA isles")
|
||||
|
||||
set(MAX_FNAME "128" CACHE STRING
|
||||
"Define the maximum length of a file name")
|
||||
|
||||
set(KERNEL_STACK_SIZE 8192 CACHE STRING
|
||||
"Kernel stack size in bytes")
|
||||
|
||||
set(DEFAULT_STACK_SIZE 262144 CACHE STRING
|
||||
"Task stack size in bytes")
|
||||
|
||||
option(DYNAMIC_TICKS
|
||||
"Don't use a periodic timer event to keep track of time" ON)
|
||||
|
||||
option(SAVE_FPU
|
||||
"Save FPU registers on context switch" ON)
|
||||
|
||||
option(HAVE_ARCH_MEMSET "Use machine specific version of memset" OFF)
|
||||
option(HAVE_ARCH_MEMCPY "Use machine specific version of memcpy" OFF)
|
||||
option(HAVE_ARCH_STRLEN "Use machine specific version of strlen" OFF)
|
||||
option(HAVE_ARCH_STRCPY "Use machine specific version of strcpy" OFF)
|
||||
option(HAVE_ARCH_STRNCPY "Use machine specific version of strncpy" OFF)
|
35
cmake/HermitCore-Paths.cmake
Normal file
35
cmake/HermitCore-Paths.cmake
Normal file
|
@ -0,0 +1,35 @@
|
|||
include(${CMAKE_CURRENT_LIST_DIR}/HermitCore-Utils.cmake)
|
||||
# no include guard here because we have to include this file twice to correctly
|
||||
# set CMAKE_INSTALL_PREFIX
|
||||
|
||||
# root of HermitCore project
|
||||
set(HERMIT_ROOT ${CMAKE_CURRENT_LIST_DIR}/..)
|
||||
|
||||
# set default install prefix if user doesn't specify one
|
||||
if(${CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT})
|
||||
# See CMake docs for reference:
|
||||
# https://cmake.org/cmake/help/v3.7/variable/CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT.html
|
||||
set(CMAKE_INSTALL_PREFIX /opt/hermit CACHE PATH "..." FORCE)
|
||||
endif()
|
||||
|
||||
# we install 3rd party libraries to an intermediate directory and relocate
|
||||
# them here later when installing the whole project
|
||||
if(NOT LOCAL_PREFIX_BASE_DIR)
|
||||
# will be injected into external project because CMAKE_BINARY_DIR will be
|
||||
# different there
|
||||
set(LOCAL_PREFIX_BASE_DIR ${CMAKE_BINARY_DIR}/local_prefix)
|
||||
endif()
|
||||
|
||||
# during build process libraries and external projects will be deployed into
|
||||
# this directory structure
|
||||
set(LOCAL_PREFIX_DIR ${LOCAL_PREFIX_BASE_DIR}/${CMAKE_INSTALL_PREFIX})
|
||||
set(LOCAL_PREFIX_ARCH_DIR ${LOCAL_PREFIX_DIR}/${TARGET_ARCH})
|
||||
set(LOCAL_PREFIX_ARCH_INCLUDE_DIR ${LOCAL_PREFIX_ARCH_DIR}/include)
|
||||
|
||||
# when building applications within the HermitCore project (tests, ...) they
|
||||
# will link prefarably against libraries in this directory in order to test
|
||||
# changes in the kernel
|
||||
set(LOCAL_PREFIX_ARCH_LIB_DIR ${LOCAL_PREFIX_ARCH_DIR}/lib)
|
||||
|
||||
# generated configs will be put here
|
||||
set(GENERATED_CONFIG_DIR ${CMAKE_BINARY_DIR}/include)
|
9
cmake/HermitCore-Toolchain-x86-bootstrap.cmake
Normal file
9
cmake/HermitCore-Toolchain-x86-bootstrap.cmake
Normal file
|
@ -0,0 +1,9 @@
|
|||
include(${CMAKE_CURRENT_LIST_DIR}/HermitCore-Toolchain-x86.cmake)
|
||||
include_guard()
|
||||
|
||||
set(CMAKE_C_COMPILER_WORKS 1 CACHE INTERNAL "")
|
||||
set(CMAKE_CXX_COMPILER_WORKS 1 CACHE INTERNAL "")
|
||||
|
||||
# bootstrap toolchain cannot compile neither Go nor Fortran
|
||||
unset(CMAKE_Go_COMPILER)
|
||||
unset(CMAKE_Fortran_COMPILER)
|
26
cmake/HermitCore-Toolchain-x86.cmake
Normal file
26
cmake/HermitCore-Toolchain-x86.cmake
Normal file
|
@ -0,0 +1,26 @@
|
|||
include(${CMAKE_CURRENT_LIST_DIR}/HermitCore-Utils.cmake)
|
||||
include_guard()
|
||||
|
||||
# let user provide a different path to the toolchain
|
||||
set_default(TOOLCHAIN_BIN_DIR /opt/hermit/bin)
|
||||
|
||||
set(TARGET_ARCH x86_64-hermit)
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
|
||||
# point CMake to our toolchain
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN_BIN_DIR}/${TARGET_ARCH}-gcc)
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN_DIR}/${TARGET_ARCH}-g++)
|
||||
set(CMAKE_Fortran_COMPILER ${TOOLCHAIN_BIN_DIR}/${TARGET_ARCH}-gfortran)
|
||||
set(CMAKE_Go_COMPILER ${TOOLCHAIN_BIN_DIR}/${TARGET_ARCH}-gccgo)
|
||||
|
||||
# hinting the prefix and location is needed in order to correctly detect
|
||||
# binutils
|
||||
set(_CMAKE_TOOLCHAIN_PREFIX "${TARGET_ARCH}-")
|
||||
set(_CMAKE_TOOLCHAIN_LOCATION ${TOOLCHAIN_BIN_DIR})
|
||||
|
||||
option(HAVE_ARCH_MEMSET "Use machine specific version of memset" ON)
|
||||
option(HAVE_ARCH_MEMCPY "Use machine specific version of memcpy" ON)
|
||||
option(HAVE_ARCH_STRLEN "Use machine specific version of strlen" ON)
|
||||
option(HAVE_ARCH_STRCPY "Use machine specific version of strcpy" ON)
|
||||
option(HAVE_ARCH_STRNCPY "Use machine specific version of strncpy" ON)
|
142
cmake/HermitCore-Utils.cmake
Normal file
142
cmake/HermitCore-Utils.cmake
Normal file
|
@ -0,0 +1,142 @@
|
|||
macro(include_guard)
|
||||
if(DEFINED "_INCLUDE_GUARD_${CMAKE_CURRENT_LIST_FILE}")
|
||||
return()
|
||||
endif()
|
||||
set("_INCLUDE_GUARD_${CMAKE_CURRENT_LIST_FILE}" INCLUDED)
|
||||
endmacro(include_guard)
|
||||
|
||||
macro(add_kernel_module_sources MODULE SOURCE_GLOB)
|
||||
file(GLOB SOURCES "${SOURCE_GLOB}")
|
||||
|
||||
if("${SOURCES}" STREQUAL "")
|
||||
message(FATAL_ERROR "Module '${MODULE}' has no sources")
|
||||
endif()
|
||||
|
||||
# make sure modules are unique, this is needed of multiple sources
|
||||
# are added to the same module
|
||||
list(APPEND _KERNEL_MODULES "${MODULE}")
|
||||
list(REMOVE_DUPLICATES _KERNEL_MODULES)
|
||||
|
||||
# append sources for module
|
||||
list(APPEND "_KERNEL_SOURCES_${MODULE}" "${SOURCES}")
|
||||
endmacro(add_kernel_module_sources)
|
||||
|
||||
|
||||
macro(get_kernel_module_sources VAR MODULE)
|
||||
set(${VAR} ${_KERNEL_SOURCES_${MODULE}})
|
||||
endmacro(get_kernel_module_sources)
|
||||
|
||||
|
||||
macro(get_kernel_modules VAR)
|
||||
set(${VAR} ${_KERNEL_MODULES})
|
||||
endmacro(get_kernel_modules)
|
||||
|
||||
|
||||
# find program in /toolchain/dir/prefix-NAME, only supply NAME
|
||||
function(find_toolchain_program NAME)
|
||||
|
||||
string(TOUPPER "${NAME}" NAME_UPPER)
|
||||
string(TOLOWER "${NAME}" NAME_LOWER)
|
||||
|
||||
set(VARNAME "CMAKE_${NAME_UPPER}")
|
||||
|
||||
find_program(${VARNAME}
|
||||
NAMES ${_CMAKE_TOOLCHAIN_PREFIX}${NAME_LOWER}
|
||||
HINTS ${TOOLCHAIN_BIN_DIR})
|
||||
|
||||
if(NOT ${VARNAME})
|
||||
message(FATAL_ERROR
|
||||
"Cannot find ${_CMAKE_TOOLCHAIN_PREFIX}${NAME_LOWER}")
|
||||
endif()
|
||||
endfunction(find_toolchain_program)
|
||||
|
||||
|
||||
macro(set_parent VAR VALUE)
|
||||
set(${VAR} ${VALUE} PARENT_SCOPE)
|
||||
set(${VAR} ${VALUE})
|
||||
endmacro(set_parent)
|
||||
|
||||
function(get_cmd_variables VAR)
|
||||
set(_OUTPUT "")
|
||||
|
||||
get_cmake_property(vs VARIABLES)
|
||||
|
||||
foreach(v ${vs})
|
||||
get_property(_HELPSTRING
|
||||
CACHE ${v}
|
||||
PROPERTY HELPSTRING)
|
||||
if("${_HELPSTRING}" STREQUAL "No help, variable specified on the command line.")
|
||||
list(APPEND _OUTPUT "${v}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(${VAR} ${_OUTPUT} PARENT_SCOPE)
|
||||
endfunction(get_cmd_variables)
|
||||
|
||||
# any additional parameters will be handed over to the cmake command that the
|
||||
# external project is invoked with
|
||||
function(build_external NAME PATH DEPENDS)
|
||||
if("${NAME}" IN_LIST PROFILE_APPS)
|
||||
set(DO_PROFILING "-DPROFILING=true")
|
||||
endif()
|
||||
|
||||
# pass through all command line variables
|
||||
get_cmd_variables(CMD_VAR_NAMES)
|
||||
foreach(var ${CMD_VAR_NAMES})
|
||||
set(CMD_VARS ${CMD_VARS} -D${var}=${${var}})
|
||||
endforeach()
|
||||
|
||||
ExternalProject_Add(${NAME}
|
||||
SOURCE_DIR ${PATH}
|
||||
BUILD_ALWAYS 1
|
||||
DEPENDS ${DEPENDS}
|
||||
INSTALL_COMMAND
|
||||
${CMAKE_COMMAND} --build <BINARY_DIR>
|
||||
--target install --
|
||||
DESTDIR=${LOCAL_PREFIX_BASE_DIR}
|
||||
CMAKE_ARGS
|
||||
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
|
||||
-DLOCAL_PREFIX_BASE_DIR=${LOCAL_PREFIX_BASE_DIR}
|
||||
-DCMAKE_INSTALL_MESSAGE=NEVER
|
||||
--no-warn-unused-cli
|
||||
${DO_PROFILING}
|
||||
${CMD_VARS}
|
||||
${ARGN})
|
||||
|
||||
ExternalProject_Add_Step(${NAME} relink
|
||||
COMMAND find . -maxdepth 1 -type f -executable -exec rm {} "\\\;"
|
||||
DEPENDEES configure
|
||||
DEPENDERS build
|
||||
WORKING_DIRECTORY <BINARY_DIR>)
|
||||
|
||||
ExternalProject_Add_StepDependencies(${NAME} relink ${DEPENDS})
|
||||
endfunction(build_external)
|
||||
|
||||
|
||||
# additional arguments are be treated as targets that will be excluded
|
||||
function(install_local_targets PATH)
|
||||
get_property(_TARGETS
|
||||
DIRECTORY .
|
||||
PROPERTY BUILDSYSTEM_TARGETS)
|
||||
|
||||
if(NOT "${ARGN}" STREQUAL "")
|
||||
list(REMOVE_ITEM _TARGETS ${ARGN})
|
||||
endif()
|
||||
|
||||
install(TARGETS ${_TARGETS}
|
||||
DESTINATION ${TARGET_ARCH}/${PATH})
|
||||
|
||||
# if there are any .map files for profiling, install them too
|
||||
foreach(TARGET ${_TARGETS})
|
||||
install(FILES $<TARGET_FILE:${TARGET}>.map
|
||||
DESTINATION ${TARGET_ARCH}/${PATH}
|
||||
OPTIONAL)
|
||||
endforeach()
|
||||
endfunction(install_local_targets)
|
||||
|
||||
# set variable if not yet set
|
||||
macro(set_default VARNAME)
|
||||
if(NOT ${VARNAME})
|
||||
set(${VARNAME} ${ARGN})
|
||||
endif()
|
||||
endmacro(set_default)
|
90
cmake/HermitCore.cmake
Normal file
90
cmake/HermitCore.cmake
Normal file
|
@ -0,0 +1,90 @@
|
|||
include(${CMAKE_CURRENT_LIST_DIR}/HermitCore-Utils.cmake)
|
||||
include_guard()
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/HermitCore-Paths.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/HermitCore-Configuration.cmake)
|
||||
|
||||
# scripts to detect HermitCore Go compiler
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/golang/)
|
||||
|
||||
if(NOT HERMIT_ARCH)
|
||||
set(HERMIT_ARCH x86)
|
||||
endif()
|
||||
|
||||
if(PROFILING)
|
||||
# link everything against XRay
|
||||
link_libraries(-lxray)
|
||||
|
||||
# generate symbol map file for XRay to resolve function names
|
||||
link_libraries(-Wl,-Map=$<TARGET_PROPERTY:NAME>.map)
|
||||
|
||||
# enable profiling with XRay
|
||||
add_compile_options(-falign-functions=32 -finstrument-functions
|
||||
-finstrument-functions-exclude-function-list=_mm_pause,_mm_setcsr,_mm_getcsr)
|
||||
add_definitions(-DXRAY -DXRAY_DISABLE_BROWSER_INTEGRATION
|
||||
-DXRAY_NO_DEMANGLE -DXRAY_ANNOTATE)
|
||||
endif()
|
||||
|
||||
# use default toolchain if not specified by user
|
||||
if(NOT CMAKE_TOOLCHAIN_FILE)
|
||||
if(BOOTSTRAP)
|
||||
# use bootstrap toolchain if requested
|
||||
set(_BOOTSTRAP_ARCH_SUFFIX -bootstrap)
|
||||
endif()
|
||||
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/HermitCore-Toolchain-${HERMIT_ARCH}${_BOOTSTRAP_ARCH_SUFFIX}.cmake)
|
||||
endif()
|
||||
|
||||
# NASM detection will change binary format depending on host system, but
|
||||
# we only want to generate elf64 for HermitCore
|
||||
# Note: Has to be set *before* ASM_NASM is enabled
|
||||
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
|
||||
|
||||
enable_language(ASM_NASM)
|
||||
|
||||
# NASM hack, because it requires include paths to have a trailing /, whereas
|
||||
# CMake explicitly will remove it when adding includes the usual way
|
||||
# Note: Has to be set *after* ASM_NASM is enabled
|
||||
set(CMAKE_ASM_NASM_FLAGS
|
||||
"${CMAKE_ASM_NASM_FLAGS} -I ${CMAKE_BINARY_DIR}/include/")
|
||||
|
||||
set(HERMIT_KERNEL_FLAGS
|
||||
-m64 -Wall -O2 -mno-red-zone
|
||||
-fno-var-tracking-assignments -fstrength-reduce
|
||||
-fomit-frame-pointer -finline-functions -ffreestanding
|
||||
-nostdinc -fno-stack-protector -mno-sse -mno-mmx
|
||||
-mno-sse2 -mno-3dnow -mno-avx
|
||||
-fno-delete-null-pointer-checks
|
||||
-falign-jumps=1 -falign-loops=1
|
||||
-mno-80387 -mno-fp-ret-in-387 -mskip-rax-setup
|
||||
-fno-common -Wframe-larger-than=1024
|
||||
-fno-strict-aliasing -fno-asynchronous-unwind-tables
|
||||
-fno-strict-overflow -maccumulate-outgoing-args)
|
||||
|
||||
set(HERMIT_APP_FLAGS
|
||||
-m64 -mtls-direct-seg-refs -O3 -ftree-vectorize)
|
||||
|
||||
if(MTUNE)
|
||||
set(HERMIT_KERNEL_FLAGS ${HERMIT_KERNEL_FLAGS} -mtune=${MTUNE})
|
||||
set(HERMIT_APP_FLAGS ${HERMIT_APP_FLAGS} -mtune=${MTUNE})
|
||||
endif()
|
||||
|
||||
set(HERMIT_KERNEL_INCLUDES
|
||||
${CMAKE_BINARY_DIR}/include
|
||||
${HERMIT_ROOT}/include
|
||||
${HERMIT_ROOT}/arch/${HERMIT_ARCH}/include
|
||||
${HERMIT_ROOT}/lwip/src/include
|
||||
${HERMIT_ROOT}/drivers)
|
||||
|
||||
# HACK: when CMake detects compilers it taints CMAKE_INSTALL_PREFIX, so in
|
||||
# order to rely on that variable (we redefine it), enable all languages
|
||||
# here and source pathes again.
|
||||
#
|
||||
# Furthermore this will produce a sensible error message if the toolchain cannot
|
||||
# be found.
|
||||
if(NOT BOOTSTRAP)
|
||||
enable_language(C CXX Fortran Go)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/HermitCore-Paths.cmake)
|
||||
endif()
|
||||
|
||||
# find elfedit, CMake doesn't use this program, so we have to find it ourself
|
||||
find_toolchain_program(elfedit)
|
67
cmake/README.md
Normal file
67
cmake/README.md
Normal file
|
@ -0,0 +1,67 @@
|
|||
HermitCore CMake build system
|
||||
=============================
|
||||
|
||||
HermitCore requires at least CMake version `3.7`, which (at the time of
|
||||
introduction) is not yet available on most Linux distributions. We therefore
|
||||
provide a script `cmake/local-cmake.sh` that fetches precompiled binaries from
|
||||
the CMake project and installs them locally in `cmake/cmake-3.7*`. Only when
|
||||
sourced for the first time it will download CMake, on further runs it detects
|
||||
the existing download and adds it to `PATH` automatically.
|
||||
|
||||
```bash
|
||||
$ . cmake/local-cmake.sh
|
||||
-- Downloading CMake
|
||||
cmake-3.7.2-Linux-x 100%[=================>] 29,26M 837KB/s in 19s
|
||||
-- Unpacking CMake
|
||||
-- Local CMake v3.7.2 installed to cmake/cmake-3.7.2-Linux-x86_64
|
||||
-- Next time you source this script, no download will be neccessary
|
||||
$ which cmake
|
||||
/home/[...]/HermitCore/cmake/cmake-3.7.2-Linux-x86_64/bin/cmake
|
||||
```
|
||||
|
||||
## Directory structure
|
||||
|
||||
```
|
||||
cmake/
|
||||
├── golang
|
||||
│ ├── CMakeDetermineGoCompiler.cmake
|
||||
│ ├── CMakeGoCompiler.cmake.in
|
||||
│ ├── CMakeGoInformation.cmake
|
||||
│ └── CMakeTestGoCompiler.cmake
|
||||
├── HermitCore-Application.cmake
|
||||
├── HermitCore.cmake
|
||||
├── HermitCore-Paths.cmake
|
||||
├── HermitCore-Toolchain-x86.cmake
|
||||
├── HermitCore-Utils.cmake
|
||||
├── local-cmake.sh
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Additional language support
|
||||
|
||||
Currently, HermitCore supports `C, C++, Fortran, Go` through Cmake. While the
|
||||
former are supported and detected by CMake out-of-the-box, Go support has been
|
||||
added manually for HermitCore.
|
||||
|
||||
Adding a new language requires you to provide CMake hints where to find the
|
||||
toolchain and then how to compile and link binaries. The Go support in
|
||||
`cmake/golang` may serve as an example on how to add a new language.
|
||||
|
||||
To finally enable the language it has to be added to CMake's module path in
|
||||
`cmake/HermitCore.cmake`:
|
||||
|
||||
```
|
||||
# scripts to detect HermitCore Go compiler
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/golang/)
|
||||
|
||||
# scripts to detect new language
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/new-language/)
|
||||
```
|
||||
|
||||
|
||||
## User applications
|
||||
|
||||
You just have to include `HermitCore-Application.cmake` before the `project()`
|
||||
command in your `CMakeLists.txt` in order to build applications for HermitCore.
|
||||
For configuration parameters of the project, please consult the `README.md` in
|
||||
the root of this repository.
|
43
cmake/golang/CMakeDetermineGoCompiler.cmake
Normal file
43
cmake/golang/CMakeDetermineGoCompiler.cmake
Normal file
|
@ -0,0 +1,43 @@
|
|||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
# determine the compiler to use for Go programs
|
||||
# NOTE, a generator may set CMAKE_Go_COMPILER before
|
||||
# loading this file to force a compiler.
|
||||
|
||||
if(NOT CMAKE_Go_COMPILER)
|
||||
# prefer the environment variable CC
|
||||
if(NOT $ENV{GO_COMPILER} STREQUAL "")
|
||||
get_filename_component(CMAKE_Go_COMPILER_INIT $ENV{GO_COMPILER} PROGRAM PROGRAM_ARGS CMAKE_Go_FLAGS_ENV_INIT)
|
||||
if(CMAKE_Go_FLAGS_ENV_INIT)
|
||||
set(CMAKE_Go_COMPILER_ARG1 "${CMAKE_Go_FLAGS_ENV_INIT}" CACHE STRING "First argument to Go compiler")
|
||||
endif()
|
||||
if(NOT EXISTS ${CMAKE_Go_COMPILER_INIT})
|
||||
message(SEND_ERROR "Could not find compiler set in environment variable GO_COMPILER:\n$ENV{GO_COMPILER}.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(Go_BIN_PATH
|
||||
$ENV{GOPATH}
|
||||
$ENV{GOROOT}
|
||||
$ENV{GOROOT}/../bin
|
||||
$ENV{GO_COMPILER}
|
||||
/usr/bin
|
||||
/usr/local/bin
|
||||
)
|
||||
# if no compiler has been specified yet, then look for one
|
||||
if(CMAKE_Go_COMPILER_INIT)
|
||||
set(CMAKE_Go_COMPILER ${CMAKE_Go_COMPILER_INIT} CACHE PATH "Go Compiler")
|
||||
else()
|
||||
find_program(CMAKE_Go_COMPILER
|
||||
NAMES go
|
||||
PATHS ${Go_BIN_PATH}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
mark_as_advanced(CMAKE_Go_COMPILER)
|
||||
|
||||
# configure variables set in this file for fast reload later on
|
||||
configure_file(${CMAKE_CURRENT_LIST_DIR}/CMakeGoCompiler.cmake.in
|
||||
${CMAKE_PLATFORM_INFO_DIR}/CMakeGoCompiler.cmake @ONLY)
|
||||
set(CMAKE_Go_COMPILER_ENV_VAR "GO_COMPILER")
|
11
cmake/golang/CMakeGoCompiler.cmake.in
Normal file
11
cmake/golang/CMakeGoCompiler.cmake.in
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
set(CMAKE_Go_COMPILER "@CMAKE_Go_COMPILER@")
|
||||
set(CMAKE_Go_COMPILER_LOADED 1)
|
||||
|
||||
set(CMAKE_Go_SOURCE_FILE_EXTENSIONS go)
|
||||
set(CMAKE_Go_LINKER_PREFERENCE 40)
|
||||
set(CMAKE_Go_OUTPUT_EXTENSION .6)
|
||||
set(CMAKE_Go_OUTPUT_EXTENSION_REPLACE 1)
|
||||
set(CMAKE_Go_COMPILER_ENV_VAR "GO_COMPILER")
|
30
cmake/golang/CMakeGoInformation.cmake
Normal file
30
cmake/golang/CMakeGoInformation.cmake
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
# This should be included before the _INIT variables are
|
||||
# used to initialize the cache. Since the rule variables
|
||||
# have if blocks on them, users can still define them here.
|
||||
# But, it should still be after the platform file so changes can
|
||||
# be made to those values.
|
||||
|
||||
if(CMAKE_USER_MAKE_RULES_OVERRIDE)
|
||||
# Save the full path of the file so try_compile can use it.
|
||||
include(${CMAKE_USER_MAKE_RULES_OVERRIDE} RESULT_VARIABLE _override)
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_override}")
|
||||
endif()
|
||||
|
||||
if(CMAKE_USER_MAKE_RULES_OVERRIDE_Go)
|
||||
# Save the full path of the file so try_compile can use it.
|
||||
include(${CMAKE_USER_MAKE_RULES_OVERRIDE_Go} RESULT_VARIABLE _override)
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE_Go "${_override}")
|
||||
endif()
|
||||
|
||||
# refer: /usr/share/cmake-3.7/Modules/CMakeCInformation.cmake
|
||||
|
||||
if(NOT CMAKE_Go_COMPILE_OBJECT)
|
||||
set(CMAKE_Go_COMPILE_OBJECT "<CMAKE_Go_COMPILER> <FLAGS> -o <OBJECT> -c <SOURCE> ")
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_Go_LINK_EXECUTABLE)
|
||||
set(CMAKE_Go_LINK_EXECUTABLE "<CMAKE_Go_COMPILER> -pthread <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
|
||||
endif()
|
4
cmake/golang/CMakeTestGoCompiler.cmake
Normal file
4
cmake/golang/CMakeTestGoCompiler.cmake
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
set(CMAKE_Go_COMPILER_WORKS 1 CACHE INTERNAL "")
|
69
cmake/local-cmake.sh
Normal file
69
cmake/local-cmake.sh
Normal file
|
@ -0,0 +1,69 @@
|
|||
#!/bin/bash
|
||||
|
||||
# which version to fetch
|
||||
MAJOR="3.7"
|
||||
MINOR="2"
|
||||
PLATFORM="Linux-x86_64"
|
||||
|
||||
# assemble url for desired version
|
||||
URL="https://cmake.org/files/v${MAJOR}/cmake-${MAJOR}.${MINOR}-${PLATFORM}.tar.gz"
|
||||
|
||||
ARCHIVE="$(basename ${URL})"
|
||||
DIR="$(basename ${ARCHIVE} .tar.gz)"
|
||||
|
||||
|
||||
relpath() {
|
||||
# workaround because Ubuntu seems to use an ancient realpath version
|
||||
# https://stackoverflow.com/questions/2564634/convert-absolute-path-into-relative-path-given-a-current-directory-using-bash#comment12808306_7305217
|
||||
python -c "import os.path; print(os.path.relpath('${2:-$PWD}','$1'))";
|
||||
}
|
||||
|
||||
HERMIT_TOP="$(git rev-parse --show-toplevel)"
|
||||
HERMIT_CMAKE="${HERMIT_TOP}/cmake"
|
||||
CMAKE_DIR="${HERMIT_CMAKE}/${DIR}"
|
||||
CMAKE_DIR_REL="$(relpath ${HERMIT_TOP} ${CMAKE_DIR})"
|
||||
|
||||
# make sure we're sourced, not executed
|
||||
if [ "$0" = "$BASH_SOURCE" ]
|
||||
then
|
||||
echo "You have to source this script:"
|
||||
echo "\$ . $0"
|
||||
exit
|
||||
fi
|
||||
|
||||
# quit if already in path
|
||||
echo "$PATH" | grep "${CMAKE_DIR_REL}" &>/dev/null && return
|
||||
|
||||
# check if already installed
|
||||
if which cmake &> /dev/null ; then
|
||||
if cmake --version | grep "cmake version ${MAJOR}.${MINOR}" &> /dev/null; then
|
||||
echo "You already have CMake ${MAJOR}.${MINOR}"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d "${CMAKE_DIR}" ]
|
||||
then
|
||||
echo "-- Downloading CMake"
|
||||
wget "${URL}" -O "${ARCHIVE}" ||
|
||||
(echo "Cannot download CMake"; return)
|
||||
|
||||
echo "-- Unpacking CMake"
|
||||
tar -C "${HERMIT_CMAKE}" -xf "${ARCHIVE}" ||
|
||||
(echo "Cannot unpack CMake archive"; return)
|
||||
|
||||
# delete temporary archive again
|
||||
rm -f "${ARCHIVE}"
|
||||
|
||||
# add cmake dir to gitignore
|
||||
GITIGNORE="${HERMIT_TOP}/.gitignore"
|
||||
if ! grep "${CMAKE_DIR_REL}" "${GITIGNORE}" &>/dev/null
|
||||
then
|
||||
echo "${CMAKE_DIR_REL}/*" >> "${GITIGNORE}"
|
||||
fi
|
||||
|
||||
echo "-- Local CMake v${MAJOR}.${MINOR} installed to ${CMAKE_DIR_REL}"
|
||||
echo "-- Next time you source this script, no download will be neccessary"
|
||||
fi
|
||||
|
||||
export PATH="${CMAKE_DIR}/bin:${PATH}"
|
BIN
config/bzImage
BIN
config/bzImage
Binary file not shown.
|
@ -139,7 +139,7 @@ CONFIG_ARCH_SUPPORTS_INT128=y
|
|||
# CONFIG_SYSFS_DEPRECATED is not set
|
||||
# CONFIG_RELAY is not set
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_INITRAMFS_SOURCE="../config/initrd.cpio"
|
||||
CONFIG_INITRAMFS_SOURCE="/work/lankes/HermitCore/config/initrd.cpio"
|
||||
CONFIG_INITRAMFS_ROOT_UID=0
|
||||
CONFIG_INITRAMFS_ROOT_GID=0
|
||||
CONFIG_RD_GZIP=y
|
||||
|
|
77
configure.ac
77
configure.ac
|
@ -1,77 +0,0 @@
|
|||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.69)
|
||||
AC_INIT(HermitCore, 0.1, slankes@eonerc.rwth-aachen.de, HermitCore, http://www.hermitcore.org)
|
||||
AC_CHECK_PROGS(QEMU, qemu-system-x86_64)
|
||||
AC_CONFIG_SRCDIR(kernel/main.c)
|
||||
AC_CONFIG_HEADERS(include/hermit/config.h)
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
# Checks for header files.
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
|
||||
# Checks for library functions.
|
||||
|
||||
# define eduOS specific constants
|
||||
AC_DEFINE(HAVE_ARCH_MEMSET, 1, Define to use machine specific version of memset)
|
||||
AC_DEFINE(HAVE_ARCH_MEMCPY, 1, Define to use machine specific version of memcpy)
|
||||
AC_DEFINE(HAVE_ARCH_STRLEN, 1, Define to use machine specific version of strlen)
|
||||
AC_DEFINE(HAVE_ARCH_STRCPY, 1, Define to use machine specific version of strcpy)
|
||||
AC_DEFINE(HAVE_ARCH_STRNCPY, 1, Define to use machine specific version of strncpy)
|
||||
AC_DEFINE(MAX_ISLE, 8, Define the maximum number of isles / numa nodes)
|
||||
AC_DEFINE(MAX_FNAME, 128, Define the maximum length of a file name)
|
||||
AC_DEFINE(VIDEO_MEM_ADDR, 0xB8000, Definition of the VGA address)
|
||||
#AC_DEFINE(CONFIG_VGA, 1, Use the VGA interface as output device)
|
||||
AC_DEFINE(DYNAMIC_TICKS, 1, Use a dynamic tick instead of a static)
|
||||
#AC_DEFINE(SAVE_FPU, 1, Set task switched flag during a context switch);
|
||||
|
||||
AC_ARG_WITH([mtune],
|
||||
[AS_HELP_STRING([--with-mtune=ARCH],
|
||||
[enable tuning for a specific architecture])],
|
||||
[if test x"$withval" != x ; then
|
||||
ARCH_OPT="-mtune=$withval -march=$withval"
|
||||
fi],
|
||||
[ARCH_OPT=])
|
||||
AC_SUBST(ARCH_OPT)
|
||||
|
||||
AC_ARG_WITH([toolchain], [AS_HELP_STRING([--with-toolchain], [build also the whole HermitCore toolchain])], [TOOLCHAIN=1], [TOOLCHAIN=0])
|
||||
AC_SUBST(TOOLCHAIN)
|
||||
|
||||
AC_ARG_WITH(max-cores, [AS_HELP_STRING([--with-max-cores=N], [specify the maximum number of cores])])
|
||||
if test "x$with_max_cores" != x; then
|
||||
AC_DEFINE_UNQUOTED(MAX_CORES, $with_max_tasks, Define the maximum number of cores)
|
||||
else
|
||||
AC_DEFINE(MAX_CORES, 512, Define the maximum number of cores)
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(max-tasks, [AS_HELP_STRING([--with-max-tasks=N], [specify the maximum number of running tasks])])
|
||||
if test "x$with_max_tasks" != x; then
|
||||
AC_DEFINE_UNQUOTED(MAX_TASKS, $with_max_tasks, Define the maximum number of running tasks)
|
||||
else
|
||||
AC_DEFINE(MAX_TASKS, (MAX_CORES*2+2), Define the maximum number of running tasks)
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(kernel-stack-size, [AS_HELP_STRING([--with-kernel-stack-size=SIZE], [specify the size of the kernel stack])])
|
||||
if test "x$with_kernel_stack_size" != x; then
|
||||
AC_DEFINE_UNQUOTED(KERNEL_STACK_SIZE, $with_stack_size, Define the size of the kernel stack)
|
||||
else
|
||||
AC_DEFINE(KERNEL_STACK_SIZE, 8192, Define the size of the kernel stack)
|
||||
fi
|
||||
|
||||
|
||||
AC_ARG_WITH(default-stack-size, [AS_HELP_STRING([--with-default-stack-size=SIZE], [specify the default stack size])])
|
||||
if test "x$with_default_stack_size" != x; then
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_STACK_SIZE, $with_default_stack_size, Define the default stack size)
|
||||
else
|
||||
AC_DEFINE(DEFAULT_STACK_SIZE, 262144, Define the default stack size)
|
||||
fi
|
||||
|
||||
AC_CONFIG_FILES(Makefile tools/Makefile usr/ircce/Makefile usr/xray/Makefile usr/libomp/Makefile)
|
||||
AC_OUTPUT
|
6
debian/README.Debian
vendored
6
debian/README.Debian
vendored
|
@ -1,6 +0,0 @@
|
|||
libhermit for Debian
|
||||
-------------------
|
||||
|
||||
<possible notes regarding this package - if none, delete this file>
|
||||
|
||||
-- Stefan Lankes <slankes@eonerc.rwth-aachen.de> Sun, 08 Jan 2017 19:14:48 +0100
|
10
debian/README.source
vendored
10
debian/README.source
vendored
|
@ -1,10 +0,0 @@
|
|||
libhermit for Debian
|
||||
-------------------
|
||||
|
||||
<this file describes information about the source package, see Debian policy
|
||||
manual section 4.14. You WILL either need to modify or delete this file>
|
||||
|
||||
|
||||
|
||||
-- Stefan Lankes <slankes@eonerc.rwth-aachen.de> Sun, 08 Jan 2017 19:14:48 +0100
|
||||
|
5
debian/changelog
vendored
5
debian/changelog
vendored
|
@ -1,5 +0,0 @@
|
|||
libhermit (0.1-1) unstable; urgency=medium
|
||||
|
||||
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
|
||||
|
||||
-- Stefan Lankes <slankes@eonerc.rwth-aachen.de> Sun, 08 Jan 2017 19:14:48 +0100
|
1
debian/compat
vendored
1
debian/compat
vendored
|
@ -1 +0,0 @@
|
|||
9
|
15
debian/control
vendored
15
debian/control
vendored
|
@ -1,15 +0,0 @@
|
|||
Source: libhermit
|
||||
Section: devel
|
||||
Priority: optional
|
||||
Maintainer: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
|
||||
Build-Depends: debhelper (>=9),autotools-dev
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: http://www.hermitcore.org
|
||||
#Vcs-Git: git://anonscm.debian.org/collab-maint/libhermit.git
|
||||
#Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/libhermit.git
|
||||
|
||||
Package: libhermit
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: A Unikernel for Extreme-Scale Computing
|
||||
|
54
debian/copyright
vendored
54
debian/copyright
vendored
|
@ -1,54 +0,0 @@
|
|||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: libhermit
|
||||
Source: http://www.hermitcore.org
|
||||
|
||||
Files: *
|
||||
Copyright: 2010-2017 Stefan Lankes <slankes@eonerc.rwth-aachen.de>
|
||||
License: Revised BSD License
|
||||
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.
|
||||
|
||||
# If you want to use GPL v2 or later for the /debian/* files use
|
||||
# the following clauses, or change it to suit. Delete these two lines
|
||||
Files: debian/*
|
||||
Copyright: 2017 Stefan Lankes <slankes@eonerc.rwth-aachen.de>
|
||||
License: GPL-2+
|
||||
This package is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
.
|
||||
This package is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
.
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
||||
|
||||
# Please also look if there are files or directories which have a
|
||||
# different copyright/license attached and list them here.
|
||||
# Please avoid picking licenses with terms that are more restrictive than the
|
||||
# packaged work, as it may make Debian's contributions unacceptable upstream.
|
26
debian/init.d.ex
vendored
26
debian/init.d.ex
vendored
|
@ -1,26 +0,0 @@
|
|||
#!/bin/sh
|
||||
# kFreeBSD do not accept scripts as interpreters, using #!/bin/sh and sourcing.
|
||||
if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then
|
||||
set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script
|
||||
fi
|
||||
### BEGIN INIT INFO
|
||||
# Provides: libhermit
|
||||
# Required-Start: $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: <Enter a short description of the software>
|
||||
# Description: <Enter a long description of the software>
|
||||
# <...>
|
||||
# <...>
|
||||
### END INIT INFO
|
||||
|
||||
# Author: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
|
||||
|
||||
DESC="libhermit"
|
||||
DAEMON=/usr/bin/libhermit
|
||||
|
||||
# This is an example to start a single forking daemon capable of writing
|
||||
# a pid file. To get other behaviors, implement do_start(), do_stop() or
|
||||
# other functions to override the defaults in /lib/init/init-d-script.
|
||||
# See also init-d-script(5)
|
2
debian/libhermit-docs.docs
vendored
2
debian/libhermit-docs.docs
vendored
|
@ -1,2 +0,0 @@
|
|||
README.Debian
|
||||
README.source
|
4
debian/libhermit.cron.d.ex
vendored
4
debian/libhermit.cron.d.ex
vendored
|
@ -1,4 +0,0 @@
|
|||
#
|
||||
# Regular cron jobs for the libhermit package
|
||||
#
|
||||
0 4 * * * root [ -x /usr/bin/libhermit_maintenance ] && /usr/bin/libhermit_maintenance
|
10
debian/libhermit.default.ex
vendored
10
debian/libhermit.default.ex
vendored
|
@ -1,10 +0,0 @@
|
|||
# Defaults for libhermit initscript
|
||||
# sourced by /etc/init.d/libhermit
|
||||
# installed at /etc/default/libhermit by the maintainer scripts
|
||||
|
||||
#
|
||||
# This is a POSIX shell fragment
|
||||
#
|
||||
|
||||
# Additional options that are passed to the Daemon.
|
||||
DAEMON_OPTS=""
|
20
debian/libhermit.doc-base.EX
vendored
20
debian/libhermit.doc-base.EX
vendored
|
@ -1,20 +0,0 @@
|
|||
Document: libhermit
|
||||
Title: Debian libhermit Manual
|
||||
Author: <insert document author here>
|
||||
Abstract: This manual describes what libhermit is
|
||||
and how it can be used to
|
||||
manage online manuals on Debian systems.
|
||||
Section: unknown
|
||||
|
||||
Format: debiandoc-sgml
|
||||
Files: /usr/share/doc/libhermit/libhermit.sgml.gz
|
||||
|
||||
Format: postscript
|
||||
Files: /usr/share/doc/libhermit/libhermit.ps.gz
|
||||
|
||||
Format: text
|
||||
Files: /usr/share/doc/libhermit/libhermit.text.gz
|
||||
|
||||
Format: HTML
|
||||
Index: /usr/share/doc/libhermit/html/index.html
|
||||
Files: /usr/share/doc/libhermit/html/*.html
|
56
debian/manpage.1.ex
vendored
56
debian/manpage.1.ex
vendored
|
@ -1,56 +0,0 @@
|
|||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.\" (C) Copyright 2017 Stefan Lankes <slankes@eonerc.rwth-aachen.de>,
|
||||
.\"
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" other parameters are allowed: see man(7), man(1)
|
||||
.TH Libhermit SECTION "January 8 2017"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.\" Some roff macros, for reference:
|
||||
.\" .nh disable hyphenation
|
||||
.\" .hy enable hyphenation
|
||||
.\" .ad l left justify
|
||||
.\" .ad b justify to both left and right margins
|
||||
.\" .nf disable filling
|
||||
.\" .fi enable filling
|
||||
.\" .br insert line break
|
||||
.\" .sp <n> insert n+1 empty lines
|
||||
.\" for manpage-specific macros, see man(7)
|
||||
.SH NAME
|
||||
libhermit \- program to do something
|
||||
.SH SYNOPSIS
|
||||
.B libhermit
|
||||
.RI [ options ] " files" ...
|
||||
.br
|
||||
.B bar
|
||||
.RI [ options ] " files" ...
|
||||
.SH DESCRIPTION
|
||||
This manual page documents briefly the
|
||||
.B libhermit
|
||||
and
|
||||
.B bar
|
||||
commands.
|
||||
.PP
|
||||
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
|
||||
.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
|
||||
.\" respectively.
|
||||
\fBlibhermit\fP is a program that...
|
||||
.SH OPTIONS
|
||||
These programs follow the usual GNU command line syntax, with long
|
||||
options starting with two dashes (`-').
|
||||
A summary of options is included below.
|
||||
For a complete description, see the Info files.
|
||||
.TP
|
||||
.B \-h, \-\-help
|
||||
Show summary of options.
|
||||
.TP
|
||||
.B \-v, \-\-version
|
||||
Show version of program.
|
||||
.SH SEE ALSO
|
||||
.BR bar (1),
|
||||
.BR baz (1).
|
||||
.br
|
||||
The programs are documented fully by
|
||||
.IR "The Rise and Fall of a Fooish Bar" ,
|
||||
available via the Info system.
|
154
debian/manpage.sgml.ex
vendored
154
debian/manpage.sgml.ex
vendored
|
@ -1,154 +0,0 @@
|
|||
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
|
||||
|
||||
<!-- Process this file with docbook-to-man to generate an nroff manual
|
||||
page: `docbook-to-man manpage.sgml > manpage.1'. You may view
|
||||
the manual page with: `docbook-to-man manpage.sgml | nroff -man |
|
||||
less'. A typical entry in a Makefile or Makefile.am is:
|
||||
|
||||
manpage.1: manpage.sgml
|
||||
docbook-to-man $< > $@
|
||||
|
||||
|
||||
The docbook-to-man binary is found in the docbook-to-man package.
|
||||
Please remember that if you create the nroff version in one of the
|
||||
debian/rules file targets (such as build), you will need to include
|
||||
docbook-to-man in your Build-Depends control field.
|
||||
|
||||
-->
|
||||
|
||||
<!-- Fill in your name for FIRSTNAME and SURNAME. -->
|
||||
<!ENTITY dhfirstname "<firstname>FIRSTNAME</firstname>">
|
||||
<!ENTITY dhsurname "<surname>SURNAME</surname>">
|
||||
<!-- Please adjust the date whenever revising the manpage. -->
|
||||
<!ENTITY dhdate "<date>January 8 2017</date>">
|
||||
<!-- SECTION should be 1-8, maybe w/ subsection other parameters are
|
||||
allowed: see man(7), man(1). -->
|
||||
<!ENTITY dhsection "<manvolnum>SECTION</manvolnum>">
|
||||
<!ENTITY dhemail "<email>slankes@eonerc.rwth-aachen.de</email>">
|
||||
<!ENTITY dhusername "Stefan Lankes">
|
||||
<!ENTITY dhucpackage "<refentrytitle>Libhermit</refentrytitle>">
|
||||
<!ENTITY dhpackage "libhermit">
|
||||
|
||||
<!ENTITY debian "<productname>Debian</productname>">
|
||||
<!ENTITY gnu "<acronym>GNU</acronym>">
|
||||
<!ENTITY gpl "&gnu; <acronym>GPL</acronym>">
|
||||
]>
|
||||
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<address>
|
||||
&dhemail;
|
||||
</address>
|
||||
<author>
|
||||
&dhfirstname;
|
||||
&dhsurname;
|
||||
</author>
|
||||
<copyright>
|
||||
<year>2003</year>
|
||||
<holder>&dhusername;</holder>
|
||||
</copyright>
|
||||
&dhdate;
|
||||
</refentryinfo>
|
||||
<refmeta>
|
||||
&dhucpackage;
|
||||
|
||||
&dhsection;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>&dhpackage;</refname>
|
||||
|
||||
<refpurpose>program to do something</refpurpose>
|
||||
</refnamediv>
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>&dhpackage;</command>
|
||||
|
||||
<arg><option>-e <replaceable>this</replaceable></option></arg>
|
||||
|
||||
<arg><option>--example <replaceable>that</replaceable></option></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
<refsect1>
|
||||
<title>DESCRIPTION</title>
|
||||
|
||||
<para>This manual page documents briefly the
|
||||
<command>&dhpackage;</command> and <command>bar</command>
|
||||
commands.</para>
|
||||
|
||||
<para>This manual page was written for the &debian; distribution
|
||||
because the original program does not have a manual page.
|
||||
Instead, it has documentation in the &gnu;
|
||||
<application>Info</application> format; see below.</para>
|
||||
|
||||
<para><command>&dhpackage;</command> is a program that...</para>
|
||||
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>OPTIONS</title>
|
||||
|
||||
<para>These programs follow the usual &gnu; command line syntax,
|
||||
with long options starting with two dashes (`-'). A summary of
|
||||
options is included below. For a complete description, see the
|
||||
<application>Info</application> files.</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>-h</option>
|
||||
<option>--help</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>Show summary of options.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-v</option>
|
||||
<option>--version</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>Show version of program.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>SEE ALSO</title>
|
||||
|
||||
<para>bar (1), baz (1).</para>
|
||||
|
||||
<para>The programs are documented fully by <citetitle>The Rise and
|
||||
Fall of a Fooish Bar</citetitle> available via the
|
||||
<application>Info</application> system.</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>AUTHOR</title>
|
||||
|
||||
<para>This manual page was written by &dhusername; &dhemail; for
|
||||
the &debian; system (and may be used by others). Permission is
|
||||
granted to copy, distribute and/or modify this document under
|
||||
the terms of the &gnu; General Public License, Version 2 any
|
||||
later version published by the Free Software Foundation.
|
||||
</para>
|
||||
<para>
|
||||
On Debian systems, the complete text of the GNU General Public
|
||||
License can be found in /usr/share/common-licenses/GPL.
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
||||
<!-- Keep this comment at the end of the file
|
||||
Local variables:
|
||||
mode: sgml
|
||||
sgml-omittag:t
|
||||
sgml-shorttag:t
|
||||
sgml-minimize-attributes:nil
|
||||
sgml-always-quote-attributes:t
|
||||
sgml-indent-step:2
|
||||
sgml-indent-data:t
|
||||
sgml-parent-document:nil
|
||||
sgml-default-dtd-file:nil
|
||||
sgml-exposed-tags:nil
|
||||
sgml-local-catalogs:nil
|
||||
sgml-local-ecat-files:nil
|
||||
End:
|
||||
-->
|
291
debian/manpage.xml.ex
vendored
291
debian/manpage.xml.ex
vendored
|
@ -1,291 +0,0 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||
|
||||
<!--
|
||||
|
||||
`xsltproc -''-nonet \
|
||||
-''-param man.charmap.use.subset "0" \
|
||||
-''-param make.year.ranges "1" \
|
||||
-''-param make.single.year.ranges "1" \
|
||||
/usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl \
|
||||
manpage.xml'
|
||||
|
||||
A manual page <package>.<section> will be generated. You may view the
|
||||
manual page with: nroff -man <package>.<section> | less'. A typical entry
|
||||
in a Makefile or Makefile.am is:
|
||||
|
||||
DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl
|
||||
XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0"
|
||||
|
||||
manpage.1: manpage.xml
|
||||
$(XP) $(DB2MAN) $<
|
||||
|
||||
The xsltproc binary is found in the xsltproc package. The XSL files are in
|
||||
docbook-xsl. A description of the parameters you can use can be found in the
|
||||
docbook-xsl-doc-* packages. Please remember that if you create the nroff
|
||||
version in one of the debian/rules file targets (such as build), you will need
|
||||
to include xsltproc and docbook-xsl in your Build-Depends control field.
|
||||
Alternatively use the xmlto command/package. That will also automatically
|
||||
pull in xsltproc and docbook-xsl.
|
||||
|
||||
Notes for using docbook2x: docbook2x-man does not automatically create the
|
||||
AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as
|
||||
<refsect1> ... </refsect1>.
|
||||
|
||||
To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections
|
||||
read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be
|
||||
found in the docbook-xsl-doc-html package.
|
||||
|
||||
Validation can be done using: `xmllint -''-noout -''-valid manpage.xml`
|
||||
|
||||
General documentation about man-pages and man-page-formatting:
|
||||
man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
|
||||
|
||||
-->
|
||||
|
||||
<!-- Fill in your name for FIRSTNAME and SURNAME. -->
|
||||
<!ENTITY dhfirstname "FIRSTNAME">
|
||||
<!ENTITY dhsurname "SURNAME">
|
||||
<!-- dhusername could also be set to "&dhfirstname; &dhsurname;". -->
|
||||
<!ENTITY dhusername "Stefan Lankes">
|
||||
<!ENTITY dhemail "slankes@eonerc.rwth-aachen.de">
|
||||
<!-- SECTION should be 1-8, maybe w/ subsection other parameters are
|
||||
allowed: see man(7), man(1) and
|
||||
http://www.tldp.org/HOWTO/Man-Page/q2.html. -->
|
||||
<!ENTITY dhsection "SECTION">
|
||||
<!-- TITLE should be something like "User commands" or similar (see
|
||||
http://www.tldp.org/HOWTO/Man-Page/q2.html). -->
|
||||
<!ENTITY dhtitle "libhermit User Manual">
|
||||
<!ENTITY dhucpackage "Libhermit">
|
||||
<!ENTITY dhpackage "libhermit">
|
||||
]>
|
||||
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<title>&dhtitle;</title>
|
||||
<productname>&dhpackage;</productname>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>&dhfirstname;</firstname>
|
||||
<surname>&dhsurname;</surname>
|
||||
<contrib>Wrote this manpage for the Debian system.</contrib>
|
||||
<address>
|
||||
<email>&dhemail;</email>
|
||||
</address>
|
||||
</author>
|
||||
</authorgroup>
|
||||
<copyright>
|
||||
<year>2007</year>
|
||||
<holder>&dhusername;</holder>
|
||||
</copyright>
|
||||
<legalnotice>
|
||||
<para>This manual page was written for the Debian system
|
||||
(and may be used by others).</para>
|
||||
<para>Permission is granted to copy, distribute and/or modify this
|
||||
document under the terms of the GNU General Public License,
|
||||
Version 2 or (at your option) any later version published by
|
||||
the Free Software Foundation.</para>
|
||||
<para>On Debian systems, the complete text of the GNU General Public
|
||||
License can be found in
|
||||
<filename>/usr/share/common-licenses/GPL</filename>.</para>
|
||||
</legalnotice>
|
||||
</refentryinfo>
|
||||
<refmeta>
|
||||
<refentrytitle>&dhucpackage;</refentrytitle>
|
||||
<manvolnum>&dhsection;</manvolnum>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>&dhpackage;</refname>
|
||||
<refpurpose>program to do something</refpurpose>
|
||||
</refnamediv>
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>&dhpackage;</command>
|
||||
<!-- These are several examples, how syntaxes could look -->
|
||||
<arg choice="plain"><option>-e <replaceable>this</replaceable></option></arg>
|
||||
<arg choice="opt"><option>--example=<parameter>that</parameter></option></arg>
|
||||
<arg choice="opt">
|
||||
<group choice="req">
|
||||
<arg choice="plain"><option>-e</option></arg>
|
||||
<arg choice="plain"><option>--example</option></arg>
|
||||
</group>
|
||||
<replaceable class="option">this</replaceable>
|
||||
</arg>
|
||||
<arg choice="opt">
|
||||
<group choice="req">
|
||||
<arg choice="plain"><option>-e</option></arg>
|
||||
<arg choice="plain"><option>--example</option></arg>
|
||||
</group>
|
||||
<group choice="req">
|
||||
<arg choice="plain"><replaceable>this</replaceable></arg>
|
||||
<arg choice="plain"><replaceable>that</replaceable></arg>
|
||||
</group>
|
||||
</arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>&dhpackage;</command>
|
||||
<!-- Normally the help and version options make the programs stop
|
||||
right after outputting the requested information. -->
|
||||
<group choice="opt">
|
||||
<arg choice="plain">
|
||||
<group choice="req">
|
||||
<arg choice="plain"><option>-h</option></arg>
|
||||
<arg choice="plain"><option>--help</option></arg>
|
||||
</group>
|
||||
</arg>
|
||||
<arg choice="plain">
|
||||
<group choice="req">
|
||||
<arg choice="plain"><option>-v</option></arg>
|
||||
<arg choice="plain"><option>--version</option></arg>
|
||||
</group>
|
||||
</arg>
|
||||
</group>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
<refsect1 id="description">
|
||||
<title>DESCRIPTION</title>
|
||||
<para>This manual page documents briefly the
|
||||
<command>&dhpackage;</command> and <command>bar</command>
|
||||
commands.</para>
|
||||
<para>This manual page was written for the Debian distribution
|
||||
because the original program does not have a manual page.
|
||||
Instead, it has documentation in the GNU <citerefentry>
|
||||
<refentrytitle>info</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry> format; see below.</para>
|
||||
<para><command>&dhpackage;</command> is a program that...</para>
|
||||
</refsect1>
|
||||
<refsect1 id="options">
|
||||
<title>OPTIONS</title>
|
||||
<para>The program follows the usual GNU command line syntax,
|
||||
with long options starting with two dashes (`-'). A summary of
|
||||
options is included below. For a complete description, see the
|
||||
<citerefentry>
|
||||
<refentrytitle>info</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry> files.</para>
|
||||
<variablelist>
|
||||
<!-- Use the variablelist.term.separator and the
|
||||
variablelist.term.break.after parameters to
|
||||
control the term elements. -->
|
||||
<varlistentry>
|
||||
<term><option>-e <replaceable>this</replaceable></option></term>
|
||||
<term><option>--example=<replaceable>that</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>Does this and that.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-h</option></term>
|
||||
<term><option>--help</option></term>
|
||||
<listitem>
|
||||
<para>Show summary of options.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-v</option></term>
|
||||
<term><option>--version</option></term>
|
||||
<listitem>
|
||||
<para>Show version of program.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1 id="files">
|
||||
<title>FILES</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><filename>/etc/foo.conf</filename></term>
|
||||
<listitem>
|
||||
<para>The system-wide configuration file to control the
|
||||
behaviour of <application>&dhpackage;</application>. See
|
||||
<citerefentry>
|
||||
<refentrytitle>foo.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry> for further details.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>${HOME}/.foo.conf</filename></term>
|
||||
<listitem>
|
||||
<para>The per-user configuration file to control the
|
||||
behaviour of <application>&dhpackage;</application>. See
|
||||
<citerefentry>
|
||||
<refentrytitle>foo.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry> for further details.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1 id="environment">
|
||||
<title>ENVIRONMENT</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><envar>FOO_CONF</envar></term>
|
||||
<listitem>
|
||||
<para>If used, the defined file is used as configuration
|
||||
file (see also <xref linkend="files"/>).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1 id="diagnostics">
|
||||
<title>DIAGNOSTICS</title>
|
||||
<para>The following diagnostics may be issued
|
||||
on <filename class="devicefile">stderr</filename>:</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errortext>Bad configuration file. Exiting.</errortext></term>
|
||||
<listitem>
|
||||
<para>The configuration file seems to contain a broken configuration
|
||||
line. Use the <option>--verbose</option> option, to get more info.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<para><command>&dhpackage;</command> provides some return codes, that can
|
||||
be used in scripts:</para>
|
||||
<segmentedlist>
|
||||
<segtitle>Code</segtitle>
|
||||
<segtitle>Diagnostic</segtitle>
|
||||
<seglistitem>
|
||||
<seg><errorcode>0</errorcode></seg>
|
||||
<seg>Program exited successfully.</seg>
|
||||
</seglistitem>
|
||||
<seglistitem>
|
||||
<seg><errorcode>1</errorcode></seg>
|
||||
<seg>The configuration file seems to be broken.</seg>
|
||||
</seglistitem>
|
||||
</segmentedlist>
|
||||
</refsect1>
|
||||
<refsect1 id="bugs">
|
||||
<!-- Or use this section to tell about upstream BTS. -->
|
||||
<title>BUGS</title>
|
||||
<para>The program is currently limited to only work
|
||||
with the <package>foobar</package> library.</para>
|
||||
<para>The upstreams <acronym>BTS</acronym> can be found
|
||||
at <ulink url="http://bugzilla.foo.tld"/>.</para>
|
||||
</refsect1>
|
||||
<refsect1 id="see_also">
|
||||
<title>SEE ALSO</title>
|
||||
<!-- In alpabetical order. -->
|
||||
<para><citerefentry>
|
||||
<refentrytitle>bar</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>, <citerefentry>
|
||||
<refentrytitle>baz</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>, <citerefentry>
|
||||
<refentrytitle>foo.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry></para>
|
||||
<para>The programs are documented fully by <citetitle>The Rise and
|
||||
Fall of a Fooish Bar</citetitle> available via the <citerefentry>
|
||||
<refentrytitle>info</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry> system.</para>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
2
debian/menu.ex
vendored
2
debian/menu.ex
vendored
|
@ -1,2 +0,0 @@
|
|||
?package(libhermit):needs="X11|text|vc|wm" section="Applications/see-menu-manual"\
|
||||
title="libhermit" command="/usr/bin/libhermit"
|
39
debian/postinst.ex
vendored
39
debian/postinst.ex
vendored
|
@ -1,39 +0,0 @@
|
|||
#!/bin/sh
|
||||
# postinst script for libhermit
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postinst> `configure' <most-recently-configured-version>
|
||||
# * <old-postinst> `abort-upgrade' <new version>
|
||||
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
|
||||
# <new-version>
|
||||
# * <postinst> `abort-remove'
|
||||
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
|
||||
# <failed-install-package> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
37
debian/postrm.ex
vendored
37
debian/postrm.ex
vendored
|
@ -1,37 +0,0 @@
|
|||
#!/bin/sh
|
||||
# postrm script for libhermit
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postrm> `remove'
|
||||
# * <postrm> `purge'
|
||||
# * <old-postrm> `upgrade' <new-version>
|
||||
# * <new-postrm> `failed-upgrade' <old-version>
|
||||
# * <new-postrm> `abort-install'
|
||||
# * <new-postrm> `abort-install' <old-version>
|
||||
# * <new-postrm> `abort-upgrade' <old-version>
|
||||
# * <disappearer's-postrm> `disappear' <overwriter>
|
||||
# <overwriter-version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postrm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
35
debian/preinst.ex
vendored
35
debian/preinst.ex
vendored
|
@ -1,35 +0,0 @@
|
|||
#!/bin/sh
|
||||
# preinst script for libhermit
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <new-preinst> `install'
|
||||
# * <new-preinst> `install' <old-version>
|
||||
# * <new-preinst> `upgrade' <old-version>
|
||||
# * <old-preinst> `abort-upgrade' <new-version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "preinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
38
debian/prerm.ex
vendored
38
debian/prerm.ex
vendored
|
@ -1,38 +0,0 @@
|
|||
#!/bin/sh
|
||||
# prerm script for libhermit
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <prerm> `remove'
|
||||
# * <old-prerm> `upgrade' <new-version>
|
||||
# * <new-prerm> `failed-upgrade' <old-version>
|
||||
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
|
||||
# * <deconfigured's-prerm> `deconfigure' `in-favour'
|
||||
# <package-being-installed> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
remove|upgrade|deconfigure)
|
||||
;;
|
||||
|
||||
failed-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "prerm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
36
debian/rules
vendored
36
debian/rules
vendored
|
@ -1,36 +0,0 @@
|
|||
#!/usr/bin/make -f
|
||||
# See debhelper(7) (uncomment to enable)
|
||||
# output every command that modifies files on the build system.
|
||||
#export DH_VERBOSE = 1
|
||||
|
||||
# see FEATURE AREAS in dpkg-buildflags(1)
|
||||
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
export DEB_BUILD_OPTS = nocheck
|
||||
|
||||
%:
|
||||
dh $@ #--parallel
|
||||
|
||||
override_dh_auto_configure:
|
||||
./configure --prefix=`pwd`/debian/libhermit/opt/hermit
|
||||
|
||||
override_dh_auto_build:
|
||||
# this target is somehow not executed by dh_auto_build and thus the build fails
|
||||
make arch/x86/kernel/boot.h
|
||||
|
||||
dh_auto_build
|
||||
make libs
|
||||
|
||||
override_dh_auto_test:
|
||||
@echo "tests are disabled"
|
||||
|
||||
override_dh_auto_install:
|
||||
#make install_libhermit
|
||||
make install
|
||||
|
||||
# delete unneded files that would cause conflicts
|
||||
rm -rf `-pwd`/debian/libhermit/opt/hermit/share/info/dir
|
||||
|
||||
override_dh_strip:
|
||||
# stripping will incorrectly use system tools for stripping, generating
|
||||
# wrong binary format, i.e. not for HermitCore
|
||||
@echo "No stripping"
|
1
debian/source/format
vendored
1
debian/source/format
vendored
|
@ -1 +0,0 @@
|
|||
3.0 (quilt)
|
39
debian/watch.ex
vendored
39
debian/watch.ex
vendored
|
@ -1,39 +0,0 @@
|
|||
# Example watch control file for uscan
|
||||
# Rename this file to "watch" and then you can run the "uscan" command
|
||||
# to check for upstream updates and more.
|
||||
# See uscan(1) for format
|
||||
|
||||
# Compulsory line, this is a version 4 file
|
||||
version=4
|
||||
|
||||
# PGP signature mangle, so foo.tar.gz has foo.tar.gz.sig
|
||||
#opts="pgpsigurlmangle=s%$%.sig%"
|
||||
|
||||
# HTTP site (basic)
|
||||
#http://example.com/downloads.html \
|
||||
# files/libhermit-([\d\.]+)\.tar\.gz debian uupdate
|
||||
|
||||
# Uncommment to examine a FTP server
|
||||
#ftp://ftp.example.com/pub/libhermit-(.*)\.tar\.gz debian uupdate
|
||||
|
||||
# SourceForge hosted projects
|
||||
# http://sf.net/libhermit/ libhermit-(.*)\.tar\.gz debian uupdate
|
||||
|
||||
# GitHub hosted projects
|
||||
#opts="filenamemangle="s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%<project>-$1.tar.gz%" \
|
||||
# https://github.com/<user>/libhermit/tags \
|
||||
# (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate
|
||||
|
||||
# PyPI
|
||||
# https://pypi.python.org/packages/source/<initial>/libhermit/ \
|
||||
# libhermit-(.+)\.tar\.gz debian uupdate
|
||||
|
||||
# Direct Git
|
||||
# opts="mode=git" http://git.example.com/libhermit.git \
|
||||
# refs/tags/v([\d\.]+) debian uupdate
|
||||
|
||||
|
||||
|
||||
|
||||
# Uncomment to find new files on GooglePages
|
||||
# http://example.googlepages.com/foo.html libhermit-(.*)\.tar\.gz
|
|
@ -1,4 +0,0 @@
|
|||
C_source := mmnif.c util.c e1000.c rtl8139.c
|
||||
MODULE := drivers_net
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* Copyright 2012 Stefan Lankes, Chair for Operating Systems,
|
||||
* RWTH Aachen University
|
||||
*
|
||||
|
@ -58,7 +58,7 @@ typedef struct {
|
|||
uint32_t device;
|
||||
} board_t;
|
||||
|
||||
static board_t board_tbl[] =
|
||||
static board_t board_tbl[] =
|
||||
{
|
||||
{"Intel", "Intel E1000 (82542)", 0x8086, 0x1000},
|
||||
{"Intel", "Intel E1000 (82543GC FIBER)", 0x8086, 0x1001},
|
||||
|
@ -67,7 +67,7 @@ static board_t board_tbl[] =
|
|||
{"Intel", "Intel E1000 (82544EI FIBER)", 0x8086, 0x1009},
|
||||
{"Intel", "Intel E1000 (82544GC COPPER)", 0x8086, 0x100C},
|
||||
{"Intel", "Intel E1000 (82544GC LOM)", 0x8086, 0x100D},
|
||||
{"Intel", "Intel E1000 (82540EM)", 0x8086, 0x100E},
|
||||
{"Intel", "Intel E1000 (82540EM)", 0x8086, 0x100E},
|
||||
{"Intel", "Intel E1000 (82540EM LOM)", 0x8086, 0x1015},
|
||||
{"Intel", "Intel E1000 (82540EP LOM)", 0x8086, 0x1016},
|
||||
{"Intel", "Intel E1000 (82540EP)", 0x8086, 0x1017},
|
||||
|
@ -132,7 +132,7 @@ static uint16_t eeprom_read(volatile uint8_t* base, uint8_t addr)
|
|||
|
||||
e1000_write(base, E1000_EERD, 1 | ((uint32_t)(addr) << 8));
|
||||
|
||||
while(!((tmp = e1000_read(base, E1000_EERD)) & (1 << 4)))
|
||||
while(!((tmp = e1000_read(base, E1000_EERD)) & (1 << 4)))
|
||||
udelay(1);
|
||||
|
||||
data = (uint16_t)((tmp >> 16) & 0xFFFF);
|
||||
|
@ -148,7 +148,7 @@ static uint16_t eeprom_read(uint8_t* base, uint8_t addr)
|
|||
|
||||
e1000_write(base, E1000_EERD, 1 | ((uint32_t)(addr) << 2));
|
||||
|
||||
while(!((tmp = e1000_read(base, E1000_EERD)) & (1 << 1)))
|
||||
while(!((tmp = e1000_read(base, E1000_EERD)) & (1 << 1)))
|
||||
udelay(1);
|
||||
|
||||
data = (uint16_t)((tmp >> 16) & 0xFFFF);
|
||||
|
@ -198,7 +198,7 @@ static err_t e1000if_output(struct netif* netif, struct pbuf* p)
|
|||
|
||||
// update the tail so the hardware knows it's ready
|
||||
e1000if->tx_tail = (e1000if->tx_tail + 1) % NUM_TX_DESCRIPTORS;
|
||||
e1000_write(e1000if->bar0, E1000_TDT, e1000if->tx_tail);
|
||||
e1000_write(e1000if->bar0, E1000_TDT, e1000if->tx_tail);
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||
|
@ -256,7 +256,7 @@ static void e1000_rx_inthandler(struct netif* netif)
|
|||
LINK_STATS_INC(link.drop);
|
||||
}
|
||||
|
||||
no_eop:
|
||||
no_eop:
|
||||
e1000if->rx_desc[e1000if->rx_tail].status = 0;
|
||||
|
||||
// update tail and write the value to the device
|
||||
|
@ -333,12 +333,12 @@ err_t e1000if_init(struct netif* netif)
|
|||
uint16_t tmp16, speed, cold = 0x40;
|
||||
uint8_t tmp8, is64bit, mem_type, prefetch;
|
||||
static uint8_t num = 0;
|
||||
|
||||
|
||||
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||
|
||||
tmp8 = 0;
|
||||
while (board_tbl[tmp8].vendor_str) {
|
||||
if (pci_get_device_info(board_tbl[tmp8].vendor, board_tbl[tmp8].device, &pci_info, 1) == 0)
|
||||
if (pci_get_device_info(board_tbl[tmp8].vendor, board_tbl[tmp8].device, PCI_IGNORE_SUBID, &pci_info, 1) == 0)
|
||||
break;
|
||||
tmp8++;
|
||||
}
|
||||
|
@ -394,7 +394,7 @@ err_t e1000if_init(struct netif* netif)
|
|||
goto oom;
|
||||
memset((void*) e1000if->tx_desc, 0x00, NUM_TX_DESCRIPTORS*sizeof(tx_desc_t));
|
||||
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: Found %s at mmio 0x%x (size 0x%x), irq %u\n", board_tbl[tmp8].device_str,
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: Found %s at mmio 0x%x (size 0x%x), irq %u\n", board_tbl[tmp8].device_str,
|
||||
pci_info.base[0] & ~0xF, pci_info.size[0], e1000if->irq));
|
||||
//LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: Map iobase to %p\n", e1000if->bar0));
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("e1000if_init: is64bit %u, prefetch %u\n", is64bit, prefetch));
|
||||
|
@ -439,7 +439,7 @@ err_t e1000if_init(struct netif* netif)
|
|||
|
||||
// transmit buffer length; NUM_TX_DESCRIPTORS 16-byte descriptors
|
||||
e1000_write(e1000if->bar0, E1000_TDLEN , (uint32_t)(NUM_TX_DESCRIPTORS * sizeof(tx_desc_t)));
|
||||
|
||||
|
||||
// setup head and tail pointers
|
||||
e1000_write(e1000if->bar0, E1000_TDH, 0);
|
||||
e1000_write(e1000if->bar0, E1000_TDT, 0);
|
||||
|
@ -472,7 +472,7 @@ err_t e1000if_init(struct netif* netif)
|
|||
tmp32 = 0;
|
||||
for(tmp8=0; tmp8<2; tmp8++)
|
||||
((uint8_t*) &tmp32)[tmp8] = netif->hwaddr[tmp8+4];
|
||||
e1000_write(e1000if->bar0, E1000_RA+4, tmp32 | (1 << 31)); // set also AV bit to check incoming packets
|
||||
e1000_write(e1000if->bar0, E1000_RA+4, tmp32 | (1 << 31)); // set also AV bit to check incoming packets
|
||||
|
||||
/* Zero out the other receive addresses. */
|
||||
for (tmp8=1; tmp8<16; tmp8++) {
|
||||
|
|
|
@ -678,7 +678,7 @@ err_t mmnif_init(struct netif *netif)
|
|||
num++;
|
||||
|
||||
/* downward functions */
|
||||
netif->output = mmnif_link_layer;
|
||||
netif->output = (netif_output_fn) mmnif_link_layer;
|
||||
|
||||
/* there is no special link layer just the ip layer */
|
||||
netif->linkoutput = mmnif_tx;
|
||||
|
@ -686,8 +686,6 @@ err_t mmnif_init(struct netif *netif)
|
|||
/* maximum transfer unit */
|
||||
netif->mtu = 1500;
|
||||
|
||||
/* broadcast capability, keep all default flags */
|
||||
//netif->flags |= NETIF_FLAG_BROADCAST;
|
||||
/* set link up */
|
||||
netif->flags |= NETIF_FLAG_LINK_UP;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* Copyright 2010 Stefan Lankes, Chair for Operating Systems,
|
||||
* RWTH Aachen University
|
||||
*
|
||||
|
@ -68,7 +68,7 @@ typedef struct {
|
|||
uint32_t device;
|
||||
} board_t;
|
||||
|
||||
static board_t board_tbl[] =
|
||||
static board_t board_tbl[] =
|
||||
{
|
||||
{"RealTek", "RealTek RTL8139", 0x10ec, 0x8139},
|
||||
{"RealTek", "RealTek RTL8129 Fast Ethernet", 0x10ec, 0x8129},
|
||||
|
@ -307,7 +307,7 @@ err_t rtl8139if_init(struct netif* netif)
|
|||
|
||||
tmp8 = 0;
|
||||
while (board_tbl[tmp8].vendor_str) {
|
||||
if (pci_get_device_info(board_tbl[tmp8].vendor, board_tbl[tmp8].device, &pci_info, 1) == 0)
|
||||
if (pci_get_device_info(board_tbl[tmp8].vendor, board_tbl[tmp8].device, PCI_IGNORE_SUBID, &pci_info, 1) == 0)
|
||||
break;
|
||||
tmp8++;
|
||||
}
|
||||
|
@ -388,8 +388,8 @@ err_t rtl8139if_init(struct netif* netif)
|
|||
outportb(rtl8139if->iobase + CR, CR_RST);
|
||||
|
||||
/*
|
||||
* The RST bit must be checked to make sure that the chip has finished the reset.
|
||||
* If the RST bit is high (1), then the reset is still in operation.
|
||||
* The RST bit must be checked to make sure that the chip has finished the reset.
|
||||
* If the RST bit is high (1), then the reset is still in operation.
|
||||
*/
|
||||
udelay(10000);
|
||||
tmp16 = 10000;
|
||||
|
@ -419,7 +419,7 @@ err_t rtl8139if_init(struct netif* netif)
|
|||
outportb(rtl8139if->iobase + CONFIG1, 0);
|
||||
|
||||
// disable driver loaded and lanwake bits, turn driver loaded bit back on
|
||||
outportb(rtl8139if->iobase + CONFIG1,
|
||||
outportb(rtl8139if->iobase + CONFIG1,
|
||||
(inportb(rtl8139if->iobase + CONFIG1) & ~(CONFIG1_DVRLOAD | CONFIG1_LWACT)) | CONFIG1_DVRLOAD);
|
||||
|
||||
// unlock config register
|
||||
|
@ -430,7 +430,7 @@ err_t rtl8139if_init(struct netif* netif)
|
|||
* AB - Accept Broadcast: Accept broadcast packets sent to mac ff:ff:ff:ff:ff:ff
|
||||
* AM - Accept Multicast: Accept multicast packets.
|
||||
* APM - Accept Physical Match: Accept packets send to NIC's MAC address.
|
||||
* AAP - Accept All Packets. Accept all packets (run in promiscuous mode).
|
||||
* AAP - Accept All Packets. Accept all packets (run in promiscuous mode).
|
||||
*/
|
||||
outportl(rtl8139if->iobase + RCR, RCR_MXDMA2|RCR_MXDMA1|RCR_MXDMA0|RCR_AB|RCR_AM|RCR_APM|RCR_AAP); // The WRAP bit isn't set!
|
||||
|
||||
|
@ -456,7 +456,7 @@ err_t rtl8139if_init(struct netif* netif)
|
|||
if (tmp16 & BMCR_SPD1000)
|
||||
speed = 1000;
|
||||
else if (tmp16 & BMCR_SPD100)
|
||||
speed = 100;
|
||||
speed = 100;
|
||||
else
|
||||
speed = 10;
|
||||
// Enable Receive and Transmitter
|
||||
|
|
458
drivers/net/vioif.c
Normal file
458
drivers/net/vioif.c
Normal file
|
@ -0,0 +1,458 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <hermit/stddef.h>
|
||||
#include <hermit/stdio.h>
|
||||
#include <hermit/string.h>
|
||||
#include <hermit/processor.h>
|
||||
#include <hermit/mailbox.h>
|
||||
#include <hermit/logging.h>
|
||||
#include <hermit/virtio_net.h>
|
||||
#include <hermit/virtio_ring.h>
|
||||
#include <hermit/virtio_pci.h>
|
||||
#include <hermit/virtio_net.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/pci.h>
|
||||
#include <lwip/sys.h>
|
||||
#include <lwip/stats.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <lwip/tcpip.h>
|
||||
#include <lwip/snmp.h>
|
||||
#include <lwip/ethip6.h>
|
||||
#include <netif/etharp.h>
|
||||
#include <net/vioif.h>
|
||||
|
||||
#define VENDOR_ID 0x1AF4
|
||||
#define VIOIF_BUFFER_SIZE 0x2048
|
||||
#define MIN(a, b) (a) < (b) ? (a) : (b)
|
||||
#define QUEUE_LIMIT 256
|
||||
|
||||
/* NOTE: RX queue is 0, TX queue is 1 - Virtio Std. §5.1.2 */
|
||||
#define TX_NUM 1
|
||||
#define RX_NUM 0
|
||||
|
||||
static struct netif* mynetif = NULL;
|
||||
|
||||
static inline void vioif_enable_interrupts(virt_queue_t* vq)
|
||||
{
|
||||
vq->vring.used->flags = 0;
|
||||
}
|
||||
|
||||
static inline void vioif_disable_interrupts(virt_queue_t* vq)
|
||||
{
|
||||
vq->vring.used->flags = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return error code
|
||||
* - ERR_OK: packet transferred to hardware
|
||||
* - ERR_CONN: no link or link failure
|
||||
* - ERR_IF: could not transfer to link (hardware buffer full?)
|
||||
*/
|
||||
static err_t vioif_output(struct netif* netif, struct pbuf* p)
|
||||
{
|
||||
vioif_t* vioif = netif->state;
|
||||
virt_queue_t* vq = &vioif->queues[TX_NUM];
|
||||
struct pbuf *q;
|
||||
uint32_t i;
|
||||
uint16_t buffer_index;
|
||||
|
||||
if (BUILTIN_EXPECT(p->tot_len > 1792, 0)) {
|
||||
LOG_ERROR("vioif_output: packet is longer than 1792 bytes\n");
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
for(buffer_index=0; buffer_index<vq->vring.num; buffer_index++) {
|
||||
if (!vq->vring.desc[buffer_index].len) {
|
||||
LOG_DEBUG("vioif_output: buffer %u is free\n", buffer_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LOG_DEBUG("vioif: found free buffer %d\n", buffer_index);
|
||||
|
||||
if (BUILTIN_EXPECT(buffer_index >= vq->vring.num, 0)) {
|
||||
LOG_ERROR("vioif_output: too many packets at once\n");
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
||||
#endif
|
||||
|
||||
const size_t hdr_sz = sizeof(struct virtio_net_hdr);
|
||||
// NOTE: packet is fully checksummed => all flags are set to zero
|
||||
memset((void*) (vq->virt_buffer + buffer_index * VIOIF_BUFFER_SIZE), 0x00, hdr_sz);
|
||||
|
||||
vq->vring.desc[buffer_index].addr = vq->phys_buffer + buffer_index * VIOIF_BUFFER_SIZE;
|
||||
vq->vring.desc[buffer_index].len = p->tot_len + hdr_sz;
|
||||
vq->vring.desc[buffer_index].flags = 0;
|
||||
// we send only one buffer because it is large enough for our packet
|
||||
vq->vring.desc[buffer_index].next = 0; //(buffer_index+1) % vq->vring.num;
|
||||
|
||||
|
||||
/*
|
||||
* q traverses through linked list of pbuf's
|
||||
* This list MUST consist of a single packet ONLY
|
||||
*/
|
||||
for (q = p, i = 0; q != 0; q = q->next) {
|
||||
memcpy((void*) (vq->virt_buffer + hdr_sz + buffer_index * VIOIF_BUFFER_SIZE + i), q->payload, q->len);
|
||||
i += q->len;
|
||||
}
|
||||
|
||||
// Add it in the available ring
|
||||
uint16_t index = vq->vring.avail->idx % vq->vring.num;
|
||||
vq->vring.avail->ring[index] = buffer_index;
|
||||
|
||||
// besure that everything is written
|
||||
mb();
|
||||
|
||||
vq->vring.avail->idx++;
|
||||
|
||||
// besure that everything is written
|
||||
mb();
|
||||
|
||||
/*
|
||||
* Notify the changes
|
||||
* NOTE: RX queue is 0, TX queue is 1 - Virtio Std. §5.1.2
|
||||
*/
|
||||
outportw(vioif->iobase+VIRTIO_PCI_QUEUE_NOTIFY, TX_NUM);
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||
#endif
|
||||
|
||||
LINK_STATS_INC(link.xmit);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void vioif_rx_inthandler(struct netif* netif)
|
||||
{
|
||||
vioif_t* vioif = mynetif->state;
|
||||
virt_queue_t* vq = &vioif->queues[RX_NUM];
|
||||
|
||||
while(vq->last_seen_used != vq->vring.used->idx)
|
||||
{
|
||||
const size_t hdr_sz = sizeof(struct virtio_net_hdr);
|
||||
struct vring_used_elem* used = &vq->vring.used->ring[vq->last_seen_used % vq->vring.num];
|
||||
struct virtio_net_hdr* hdr = (struct virtio_net_hdr*) (vq->virt_buffer + used->id * VIOIF_BUFFER_SIZE);
|
||||
|
||||
LOG_DEBUG("vq->vring.used->idx %d, vq->vring.used->flags %d, vq->last_seen_used %d\n", vq->vring.used->idx, vq->vring.used->flags, vq->last_seen_used);
|
||||
LOG_DEBUG("used id %d, len %d\n", used->id, used->len);
|
||||
LOG_DEBUG("hdr len %d, flags %d\n", hdr->hdr_len, hdr->flags);
|
||||
|
||||
struct pbuf* p = pbuf_alloc(PBUF_RAW, used->len, PBUF_POOL);
|
||||
if (p) {
|
||||
uint16_t pos;
|
||||
struct pbuf* q;
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
||||
#endif
|
||||
for(q=p, pos=0; q!=NULL; q=q->next) {
|
||||
memcpy((uint8_t*) q->payload,
|
||||
(uint8_t*) (vq->virt_buffer + hdr_sz + used->id * VIOIF_BUFFER_SIZE + pos),
|
||||
q->len);
|
||||
pos += q->len;
|
||||
}
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||
#endif
|
||||
LINK_STATS_INC(link.recv);
|
||||
|
||||
// forward packet to LwIP
|
||||
netif->input(p, netif);
|
||||
} else {
|
||||
LOG_ERROR("vioif_rx_inthandler: not enough memory!\n");
|
||||
LINK_STATS_INC(link.memerr);
|
||||
LINK_STATS_INC(link.drop);
|
||||
goto oom;
|
||||
}
|
||||
|
||||
vq->vring.avail->ring[vq->vring.avail->idx % vq->vring.num] = used->id;
|
||||
vq->vring.avail->idx++;
|
||||
vq->last_seen_used++;
|
||||
}
|
||||
|
||||
oom:
|
||||
vioif->polling = 0;
|
||||
vioif_enable_interrupts(vq);
|
||||
mb();
|
||||
}
|
||||
|
||||
|
||||
/* this function is called in the context of the tcpip thread or the irq handler (by using NO_SYS) */
|
||||
static void vioif_poll(void* ctx)
|
||||
{
|
||||
vioif_rx_inthandler(mynetif);
|
||||
}
|
||||
|
||||
static void vioif_handler(struct state* s)
|
||||
{
|
||||
vioif_t* vioif = mynetif->state;
|
||||
|
||||
LOG_DEBUG("vioif: receive interrupt\n");
|
||||
|
||||
// reset interrupt by reading the isr port
|
||||
uint8_t isr = inportb(vioif->iobase+VIRTIO_PCI_ISR);
|
||||
|
||||
// do we receiven an interrupt for this device?
|
||||
if (!(isr & 0x01))
|
||||
return;
|
||||
|
||||
// free TX queue
|
||||
virt_queue_t* vq = &vioif->queues[1];
|
||||
|
||||
vioif_disable_interrupts(vq);
|
||||
while(vq->last_seen_used != vq->vring.used->idx)
|
||||
{
|
||||
struct vring_used_elem* used = &vq->vring.used->ring[vq->last_seen_used % vq->vring.num];
|
||||
LOG_DEBUG("consumed TX elements: index %u, len %u\n", used->id, used->len);
|
||||
// mark as free
|
||||
vq->vring.desc[used->id].len = 0;
|
||||
vq->last_seen_used++;
|
||||
}
|
||||
vioif_enable_interrupts(vq);
|
||||
mb();
|
||||
|
||||
// check RX qeueue
|
||||
vq = &vioif->queues[0];
|
||||
vioif_disable_interrupts(vq);
|
||||
if (!vioif->polling && (vq->last_seen_used != vq->vring.used->idx))
|
||||
{
|
||||
#if NO_SYS
|
||||
vioif_poll(NULL);
|
||||
#else
|
||||
if (tcpip_callback_with_block(vioif_poll, NULL, 0) == ERR_OK) {
|
||||
vioif->polling = 1;
|
||||
} else {
|
||||
LOG_ERROR("rtl8139if_handler: unable to send a poll request to the tcpip thread\n");
|
||||
}
|
||||
#endif
|
||||
} else vioif_enable_interrupts(vq);
|
||||
mb();
|
||||
}
|
||||
|
||||
static int vioif_queue_setup(vioif_t* dev)
|
||||
{
|
||||
virt_queue_t* vq;
|
||||
uint32_t total_size;
|
||||
unsigned int num;
|
||||
|
||||
for (uint32_t index=0; index<VIOIF_NUM_QUEUES; index++) {
|
||||
vq = &dev->queues[index];
|
||||
|
||||
memset(vq, 0x00, sizeof(virt_queue_t));
|
||||
|
||||
// determine queue size
|
||||
outportw(dev->iobase+VIRTIO_PCI_QUEUE_SEL, index);
|
||||
num = inportw(dev->iobase+VIRTIO_PCI_QUEUE_NUM);
|
||||
if (!num) return -1;
|
||||
|
||||
LOG_INFO("vioif: queue_size %u (index %u)\n", num, index);
|
||||
|
||||
total_size = vring_size(num, PAGE_SIZE);
|
||||
|
||||
// allocate and init memory for the virtual queue
|
||||
void* vring_base = page_alloc(total_size, VMA_READ|VMA_WRITE|VMA_CACHEABLE);
|
||||
if (BUILTIN_EXPECT(!vring_base, 0)) {
|
||||
LOG_INFO("Not enough memory to create queue %u\n", index);
|
||||
return -1;
|
||||
}
|
||||
memset((void*)vring_base, 0x00, total_size);
|
||||
vring_init(&vq->vring, num, vring_base, PAGE_SIZE);
|
||||
|
||||
if (num > QUEUE_LIMIT) {
|
||||
vq->vring.num = num = QUEUE_LIMIT;
|
||||
LOG_INFO("vioif: set queue limit to %u (index %u)\n", vq->vring.num, index);
|
||||
}
|
||||
|
||||
vq->virt_buffer = (uint64_t) page_alloc(num*VIOIF_BUFFER_SIZE, VMA_READ|VMA_WRITE|VMA_CACHEABLE);
|
||||
if (BUILTIN_EXPECT(!vq->virt_buffer, 0)) {
|
||||
LOG_INFO("Not enough memory to create buffer %u\n", index);
|
||||
return -1;
|
||||
}
|
||||
vq->phys_buffer = virt_to_phys(vq->virt_buffer);
|
||||
|
||||
for(int i=0; i<num; i++) {
|
||||
vq->vring.desc[i].addr = vq->phys_buffer + i * VIOIF_BUFFER_SIZE;
|
||||
if (index == RX_NUM) {
|
||||
/* NOTE: RX queue is 0, TX queue is 1 - Virtio Std. §5.1.2 */
|
||||
vq->vring.desc[i].len = VIOIF_BUFFER_SIZE;
|
||||
vq->vring.desc[i].flags = VRING_DESC_F_WRITE;
|
||||
vq->vring.avail->ring[vq->vring.avail->idx % num] = i;
|
||||
vq->vring.avail->idx++;
|
||||
}
|
||||
}
|
||||
|
||||
// register buffer
|
||||
outportw(dev->iobase+VIRTIO_PCI_QUEUE_SEL, index);
|
||||
outportl(dev->iobase+VIRTIO_PCI_QUEUE_PFN, virt_to_phys((size_t) vring_base) >> PAGE_BITS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
err_t vioif_init(struct netif* netif)
|
||||
{
|
||||
static uint8_t num = 0;
|
||||
vioif_t* vioif;
|
||||
pci_info_t pci_info;
|
||||
int i;
|
||||
|
||||
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||
|
||||
for(i=0x100; i<=0x103F; i++) {
|
||||
if ((pci_get_device_info(VENDOR_ID, i, 1, &pci_info, 1) == 0)) {
|
||||
LOG_INFO("Found vioif (Vendor ID 0x%x, Device Id 0x%x)\n", VENDOR_ID, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0x103F)
|
||||
return ERR_ARG;
|
||||
|
||||
vioif = kmalloc(sizeof(vioif_t));
|
||||
if (!vioif) {
|
||||
LOG_ERROR("virtioif_init: out of memory\n");
|
||||
return ERR_MEM;
|
||||
}
|
||||
memset(vioif, 0x00, sizeof(vioif_t));
|
||||
|
||||
vioif->iomem = pci_info.base[1];
|
||||
vioif->iobase = pci_info.base[0];
|
||||
vioif->irq = pci_info.irq;
|
||||
LOG_INFO("vioif uses IRQ %d and IO port 0x%x, IO men 0x%x\n", (int32_t) vioif->irq, vioif->iobase, vioif->iomem);
|
||||
|
||||
// reset interface
|
||||
outportb(vioif->iobase + VIRTIO_PCI_STATUS, 0);
|
||||
LOG_INFO("vioif status: 0x%x\n", (uint32_t) inportb(vioif->iobase + VIRTIO_PCI_STATUS));
|
||||
|
||||
// tell the device that we have noticed it
|
||||
outportb(vioif->iobase + VIRTIO_PCI_STATUS, VIRTIO_CONFIG_S_ACKNOWLEDGE);
|
||||
// tell the device that we will support it.
|
||||
outportb(vioif->iobase + VIRTIO_PCI_STATUS, VIRTIO_CONFIG_S_ACKNOWLEDGE|VIRTIO_CONFIG_S_DRIVER);
|
||||
|
||||
LOG_INFO("host features 0x%x\n", inportl(vioif->iobase + VIRTIO_PCI_HOST_FEATURES));
|
||||
|
||||
uint32_t features = inportl(vioif->iobase + VIRTIO_PCI_HOST_FEATURES);
|
||||
uint32_t required = (1UL << VIRTIO_NET_F_MAC) | (1UL << VIRTIO_NET_F_STATUS);
|
||||
|
||||
if ((features & required) != required) {
|
||||
LOG_ERROR("Host isn't able to fulfill HermireCore's requirements\n");
|
||||
outportb(vioif->iobase + VIRTIO_PCI_STATUS, VIRTIO_CONFIG_S_FAILED);
|
||||
kfree(vioif);
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
required = features;
|
||||
required &= ~(1UL << VIRTIO_NET_F_CTRL_VQ);
|
||||
required &= ~(1UL << VIRTIO_NET_F_GUEST_TSO4);
|
||||
required &= ~(1UL << VIRTIO_NET_F_GUEST_TSO6);
|
||||
required &= ~(1UL << VIRTIO_NET_F_GUEST_UFO);
|
||||
required &= ~(1UL << VIRTIO_RING_F_EVENT_IDX);
|
||||
required &= ~(1UL << VIRTIO_NET_F_MRG_RXBUF);
|
||||
required &= ~(1UL << VIRTIO_NET_F_MQ);
|
||||
|
||||
LOG_INFO("wanted guest features 0x%x\n", required);
|
||||
outportl(vioif->iobase + VIRTIO_PCI_GUEST_FEATURES, required);
|
||||
vioif->features = inportl(vioif->iobase + VIRTIO_PCI_GUEST_FEATURES);
|
||||
LOG_INFO("current guest features 0x%x\n", vioif->features);
|
||||
|
||||
// tell the device that the features are OK
|
||||
outportb(vioif->iobase + VIRTIO_PCI_STATUS, VIRTIO_CONFIG_S_ACKNOWLEDGE|VIRTIO_CONFIG_S_DRIVER|VIRTIO_CONFIG_S_FEATURES_OK);
|
||||
|
||||
// check if the host accept these features
|
||||
uint8_t status = inportb(vioif->iobase + VIRTIO_PCI_STATUS);
|
||||
if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) {
|
||||
LOG_ERROR("device features are ignored: status 0x%x\n", (uint32_t) status);
|
||||
outportb(vioif->iobase + VIRTIO_PCI_STATUS, VIRTIO_CONFIG_S_FAILED);
|
||||
kfree(vioif);
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/* hardware address length */
|
||||
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||||
|
||||
// determine the mac address of this card
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("vioif_init: MAC address "));
|
||||
for (uint8_t tmp8=0; tmp8<ETHARP_HWADDR_LEN; tmp8++) {
|
||||
netif->hwaddr[tmp8] = inportb(vioif->iobase + VIRTIO_PCI_CONFIG_OFF(vioif->msix_enabled) + tmp8);
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("%02x ", netif->hwaddr[tmp8]));
|
||||
}
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
|
||||
|
||||
// Setup virt queues
|
||||
if (BUILTIN_EXPECT(vioif_queue_setup(vioif) < 0, 0)) {
|
||||
outportb(vioif->iobase + VIRTIO_PCI_STATUS, VIRTIO_CONFIG_S_FAILED);
|
||||
kfree(vioif);
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
netif->state = vioif;
|
||||
mynetif = netif;
|
||||
|
||||
irq_install_handler(vioif->irq+32, vioif_handler);
|
||||
|
||||
/*
|
||||
* Initialize the snmp variables and counters inside the struct netif.
|
||||
* The last argument should be replaced with your link speed, in units
|
||||
* of bits per second.
|
||||
*/
|
||||
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 1000);
|
||||
|
||||
/* administrative details */
|
||||
netif->name[0] = 'e';
|
||||
netif->name[1] = 'n';
|
||||
netif->num = num;
|
||||
num++;
|
||||
/* downward functions */
|
||||
netif->output = etharp_output;
|
||||
netif->linkoutput = vioif_output;
|
||||
/* set maximum transfer unit
|
||||
* Google Compute Platform supports only a MTU from 1460
|
||||
*/
|
||||
netif->mtu = 1460;
|
||||
/* broadcast capability */
|
||||
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP | NETIF_FLAG_LINK_UP | NETIF_FLAG_MLD6;
|
||||
#if LWIP_IPV6
|
||||
netif->output_ip6 = ethip6_output;
|
||||
netif_create_ip6_linklocal_address(netif, 1);
|
||||
netif->ip6_autoconfig_enabled = 1;
|
||||
#endif
|
||||
|
||||
// tell the device that the drivers is initialized
|
||||
outportb(vioif->iobase + VIRTIO_PCI_STATUS, VIRTIO_CONFIG_S_ACKNOWLEDGE|VIRTIO_CONFIG_S_DRIVER|VIRTIO_CONFIG_S_DRIVER_OK|VIRTIO_CONFIG_S_FEATURES_OK);
|
||||
|
||||
LOG_INFO("vioif status: 0x%x\n", (uint32_t) inportb(vioif->iobase + VIRTIO_PCI_STATUS));
|
||||
LOG_INFO("vioif link is %s\n",
|
||||
inportl(vioif->iobase + VIRTIO_PCI_CONFIG_OFF(vioif->msix_enabled) + ETHARP_HWADDR_LEN) & VIRTIO_NET_S_LINK_UP ? "up" : "down");
|
||||
|
||||
return ERR_OK;
|
||||
}
|
64
drivers/net/vioif.h
Normal file
64
drivers/net/vioif.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __NET_VIOIF_H__
|
||||
#define __NET_VIOIF_H__
|
||||
|
||||
#include <hermit/stddef.h>
|
||||
#include <hermit/virtio_ring.h>
|
||||
|
||||
#define VIOIF_NUM_QUEUES 2
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct vring vring;
|
||||
uint64_t virt_buffer;
|
||||
uint64_t phys_buffer;
|
||||
uint16_t last_seen_used;
|
||||
} virt_queue_t;
|
||||
|
||||
/*
|
||||
* Helper struct to hold private data used to operate your ethernet interface.
|
||||
*/
|
||||
typedef struct vioif {
|
||||
struct eth_addr *ethaddr;
|
||||
/* Add whatever per-interface state that is needed here. */
|
||||
uint32_t iomem;
|
||||
uint32_t iobase;
|
||||
uint32_t features;
|
||||
uint8_t msix_enabled;
|
||||
uint8_t irq;
|
||||
uint8_t polling;
|
||||
virt_queue_t queues[VIOIF_NUM_QUEUES];
|
||||
} vioif_t;
|
||||
|
||||
/*
|
||||
* Initialize the network driver for the virtio network interface
|
||||
*/
|
||||
err_t vioif_init(struct netif* netif);
|
||||
|
||||
#endif
|
BIN
img/demo.gif
Normal file
BIN
img/demo.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 MiB |
BIN
img/hermitcore_logo.png
Executable file
BIN
img/hermitcore_logo.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 9.9 KiB |
1
img/hermitcore_logo.svg
Executable file
1
img/hermitcore_logo.svg
Executable file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" enable-background="new 0 0 64 64"><path d="m27.6 5.4c-.6.3-3.1 3.4-4.6 3.4s.4-2.7 2.4-4.8c2-2.1 2.8-2.9-1.3-1-2.3 1.1-3.8 2.2-4.7 3.3-.2-.7-.4-1-1.3.1-1.9 2.1-4 5.6-3.1 9.4.1.5.3 1 .5 1.3-.5 3.1.7 7.2 5.6 11.3h1.8c0 0-5-4.1-4.1-9.6 2.2-.4 1.6-.9 4.3-4.4 1.2-1.5 1.3-2.6.9-3.5 3.8-3.1 4.1-5.7 3.6-5.5" fill="#d64553"/><path d="m14.9 15.8c-.9-3.8 1.3-7.2 3.1-9.3 1.9-2.1.7 1.1 2.7 2.2 2 1.1 5 2.4 2.2 5.9-2.7 3.5-2.2 4-4.3 4.4-1 .1-3-.2-3.7-3.2" fill="#ed4c5c"/><path d="m36.4 5.4c.6.3 3.1 3.4 4.6 3.4s-.4-2.7-2.4-4.8c-2-2.1-2.8-2.9 1.3-1 2.3 1.1 3.8 2.2 4.7 3.3.2-.7.4-1 1.3.1 1.9 2.1 4 5.6 3.1 9.4-.1.5-.3 1-.5 1.3.5 3.1-.7 7.2-5.6 11.3h-1.8c0 0 5-4.1 4.1-9.6-2.2-.4-1.6-.9-4.3-4.4-1.2-1.5-1.3-2.6-.9-3.5-3.8-3.1-4.1-5.7-3.6-5.5" fill="#d64553"/><path d="m49.1 15.8c.9-3.8-1.3-7.2-3.1-9.3-1.9-2.1-.7 1.1-2.7 2.2-2 1.1-5 2.4-2.2 5.9 2.7 3.5 2.2 4 4.3 4.4 1 .1 3-.2 3.7-3.2" fill="#ed4c5c"/><g fill="#d64553"><path d="m24.5 23.1c-.6-1.9-1.6-1-1.3-.2.3.9 1.9 4.5.5 7.5l.6.4c0 0 1.6-3 .2-7.7"/><path d="m4.8 35.4c.1.1.3.1.4.1.5 0 1.8-1.3 3.5-2.4.5.2 1.9-.2 3.7-.3 1 .8 4.9 1.8 7.5 3.9 0 0 1.4-.3.7-2.3 0 0-5.2-4.9-6.8-4.4-.3.1-.6.2-.8.4-1.7-.3-3.7-.4-4.3.1-.3.3-.4.6-.5.8-1.5.5-3.8 1.5-4 2.3-.1.3-.1.6 0 .8-.8.9-1.8 2.6-2.2 5.7 0 0 .6-2.4 2.8-4.7"/><path d="m16.6 52.3c.4-.3 1.1-1.6 2-3.1 1.2-.3 4.4-2.8 7.6-3.5 0 0 .6-1.3-1.3-2 0 0-7 1-7.7 2.6-.1.3-.2.6-.2.9-1.3 1.2-2.7 2.7-2.6 3.5 0 .4.2.7.3.9-.5 1.5-1.2 3.9-.7 4.6.2.2.4.4.6.6.2 1.2.9 3.1 3 5.3 0 0-1.4-1.9-1.8-5.1.2-.1.3-.1.4-.3.4-.4.2-2.4.4-4.4"/><path d="m9.4 54.1c.2-.1.3-.1.4-.3.3-.4.1-2.3.3-4.3.4-.3 1.1-1.6 2-3.1 1.2-.3 4.4-2.8 7.6-3.5 0 0 .6-1.3-1.3-2 0 0-7 1-7.7 2.6-.1.3-.2.6-.2.9-1.3 1.2-2.7 2.7-2.6 3.5 0 .4.2.7.3.9-.5 1.5-1.2 3.9-.7 4.6.2.3.4.4.6.6.2 1.2.9 3.1 3 5.3.1-.1-1.3-2-1.7-5.2"/><path d="m11.6 39.2c1.2.4 5.2 0 8.3 1.1 0 0 1.2-.8-.1-2.4 0 0-6.5-2.9-7.9-1.9-.3.2-.5.4-.6.6-1.7.3-3.7.9-4 1.6-.2.3-.2.7-.2 1-1.2 1-3.1 2.7-3 3.5 0 .3.1.6.2.8-.4 1.1-.8 3.1-.2 6.1 0 0-.2-2.4 1.1-5.3.2 0 .3 0 .5 0 .4-.1 1.3-1.9 2.5-3.5.6-.1 1.9-.9 3.4-1.6"/><path d="m39.5 23.1c.6-1.9 1.6-1 1.3-.2-.3.9-1.9 4.5-.5 7.5l-.6.4c0 0-1.6-3-.2-7.7"/><path d="m44.1 36.7c2.6-2.1 6.4-3.1 7.5-3.9 1.7.2 3.2.5 3.7.3 1.7 1.1 3 2.4 3.5 2.4.1 0 .3-.1.4-.1 2.2 2.3 2.8 4.6 2.8 4.6-.4-3-1.4-4.8-2.2-5.6 0-.2 0-.5 0-.8-.2-.8-2.5-1.8-4-2.3-.1-.3-.3-.6-.5-.8-.5-.6-2.6-.4-4.3-.1-.2-.2-.5-.3-.8-.4-1.6-.5-6.8 4.4-6.8 4.4-.7 1.9.7 2.3.7 2.3"/><path d="m49.5 50.7c.1-.8-1.3-2.3-2.6-3.5 0-.3-.1-.6-.2-.9-.6-1.6-7.7-2.6-7.7-2.6-2 .7-1.3 2-1.3 2 3.2.7 6.4 3.2 7.6 3.5.9 1.5 1.6 2.8 2 3.1.2 2 0 3.9.3 4.3.1.1.2.2.4.3-.4 3.2-1.8 5.1-1.8 5.1 2.1-2.2 2.8-4.1 3-5.3.2-.1.4-.3.6-.6.5-.7-.2-3.1-.7-4.6.2-.2.3-.5.4-.8"/><path d="m56 47.8c.1-.8-1.3-2.3-2.6-3.5 0-.3-.1-.6-.2-.9-.6-1.6-7.7-2.6-7.7-2.6-2 .7-1.3 2-1.3 2 3.2.7 6.4 3.2 7.6 3.5.9 1.5 1.6 2.8 2 3.1.2 2 0 3.9.3 4.3.1.1.2.2.4.3-.4 3.2-1.8 5.1-1.8 5.1 2.1-2.2 2.8-4.1 3-5.3.2-.1.4-.3.6-.6.5-.7-.2-3.1-.7-4.6.2-.1.3-.4.4-.8"/><path d="m59.8 42.7c.1-.8-1.8-2.5-3-3.5 0-.3-.1-.6-.2-1-.3-.7-2.3-1.3-4-1.6-.2-.2-.4-.4-.6-.6-1.4-1-7.9 1.9-7.9 1.9-1.3 1.7-.1 2.4-.1 2.4 3.1-1.1 7.1-.7 8.3-1.1 1.5.8 2.8 1.5 3.3 1.6 1.2 1.6 2 3.3 2.5 3.5.1 0 .3 0 .5 0 1.3 2.9 1.1 5.3 1.1 5.3.6-3 .2-5-.2-6.1.2-.3.3-.5.3-.8"/></g><g fill="#ed4c5c"><path d="m37.9 26.6c-.8 0-1.1-1.5-1.4-1.5-.3 0-.1.8-.6 1.2-.2.2-.7.1-.9-.2-.7-.7-.4-1.8-.7-1.8-.3 0 0 1-.7 1.6-.2.2-.6.2-.8 0-.7-.6-.4-1.6-.7-1.6s-.1 1-.7 1.6c-.2.2-.6.2-.8 0-.7-.6-.4-1.6-.7-1.6-.4 0 0 1-.7 1.8-.2.2-.6.3-.9.2-.6-.4-.4-1.2-.6-1.2-.3 0-.6 1.5-1.4 1.5-6.1 0-9.1 5.4-9.1 9.9 0 5.9 6.7 17.8 15 17.8 8.3 0 15-12 15-17.8-.2-4.6-3.2-9.9-9.3-9.9"/><ellipse cx="40.4" cy="22.3" rx="3.9" ry="3.8"/></g><ellipse cx="40.4" cy="22.3" rx="3.4" ry="3.4" fill="#fcfcfa"/><path d="m42.7 22.3c0 1.3-1 2.4-2.3 2.4-1.3 0-2.3-1.1-2.3-2.4 0-1.3 1-2.4 2.3-2.4 1.3 0 2.3 1.1 2.3 2.4" fill="#3e4347"/><ellipse cx="23.6" cy="22.3" rx="3.9" ry="3.8" fill="#ed4c5c"/><ellipse cx="23.6" cy="22.3" rx="3.4" ry="3.4" fill="#fcfcfa"/><path d="m25.9 22.3c0 1.3-1 2.4-2.3 2.4-1.3 0-2.3-1.1-2.3-2.4 0-1.3 1-2.4 2.3-2.4 1.3 0 2.3 1.1 2.3 2.4" fill="#3e4347"/></svg>
|
After Width: | Height: | Size: 4 KiB |
15
include/hermit/CMakeLists.txt
Normal file
15
include/hermit/CMakeLists.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
cmake_minimum_required(VERSION 3.7)
|
||||
|
||||
configure_file(config.h.in config.h)
|
||||
configure_file(config.asm.in config.asm)
|
||||
|
||||
# Show include files in IDE
|
||||
file(GLOB_RECURSE HERMIT_INCLUDES "*")
|
||||
add_custom_target(hermit_includes_ide SOURCES ${HERMIT_INCLUDES})
|
||||
|
||||
# install generated config files when building libhermit for bootstrapping
|
||||
install(FILES
|
||||
${GENERATED_CONFIG_DIR}/hermit/config.h
|
||||
${GENERATED_CONFIG_DIR}/hermit/config.asm
|
||||
DESTINATION ${TARGET_ARCH}/include/hermit/
|
||||
COMPONENT bootstrap)
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue