Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b3fb07c4f6 |
47 changed files with 248 additions and 4903 deletions
104
Doxyfile
104
Doxyfile
|
@ -1,4 +1,4 @@
|
|||
# Doxyfile 1.8.7
|
||||
# Doxyfile 1.8.5
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
|
@ -70,25 +70,15 @@ OUTPUT_DIRECTORY = documentation/
|
|||
|
||||
CREATE_SUBDIRS = NO
|
||||
|
||||
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
|
||||
# characters to appear in the names of generated files. If set to NO, non-ASCII
|
||||
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
|
||||
# U+3044.
|
||||
# The default value is: NO.
|
||||
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
|
||||
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
|
||||
# documentation generated by doxygen is written. Doxygen will use this
|
||||
# information to generate all constant output in the proper language.
|
||||
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
|
||||
# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
|
||||
# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
|
||||
# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
|
||||
# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
|
||||
# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
|
||||
# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
|
||||
# Ukrainian and Vietnamese.
|
||||
# Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-
|
||||
# Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi,
|
||||
# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en,
|
||||
# Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish,
|
||||
# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
|
||||
# Turkish, Ukrainian and Vietnamese.
|
||||
# The default value is: English.
|
||||
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
@ -269,12 +259,9 @@ OPTIMIZE_OUTPUT_VHDL = NO
|
|||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
||||
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
|
||||
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
|
||||
# Fortran. In the later case the parser tries to guess whether the code is fixed
|
||||
# or free formatted code, this is the default for Fortran type files), VHDL. For
|
||||
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
|
||||
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
|
||||
# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
|
||||
# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
|
||||
# (default is Fortran), use: inc=Fortran f=C.
|
||||
#
|
||||
# Note For files without extension you can use no_extension as a placeholder.
|
||||
#
|
||||
|
@ -513,13 +500,6 @@ HIDE_SCOPE_NAMES = NO
|
|||
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
|
||||
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
|
||||
# grouped member an include statement to the documentation, telling the reader
|
||||
# which file to include in order to use the member.
|
||||
# The default value is: NO.
|
||||
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
|
||||
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
|
||||
# files with double quotes in the documentation rather than with sharp brackets.
|
||||
# The default value is: NO.
|
||||
|
@ -541,8 +521,7 @@ SORT_MEMBER_DOCS = YES
|
|||
|
||||
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
|
||||
# descriptions of file, namespace and class members alphabetically by member
|
||||
# name. If set to NO the members will appear in declaration order. Note that
|
||||
# this will also influence the order of the classes in the class list.
|
||||
# name. If set to NO the members will appear in declaration order.
|
||||
# The default value is: NO.
|
||||
|
||||
SORT_BRIEF_DOCS = NO
|
||||
|
@ -1178,7 +1157,7 @@ GENERATE_DOCSET = NO
|
|||
# The default value is: Doxygen generated docs.
|
||||
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||
|
||||
DOCSET_FEEDNAME = "eduOS Documentation"
|
||||
DOCSET_FEEDNAME = "MetalSVM Documentation"
|
||||
|
||||
# This tag specifies a string that should uniquely identify the documentation
|
||||
# set bundle. This should be a reverse domain-name style string, e.g.
|
||||
|
@ -1186,7 +1165,7 @@ DOCSET_FEEDNAME = "eduOS Documentation"
|
|||
# The default value is: org.doxygen.Project.
|
||||
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||
|
||||
DOCSET_BUNDLE_ID = com.github/RWTH-OS/eduOS
|
||||
DOCSET_BUNDLE_ID = org.metalsvm
|
||||
|
||||
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
|
||||
# the documentation publisher. This should be a reverse domain-name style
|
||||
|
@ -1194,13 +1173,13 @@ DOCSET_BUNDLE_ID = com.github/RWTH-OS/eduOS
|
|||
# The default value is: org.doxygen.Publisher.
|
||||
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||
|
||||
DOCSET_PUBLISHER_ID = de.rwth-aachen.eonerc
|
||||
DOCSET_PUBLISHER_ID = de.rwth-aachen.lfbs
|
||||
|
||||
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
|
||||
# The default value is: Publisher.
|
||||
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||
|
||||
DOCSET_PUBLISHER_NAME = ACS
|
||||
DOCSET_PUBLISHER_NAME = LfBS
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
||||
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
||||
|
@ -1249,8 +1228,7 @@ GENERATE_CHI = NO
|
|||
CHM_INDEX_ENCODING =
|
||||
|
||||
# The BINARY_TOC flag controls whether a binary table of contents is generated (
|
||||
# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
|
||||
# enables the Previous and Next buttons.
|
||||
# YES) or a normal table of contents ( NO) in the .chm file.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
|
||||
|
@ -1490,11 +1468,11 @@ SEARCHENGINE = YES
|
|||
|
||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
||||
# implemented using a web server instead of a web client using Javascript. There
|
||||
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
||||
# setting. When disabled, doxygen will generate a PHP script for searching and
|
||||
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
||||
# and searching needs to be provided by external tools. See the section
|
||||
# "External Indexing and Searching" for details.
|
||||
# are two flavours of web server based searching depending on the
|
||||
# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
|
||||
# searching and an index file used by the script. When EXTERNAL_SEARCH is
|
||||
# enabled the indexing and searching needs to be provided by external tools. See
|
||||
# the section "External Indexing and Searching" for details.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
|
||||
|
@ -1782,13 +1760,6 @@ MAN_OUTPUT = man
|
|||
|
||||
MAN_EXTENSION = .3
|
||||
|
||||
# The MAN_SUBDIR tag determines the name of the directory created within
|
||||
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
|
||||
# MAN_EXTENSION with the initial . removed.
|
||||
# This tag requires that the tag GENERATE_MAN is set to YES.
|
||||
|
||||
MAN_SUBDIR =
|
||||
|
||||
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
|
||||
# will generate one additional man file for each entity documented in the real
|
||||
# man page(s). These additional files only source the real man page, but without
|
||||
|
@ -1816,6 +1787,18 @@ GENERATE_XML = NO
|
|||
|
||||
XML_OUTPUT = xml
|
||||
|
||||
# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
|
||||
# validating XML parser to check the syntax of the XML files.
|
||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
||||
|
||||
XML_SCHEMA =
|
||||
|
||||
# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
|
||||
# validating XML parser to check the syntax of the XML files.
|
||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
||||
|
||||
XML_DTD =
|
||||
|
||||
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
|
||||
# listings (including syntax highlighting and cross-referencing information) to
|
||||
# the XML output. Note that enabling this will significantly increase the size
|
||||
|
@ -1964,9 +1947,9 @@ PREDEFINED = __attribute__(x)= \
|
|||
EXPAND_AS_DEFINED =
|
||||
|
||||
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
|
||||
# remove all references to function-like macros that are alone on a line, have
|
||||
# an all uppercase name, and do not end with a semicolon. Such function macros
|
||||
# are typically used for boiler-plate code, and will confuse the parser if not
|
||||
# remove all refrences to function-like macros that are alone on a line, have an
|
||||
# all uppercase name, and do not end with a semicolon. Such function macros are
|
||||
# typically used for boiler-plate code, and will confuse the parser if not
|
||||
# removed.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
@ -1986,7 +1969,7 @@ SKIP_FUNCTION_MACROS = YES
|
|||
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
|
||||
# section "Linking to external documentation" for more information about the use
|
||||
# of tag files.
|
||||
# Note: Each tag file must have a unique name (where the name does NOT include
|
||||
# Note: Each tag file must have an unique name (where the name does NOT include
|
||||
# the path). If a tag file is not located in the directory in which doxygen is
|
||||
# run, you must also specify the path to the tagfile here.
|
||||
|
||||
|
@ -2046,13 +2029,6 @@ CLASS_DIAGRAMS = YES
|
|||
|
||||
MSCGEN_PATH =
|
||||
|
||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
||||
# then run dia to produce the diagram and insert it in the documentation. The
|
||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||
# If left empty dia is assumed to be found in the default search path.
|
||||
|
||||
DIA_PATH =
|
||||
|
||||
# If set to YES, the inheritance and collaboration graphs will hide inheritance
|
||||
# and usage relations if the target is undocumented or is not a class.
|
||||
# The default value is: YES.
|
||||
|
@ -2253,12 +2229,6 @@ DOTFILE_DIRS =
|
|||
|
||||
MSCFILE_DIRS =
|
||||
|
||||
# The DIAFILE_DIRS tag can be used to specify one or more directories that
|
||||
# contain dia files that are included in the documentation (see the \diafile
|
||||
# command).
|
||||
|
||||
DIAFILE_DIRS =
|
||||
|
||||
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
|
||||
# that will be shown in the graph. If the number of nodes in a graph becomes
|
||||
# larger than this value, doxygen will truncate the graph, which is visualized
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
TERM = xterm
|
||||
TOPDIR = $(shell pwd)
|
||||
ARCH = x86
|
||||
NAME = eduos
|
||||
KERNDIRS = libkern kernel mm arch/$(ARCH)/kernel arch/$(ARCH)/mm
|
||||
KERNDIRS = libkern kernel mm arch/$(ARCH)/kernel
|
||||
SUBDIRS = $(KERNDIRS)
|
||||
|
||||
# Set your own cross compiler tool chain prefix here
|
||||
|
@ -21,26 +20,14 @@ OBJCOPY_FOR_TARGET = $(CROSSCOMPREFIX)objcopy
|
|||
RANLIB_FOR_TARGET = $(CROSSCOMPREFIX)ranlib
|
||||
STRIP_FOR_TARGET = $(CROSSCOMPREFIX)strip
|
||||
READELF_FOR_TARGET = $(CROSSCOMPREFIX)readelf
|
||||
|
||||
NASM = nasm
|
||||
NASMFLAGS = -felf32 -g -i$(TOPDIR)/include/eduos/
|
||||
GDB = $(CROSSCOMPREFIX)gdb
|
||||
GDBFLAGS = -x debug.gdb
|
||||
QEMU = qemu-system-i386
|
||||
QEMUFLAGS = -smp 2 -monitor stdio \
|
||||
-net nic,model=rtl8139 \
|
||||
-net user,hostfwd=tcp::12345-:7
|
||||
QEMUDEBUGFLAGS = -monitor none -daemonize \
|
||||
-net nic,model=rtl8139 \
|
||||
-net user,hostfwd=tcp::12345-:7
|
||||
QEMUSERIALFLAGS = -device pci-serial,chardev=tS0 \
|
||||
-chardev socket,host=localhost,port=4555,server,id=tS0
|
||||
|
||||
NASMFLAGS = -felf32 -g -i$(TOPDIR)/include/eduos/
|
||||
INCLUDE = -I$(TOPDIR)/include -I$(TOPDIR)/arch/$(ARCH)/include
|
||||
# Compiler options for final code
|
||||
CFLAGS = -g -m32 -march=i586 -Wall -O2 -fno-builtin -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc $(INCLUDE) -fno-stack-protector
|
||||
# Compiler options for debugging
|
||||
debug debug-eclipse : CFLAGS = -g -O0 -m32 -march=i586 -Wall -fno-builtin -DWITH_FRAME_POINTER -nostdinc $(INCLUDE) -fno-stack-protector
|
||||
#CFLAGS = -g -O -m32 -march=i586 -Wall -fno-builtin -DWITH_FRAME_POINTER -nostdinc $(INCLUDE) -fno-stack-protector
|
||||
AR = ar
|
||||
ARFLAGS = rsv
|
||||
RM = rm -rf
|
||||
|
@ -63,8 +50,8 @@ $(NAME).elf:
|
|||
$Q$(LD_FOR_TARGET) $(LDFLAGS) -o $(NAME).elf $^
|
||||
@echo [OBJCOPY] $(NAME).sym
|
||||
$Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $(NAME).elf $(NAME).sym
|
||||
#@echo [OBJCOPY] $(NAME).elf
|
||||
#$Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $(NAME).elf
|
||||
@echo [OBJCOPY] $(NAME).elf
|
||||
$Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $(NAME).elf
|
||||
|
||||
clean:
|
||||
$Q$(RM) $(NAME).elf $(NAME).sym *~
|
||||
|
@ -75,22 +62,14 @@ veryclean: clean
|
|||
@echo Very cleaned
|
||||
|
||||
qemu: $(NAME).elf
|
||||
$(QEMU) $(QEMUFLAGS) -kernel $(NAME).elf
|
||||
qemu-system-i386 -monitor stdio -smp 2 -net nic,model=rtl8139 -net user,hostfwd=tcp::12345-:7 -net dump -kernel $(NAME).elf
|
||||
|
||||
uart: $(NAME).elf
|
||||
$(QEMU) $(QEMUFLAGS) $(QEMUSERIALFLAGS) -kernel $(NAME).elf
|
||||
|
||||
debug: $(NAME).elf
|
||||
$(TERM) -e $(GDB) $(GDBFLAGS) &
|
||||
$(QEMU) $(QEMUDEBUGFLAGS) -s -S -kernel $(NAME).elf
|
||||
|
||||
debug-eclipse: clean $(NAME).elf
|
||||
killall $(QEMU) &
|
||||
( ( $(QEMU) $(QEMUDEBUGFLAGS) $(QEMUSERIALFLAGS) -s -S -kernel $(NAME).elf & ) & )
|
||||
qemu-dbg: $(NAME).elf
|
||||
qemu-system-i386 -monitor stdio -s -S -smp 2 -net nic,model=rtl8139 -net user,hostfwd=tcp::12345-:7 -net dump -kernel $(NAME).elf
|
||||
|
||||
doc:
|
||||
@echo Create documentation...
|
||||
@doxygen
|
||||
@echo Create documentation...
|
||||
|
||||
%.o : %.c
|
||||
@echo [CC] $@
|
||||
|
@ -112,5 +91,5 @@ include/eduos/config.inc: include/eduos/config.h
|
|||
$Q$(CC_FOR_TARGET) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
.PHONY: default all clean emu gdb newlib tools
|
||||
|
||||
|
||||
include $(addsuffix /Makefile,$(SUBDIRS))
|
||||
|
|
51
README.md
51
README.md
|
@ -1,4 +1,4 @@
|
|||
eduOS - A teaching operating system
|
||||
eduOS - A learning operating system
|
||||
===================================
|
||||
|
||||
Introduction
|
||||
|
@ -7,14 +7,14 @@ Introduction
|
|||
eduOS is a Unix-like computer operating system based on a monolithic architecture for educational purposes.
|
||||
It is derived from following tutorials and software distributions.
|
||||
|
||||
0. bkerndev - Bran's Kernel Development Tutorial
|
||||
1. bkerndev - Bran's Kernel Development Tutorial
|
||||
|
||||
The first steps to realize eduOS based on Bran's Kernel Development
|
||||
Tutorial (http://www.osdever.net/tutorials/view/brans-kernel-development-tutorial).
|
||||
In particular, the initialization of GDT, IDT and the interrupt handlers are derived
|
||||
from this tutorial.
|
||||
|
||||
1. kprintf, umoddu3, udivdi3, qdivrem, divdi3, lshrdi3, moddi3, strtol, strtoul, ucmpdi2
|
||||
2. kprintf, umoddu3, udivdi3, qdivrem, divdi3, lshrdi3, moddi3, strtol, strtoul, ucmpdi2
|
||||
|
||||
This software contains code derived from material licensed
|
||||
to the University of California by American Telephone and Telegraph
|
||||
|
@ -33,20 +33,20 @@ Requirements of eduOS
|
|||
Building eduOS
|
||||
--------------
|
||||
|
||||
0. Copy Makefile.example to Makefile and edit this Makefile to meet your individual convenience.
|
||||
1. Copy include/eduos/config.h.example to include/eduos/config.h and edit this config file to
|
||||
1. Copy Makefile.example to Makefile and edit this Makefile to meet your individual convenience.
|
||||
2. Copy include/eduos/config.h.example to include/eduos/config.h and edit this config file to
|
||||
meet your individual convenience.
|
||||
2. Build kernel with "make"
|
||||
3. Build kernel with "make"
|
||||
|
||||
Start eduOS via qemu
|
||||
--------------------
|
||||
0. Install qemu to emulate an x86 architecture
|
||||
1. Start emulator with "make qemu"
|
||||
1. Install qemu to emulate an x86 architecture
|
||||
2. Start emulator with "make qemu"
|
||||
|
||||
Boot eduOS via grub
|
||||
-------------------
|
||||
0. Copy eduos.elf as eduos.bin into the directory /boot. (cp eduos.elf /boot/eduos.bin)
|
||||
1. Create a boot entry in the grub menu. This depends on the version of grub, which is used by
|
||||
1. Copy eduos.elf as eduos.bin into the directory /boot. (cp eduos.elf /boot/eduos.bin)
|
||||
2. Create a boot entry in the grub menu. This depends on the version of grub, which is used by
|
||||
the installed Linux system. For instance, we added following lines to /boot/grub/grub.cfg:
|
||||
|
||||
<pre>
|
||||
|
@ -62,41 +62,26 @@ Boot eduOS via grub
|
|||
|
||||
Overview of all branches
|
||||
------------------------
|
||||
0. stage0 - Smallest HelloWorld of the World
|
||||
1. stage0 - Smallest HelloWorld of the World
|
||||
|
||||
Description of loading a minimal 32bit kernel
|
||||
|
||||
1. stage1 - Non-preemptive multitasking
|
||||
2. stage1 - Non-preemptive multitasking
|
||||
|
||||
Introduction into a simple form of multitasking, where no interrupts are
|
||||
required.
|
||||
|
||||
2. stage2 - Synchronisation primitives
|
||||
3. stage2 - Synchronisation primitives
|
||||
|
||||
Description of basic synchronization primitives
|
||||
|
||||
3. stage3 - Preemptive multitasking
|
||||
4. stage3 - Preemptive multitasking
|
||||
|
||||
Introduction into preemptive multitasking and interrupt handling
|
||||
|
||||
4. stage4 - Support of user-level tasks
|
||||
|
||||
Add support of user-level tasks with an small interface for basic system calls
|
||||
|
||||
5. stage5 - Enabling paging
|
||||
|
||||
Add support of paging. See http://www.noteblok.net/2014/06/14/bachelor
|
||||
for a detailed description.
|
||||
|
||||
6. stage6 - Add UART support
|
||||
|
||||
Add basic support of a serial device
|
||||
|
||||
Usefull Links
|
||||
-------------
|
||||
0. http://www.gnu.org/software/grub/manual/multiboot/
|
||||
1. http://www.osdever.net/tutorials/view/brans-kernel-development-tutorial
|
||||
2. http://www.jamesmolloy.co.uk/tutorial_html/index.html
|
||||
3. http://techblog.lankes.org/tutorials/
|
||||
4. http://www.os.rwth-aachen.de
|
||||
5. http://www.noteblok.net/2014/06/14/bachelor
|
||||
1. http://www.gnu.org/software/grub/manual/multiboot/
|
||||
2. http://www.osdever.net/tutorials/view/brans-kernel-development-tutorial
|
||||
3. http://www.jamesmolloy.co.uk/tutorial_html/index.html
|
||||
4. http://techblog.lankes.org/tutorials/
|
||||
|
|
|
@ -122,8 +122,8 @@ 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);
|
||||
inline static void atomic_int32_inc(atomic_int32_t* d) {
|
||||
asm volatile(LOCK "incl %0" : "+m" (d->counter));
|
||||
}
|
||||
|
||||
/** @brief Atomic decrement by one
|
||||
|
@ -132,8 +132,8 @@ 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);
|
||||
inline static void atomic_int32_dec(atomic_int32_t* d) {
|
||||
asm volatile(LOCK "decl %0" : "+m" (d->counter));
|
||||
}
|
||||
|
||||
/** @brief Read out an atomic_int32_t var
|
||||
|
|
|
@ -58,7 +58,7 @@ inline static void irq_disable(void) {
|
|||
*
|
||||
* @return The set of flags which have been set until now
|
||||
*/
|
||||
inline static uint8_t irq_nested_disable(void) {
|
||||
inline static uint32_t irq_nested_disable(void) {
|
||||
size_t flags;
|
||||
asm volatile("pushf; cli; pop %0": "=r"(flags) : : "memory");
|
||||
if (flags & (1 << 9))
|
||||
|
|
|
@ -41,13 +41,6 @@
|
|||
|
||||
#include <eduos/stddef.h>
|
||||
|
||||
/// Does the bootloader provide mem_* fields?
|
||||
#define MULTIBOOT_INFO_MEM (1 << 0)
|
||||
/// Does the bootloader provide a list of modules?
|
||||
#define MULTIBOOT_INFO_MODS (1 << 3)
|
||||
/// Does the bootloader provide a full memory map?
|
||||
#define MULTIBOOT_INFO_MEM_MAP (1 << 6)
|
||||
|
||||
typedef uint16_t multiboot_uint16_t;
|
||||
typedef uint32_t multiboot_uint32_t;
|
||||
typedef uint64_t multiboot_uint64_t;
|
||||
|
@ -150,8 +143,6 @@ struct multiboot_mod_list
|
|||
};
|
||||
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 multiboot_info_t* mb_info;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Steffen Vogel
|
||||
* @file arch/x86/include/asm/page.h
|
||||
* @brief Paging related functions
|
||||
*
|
||||
* This file contains the several functions to manage the page tables
|
||||
*/
|
||||
|
||||
#include <eduos/tasks_types.h>
|
||||
|
||||
#ifndef __PAGE_H__
|
||||
#define __PAGE_H__
|
||||
|
||||
/// Page offset bits
|
||||
#define PAGE_BITS 12
|
||||
/// The size of a single page in bytes
|
||||
#define PAGE_SIZE ( 1L << PAGE_BITS)
|
||||
/// Mask the page address without page map flags
|
||||
#define PAGE_MASK (-1L << PAGE_BITS)
|
||||
|
||||
/// Total operand width in bits
|
||||
#define BITS 32
|
||||
/// Linear/virtual address width
|
||||
#define VIRT_BITS BITS
|
||||
/// Physical address width (we dont support PAE)
|
||||
#define PHYS_BITS BITS
|
||||
/// Page map bits
|
||||
#define PAGE_MAP_BITS 10
|
||||
/// Number of page map indirections
|
||||
#define PAGE_LEVELS 2
|
||||
|
||||
/// Make address canonical
|
||||
#define CANONICAL(addr) (addr) // only for 32 bit paging
|
||||
|
||||
/// The number of entries in a page map table
|
||||
#define PAGE_MAP_ENTRIES (1L << PAGE_MAP_BITS)
|
||||
|
||||
/// Align to next page
|
||||
#define PAGE_FLOOR(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
|
||||
/// Align to page
|
||||
#define PAGE_CEIL(addr) ( (addr) & PAGE_MASK)
|
||||
|
||||
/// Page is present
|
||||
#define PG_PRESENT (1 << 0)
|
||||
/// Page is read- and writable
|
||||
#define PG_RW (1 << 1)
|
||||
/// Page is addressable from userspace
|
||||
#define PG_USER (1 << 2)
|
||||
/// Page write through is activated
|
||||
#define PG_PWT (1 << 3)
|
||||
/// Page cache is disabled
|
||||
#define PG_PCD (1 << 4)
|
||||
/// Page was recently accessed (set by CPU)
|
||||
#define PG_ACCESSED (1 << 5)
|
||||
/// Page is dirty due to recent write-access (set by CPU)
|
||||
#define PG_DIRTY (1 << 6)
|
||||
/// Huge page: 4MB (or 2MB, 1GB)
|
||||
#define PG_PSE (1 << 7)
|
||||
/// Page attribute table
|
||||
#define PG_PAT PG_PSE
|
||||
/// Global TLB entry (Pentium Pro and later)
|
||||
#define PG_GLOBAL (1 << 8)
|
||||
/// This table is a self-reference and should skipped by page_map_copy()
|
||||
#define PG_SELF (1 << 9)
|
||||
/// This page is used for bootstrapping the paging code.
|
||||
#define PG_BOOT PG_SELF
|
||||
|
||||
/// This page is reserved for copying
|
||||
#define PAGE_TMP (PAGE_FLOOR((size_t) &kernel_start) - PAGE_SIZE)
|
||||
|
||||
/** @brief Converts a virtual address to a physical
|
||||
*
|
||||
* A non mapped virtual address causes a pagefault!
|
||||
*
|
||||
* @param addr Virtual address to convert
|
||||
* @return physical address
|
||||
*/
|
||||
size_t page_virt_to_phys(size_t vir);
|
||||
|
||||
/** @brief Initialize paging subsystem
|
||||
*
|
||||
* This function uses the existing bootstrap page tables (boot_{pgd, pgt})
|
||||
* to map required regions (video memory, kernel, etc..).
|
||||
* Before calling page_init(), the bootstrap tables contain a simple identity
|
||||
* paging. Which is replaced by more specific mappings.
|
||||
*/
|
||||
int page_init();
|
||||
|
||||
/** @brief Map a continious region of pages
|
||||
*
|
||||
* @param viraddr
|
||||
* @param phyaddr
|
||||
* @param npages
|
||||
* @param bits
|
||||
* @return
|
||||
*/
|
||||
int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits);
|
||||
|
||||
/** @brief Unmap a continious region of pages
|
||||
*
|
||||
* @param viraddr
|
||||
* @param npages
|
||||
* @return
|
||||
*/
|
||||
int page_unmap(size_t viraddr, size_t npages);
|
||||
|
||||
/** @brief Copy a whole page map tree
|
||||
*
|
||||
* @param dest Physical address of new page map
|
||||
* @retval 0 Success. Everything went fine.
|
||||
* @retval <0 Error. Something went wrong.
|
||||
*/
|
||||
int page_map_copy(task_t *dest);
|
||||
|
||||
/** @brief Free a whole page map tree */
|
||||
int page_map_drop();
|
||||
|
||||
#endif
|
|
@ -1,82 +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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file arch/x86/include/asm/pci.h
|
||||
* @brief functions related to PCI initialization and information
|
||||
*
|
||||
* This file contains a procedure to initialize the PCI environment
|
||||
* and functions to access information about specific PCI devices.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_PCI_H__
|
||||
#define __ARCH_PCI_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint8_t slot, bus, irq;
|
||||
uint32_t base[6];
|
||||
uint32_t size[6];
|
||||
uint8_t type[6];
|
||||
} pci_info_t;
|
||||
|
||||
/** @brief Initialize the PCI environment
|
||||
*
|
||||
* return
|
||||
* - 0 on success
|
||||
*/
|
||||
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 info Pointer to the record pci_info_t where among other the IObase address will be stored
|
||||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL on failure
|
||||
*/
|
||||
int pci_get_device_info(uint32_t vendor_id, uint32_t device_id, pci_info_t* info);
|
||||
|
||||
#ifdef WITH_PCI_NAMES
|
||||
/** @brief Print information of existing pci adapters
|
||||
*
|
||||
* @return 0 in any case
|
||||
*/
|
||||
int print_pci_adapters(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -38,73 +38,11 @@
|
|||
|
||||
#include <eduos/stddef.h>
|
||||
#include <asm/gdt.h>
|
||||
#ifdef CONFIG_PCI
|
||||
#include <asm/pci.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// feature list 1
|
||||
#define CPU_FEATURE_FPU (1 << 0)
|
||||
#define CPU_FEATURE_MSR (1 << 5)
|
||||
#define CPU_FEATURE_APIC (1 << 9)
|
||||
#define CPU_FEATURE_MMX (1 << 23)
|
||||
#define CPU_FEATURE_FXSR (1 << 24)
|
||||
#define CPU_FEATURE_SSE (1 << 25)
|
||||
#define CPU_FEATURE_SSE2 (1 << 26)
|
||||
|
||||
// feature list 2
|
||||
#define CPU_FEATURE_X2APIC (1 << 21)
|
||||
#define CPU_FEATURE_AVX (1 << 28)
|
||||
#define CPU_FEATURE_HYPERVISOR (1 << 31)
|
||||
|
||||
typedef struct {
|
||||
uint32_t feature1, feature2;
|
||||
} cpu_info_t;
|
||||
|
||||
extern cpu_info_t cpu_info;
|
||||
|
||||
// determine the cpu features
|
||||
int cpu_detection(void);
|
||||
|
||||
inline static uint32_t has_fpu(void) {
|
||||
return (cpu_info.feature1 & CPU_FEATURE_FPU);
|
||||
}
|
||||
|
||||
inline static uint32_t has_msr(void) {
|
||||
return (cpu_info.feature1 & CPU_FEATURE_MSR);
|
||||
}
|
||||
|
||||
inline static uint32_t has_apic(void) {
|
||||
return (cpu_info.feature1 & CPU_FEATURE_APIC);
|
||||
}
|
||||
|
||||
inline static uint32_t has_fxsr(void) {
|
||||
return (cpu_info.feature1 & CPU_FEATURE_FXSR);
|
||||
}
|
||||
|
||||
inline static uint32_t has_sse(void) {
|
||||
return (cpu_info.feature1 & CPU_FEATURE_SSE);
|
||||
}
|
||||
|
||||
inline static uint32_t has_sse2(void) {
|
||||
return (cpu_info.feature1 & CPU_FEATURE_SSE2);
|
||||
}
|
||||
|
||||
inline static uint32_t has_x2apic(void) {
|
||||
return (cpu_info.feature2 & CPU_FEATURE_X2APIC);
|
||||
}
|
||||
|
||||
inline static uint32_t has_avx(void) {
|
||||
return (cpu_info.feature2 & CPU_FEATURE_AVX);
|
||||
}
|
||||
|
||||
inline static uint32_t on_hypervisor(void) {
|
||||
return (cpu_info.feature2 & CPU_FEATURE_HYPERVISOR);
|
||||
}
|
||||
|
||||
/** @brief Read out time stamp counter
|
||||
*
|
||||
* The rdtsc asm command puts a 64 bit time stamp value
|
||||
|
@ -119,102 +57,6 @@ inline static uint64_t rdtsc(void)
|
|||
return x;
|
||||
}
|
||||
|
||||
/** @brief Read MSR
|
||||
*
|
||||
* The asm instruction rdmsr which stands for "Read from model specific register"
|
||||
* is used here.
|
||||
*
|
||||
* @param msr The parameter which rdmsr assumes in ECX
|
||||
* @return The value rdmsr put into EDX:EAX
|
||||
*/
|
||||
inline static uint64_t rdmsr(uint32_t msr) {
|
||||
uint32_t low, high;
|
||||
|
||||
asm volatile ("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
|
||||
|
||||
return ((uint64_t)high << 32) | low;
|
||||
}
|
||||
|
||||
/** @brief Write a value to a Machine-Specific Registers (MSR)
|
||||
*
|
||||
* The asm instruction wrmsr which stands for "Write to model specific register"
|
||||
* is used here.
|
||||
*
|
||||
* @param msr The MSR identifier
|
||||
* @param value Value, which will be store in the MSR
|
||||
*/
|
||||
inline static void wrmsr(uint32_t msr, uint64_t value)
|
||||
{
|
||||
uint32_t low = value & 0xFFFFFFFF;
|
||||
uint32_t high = value >> 32;
|
||||
|
||||
asm volatile("wrmsr" :: "a"(low), "c"(msr), "d"(high));
|
||||
}
|
||||
|
||||
/** @brief Read cr0 register
|
||||
* @return cr0's value
|
||||
*/
|
||||
static inline size_t read_cr0(void) {
|
||||
size_t val;
|
||||
asm volatile("mov %%cr0, %0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
/** @brief Write a value into cr0 register
|
||||
* @param val The value you want to write into cr0
|
||||
*/
|
||||
static inline void write_cr0(size_t val) {
|
||||
asm volatile("mov %0, %%cr0" : : "r"(val));
|
||||
}
|
||||
|
||||
/** @brief Read cr2 register
|
||||
* @return cr2's value
|
||||
*/
|
||||
static inline size_t read_cr2(void) {
|
||||
size_t val;
|
||||
asm volatile("mov %%cr2, %0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
/** @brief Write a value into cr2 register
|
||||
* @param val The value you want to write into cr2
|
||||
*/
|
||||
static inline void write_cr2(size_t val) {
|
||||
asm volatile("mov %0, %%cr2" : : "r"(val));
|
||||
}
|
||||
|
||||
/** @brief Read cr3 register
|
||||
* @return cr3's value
|
||||
*/
|
||||
static inline size_t read_cr3(void) {
|
||||
size_t val;
|
||||
asm volatile("mov %%cr3, %0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
/** @brief Write a value into cr3 register
|
||||
* @param val The value you want to write into cr3
|
||||
*/
|
||||
static inline void write_cr3(size_t val) {
|
||||
asm volatile("mov %0, %%cr3" : : "r"(val));
|
||||
}
|
||||
|
||||
/** @brief Read cr4 register
|
||||
* @return cr4's value
|
||||
*/
|
||||
static inline size_t read_cr4(void) {
|
||||
size_t val;
|
||||
asm volatile("mov %%cr4, %0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
/** @brief Write a value into cr4 register
|
||||
* @param val The value you want to write into cr4
|
||||
*/
|
||||
static inline void write_cr4(size_t val) {
|
||||
asm volatile("mov %0, %%cr4" : : "r"(val));
|
||||
}
|
||||
|
||||
/** @brief Flush cache
|
||||
*
|
||||
* The wbinvd asm instruction which stands for "Write back and invalidate"
|
||||
|
@ -224,26 +66,6 @@ inline static void flush_cache(void) {
|
|||
asm volatile ("wbinvd" : : : "memory");
|
||||
}
|
||||
|
||||
/** @brief Flush Translation Lookaside Buffer
|
||||
*
|
||||
* Just reads cr3 and writes the same value back into it.
|
||||
*/
|
||||
static inline void flush_tlb(void)
|
||||
{
|
||||
size_t val = read_cr3();
|
||||
|
||||
if (val)
|
||||
write_cr3(val);
|
||||
}
|
||||
|
||||
/** @brief Flush a specific page entry in TLB
|
||||
* @param addr The (virtual) address of the page to flush
|
||||
*/
|
||||
static inline void tlb_flush_one_page(size_t addr)
|
||||
{
|
||||
asm volatile("invlpg (%0)" : : "r"(addr) : "memory");
|
||||
}
|
||||
|
||||
/** @brief Invalidate cache
|
||||
*
|
||||
* The invd asm instruction which invalidates cache without writing back
|
||||
|
@ -253,41 +75,12 @@ inline static void invalid_cache(void) {
|
|||
asm volatile ("invd");
|
||||
}
|
||||
|
||||
/* Force strict CPU ordering */
|
||||
typedef void (*func_memory_barrier)(void);
|
||||
|
||||
/// Force strict CPU ordering, serializes load and store operations.
|
||||
extern func_memory_barrier mb;
|
||||
inline static void mb(void) { asm volatile("mfence" ::: "memory"); }
|
||||
/// Force strict CPU ordering, serializes load operations.
|
||||
extern func_memory_barrier rmb;
|
||||
inline static void rmb(void) { asm volatile("lfence" ::: "memory"); }
|
||||
/// Force strict CPU ordering, serializes store operations.
|
||||
extern func_memory_barrier wmb;
|
||||
|
||||
/** @brief Read out CPU ID
|
||||
*
|
||||
* The cpuid asm-instruction does fill some information into registers and
|
||||
* this function fills those register values into the given uint32_t vars.\n
|
||||
*
|
||||
* @param code Input parameter for the cpuid instruction. Take a look into the intel manual.
|
||||
* @param a EAX value will be stores here
|
||||
* @param b EBX value will be stores here
|
||||
* @param c ECX value will be stores here
|
||||
* @param d EDX value will be stores here
|
||||
*/
|
||||
inline static void cpuid(uint32_t code, uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d) {
|
||||
asm volatile ("cpuid" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "0"(code), "2"(*c));
|
||||
}
|
||||
|
||||
/** @brief Read EFLAGS
|
||||
*
|
||||
* @return The EFLAGS value
|
||||
*/
|
||||
static inline uint32_t read_eflags(void)
|
||||
{
|
||||
uint32_t result;
|
||||
asm volatile ("pushf; pop %0" : "=r"(result));
|
||||
return result;
|
||||
}
|
||||
inline static void wmb(void) { asm volatile("sfence" ::: "memory"); }
|
||||
|
||||
/** @brief search the first most significant bit
|
||||
*
|
||||
|
@ -350,10 +143,6 @@ static inline size_t lsb(size_t i)
|
|||
inline static int system_init(void)
|
||||
{
|
||||
gdt_install();
|
||||
cpu_detection();
|
||||
#ifdef CONFIG_PCI
|
||||
pci_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 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 arch/x86/include/asm/syscall.h
|
||||
* @brief Systemcall related code
|
||||
*
|
||||
* This file defines the syscall function and convenience
|
||||
* based macro definitions for calling it.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_SYSCALL_H__
|
||||
#define __ARCH_SYSCALL_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _STR(token) #token
|
||||
#define _SYSCALLSTR(x) "int $" _STR(x) " "
|
||||
|
||||
/** @brief the syscall function which issues an interrupt to the kernel
|
||||
*
|
||||
* It's supposed to be used by the macros defined in this file as the could would read
|
||||
* cleaner then.
|
||||
*
|
||||
* @param nr System call number
|
||||
* @param arg0 Argument 0
|
||||
* @param arg1 Argument 1
|
||||
* @param arg2 Argument 2
|
||||
* @param arg3 Argument 3
|
||||
* @param arg4 Argument 4
|
||||
* @return The return value of the system call
|
||||
*/
|
||||
inline static long
|
||||
syscall(int nr, unsigned long arg0, unsigned long arg1, unsigned long arg2,
|
||||
unsigned long arg3, unsigned long arg4)
|
||||
{
|
||||
long res;
|
||||
|
||||
asm volatile (_SYSCALLSTR(INT_SYSCALL)
|
||||
: "=a" (res)
|
||||
: "0" (nr), "b" (arg0), "c" (arg1), "d" (arg2), "S" (arg3), "D" (arg4)
|
||||
: "memory", "cc");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/// System call macro with one single argument; the syscall number
|
||||
#define SYSCALL0(NR) \
|
||||
syscall(NR, 0, 0, 0, 0, 0)
|
||||
/// System call macro with system call number and one argument
|
||||
#define SYSCALL1(NR, ARG1) \
|
||||
syscall(NR, (unsigned long)ARG1, 0, 0, 0, 0)
|
||||
/// System call macro with system call number and 2 arguments
|
||||
#define SYSCALL2(NR, ARG1, ARG2) \
|
||||
syscall(NR, (unsigned long)ARG1, (unsigned long)ARG2, 0, 0, 0)
|
||||
/// System call macro with system call number and 3 arguments
|
||||
#define SYSCALL3(NR, ARG1, ARG2, ARG3) \
|
||||
syscall(NR, (unsigned long)ARG1, (unsigned long)ARG2, (unsigned long)ARG3, 0, 0)
|
||||
/// System call macro with system call number and 4 arguments
|
||||
#define SYSCALL4(NR, ARG1, ARG2, ARG3, ARG4) \
|
||||
syscall(NR, (unsigned long)ARG1, (unsigned long)ARG2, (unsigned long)ARG3, (unsigned long) ARG4, 0)
|
||||
/// System call macro with system call number and 5 arguments
|
||||
#define SYSCALL5(NR, ARG1, ARG2, ARG3, ARG4) \
|
||||
syscall(NR, (unsigned long)ARG1, (unsigned long)ARG2, (unsigned long)ARG3, (unsigned long) ARG4, (unsigned long) ARG5)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -61,36 +61,6 @@ void switch_context(size_t** stack);
|
|||
*/
|
||||
int create_default_frame(task_t* task, entry_point_t ep, void* arg);
|
||||
|
||||
/** @brief Register a task's TSS at GDT
|
||||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
*/
|
||||
static inline int register_task(void)
|
||||
{
|
||||
uint16_t sel = 5 << 3;
|
||||
|
||||
asm volatile ("ltr %%ax" : : "a"(sel));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Jump back to user code
|
||||
*
|
||||
* This function runs the user code after stopping it just as if
|
||||
* it was a return from a procedure.
|
||||
*
|
||||
* @return 0 in any case
|
||||
*/
|
||||
static inline int jump_to_user_code(uint32_t ep, uint32_t stack)
|
||||
{
|
||||
asm volatile ("mov %0, %%ds; mov %0, %%fs; mov %0, %%gs; mov %0, %%es" :: "r"(0x23));
|
||||
asm volatile ("push $0x23; push %0; push $0x1B; push %1" :: "r"(stack), "r"(ep));
|
||||
asm volatile ("lret" ::: "cc");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Stefan Lankes, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file arch/x86/include/asm/uart.h
|
||||
* @brief UART related code
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_UART_H__
|
||||
#define __ARCH_UART_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Initialize UART output
|
||||
*
|
||||
* @return Returns 0 on success
|
||||
*/
|
||||
int uart_init(void);
|
||||
|
||||
/** @brief Simple string output on a serial device.
|
||||
*
|
||||
* If you want a new line you will have to "\\n".
|
||||
*
|
||||
* @return Length of output in bytes
|
||||
*/
|
||||
int uart_puts(const char *text);
|
||||
|
||||
/** @brief Simple character output on a serial device.
|
||||
*
|
||||
* @return The original input character casted to int
|
||||
*/
|
||||
int uart_putchar(unsigned char c);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
C_source := tasks.c vga.c gdt.c irq.c idt.c isrs.c timer.c processor.c uart.c pci.c
|
||||
C_source := tasks.c multiboot.c vga.c gdt.c irq.c idt.c isrs.c timer.c processor.c
|
||||
ASM_source := entry.asm string32.asm
|
||||
MODULE := arch_x86_kernel
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
;
|
||||
; Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
; All rights reserved.
|
||||
;
|
||||
|
@ -32,20 +32,19 @@
|
|||
%include "config.inc"
|
||||
|
||||
[BITS 32]
|
||||
|
||||
; We use a special name to map this section at the begin of our kernel
|
||||
; => Multiboot expects its magic number at the beginning of the kernel.
|
||||
; => Multiboot needs its magic number at the begin of the kernel
|
||||
SECTION .mboot
|
||||
global start
|
||||
start:
|
||||
jmp stublet
|
||||
|
||||
; This part MUST be 4 byte aligned, so we solve that issue using 'ALIGN 4'.
|
||||
; This part MUST be 4byte aligned, so we solve that issue using 'ALIGN 4'
|
||||
ALIGN 4
|
||||
mboot:
|
||||
; Multiboot macros to make a few lines more readable later
|
||||
MULTIBOOT_PAGE_ALIGN equ (1 << 0)
|
||||
MULTIBOOT_MEMORY_INFO equ (1 << 1)
|
||||
MULTIBOOT_PAGE_ALIGN equ 1<<0
|
||||
MULTIBOOT_MEMORY_INFO equ 1<<1
|
||||
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
|
||||
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
|
||||
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
|
||||
|
@ -58,43 +57,37 @@ mboot:
|
|||
SECTION .text
|
||||
ALIGN 4
|
||||
stublet:
|
||||
; Initialize stack pointer
|
||||
; initialize stack pointer
|
||||
mov esp, boot_stack
|
||||
add esp, KERNEL_STACK_SIZE-16
|
||||
; Initialize CPU features
|
||||
; initialize cpu features
|
||||
call cpu_init
|
||||
; Interpret multiboot information
|
||||
mov DWORD [mb_info], ebx
|
||||
; interpret multiboot information
|
||||
extern multiboot_init
|
||||
push ebx
|
||||
call multiboot_init
|
||||
add esp, 4
|
||||
|
||||
; Jump to the boot processors's C code
|
||||
; jump to the boot processors's C code
|
||||
extern main
|
||||
call main
|
||||
jmp $
|
||||
|
||||
; 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:
|
||||
; Set CR3
|
||||
mov eax, boot_pgd
|
||||
mov cr3, eax
|
||||
|
||||
; Set CR4
|
||||
mov cr4, eax
|
||||
and eax, ~(1 << 9) ; disable SSE
|
||||
or eax, (1 << 4) ; enable PSE
|
||||
mov cr4, eax
|
||||
|
||||
; Set CR0
|
||||
mov eax, cr0
|
||||
and eax, ~(1 << 2) ; disable FPU emulation
|
||||
and eax, ~(1 << 30) ; enable caching
|
||||
or eax, (1 << 31) ; enable paging
|
||||
or eax, (1 << 5) ; enable FPU exceptions
|
||||
; enable caching, disable paging and fpu emulation
|
||||
and eax, 0x1ffffffb
|
||||
; ...and turn on FPU exceptions
|
||||
or eax, 0x22
|
||||
mov cr0, eax
|
||||
|
||||
; clears the current pgd entry
|
||||
xor eax, eax
|
||||
mov cr3, eax
|
||||
; at this stage, we disable the SSE support
|
||||
mov eax, cr4
|
||||
and eax, 0xfffbf9ff
|
||||
mov cr4, eax
|
||||
ret
|
||||
|
||||
; This will set up our new segment registers. We need to do
|
||||
|
@ -115,12 +108,12 @@ gdt_flush:
|
|||
flush2:
|
||||
ret
|
||||
|
||||
; The first 32 interrupt service routines (ISR) entries correspond to exceptions.
|
||||
; Some exceptions will push an error code onto the stack which is specific to
|
||||
; The first 32 interrupt service routines (isr) entries correspond to exceptions.
|
||||
; Some exceptions will push an error code onto the stack which is specific to
|
||||
; the exception caused. To decrease the complexity, we handle this by pushing a
|
||||
; Dummy error code of 0 onto the stack for any ISR that doesn't push an error
|
||||
; code already.
|
||||
;
|
||||
; dummy error code of 0 onto the stack for any ISR that doesn't push an error
|
||||
; code already.
|
||||
;
|
||||
; ISRs are registered as "Interrupt Gate".
|
||||
; Therefore, the interrupt flag (IF) is already cleared.
|
||||
|
||||
|
@ -143,8 +136,8 @@ flush2:
|
|||
jmp common_stub
|
||||
%endmacro
|
||||
|
||||
; Create isr entries, where the number after the
|
||||
; pseudo error code represents following interrupts:
|
||||
; create isr entries, where the number after the
|
||||
; pseudo error code represents following interrupts
|
||||
; 0: Divide By Zero Exception
|
||||
; 1: Debug Exception
|
||||
; 2: Non Maskable Interrupt Exception
|
||||
|
@ -153,10 +146,10 @@ flush2:
|
|||
; 5: Out of Bounds Exception
|
||||
; 6: Invalid Opcode Exception
|
||||
; 7: Coprocessor Not Available Exception
|
||||
%assign i 0
|
||||
%assign i 0
|
||||
%rep 8
|
||||
isrstub_pseudo_error i
|
||||
%assign i i+1
|
||||
%assign i i+1
|
||||
%endrep
|
||||
|
||||
; 8: Double Fault Exception (With Error Code!)
|
||||
|
@ -196,63 +189,24 @@ isrstub_pseudo_error 9
|
|||
jmp common_stub
|
||||
%endmacro
|
||||
|
||||
; Create entries for the interrupts 0 to 23
|
||||
; create entries for the interrupts 0 to 23
|
||||
%assign i 0
|
||||
%rep 24
|
||||
irqstub i
|
||||
%assign i i+1
|
||||
%endrep
|
||||
|
||||
; Used to realize system calls.
|
||||
; By entering the handler, the interrupt flag is not cleared.
|
||||
global isrsyscall
|
||||
isrsyscall:
|
||||
cli
|
||||
push es
|
||||
push ds
|
||||
push ebp
|
||||
push edi
|
||||
push esi
|
||||
push edx
|
||||
push ecx
|
||||
push ebx
|
||||
push eax
|
||||
|
||||
; Set kernel data segmenets
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov eax, [esp]
|
||||
sti
|
||||
|
||||
extern syscall_handler
|
||||
call syscall_handler
|
||||
|
||||
cli
|
||||
add esp, 4 ; eax contains the return value
|
||||
; => we did not restore eax
|
||||
|
||||
pop ebx
|
||||
pop ecx
|
||||
pop edx
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebp
|
||||
pop ds
|
||||
pop es
|
||||
sti
|
||||
iret
|
||||
|
||||
extern irq_handler
|
||||
extern get_current_stack
|
||||
extern finish_task_switch
|
||||
extern set_kernel_stack
|
||||
|
||||
; Create a pseudo interrupt on top of the stack.
|
||||
; Afterwards, we switch to the task with iret.
|
||||
; We already are in kernel space => no pushing of SS required.
|
||||
global switch_context
|
||||
ALIGN 4
|
||||
switch_context:
|
||||
; create on the stack a pseudo interrupt
|
||||
; afterwards, we switch to the task with iret
|
||||
; we already in kernel space => no pushing of SS required
|
||||
mov eax, [esp+4] ; on the stack is already the address to store the old esp
|
||||
pushf ; push controll register
|
||||
push DWORD 0x8 ; CS
|
||||
|
@ -278,10 +232,8 @@ common_stub:
|
|||
mov es, ax
|
||||
mov ds, ax
|
||||
|
||||
; Use the same handler for interrupts and exceptions
|
||||
; use the same handler for interrupts and exceptions
|
||||
push esp
|
||||
|
||||
extern set_kernel_stack
|
||||
call irq_handler
|
||||
add esp, 4
|
||||
|
||||
|
@ -293,15 +245,15 @@ common_switch:
|
|||
call get_current_stack ; get new esp
|
||||
xchg eax, esp
|
||||
|
||||
; Set task switched flag
|
||||
; set task switched flag
|
||||
mov eax, cr0
|
||||
or eax, 8
|
||||
mov cr0, eax
|
||||
|
||||
; Set esp0 in the task state segment
|
||||
; set esp0 in the task state segment
|
||||
call set_kernel_stack
|
||||
|
||||
; Call cleanup code
|
||||
; call cleanup code
|
||||
call finish_task_switch
|
||||
|
||||
no_context_switch:
|
||||
|
@ -311,34 +263,9 @@ no_context_switch:
|
|||
add esp, 8
|
||||
iret
|
||||
|
||||
SECTION .data
|
||||
|
||||
global mb_info:
|
||||
ALIGN 4
|
||||
mb_info:
|
||||
DD 0
|
||||
|
||||
ALIGN 4096
|
||||
global boot_stack
|
||||
boot_stack:
|
||||
TIMES (KERNEL_STACK_SIZE) DB 0xcd
|
||||
|
||||
; Bootstrap page tables are used during the initialization.
|
||||
; These tables do a simple identity paging and will
|
||||
; be replaced in page_init() by more fine-granular mappings.
|
||||
ALIGN 4096
|
||||
global boot_map
|
||||
boot_map:
|
||||
boot_pgd:
|
||||
DD boot_pgt + 0x107 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_USER
|
||||
times 1022 DD 0 ; PAGE_MAP_ENTRIES - 2
|
||||
DD boot_pgd + 0x303 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_SELF (self-reference)
|
||||
boot_pgt:
|
||||
%assign i 0
|
||||
%rep 1024 ; PAGE_MAP_ENTRIES
|
||||
DD i + 0x203 ; PG_PRESENT | PG_BOOT | PG_RW
|
||||
%assign i i + 4096 ; PAGE_SIZE
|
||||
%endrep
|
||||
boot_stack:
|
||||
TIMES (KERNEL_STACK_SIZE) DB 0xcd
|
||||
|
||||
; add some hints to the ELF file
|
||||
SECTION .note.GNU-stack noalloc noexec nowrite progbits
|
||||
|
|
|
@ -34,12 +34,11 @@
|
|||
#include <eduos/time.h>
|
||||
#include <asm/gdt.h>
|
||||
#include <asm/tss.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
gdt_ptr_t gp;
|
||||
static tss_t task_state_segment __attribute__ ((aligned (PAGE_SIZE)));
|
||||
gdt_ptr_t gp;
|
||||
static tss_t task_state_segment __attribute__ ((aligned (PAGE_SIZE)));
|
||||
// currently, our kernel has full access to the ioports
|
||||
static gdt_entry_t gdt[GDT_ENTRIES] = {[0 ... GDT_ENTRIES-1] = {0, 0, 0, 0, 0, 0}};
|
||||
static gdt_entry_t gdt[GDT_ENTRIES] = {[0 ... GDT_ENTRIES-1] = {0, 0, 0, 0, 0, 0}};
|
||||
|
||||
/*
|
||||
* This is defined in entry.asm. We use this to properly reload
|
||||
|
@ -130,8 +129,8 @@ void gdt_install(void)
|
|||
* Create data segement for userspace applications (ring 3)
|
||||
*/
|
||||
gdt_set_gate(4, 0, limit,
|
||||
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT,
|
||||
GDT_FLAG_4K_GRAN | mode);
|
||||
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT,
|
||||
GDT_FLAG_4K_GRAN | mode);
|
||||
|
||||
/* set default values */
|
||||
task_state_segment.eflags = 0x1202;
|
||||
|
|
|
@ -74,8 +74,6 @@ void idt_set_gate(unsigned char num, size_t base, unsigned short sel,
|
|||
configure_idt_entry(&idt[num], base, sel, flags);
|
||||
}
|
||||
|
||||
extern void isrsyscall(void);
|
||||
|
||||
/* Installs the IDT */
|
||||
void idt_install(void)
|
||||
{
|
||||
|
@ -89,8 +87,6 @@ void idt_install(void)
|
|||
idtp.base = (size_t)&idt;
|
||||
|
||||
/* Add any new ISRs to the IDT here using idt_set_gate */
|
||||
idt_set_gate(INT_SYSCALL, (size_t)isrsyscall, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING3|IDT_FLAG_32BIT|IDT_FLAG_TRAPGATE);
|
||||
}
|
||||
|
||||
/* Points the processor's internal register to the new IDT */
|
||||
|
|
|
@ -25,24 +25,17 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Steffen Vogel
|
||||
* @file include/memory.h
|
||||
* @brief Memory related functions
|
||||
*
|
||||
* This file contains platform independent memory functions
|
||||
#include <eduos/stddef.h>
|
||||
#include <asm/multiboot.h>
|
||||
|
||||
/*
|
||||
* eduOS is able to use Multiboot (http://www.gnu.org/software/grub/manual/multiboot/),
|
||||
* which specifies an interface between a boot loader and a operating system
|
||||
*/
|
||||
|
||||
#ifndef __MEMORY_H__
|
||||
#define __MEMORY_H__
|
||||
multiboot_info_t* mb_info __attribute__ ((section (".data"))) = NULL;
|
||||
|
||||
/** @brief Initialize the memory subsystem */
|
||||
int memory_init();
|
||||
|
||||
/** @brief Request physical page frames */
|
||||
size_t get_pages(size_t npages);
|
||||
|
||||
/** @brief release physical page frames */
|
||||
int put_pages(size_t phyaddr, size_t npages);
|
||||
|
||||
#endif
|
||||
void multiboot_init(void* mb)
|
||||
{
|
||||
mb_info = (multiboot_info_t*) mb;
|
||||
}
|
|
@ -1,224 +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 <eduos/stdio.h>
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/errno.h>
|
||||
#include <asm/irqflags.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
#include <asm/pci.h>
|
||||
#ifdef WITH_PCI_NAMES
|
||||
#include "pcihdr.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PCI configuration registers
|
||||
*/
|
||||
#define PCI_CFID 0x00 /* Configuration ID */
|
||||
#define PCI_CFCS 0x04 /* Configurtion Command/Status */
|
||||
#define PCI_CFRV 0x08 /* Configuration Revision */
|
||||
#define PCI_CFLT 0x0c /* Configuration Latency Timer */
|
||||
#define PCI_CBIO 0x10 /* Configuration Base IO Address */
|
||||
#define PCI_CFIT 0x3c /* Configuration Interrupt */
|
||||
#define PCI_CFDA 0x40 /* Configuration Driver Area */
|
||||
|
||||
#define PHYS_IO_MEM_START 0
|
||||
#define PCI_MEM 0
|
||||
#define PCI_INTA 0
|
||||
#define PCI_NSLOTS 22
|
||||
#define PCI_NBUS 0
|
||||
|
||||
#define PCI_CONF_ADDR_REG 0xcf8
|
||||
#define PCI_CONF_FRWD_REG 0xcf8
|
||||
#define PCI_CONF_DATA_REG 0xcfc
|
||||
|
||||
#define PCI_IO_CONF_START 0xc000
|
||||
|
||||
#define MAX_BUS 16
|
||||
#define MAX_SLOTS 32
|
||||
|
||||
static uint32_t mechanism = 0;
|
||||
static uint32_t adapters[MAX_BUS][MAX_SLOTS] = {[0 ... MAX_BUS-1][0 ... MAX_SLOTS-1] = -1};
|
||||
|
||||
static void pci_conf_write(uint32_t bus, uint32_t slot, uint32_t off, uint32_t val)
|
||||
{
|
||||
if (mechanism == 1) {
|
||||
outportl(PCI_CONF_FRWD_REG, bus);
|
||||
outportl(PCI_CONF_ADDR_REG, 0xf0);
|
||||
outportl(PCI_IO_CONF_START | (slot << 8) | off, val);
|
||||
} else {
|
||||
outportl(PCI_CONF_ADDR_REG, (0x80000000 | (bus << 16) | (slot << 11) | off));
|
||||
outportl(PCI_CONF_DATA_REG, val);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t pci_conf_read(uint32_t bus, uint32_t slot, uint32_t off)
|
||||
{
|
||||
uint32_t data = -1;
|
||||
|
||||
outportl(PCI_CONF_ADDR_REG, (0x80000000 | (bus << 16) | (slot << 11) | off));
|
||||
data = inportl(PCI_CONF_DATA_REG);
|
||||
|
||||
if ((data == 0xffffffff) && (slot < 0x10)) {
|
||||
outportl(PCI_CONF_FRWD_REG, bus);
|
||||
outportl(PCI_CONF_ADDR_REG, 0xf0);
|
||||
data = inportl(PCI_IO_CONF_START | (slot << 8) | off);
|
||||
if (data == 0xffffffff)
|
||||
return data;
|
||||
if (!mechanism)
|
||||
mechanism = 1;
|
||||
} else if (!mechanism)
|
||||
mechanism = 2;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline uint8_t pci_what_irq(uint32_t bus, uint32_t slot)
|
||||
{
|
||||
return pci_conf_read(bus, slot, PCI_CFIT) & 0xFF;
|
||||
}
|
||||
|
||||
static inline uint32_t pci_what_iobase(uint32_t bus, uint32_t slot, uint32_t nr)
|
||||
{
|
||||
return pci_conf_read(bus, slot, PCI_CBIO + nr*4) & 0xFFFFFFFC;
|
||||
}
|
||||
|
||||
static inline uint32_t pci_what_type(uint32_t bus, uint32_t slot, uint32_t nr)
|
||||
{
|
||||
return pci_conf_read(bus, slot, PCI_CBIO + nr*4) & 0x1;
|
||||
}
|
||||
|
||||
static inline uint32_t pci_what_size(uint32_t bus, uint32_t slot, uint32_t nr)
|
||||
{
|
||||
uint32_t tmp, ret;
|
||||
|
||||
// backup the original value
|
||||
tmp = pci_conf_read(bus, slot, PCI_CBIO + nr*4);
|
||||
|
||||
// determine size
|
||||
pci_conf_write(bus, slot, PCI_CBIO + nr*4, 0xFFFFFFFF);
|
||||
ret = ~pci_conf_read(bus, slot, PCI_CBIO + nr*4) + 1;
|
||||
|
||||
// restore original value
|
||||
pci_conf_write(bus, slot, PCI_CBIO + nr*4, tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
uint32_t slot, bus, i;
|
||||
|
||||
if (!info)
|
||||
return -EINVAL;
|
||||
|
||||
if (!mechanism)
|
||||
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)) {
|
||||
info->slot = slot;
|
||||
info->bus = bus;
|
||||
for(i=0; i<6; i++) {
|
||||
info->base[i] = pci_what_iobase(bus, slot, i);
|
||||
info->type[i] = pci_what_type(bus, slot, i);
|
||||
info->size[i] = (info->base[i]) ? pci_what_size(bus, slot, i) : 0;
|
||||
}
|
||||
info->irq = pci_what_irq(bus, slot);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef WITH_PCI_NAMES
|
||||
int print_pci_adapters(void)
|
||||
{
|
||||
uint32_t slot, bus;
|
||||
uint32_t i, counter = 0;
|
||||
|
||||
if (!mechanism)
|
||||
pci_init();
|
||||
|
||||
for (bus = 0; bus < MAX_BUS; bus++) {
|
||||
for (slot = 0; slot < MAX_SLOTS; slot++) {
|
||||
|
||||
if (adapters[bus][slot] != -1) {
|
||||
counter++;
|
||||
|
||||
kprintf("%d) Vendor ID: 0x%x Device Id: 0x%x\n",
|
||||
counter, adapters[bus][slot] & 0xffff,
|
||||
(adapters[bus][slot] & 0xffff0000) >> 16);
|
||||
|
||||
for (i=0; i<PCI_VENTABLE_LEN; i++) {
|
||||
if ((adapters[bus][slot] & 0xffff) ==
|
||||
(uint32_t)PciVenTable[i].VenId)
|
||||
kprintf("\tVendor is %s\n",
|
||||
PciVenTable[i].VenShort);
|
||||
}
|
||||
|
||||
for (i=0; i<PCI_DEVTABLE_LEN; i++) {
|
||||
if ((adapters[bus][slot] & 0xffff) ==
|
||||
(uint32_t)PciDevTable[i].VenId) {
|
||||
if (((adapters[bus][slot] & 0xffff0000) >> 16) ==
|
||||
PciDevTable[i].DevId) {
|
||||
kprintf
|
||||
("\tChip: %s ChipDesc: %s\n",
|
||||
PciDevTable[i].Chip,
|
||||
PciDevTable[i].ChipDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -32,22 +32,8 @@
|
|||
#include <eduos/processor.h>
|
||||
#include <eduos/tasks.h>
|
||||
|
||||
cpu_info_t cpu_info = { 0, 0 };
|
||||
static uint32_t cpu_freq = 0;
|
||||
|
||||
static void default_mb(void)
|
||||
{
|
||||
asm volatile ("lock; addl $0,0(%%esp)" ::: "memory", "cc");
|
||||
}
|
||||
|
||||
func_memory_barrier mb = default_mb;
|
||||
func_memory_barrier rmb = default_mb;
|
||||
func_memory_barrier wmb = default_mb;
|
||||
|
||||
static void mfence(void) { asm volatile("mfence" ::: "memory"); }
|
||||
static void lfence(void) { asm volatile("lfence" ::: "memory"); }
|
||||
static void sfence(void) { asm volatile("sfence" ::: "memory"); }
|
||||
|
||||
uint32_t detect_cpu_frequency(void)
|
||||
{
|
||||
uint64_t start, end, diff;
|
||||
|
@ -76,61 +62,6 @@ uint32_t detect_cpu_frequency(void)
|
|||
return cpu_freq;
|
||||
}
|
||||
|
||||
int cpu_detection(void) {
|
||||
uint32_t a, b;
|
||||
size_t cr4;
|
||||
uint8_t first_time = 0;
|
||||
|
||||
if (!cpu_info.feature1) {
|
||||
first_time = 1;
|
||||
cpuid(1, &a, &b, &cpu_info.feature2, &cpu_info.feature1);
|
||||
}
|
||||
|
||||
cr4 = read_cr4();
|
||||
if (has_fxsr())
|
||||
cr4 |= 0x200; // set the OSFXSR bit
|
||||
if (has_sse())
|
||||
cr4 |= 0x400; // set the OSXMMEXCPT bit
|
||||
write_cr4(cr4);
|
||||
|
||||
if (first_time && has_sse())
|
||||
wmb = sfence;
|
||||
|
||||
if (first_time && has_sse2()) {
|
||||
rmb = lfence;
|
||||
mb = mfence;
|
||||
}
|
||||
|
||||
if (first_time && has_avx())
|
||||
kprintf(
|
||||
"The CPU owns the Advanced Vector Extensions (AVX). However, eduOS doesn't support AVX!\n");
|
||||
|
||||
if (has_fpu()) {
|
||||
if (first_time)
|
||||
kputs("Found and initialized FPU!\n");
|
||||
asm volatile ("fninit");
|
||||
}
|
||||
|
||||
|
||||
if (first_time && on_hypervisor()) {
|
||||
uint32_t c, d;
|
||||
char vendor_id[13];
|
||||
|
||||
kprintf("eduOS 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);
|
||||
vendor_id[12] = '\0';
|
||||
|
||||
kprintf("Hypervisor Vendor Id: %s\n", vendor_id);
|
||||
kprintf("Maximum input value for hypervisor: 0x%x\n", a);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t get_cpu_frequency(void)
|
||||
{
|
||||
if (cpu_freq > 0)
|
||||
|
|
|
@ -36,9 +36,6 @@ size_t* get_current_stack(void)
|
|||
{
|
||||
task_t* curr_task = current_task;
|
||||
|
||||
// use new page table
|
||||
write_cr3(curr_task->page_map);
|
||||
|
||||
return curr_task->last_stack_pointer;
|
||||
}
|
||||
|
||||
|
@ -60,7 +57,7 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg)
|
|||
* and not for HW-task-switching is setting up a stack and not a TSS.
|
||||
* This is the stack which will be activated and popped off for iret later.
|
||||
*/
|
||||
stack = (size_t*) (task->stack + KERNEL_STACK_SIZE - 16); // => stack is 16byte aligned
|
||||
stack = (size_t*) (task->stack + KERNEL_STACK_SIZE - 16); // => stack is 16byte aligned
|
||||
|
||||
/* Only marker for debugging purposes, ... */
|
||||
*stack-- = 0xDEADBEEF;
|
||||
|
@ -75,6 +72,7 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg)
|
|||
* The stack must look like the stack of a task which was
|
||||
* scheduled away previously. */
|
||||
|
||||
/* In legacy modes, this push is conditional and based on a change in current privilege level (CPL).*/
|
||||
state_size = sizeof(struct state) - 2*sizeof(size_t);
|
||||
stack = (size_t*) ((size_t) stack - state_size);
|
||||
|
||||
|
@ -91,9 +89,8 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg)
|
|||
stptr->cs = 0x08;
|
||||
stptr->ds = stptr->es = 0x10;
|
||||
stptr->eflags = 0x1202;
|
||||
|
||||
// the creation of a kernel-level tasks don't change the IOPL level
|
||||
// => useresp & ss isn't required
|
||||
// the creation of a kernel tasks didn't change the IOPL level
|
||||
// => useresp & ss is not required
|
||||
|
||||
/* Set the task's stack pointer entry to the stack we have crafted right now. */
|
||||
task->last_stack_pointer = (size_t*)stack;
|
||||
|
|
|
@ -60,9 +60,9 @@ static void timer_handler(struct state *s)
|
|||
* Every TIMER_FREQ clocks (approximately 1 second), we will
|
||||
* display a message on the screen
|
||||
*/
|
||||
//if (timer_ticks % TIMER_FREQ == 0) {
|
||||
// vga_puts("One second has passed\n");
|
||||
//}
|
||||
/*if (timer_ticks % TIMER_FREQ == 0) {
|
||||
vga_puts("One second has passed\n");
|
||||
}*/
|
||||
}
|
||||
|
||||
#define LATCH(f) ((CLOCK_TICK_RATE + f/2) / f)
|
||||
|
@ -108,3 +108,4 @@ int timer_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,294 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Stefan Lankes, 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 <eduos/stdio.h>
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/mailbox.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/uart.h>
|
||||
#include <asm/irq.h>
|
||||
#ifdef CONFIG_PCI
|
||||
#include <asm/pci.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_UART
|
||||
|
||||
/*
|
||||
* This implementation based on following tutorial:
|
||||
* http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming
|
||||
*/
|
||||
|
||||
#define UART_RX 0 /* In: Receive buffer */
|
||||
#define UART_IIR 2 /* In: Interrupt ID Register */
|
||||
#define UART_TX 0 /* Out: Transmit buffer */
|
||||
#define UART_IER 1 /* Out: Interrupt Enable Register */
|
||||
#define UART_FCR 2 /* Out: FIFO Control Register */
|
||||
#define UART_MCR 4 /* Out: Modem Control Register */
|
||||
#define UART_DLL 0 /* Out: Divisor Latch Low */
|
||||
#define UART_DLM 1 /* Out: Divisor Latch High */
|
||||
#define UART_LCR 3 /* Out: Line Control Register */
|
||||
#define UART_LSR 5 /* Line Status Register */
|
||||
|
||||
#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
|
||||
#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
|
||||
#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
|
||||
#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
|
||||
|
||||
#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
|
||||
#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
|
||||
#define UART_IIR_MSI 0x00 /* Modem status interrupt */
|
||||
#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
|
||||
#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
|
||||
#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
|
||||
|
||||
#define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */
|
||||
#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
|
||||
#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
|
||||
#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
|
||||
#define UART_FCR_TRIGGER_1 0x00 /* Trigger RDI at FIFO level 1 byte */
|
||||
#define UART_FCR_TRIGGER_4 0x40 /* Trigger RDI at FIFO level 4 byte */
|
||||
#define UART_FCR_TRIGGER_8 0x80 /* Trigger RDI at FIFO level 8 byte */
|
||||
#define UART_FCR_TRIGGER_14 0xc0 /* Trigger RDI at FIFO level 14 byte*/
|
||||
|
||||
|
||||
#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
|
||||
#define UART_LCR_SBC 0x40 /* Set break control */
|
||||
#define UART_LCR_SPAR 0x20 /* Stick parity (?) */
|
||||
#define UART_LCR_EPAR 0x10 /* Even parity select */
|
||||
#define UART_LCR_PARITY 0x08 /* Parity Enable */
|
||||
#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 bit, 1=2 bits */
|
||||
#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
|
||||
|
||||
#define UART_MCR_CLKSEL 0x80 /* Divide clock by 4 (TI16C752, EFR[4]=1) */
|
||||
#define UART_MCR_TCRTLR 0x40 /* Access TCR/TLR (TI16C752, EFR[4]=1) */
|
||||
#define UART_MCR_XONANY 0x20 /* Enable Xon Any (TI16C752, EFR[4]=1) */
|
||||
#define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS (TI16C550C/TI16C750) */
|
||||
#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
|
||||
#define UART_MCR_OUT2 0x08 /* Out2 complement */
|
||||
#define UART_MCR_OUT1 0x04 /* Out1 complement */
|
||||
#define UART_MCR_RTS 0x02 /* RTS complement */
|
||||
#define UART_MCR_DTR 0x01 /* DTR complement */
|
||||
|
||||
static uint8_t mmio = 0;
|
||||
static uint32_t iobase = 0;
|
||||
static tid_t id;
|
||||
static mailbox_uint8_t input_queue;
|
||||
|
||||
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);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static void write_to_uart(uint32_t off, unsigned char c)
|
||||
{
|
||||
if (mmio)
|
||||
*((volatile unsigned char*) (iobase + off)) = c;
|
||||
else
|
||||
outportb(iobase + off, c);
|
||||
}
|
||||
|
||||
|
||||
/* Get a single character on a serial device */
|
||||
static unsigned char uart_getchar(void)
|
||||
{
|
||||
return read_from_uart(UART_RX);
|
||||
}
|
||||
|
||||
/* Puts a single character on a serial device */
|
||||
int uart_putchar(unsigned char c)
|
||||
{
|
||||
if (!iobase)
|
||||
return 0;
|
||||
|
||||
write_to_uart(UART_TX, c);
|
||||
|
||||
return (int) c;
|
||||
}
|
||||
|
||||
/* Uses the routine above to output a string... */
|
||||
int uart_puts(const char *text)
|
||||
{
|
||||
size_t i, len = strlen(text);
|
||||
|
||||
if (!iobase)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
uart_putchar(text[i]);
|
||||
|
||||
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();
|
||||
|
||||
mailbox_uint8_post(&input_queue, c);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* thread entry point => handles all incoming messages */
|
||||
static int uart_thread(void* arg)
|
||||
{
|
||||
unsigned char c = 0;
|
||||
|
||||
while(1) {
|
||||
mailbox_uint8_fetch(&input_queue, &c);
|
||||
|
||||
kputchar(c);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uart_config(void)
|
||||
{
|
||||
mailbox_uint8_init(&input_queue);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/* 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
|
||||
* no partity
|
||||
* set DLAB=1
|
||||
*/
|
||||
char lcr = UART_LCR_WLEN8;
|
||||
write_to_uart(UART_LCR, lcr);
|
||||
lcr = read_from_uart(UART_LCR) | UART_LCR_DLAB;
|
||||
write_to_uart(UART_LCR, lcr);
|
||||
|
||||
/*
|
||||
* set baudrate to 115200
|
||||
*/
|
||||
uint32_t divisor = 1843200 / 115200;
|
||||
write_to_uart(UART_DLL, divisor & 0xff);
|
||||
write_to_uart(UART_DLM, (divisor >> 8) & 0xff);
|
||||
|
||||
/* set DLAB=0 */
|
||||
write_to_uart(UART_LCR, lcr & (~UART_LCR_DLAB));
|
||||
|
||||
/* enable interrupt */
|
||||
write_to_uart(UART_IER, UART_IER_RDI | UART_IER_RLSI | UART_IER_THRI);
|
||||
|
||||
int err = create_kernel_task(&id, uart_thread, NULL, HIGH_PRIO);
|
||||
if (BUILTIN_EXPECT(err, 0))
|
||||
kprintf("Failed to create task for the uart device: %d\n", err);
|
||||
|
||||
koutput_add_uart();
|
||||
}
|
||||
|
||||
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, &pci_info) == 0)
|
||||
goto Lsuccess;
|
||||
// Searching for Qemu's UART device
|
||||
if (pci_get_device_info(0x1b36, 0x0002, &pci_info) == 0)
|
||||
goto Lsuccess;
|
||||
// Searching for Qemu's 2x UART device (pci-serial-2x)
|
||||
if (pci_get_device_info(0x1b36, 0x0003, &pci_info) == 0)
|
||||
goto Lsuccess;
|
||||
// Searching for Qemu's 4x UART device (pci-serial-4x)
|
||||
if (pci_get_device_info(0x1b36, 0x0003, &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_RW | PG_PCD);
|
||||
kprintf("UART uses mmio address 0x%x\n", iobase);
|
||||
}
|
||||
#else
|
||||
// per default we use COM1...
|
||||
mmio = 0;
|
||||
iobase = 0x3F8;
|
||||
irq_install_handler(32+4, uart_handler);
|
||||
#endif
|
||||
|
||||
// configure uart
|
||||
uart_config();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,4 +0,0 @@
|
|||
C_source := page.c
|
||||
MODULE := arch_x86_mm
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
|
@ -1,299 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a 32/64 bit portable paging implementation for the x86 architecture
|
||||
* using self-referenced page tablesi.
|
||||
* See http://www.noteblok.net/2014/06/14/bachelor/ for a detailed description.
|
||||
*
|
||||
* @author Steffen Vogel <steffen.vogel@rwth-aachen.de>
|
||||
*/
|
||||
|
||||
#include <eduos/stdio.h>
|
||||
#include <eduos/memory.h>
|
||||
#include <eduos/errno.h>
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/spinlock.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/multiboot.h>
|
||||
|
||||
/* 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;
|
||||
|
||||
/** Lock for kernel space page tables */
|
||||
static spinlock_t kslock = SPINLOCK_INIT;
|
||||
|
||||
/** This PGD table is initialized in entry.asm */
|
||||
extern size_t boot_map[PAGE_MAP_ENTRIES];
|
||||
|
||||
/** A self-reference enables direct access to all page tables */
|
||||
static size_t* self[PAGE_LEVELS] = {
|
||||
(size_t *) 0xFFC00000,
|
||||
(size_t *) 0xFFFFF000
|
||||
};
|
||||
|
||||
/** An other self-reference for page_map_copy() */
|
||||
static size_t * other[PAGE_LEVELS] = {
|
||||
(size_t *) 0xFF800000,
|
||||
(size_t *) 0xFFFFE000
|
||||
};
|
||||
|
||||
size_t page_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
|
||||
|
||||
return phy | off;
|
||||
}
|
||||
|
||||
int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits)
|
||||
{
|
||||
int lvl, ret = -ENOMEM;
|
||||
long vpn = viraddr >> PAGE_BITS;
|
||||
long first[PAGE_LEVELS], last[PAGE_LEVELS];
|
||||
|
||||
/* Calculate index boundaries for page map traversal */
|
||||
for (lvl=0; lvl<PAGE_LEVELS; lvl++) {
|
||||
first[lvl] = (vpn ) >> (lvl * PAGE_MAP_BITS);
|
||||
last[lvl] = (vpn+npages-1) >> (lvl * PAGE_MAP_BITS);
|
||||
}
|
||||
|
||||
/** @todo: might not be sufficient! */
|
||||
if (bits & PG_USER)
|
||||
spinlock_irqsave_lock(¤t_task->page_lock);
|
||||
else
|
||||
spinlock_lock(&kslock);
|
||||
|
||||
/* Start iterating through the entries
|
||||
* beginning at the root table (PGD or PML4) */
|
||||
for (lvl=PAGE_LEVELS-1; lvl>=0; lvl--) {
|
||||
for (vpn=first[lvl]; vpn<=last[lvl]; vpn++) {
|
||||
if (lvl) { /* PML4, PDPT, PGD */
|
||||
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))
|
||||
goto out;
|
||||
|
||||
if (bits & PG_USER)
|
||||
atomic_int32_inc(¤t_task->user_usage);
|
||||
|
||||
/* Reference the new table within its parent */
|
||||
self[lvl][vpn] = phyaddr | bits | PG_PRESENT;
|
||||
|
||||
/* Fill new table with zeros */
|
||||
memset(&self[lvl-1][vpn<<PAGE_MAP_BITS], 0, PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
else { /* PGT */
|
||||
if (self[lvl][vpn] & PG_PRESENT)
|
||||
/* There's already a page mapped at this address.
|
||||
* We have to flush a single TLB entry. */
|
||||
tlb_flush_one_page(vpn << PAGE_BITS);
|
||||
|
||||
self[lvl][vpn] = phyaddr | bits | PG_PRESENT;
|
||||
phyaddr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
if (bits & PG_USER)
|
||||
spinlock_irqsave_unlock(¤t_task->page_lock);
|
||||
else
|
||||
spinlock_unlock(&kslock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Tables are freed by page_map_drop() */
|
||||
int page_unmap(size_t viraddr, size_t npages)
|
||||
{
|
||||
/* We aquire both locks for kernel and task tables
|
||||
* as we dont know to which the region belongs. */
|
||||
spinlock_irqsave_lock(¤t_task->page_lock);
|
||||
spinlock_lock(&kslock);
|
||||
|
||||
/* Start iterating through the entries.
|
||||
* Only the PGT entries are removed. Tables remain allocated. */
|
||||
size_t vpn, start = viraddr>>PAGE_BITS;
|
||||
for (vpn=start; vpn<start+npages; vpn++)
|
||||
self[0][vpn] = 0;
|
||||
|
||||
spinlock_irqsave_unlock(¤t_task->page_lock);
|
||||
spinlock_unlock(&kslock);
|
||||
|
||||
/* This can't fail because we don't make checks here */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int page_map_drop()
|
||||
{
|
||||
void traverse(int lvl, long vpn) {
|
||||
long stop;
|
||||
for (stop=vpn+PAGE_MAP_ENTRIES; vpn<stop; vpn++) {
|
||||
if ((self[lvl][vpn] & PG_PRESENT) && (self[lvl][vpn] & PG_USER)) {
|
||||
/* Post-order traversal */
|
||||
if (lvl)
|
||||
traverse(lvl-1, vpn<<PAGE_MAP_BITS);
|
||||
|
||||
put_pages(self[lvl][vpn] & PAGE_MASK, 1);
|
||||
atomic_int32_dec(¤t_task->user_usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spinlock_irqsave_lock(¤t_task->page_lock);
|
||||
|
||||
traverse(PAGE_LEVELS-1, 0);
|
||||
|
||||
spinlock_irqsave_unlock(¤t_task->page_lock);
|
||||
|
||||
/* This can't fail because we don't make checks here */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int page_map_copy(task_t *dest)
|
||||
{
|
||||
int traverse(int lvl, long vpn) {
|
||||
long stop;
|
||||
for (stop=vpn+PAGE_MAP_ENTRIES; vpn<stop; vpn++) {
|
||||
if (self[lvl][vpn] & PG_PRESENT) {
|
||||
if (self[lvl][vpn] & PG_USER) {
|
||||
size_t phyaddr = get_pages(1);
|
||||
if (BUILTIN_EXPECT(!phyaddr, 0))
|
||||
return -ENOMEM;
|
||||
|
||||
atomic_int32_inc(&dest->user_usage);
|
||||
|
||||
other[lvl][vpn] = phyaddr | (self[lvl][vpn] & ~PAGE_MASK);
|
||||
if (lvl) /* PML4, PDPT, PGD */
|
||||
traverse(lvl-1, vpn<<PAGE_MAP_BITS); /* Pre-order traversal */
|
||||
else { /* PGT */
|
||||
page_map(PAGE_TMP, phyaddr, 1, PG_RW);
|
||||
memcpy((void*) PAGE_TMP, (void*) (vpn<<PAGE_BITS), PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
else if (self[lvl][vpn] & PG_SELF)
|
||||
other[lvl][vpn] = 0;
|
||||
else
|
||||
other[lvl][vpn] = self[lvl][vpn];
|
||||
}
|
||||
else
|
||||
other[lvl][vpn] = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
spinlock_irqsave_lock(¤t_task->page_lock);
|
||||
self[PAGE_LEVELS-1][PAGE_MAP_ENTRIES-2] = dest->page_map | PG_PRESENT | PG_SELF | PG_RW;
|
||||
|
||||
int ret = traverse(PAGE_LEVELS-1, 0);
|
||||
|
||||
other[PAGE_LEVELS-1][PAGE_MAP_ENTRIES-1] = dest->page_map | PG_PRESENT | PG_SELF | PG_RW;
|
||||
self [PAGE_LEVELS-1][PAGE_MAP_ENTRIES-2] = 0;
|
||||
spinlock_irqsave_unlock(¤t_task->page_lock);
|
||||
|
||||
/* Flush TLB entries of 'other' self-reference */
|
||||
flush_tlb();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void page_fault_handler(struct state *s)
|
||||
{
|
||||
size_t viraddr = read_cr2();
|
||||
|
||||
kprintf("Page Fault Exception (%d) at cs:ip = %#x:%#lx, task = %u, addr = %#lx, error = %#x [ %s %s %s %s %s ]\n",
|
||||
s->int_no, s->cs, s->eip, current_task->id, viraddr, s->error,
|
||||
(s->error & 0x4) ? "user" : "supervisor",
|
||||
(s->error & 0x10) ? "instruction" : "data",
|
||||
(s->error & 0x2) ? "write" : ((s->error & 0x10) ? "fetch" : "read"),
|
||||
(s->error & 0x1) ? "protection" : "not present",
|
||||
(s->error & 0x8) ? "reserved bit" : "\b");
|
||||
|
||||
while(1) HALT;
|
||||
}
|
||||
|
||||
int page_init()
|
||||
{
|
||||
size_t addr, npages;
|
||||
int i;
|
||||
|
||||
/* Replace default pagefault handler */
|
||||
irq_uninstall_handler(14);
|
||||
irq_install_handler(14, page_fault_handler);
|
||||
|
||||
/* Map kernel */
|
||||
addr = (size_t) &kernel_start;
|
||||
npages = PAGE_FLOOR((size_t) &kernel_end - (size_t) &kernel_start) >> PAGE_BITS;
|
||||
page_map(addr, addr, npages, PG_RW | PG_GLOBAL);
|
||||
|
||||
#ifdef CONFIG_VGA
|
||||
/* Map video memory */
|
||||
page_map(VIDEO_MEM_ADDR, VIDEO_MEM_ADDR, 1, PG_RW | PG_PCD | PG_GLOBAL);
|
||||
#endif
|
||||
|
||||
/* Map multiboot information and modules */
|
||||
if (mb_info) {
|
||||
addr = (size_t) mb_info & PAGE_MASK;
|
||||
npages = PAGE_FLOOR(sizeof(*mb_info)) >> PAGE_BITS;
|
||||
page_map(addr, addr, npages, PG_GLOBAL);
|
||||
|
||||
if (mb_info->flags & MULTIBOOT_INFO_MODS) {
|
||||
addr = mb_info->mods_addr;
|
||||
npages = PAGE_FLOOR(mb_info->mods_count*sizeof(multiboot_module_t)) >> PAGE_BITS;
|
||||
page_map(addr, addr, npages, PG_GLOBAL);
|
||||
|
||||
multiboot_module_t* mmodule = (multiboot_module_t*) ((size_t) mb_info->mods_addr);
|
||||
for(i=0; i<mb_info->mods_count; i++) {
|
||||
addr = mmodule[i].mod_start;
|
||||
npages = PAGE_FLOOR(mmodule[i].mod_end - mmodule[i].mod_start) >> PAGE_BITS;
|
||||
page_map(addr, addr, npages, PG_USER | PG_GLOBAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Unmap bootstrap identity paging (see entry.asm, PG_BOOT) */
|
||||
for (i=0; i<PAGE_MAP_ENTRIES; i++)
|
||||
if (self[0][i] & PG_BOOT)
|
||||
self[0][i] = 0;
|
||||
|
||||
/* Flush TLB to adopt changes above */
|
||||
flush_tlb();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
# Constant part of the script
|
||||
symbol-file eduos.elf
|
||||
target remote localhost:1234
|
||||
|
||||
set architecture i386
|
||||
break main
|
||||
continue
|
|
@ -11,7 +11,7 @@
|
|||
*
|
||||
* The eduOS project is hosted in a Git repository. To check it out, just type:
|
||||
*
|
||||
* \verbatim$ git clone https://github.com/RWTH-OS/eduOS.git \endverbatim
|
||||
* \verbatim$ git clone https://github.com/stlankes/eduOS.git \endverbatim
|
||||
*
|
||||
* @section compiling Compiling eduOS
|
||||
*
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
<!-- HTML footer for doxygen 1.8.7-->
|
||||
<!-- start footer part -->
|
||||
<!--BEGIN GENERATE_TREEVIEW-->
|
||||
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
||||
|
@ -6,14 +5,14 @@
|
|||
$navpath
|
||||
<li class="footer">$generatedby
|
||||
<a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
|
||||
<img class="footer" src="$relpath$doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--END GENERATE_TREEVIEW-->
|
||||
<!--BEGIN !GENERATE_TREEVIEW-->
|
||||
<hr class="footer"/><address class="footer"><small>
|
||||
$generatedby  <a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
|
||||
<img class="footer" src="$relpath$doxygen.png" alt="doxygen"/>
|
||||
</a> $doxygenversion
|
||||
</small></address>
|
||||
<!--END !GENERATE_TREEVIEW-->
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
<!-- HTML header for doxygen 1.8.7-->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||
<meta name="generator" content="Doxygen $doxygenversion"/>
|
||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
|
||||
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="$relpath^jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
||||
<link href="$relpath$tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="$relpath$jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath$dynsections.js"></script>
|
||||
$treeview
|
||||
$search
|
||||
$mathjax
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
<link href="stylesheet.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
|
@ -25,13 +22,15 @@ $extrastylesheet
|
|||
<tbody>
|
||||
<tr style="height: 56px;">
|
||||
<!--BEGIN PROJECT_LOGO-->
|
||||
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
|
||||
<td id="projectlogo">
|
||||
<div id="ostrichlogo"><img src="../img/mike_ostrich.jpg" alt="Mike Ostrich, MetalSVM's official mascot" /></div>
|
||||
<div id="lfbslogo"><img src="../img/lfbs_logo.gif" alt="Chair for Operating Systems" /></div>
|
||||
<div id="rwthlogo"><img src="../img/rwth_logo.gif" alt="RWTH Aachen University" /></div>
|
||||
</td>
|
||||
<!--END PROJECT_LOGO-->
|
||||
<!--BEGIN PROJECT_NAME-->
|
||||
<td style="padding-left: 0.5em;">
|
||||
<div id="projectname">$projectname
|
||||
<!--BEGIN PROJECT_NUMBER--> <span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
|
||||
</div>
|
||||
<div id="projectname">$projectname</div>
|
||||
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
|
||||
</td>
|
||||
<!--END PROJECT_NAME-->
|
||||
|
|
|
@ -1,34 +1,28 @@
|
|||
/* The standard CSS for doxygen 1.8.7 */
|
||||
/* The standard CSS for doxygen */
|
||||
|
||||
body, table, div, p, dl {
|
||||
font: 400 14px/22px Roboto,sans-serif;
|
||||
font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* @group Heading Levels */
|
||||
|
||||
h1.groupheader {
|
||||
h1 {
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
.title {
|
||||
font: 400 14px/28px Roboto,sans-serif;
|
||||
font-size: 150%;
|
||||
font-weight: bold;
|
||||
margin: 10px 2px;
|
||||
}
|
||||
|
||||
h2.groupheader {
|
||||
border-bottom: 1px solid #879ECB;
|
||||
color: #354C7B;
|
||||
font-size: 150%;
|
||||
font-weight: normal;
|
||||
margin-top: 1.75em;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 4px;
|
||||
width: 100%;
|
||||
h2 {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
h3.groupheader {
|
||||
h3 {
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
|
@ -56,14 +50,10 @@ div.multicol {
|
|||
-webkit-column-count: 3;
|
||||
}
|
||||
|
||||
p.startli, p.startdd {
|
||||
p.startli, p.startdd, p.starttd {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
p.starttd {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
p.endli {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
@ -145,11 +135,11 @@ a.el {
|
|||
a.elRef {
|
||||
}
|
||||
|
||||
a.code, a.code:visited, a.line, a.line:visited {
|
||||
a.code, a.code:visited {
|
||||
color: #4665A2;
|
||||
}
|
||||
|
||||
a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
|
||||
a.codeRef, a.codeRef:visited {
|
||||
color: #4665A2;
|
||||
}
|
||||
|
||||
|
@ -173,8 +163,8 @@ pre.fragment {
|
|||
}
|
||||
|
||||
div.fragment {
|
||||
padding: 4px 6px;
|
||||
margin: 4px 8px 4px 2px;
|
||||
padding: 4px;
|
||||
margin: 4px;
|
||||
background-color: #FBFCFD;
|
||||
border: 1px solid #C4CFE5;
|
||||
}
|
||||
|
@ -428,7 +418,7 @@ table.memberdecls {
|
|||
padding: 0px;
|
||||
}
|
||||
|
||||
.memberdecls td, .fieldtable tr {
|
||||
.memberdecls td {
|
||||
-webkit-transition-property: background-color, box-shadow;
|
||||
-webkit-transition-duration: 0.5s;
|
||||
-moz-transition-property: background-color, box-shadow;
|
||||
|
@ -441,7 +431,7 @@ table.memberdecls {
|
|||
transition-duration: 0.5s;
|
||||
}
|
||||
|
||||
.memberdecls td.glow, .fieldtable tr.glow {
|
||||
.memberdecls td.glow {
|
||||
background-color: cyan;
|
||||
box-shadow: 0 0 15px cyan;
|
||||
}
|
||||
|
@ -460,11 +450,8 @@ table.memberdecls {
|
|||
color: #555;
|
||||
}
|
||||
|
||||
.memSeparator {
|
||||
border-bottom: 1px solid #DEE4F0;
|
||||
line-height: 1px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
.memItemLeft, .memItemRight, .memTemplParams {
|
||||
border-top: 1px solid #C4CFE5;
|
||||
}
|
||||
|
||||
.memItemLeft, .memTemplItemLeft {
|
||||
|
@ -478,7 +465,6 @@ table.memberdecls {
|
|||
.memTemplParams {
|
||||
color: #4665A2;
|
||||
white-space: nowrap;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
@ -657,25 +643,24 @@ span.mlabel {
|
|||
border-right:1px solid #C4CFE5;
|
||||
border-bottom:1px solid #C4CFE5;
|
||||
text-shadow: none;
|
||||
color: white;
|
||||
margin-right: 4px;
|
||||
padding: 2px 3px;
|
||||
border-radius: 3px;
|
||||
font-size: 7pt;
|
||||
color: white;
|
||||
margin-right: 4px;
|
||||
padding: 2px 3px;
|
||||
border-radius: 3px;
|
||||
font-size: 7pt;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* @end */
|
||||
|
||||
/* these are for tree view inside a (index) page */
|
||||
/* these are for tree view when not used as main index */
|
||||
|
||||
div.directory {
|
||||
margin: 10px 0px;
|
||||
border-top: 1px solid #9CAFD4;
|
||||
border-bottom: 1px solid #9CAFD4;
|
||||
border-top: 1px solid #A8B8D9;
|
||||
border-bottom: 1px solid #A8B8D9;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
@ -692,7 +677,6 @@ div.directory {
|
|||
.directory td.entry {
|
||||
white-space: nowrap;
|
||||
padding-right: 6px;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.directory td.entry a {
|
||||
|
@ -707,7 +691,6 @@ div.directory {
|
|||
width: 100%;
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
padding-top: 3px;
|
||||
border-left: 1px solid rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
|
@ -734,80 +717,6 @@ div.directory {
|
|||
color: #3D578C;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
color: #9CAFD4;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
font-size: 80%;
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-family: Arial, Helvetica;
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
height: 14px;
|
||||
width: 16px;
|
||||
display: inline-block;
|
||||
background-color: #728DC1;
|
||||
color: white;
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.icona {
|
||||
width: 24px;
|
||||
height: 22px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.iconfopen {
|
||||
width: 24px;
|
||||
height: 18px;
|
||||
margin-bottom: 4px;
|
||||
background-image:url('ftv2folderopen.png');
|
||||
background-position: 0px -4px;
|
||||
background-repeat: repeat-y;
|
||||
vertical-align:top;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.iconfclosed {
|
||||
width: 24px;
|
||||
height: 18px;
|
||||
margin-bottom: 4px;
|
||||
background-image:url('ftv2folderclosed.png');
|
||||
background-position: 0px -4px;
|
||||
background-repeat: repeat-y;
|
||||
vertical-align:top;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.icondoc {
|
||||
width: 24px;
|
||||
height: 18px;
|
||||
margin-bottom: 4px;
|
||||
background-image:url('ftv2doc.png');
|
||||
background-position: 0px -4px;
|
||||
background-repeat: repeat-y;
|
||||
vertical-align:top;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
table.directory {
|
||||
font: 400 14px Roboto,sans-serif;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
div.dynheader {
|
||||
margin-top: 8px;
|
||||
-webkit-touch-callout: none;
|
||||
|
@ -843,7 +752,7 @@ table.doxtable th {
|
|||
}
|
||||
|
||||
table.fieldtable {
|
||||
/*width: 100%;*/
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid #A8B8D9;
|
||||
border-spacing: 0px;
|
||||
|
@ -866,21 +775,9 @@ table.fieldtable {
|
|||
vertical-align: top;
|
||||
}
|
||||
|
||||
.fieldtable td.fieldname {
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.fieldtable td.fielddoc {
|
||||
border-bottom: 1px solid #A8B8D9;
|
||||
/*width: 100%;*/
|
||||
}
|
||||
|
||||
.fieldtable td.fielddoc p:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.fieldtable td.fielddoc p:last-child {
|
||||
margin-bottom: 2px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.fieldtable tr:last-child td {
|
||||
|
@ -921,7 +818,6 @@ table.fieldtable {
|
|||
font-size: 11px;
|
||||
background-image:url('tab_b.png');
|
||||
background-repeat:repeat-x;
|
||||
background-position: 0 -5px;
|
||||
height:30px;
|
||||
line-height:30px;
|
||||
color:#8AA0CC;
|
||||
|
@ -949,10 +845,6 @@ table.fieldtable {
|
|||
display:block;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
color: #283A5D;
|
||||
font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
|
||||
text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.navpath li.navelem a:hover
|
||||
|
@ -1011,7 +903,7 @@ div.header
|
|||
|
||||
div.headertitle
|
||||
{
|
||||
padding: 5px 5px 5px 10px;
|
||||
padding: 5px 5px 5px 7px;
|
||||
}
|
||||
|
||||
dl
|
||||
|
@ -1086,7 +978,6 @@ dl.section dd {
|
|||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
|
||||
#projectlogo
|
||||
{
|
||||
text-align: center;
|
||||
|
@ -1098,9 +989,33 @@ dl.section dd {
|
|||
{
|
||||
border: 0px none;
|
||||
}
|
||||
|
||||
#lfbslogo
|
||||
{
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 200px;
|
||||
}
|
||||
|
||||
#rwthlogo
|
||||
{
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
#ostrichlogo
|
||||
{
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
|
||||
#projectname
|
||||
{
|
||||
position: relative;
|
||||
left: 50px;
|
||||
font: 300% Tahoma, Arial,sans-serif;
|
||||
margin: 0px;
|
||||
padding: 2px 0px;
|
||||
|
@ -1108,6 +1023,8 @@ dl.section dd {
|
|||
|
||||
#projectbrief
|
||||
{
|
||||
position: relative;
|
||||
left: 50px;
|
||||
font: 120% Tahoma, Arial,sans-serif;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
|
@ -1143,11 +1060,6 @@ dl.section dd {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.diagraph
|
||||
{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.caption
|
||||
{
|
||||
font-weight: bold;
|
||||
|
@ -1248,177 +1160,6 @@ tr.heading h2 {
|
|||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/* tooltip related style info */
|
||||
|
||||
.ttc {
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#powerTip {
|
||||
cursor: default;
|
||||
white-space: nowrap;
|
||||
background-color: white;
|
||||
border: 1px solid gray;
|
||||
border-radius: 4px 4px 4px 4px;
|
||||
box-shadow: 1px 1px 7px gray;
|
||||
display: none;
|
||||
font-size: smaller;
|
||||
max-width: 80%;
|
||||
opacity: 0.9;
|
||||
padding: 1ex 1em 1em;
|
||||
position: absolute;
|
||||
z-index: 2147483647;
|
||||
}
|
||||
|
||||
#powerTip div.ttdoc {
|
||||
color: grey;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#powerTip div.ttname a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#powerTip div.ttname {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#powerTip div.ttdeci {
|
||||
color: #006318;
|
||||
}
|
||||
|
||||
#powerTip div {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
font: 12px/16px Roboto,sans-serif;
|
||||
}
|
||||
|
||||
#powerTip:before, #powerTip:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#powerTip.n:after, #powerTip.n:before,
|
||||
#powerTip.s:after, #powerTip.s:before,
|
||||
#powerTip.w:after, #powerTip.w:before,
|
||||
#powerTip.e:after, #powerTip.e:before,
|
||||
#powerTip.ne:after, #powerTip.ne:before,
|
||||
#powerTip.se:after, #powerTip.se:before,
|
||||
#powerTip.nw:after, #powerTip.nw:before,
|
||||
#powerTip.sw:after, #powerTip.sw:before {
|
||||
border: solid transparent;
|
||||
content: " ";
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#powerTip.n:after, #powerTip.s:after,
|
||||
#powerTip.w:after, #powerTip.e:after,
|
||||
#powerTip.nw:after, #powerTip.ne:after,
|
||||
#powerTip.sw:after, #powerTip.se:after {
|
||||
border-color: rgba(255, 255, 255, 0);
|
||||
}
|
||||
|
||||
#powerTip.n:before, #powerTip.s:before,
|
||||
#powerTip.w:before, #powerTip.e:before,
|
||||
#powerTip.nw:before, #powerTip.ne:before,
|
||||
#powerTip.sw:before, #powerTip.se:before {
|
||||
border-color: rgba(128, 128, 128, 0);
|
||||
}
|
||||
|
||||
#powerTip.n:after, #powerTip.n:before,
|
||||
#powerTip.ne:after, #powerTip.ne:before,
|
||||
#powerTip.nw:after, #powerTip.nw:before {
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after {
|
||||
border-top-color: #ffffff;
|
||||
border-width: 10px;
|
||||
margin: 0px -10px;
|
||||
}
|
||||
#powerTip.n:before {
|
||||
border-top-color: #808080;
|
||||
border-width: 11px;
|
||||
margin: 0px -11px;
|
||||
}
|
||||
#powerTip.n:after, #powerTip.n:before {
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
#powerTip.nw:after, #powerTip.nw:before {
|
||||
right: 14px;
|
||||
}
|
||||
|
||||
#powerTip.ne:after, #powerTip.ne:before {
|
||||
left: 14px;
|
||||
}
|
||||
|
||||
#powerTip.s:after, #powerTip.s:before,
|
||||
#powerTip.se:after, #powerTip.se:before,
|
||||
#powerTip.sw:after, #powerTip.sw:before {
|
||||
bottom: 100%;
|
||||
}
|
||||
|
||||
#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after {
|
||||
border-bottom-color: #ffffff;
|
||||
border-width: 10px;
|
||||
margin: 0px -10px;
|
||||
}
|
||||
|
||||
#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before {
|
||||
border-bottom-color: #808080;
|
||||
border-width: 11px;
|
||||
margin: 0px -11px;
|
||||
}
|
||||
|
||||
#powerTip.s:after, #powerTip.s:before {
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
#powerTip.sw:after, #powerTip.sw:before {
|
||||
right: 14px;
|
||||
}
|
||||
|
||||
#powerTip.se:after, #powerTip.se:before {
|
||||
left: 14px;
|
||||
}
|
||||
|
||||
#powerTip.e:after, #powerTip.e:before {
|
||||
left: 100%;
|
||||
}
|
||||
#powerTip.e:after {
|
||||
border-left-color: #ffffff;
|
||||
border-width: 10px;
|
||||
top: 50%;
|
||||
margin-top: -10px;
|
||||
}
|
||||
#powerTip.e:before {
|
||||
border-left-color: #808080;
|
||||
border-width: 11px;
|
||||
top: 50%;
|
||||
margin-top: -11px;
|
||||
}
|
||||
|
||||
#powerTip.w:after, #powerTip.w:before {
|
||||
right: 100%;
|
||||
}
|
||||
#powerTip.w:after {
|
||||
border-right-color: #ffffff;
|
||||
border-width: 10px;
|
||||
top: 50%;
|
||||
margin-top: -10px;
|
||||
}
|
||||
#powerTip.w:before {
|
||||
border-right-color: #808080;
|
||||
border-width: 11px;
|
||||
top: 50%;
|
||||
margin-top: -11px;
|
||||
}
|
||||
|
||||
@media print
|
||||
{
|
||||
#top { display: none; }
|
||||
|
|
|
@ -34,21 +34,16 @@ extern "C" {
|
|||
|
||||
#define EDUOS_VERSION "0.1"
|
||||
#define MAX_TASKS 16
|
||||
#define TIMER_FREQ 100 /* in HZ */
|
||||
#define CLOCK_TICK_RATE 1193182 /* 8254 chip's internal oscillator frequency */
|
||||
#define VIDEO_MEM_ADDR 0xB8000 /* the video memory address */
|
||||
#define TIMER_FREQ 100 /* in HZ */
|
||||
#define CLOCK_TICK_RATE 1193182 /* 8254 chip's internal oscillator frequency */
|
||||
#define VIDEO_MEM_ADDR 0xB8000 // the video memora address
|
||||
#define CACHE_LINE 64
|
||||
#define KERNEL_STACK_SIZE (8<<10) /* 8 KiB */
|
||||
#define BITMAP_SIZE (128<<5) /* for 128 MiB of RAM */
|
||||
#define KMSG_SIZE (8*1024)
|
||||
#define INT_SYSCALL 0x80
|
||||
#define MAILBOX_SIZE 32
|
||||
#define KERNEL_STACK_SIZE (8*1024)
|
||||
#define PAGE_SHIFT 12
|
||||
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
#define CONFIG_VGA
|
||||
#define CONFIG_PCI
|
||||
#define CONFIG_UART
|
||||
|
||||
#define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b))
|
||||
//#define BUILTIN_EXPECT(exp, b) (exp)
|
||||
|
|
|
@ -1,142 +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.
|
||||
*/
|
||||
|
||||
#ifndef __MAILBOX_H__
|
||||
#define __MAILBOX_H__
|
||||
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/mailbox_types.h>
|
||||
#include <eduos/tasks.h>
|
||||
#include <eduos/semaphore.h>
|
||||
#include <eduos/errno.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAILBOX(name, type) \
|
||||
inline static int mailbox_##name##_init(mailbox_##name##_t* m) { \
|
||||
if (BUILTIN_EXPECT(!m, 0)) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
memset(m->buffer, 0x00, sizeof(type)*MAILBOX_SIZE); \
|
||||
m->wpos = m->rpos = 0; \
|
||||
sem_init(&m->mails, 0); \
|
||||
sem_init(&m->boxes, MAILBOX_SIZE); \
|
||||
spinlock_init(&m->rlock); \
|
||||
spinlock_init(&m->wlock); \
|
||||
\
|
||||
return 0; \
|
||||
}\
|
||||
\
|
||||
inline static int mailbox_##name##_destroy(mailbox_##name##_t* m) { \
|
||||
if (BUILTIN_EXPECT(!m, 0)) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
sem_destroy(&m->mails); \
|
||||
sem_destroy(&m->boxes); \
|
||||
spinlock_destroy(&m->rlock); \
|
||||
spinlock_destroy(&m->wlock); \
|
||||
\
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
inline static int mailbox_##name##_post(mailbox_##name##_t* m, type mail) { \
|
||||
if (BUILTIN_EXPECT(!m, 0)) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
sem_wait(&m->boxes); \
|
||||
spinlock_lock(&m->wlock); \
|
||||
m->buffer[m->wpos] = mail; \
|
||||
m->wpos = (m->wpos+1) % MAILBOX_SIZE; \
|
||||
spinlock_unlock(&m->wlock); \
|
||||
sem_post(&m->mails); \
|
||||
\
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
inline static int mailbox_##name##_trypost(mailbox_##name##_t* m, type mail) { \
|
||||
if (BUILTIN_EXPECT(!m, 0)) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
if (sem_trywait(&m->boxes)) \
|
||||
return -EBUSY; \
|
||||
spinlock_lock(&m->wlock); \
|
||||
m->buffer[m->wpos] = mail; \
|
||||
m->wpos = (m->wpos+1) % MAILBOX_SIZE; \
|
||||
spinlock_unlock(&m->wlock); \
|
||||
sem_post(&m->mails); \
|
||||
\
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
inline static int mailbox_##name##_fetch(mailbox_##name##_t* m, type* mail) { \
|
||||
int err; \
|
||||
\
|
||||
if (BUILTIN_EXPECT(!m || !mail, 0)) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
err = sem_wait(&m->mails); \
|
||||
if (err) return err; \
|
||||
spinlock_lock(&m->rlock); \
|
||||
*mail = m->buffer[m->rpos]; \
|
||||
m->rpos = (m->rpos+1) % MAILBOX_SIZE; \
|
||||
spinlock_unlock(&m->rlock); \
|
||||
sem_post(&m->boxes); \
|
||||
\
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
inline static int mailbox_##name##_tryfetch(mailbox_##name##_t* m, type* mail) { \
|
||||
if (BUILTIN_EXPECT(!m || !mail, 0)) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
if (sem_trywait(&m->mails) != 0) \
|
||||
return -EINVAL; \
|
||||
spinlock_lock(&m->rlock); \
|
||||
*mail = m->buffer[m->rpos]; \
|
||||
m->rpos = (m->rpos+1) % MAILBOX_SIZE; \
|
||||
spinlock_unlock(&m->rlock); \
|
||||
sem_post(&m->boxes); \
|
||||
\
|
||||
return 0; \
|
||||
}\
|
||||
|
||||
MAILBOX(wait_msg, wait_msg_t)
|
||||
MAILBOX(int32, int32_t)
|
||||
MAILBOX(int16, int16_t)
|
||||
MAILBOX(int8, int8_t)
|
||||
MAILBOX(uint32, uint32_t)
|
||||
MAILBOX(uint16, uint16_t)
|
||||
MAILBOX(uint8, uint8_t)
|
||||
MAILBOX(ptr, void*)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,75 +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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file include/metalsvm/mailbox_types.h
|
||||
* @brief Mailbox system for inter-task communication
|
||||
*/
|
||||
|
||||
#ifndef __MAILBOX_TYPES_H__
|
||||
#define __MAILBOX_TYPES_H__
|
||||
|
||||
#include <eduos/semaphore_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Wait message structure
|
||||
*
|
||||
* This message struct keeps a recipient task id and the message itself */
|
||||
typedef struct {
|
||||
/// The task id of the task which is waiting for this message
|
||||
tid_t id;
|
||||
/// The message payload
|
||||
int32_t result;
|
||||
} wait_msg_t;
|
||||
|
||||
#define MAILBOX_TYPES(name, type) \
|
||||
typedef struct mailbox_##name { \
|
||||
type buffer[MAILBOX_SIZE]; \
|
||||
int wpos, rpos; \
|
||||
sem_t mails; \
|
||||
sem_t boxes; \
|
||||
spinlock_t rlock, wlock; \
|
||||
} mailbox_##name##_t;
|
||||
|
||||
MAILBOX_TYPES(wait_msg, wait_msg_t)
|
||||
MAILBOX_TYPES(int32, int32_t)
|
||||
MAILBOX_TYPES(int16, int16_t)
|
||||
MAILBOX_TYPES(int8, int8_t)
|
||||
MAILBOX_TYPES(uint32, uint32_t)
|
||||
MAILBOX_TYPES(uint16, uint16_t)
|
||||
MAILBOX_TYPES(uint8, uint8_t)
|
||||
MAILBOX_TYPES(ptr, void*)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -35,7 +35,6 @@
|
|||
#define __SEMAPHORE_H__
|
||||
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/tasks.h>
|
||||
#include <eduos/semaphore_types.h>
|
||||
#include <eduos/spinlock.h>
|
||||
#include <eduos/errno.h>
|
||||
|
|
|
@ -46,6 +46,10 @@ extern "C" {
|
|||
/// represents a task identifier
|
||||
typedef unsigned int tid_t;
|
||||
|
||||
#define PAGE_SIZE (1 << PAGE_SHIFT)
|
||||
#define PAGE_MASK ~(PAGE_SIZE - 1)
|
||||
#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
|
||||
|
||||
struct task;
|
||||
/// pointer to the current (running) task
|
||||
extern struct task* current_task;
|
||||
|
|
|
@ -62,26 +62,11 @@ int kprintf(const char*, ...);
|
|||
*/
|
||||
int koutput_init(void);
|
||||
|
||||
/**
|
||||
* Works like the ANSI c function sprintf
|
||||
*/
|
||||
int ksprintf(char *str, const char *format, ...);
|
||||
|
||||
/**
|
||||
* Works like the ANSI c function sprintf
|
||||
*/
|
||||
int ksnprintf(char *str, size_t size, const char *format, ...);
|
||||
|
||||
/**
|
||||
* Scaled down version of printf(3)
|
||||
*/
|
||||
int kvprintf(char const *fmt, void (*func) (int, void *), void *arg, int radix, va_list ap);
|
||||
|
||||
/**
|
||||
* Add UART device to dump kernel messages
|
||||
*/
|
||||
int koutput_add_uart(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 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/eduos/syscall.h
|
||||
* @brief System call number definitions
|
||||
*
|
||||
* This file contains define constants for every syscall's number.
|
||||
*/
|
||||
|
||||
#ifndef __SYSCALL_H__
|
||||
#define __SYSCALL_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
#include <asm/syscall.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define __NR_exit 0
|
||||
#define __NR_write 1
|
||||
#define __NR_open 2
|
||||
#define __NR_close 3
|
||||
#define __NR_read 4
|
||||
#define __NR_lseek 6
|
||||
#define __NR_unlink 7
|
||||
#define __NR_getpid 8
|
||||
#define __NR_kill 9
|
||||
#define __NR_fstat 10
|
||||
#define __NR_sbrk 11
|
||||
#define __NR_fork 12
|
||||
#define __NR_wait 13
|
||||
#define __NR_execve 14
|
||||
#define __NR_times 15
|
||||
#define __NR_accept 16
|
||||
#define __NR_bind 17
|
||||
#define __NR_closesocket 18
|
||||
#define __NR_connect 19
|
||||
#define __NR_listen 20
|
||||
#define __NR_recv 21
|
||||
#define __NR_send 22
|
||||
#define __NR_socket 23
|
||||
#define __NR_getsockopt 24
|
||||
#define __NR_setsockopt 25
|
||||
#define __NR_gethostbyname 26
|
||||
#define __NR_sendto 27
|
||||
#define __NR_recvfrom 28
|
||||
#define __NR_select 29
|
||||
#define __NR_stat 30
|
||||
#define __NR_dup 31
|
||||
#define __NR_dup2 32
|
||||
#define __NR_clone 33
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -44,9 +44,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief System call to terminate a user level process */
|
||||
void NORETURN sys_exit(int);
|
||||
|
||||
/** @brief Task switcher
|
||||
*
|
||||
* Timer-interrupted use of this function for task switching
|
||||
|
@ -68,7 +65,7 @@ size_t** scheduler(void);
|
|||
*/
|
||||
int multitasking_init(void);
|
||||
|
||||
/** @brief create a kernel-level task.
|
||||
/** @brief create a kernel task.
|
||||
*
|
||||
* @param id The value behind this pointer will be set to the new task's id
|
||||
* @param ep Pointer to the entry function for the new task
|
||||
|
@ -118,12 +115,9 @@ int block_current_task(void);
|
|||
/** @brief Abort current task */
|
||||
void NORETURN abort(void);
|
||||
|
||||
/** @brief This function shall be called by leaving kernel-level tasks */
|
||||
/** @brief This function shall be called by leaving kernel level tasks */
|
||||
void NORETURN leave_kernel_task(void);
|
||||
|
||||
/** @brief This function shall be called by leaving user-level tasks */
|
||||
void NORETURN leave_user_task(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -39,9 +39,7 @@
|
|||
|
||||
#include <eduos/stddef.h>
|
||||
#include <eduos/spinlock_types.h>
|
||||
|
||||
#include <asm/tasks_types.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -75,12 +73,6 @@ typedef struct task {
|
|||
void* stack;
|
||||
/// Task priority
|
||||
uint8_t prio;
|
||||
/// Physical address of root page table
|
||||
size_t page_map;
|
||||
/// Lock for page tables
|
||||
spinlock_irqsave_t page_lock;
|
||||
/// usage in number of pages (including page map tables)
|
||||
atomic_int32_t user_usage;
|
||||
/// next task in the queue
|
||||
struct task* next;
|
||||
/// previous task in the queue
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
C_source := main.c tasks.c syscall.c
|
||||
C_source := main.c tasks.c
|
||||
MODULE := kernel
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
||||
|
|
|
@ -32,16 +32,11 @@
|
|||
#include <eduos/tasks.h>
|
||||
#include <eduos/processor.h>
|
||||
#include <eduos/tasks.h>
|
||||
#include <eduos/syscall.h>
|
||||
#include <eduos/memory.h>
|
||||
|
||||
#include <eduos/semaphore.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/irqflags.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/uart.h>
|
||||
|
||||
/*
|
||||
/*
|
||||
* Note that linker symbols are not variables, they have no memory allocated for
|
||||
* maintaining a value, rather their address is their value.
|
||||
*/
|
||||
|
@ -52,49 +47,7 @@ extern const void bss_end;
|
|||
extern char __BUILD_DATE;
|
||||
extern char __BUILD_TIME;
|
||||
|
||||
/* Page frame counters */
|
||||
extern atomic_int32_t total_pages;
|
||||
extern atomic_int32_t total_allocated_pages;
|
||||
extern atomic_int32_t total_available_pages;
|
||||
|
||||
static void NORETURN userfoo(void* arg)
|
||||
{
|
||||
|
||||
SYSCALL1(__NR_write, "hello from userfoo\n");
|
||||
SYSCALL1(__NR_exit, 0);
|
||||
|
||||
while(1) ;
|
||||
}
|
||||
|
||||
static char ustack[KERNEL_STACK_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
|
||||
|
||||
static int wrapper(void* arg)
|
||||
{
|
||||
size_t* stack = (size_t*) (ustack+KERNEL_STACK_SIZE-16);
|
||||
|
||||
memset(ustack, 0xCD, KERNEL_STACK_SIZE);
|
||||
*stack-- = (size_t) arg;
|
||||
*stack = (size_t) NULL; // put exit function as caller on the stack
|
||||
|
||||
#if 0
|
||||
// this triggers a page fault because a user task is not able to access the kernel space
|
||||
return jump_to_user_code((uint32_t) userfoo, (uint32_t) stack);
|
||||
#else
|
||||
// dirty hack, map userfoo to the user space
|
||||
size_t phys = page_virt_to_phys(((size_t) userfoo) & PAGE_MASK);
|
||||
size_t vuserfoo = 0x40000000;
|
||||
page_map(vuserfoo, phys, 2, PG_PRESENT | PG_USER);
|
||||
vuserfoo += (size_t)userfoo & 0xFFF;
|
||||
|
||||
// dirty hack, map ustack to the user space
|
||||
phys = page_virt_to_phys((size_t) ustack);
|
||||
size_t vstack = 0x80000000;
|
||||
page_map(vstack, phys, KERNEL_STACK_SIZE >> PAGE_BITS, PG_PRESENT | PG_RW | PG_USER);
|
||||
vstack = (vstack + KERNEL_STACK_SIZE - 16 - sizeof(size_t));
|
||||
|
||||
return jump_to_user_code(vuserfoo, vstack);
|
||||
#endif
|
||||
}
|
||||
static sem_t sem;
|
||||
|
||||
static int foo(void* arg)
|
||||
{
|
||||
|
@ -104,11 +57,6 @@ static int foo(void* arg)
|
|||
kprintf("hello from %s\n", (char*) arg);
|
||||
}
|
||||
|
||||
// demo of an exception
|
||||
/*i = 0;
|
||||
i = 32 / i;
|
||||
kprintf("i = %d\n", i);*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -117,15 +65,11 @@ static int eduos_init(void)
|
|||
// initialize .bss section
|
||||
memset((void*)&bss_start, 0x00, ((size_t) &bss_end - (size_t) &bss_start));
|
||||
|
||||
koutput_init();
|
||||
system_init();
|
||||
irq_init();
|
||||
timer_init();
|
||||
koutput_init();
|
||||
multitasking_init();
|
||||
memory_init();
|
||||
#ifdef CONFIG_UART
|
||||
uart_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -134,20 +78,19 @@ int main(void)
|
|||
{
|
||||
tid_t id1;
|
||||
tid_t id2;
|
||||
|
||||
eduos_init();
|
||||
irq_enable();
|
||||
system_calibration();
|
||||
|
||||
kprintf("This is eduOS %s Build %u, %u\n", EDUOS_VERSION, &__BUILD_DATE, &__BUILD_TIME);
|
||||
kprintf("Kernel starts at %p and ends at %p\n", &kernel_start, &kernel_end);
|
||||
|
||||
irq_enable();
|
||||
system_calibration();
|
||||
|
||||
kprintf("Processor frequency: %u MHz\n", get_cpu_frequency());
|
||||
kprintf("Total memory: %lu KiB\n", atomic_int32_read(&total_pages) * PAGE_SIZE / 1024);
|
||||
kprintf("Total memory available: %lu KiB\n", atomic_int32_read(&total_available_pages) * PAGE_SIZE / 1024);
|
||||
|
||||
|
||||
|
||||
sem_init(&sem, 1);
|
||||
create_kernel_task(&id1, foo, "foo1", NORMAL_PRIO);
|
||||
create_kernel_task(&id2, wrapper, "userfoo", NORMAL_PRIO);
|
||||
create_kernel_task(&id2, foo, "foo2", NORMAL_PRIO);
|
||||
|
||||
while(1) {
|
||||
HALT;
|
||||
|
|
|
@ -1,66 +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 <eduos/stddef.h>
|
||||
#include <eduos/stdio.h>
|
||||
#include <eduos/tasks.h>
|
||||
#include <eduos/errno.h>
|
||||
#include <eduos/syscall.h>
|
||||
|
||||
static int sys_write(const char* buff)
|
||||
{
|
||||
kputs(buff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int syscall_handler(uint32_t sys_nr, ...)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
va_list vl;
|
||||
|
||||
va_start(vl, sys_nr);
|
||||
|
||||
switch(sys_nr)
|
||||
{
|
||||
case __NR_exit:
|
||||
sys_exit(va_arg(vl, uint32_t));
|
||||
ret = 0;
|
||||
break;
|
||||
case __NR_write:
|
||||
ret = sys_write(va_arg(vl, const char*));
|
||||
break;
|
||||
default:
|
||||
kputs("invalid system call\n");
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
};
|
||||
|
||||
va_end(vl);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -28,23 +28,18 @@
|
|||
#include <eduos/stddef.h>
|
||||
#include <eduos/stdlib.h>
|
||||
#include <eduos/stdio.h>
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/tasks.h>
|
||||
#include <eduos/tasks_types.h>
|
||||
#include <eduos/spinlock.h>
|
||||
#include <eduos/errno.h>
|
||||
#include <eduos/syscall.h>
|
||||
#include <eduos/memory.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
/** @brief Array of task structures (aka PCB)
|
||||
*
|
||||
* A task's id will be its position in this array.
|
||||
*/
|
||||
static task_t task_table[MAX_TASKS] = { \
|
||||
[0] = {0, TASK_IDLE, NULL, NULL, 0, 0, SPINLOCK_IRQSAVE_INIT, ATOMIC_INIT(0), NULL, NULL}, \
|
||||
[1 ... MAX_TASKS-1] = {0, TASK_INVALID, NULL, NULL, 0, 0, SPINLOCK_IRQSAVE_INIT, ATOMIC_INIT(0), NULL, NULL}};
|
||||
[0] = {0, TASK_IDLE, NULL, NULL, 0, NULL, NULL}, \
|
||||
[1 ... MAX_TASKS-1] = {0, TASK_INVALID, NULL, NULL, 0, NULL, NULL}};
|
||||
|
||||
static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT;
|
||||
|
||||
|
@ -56,7 +51,7 @@ extern const void boot_stack;
|
|||
/** @brief helper function for the assembly code to determine the current task
|
||||
* @return Pointer to the task_t structure of current task
|
||||
*/
|
||||
task_t* get_current_task(void)
|
||||
task_t* get_current_task(void)
|
||||
{
|
||||
return current_task;
|
||||
}
|
||||
|
@ -75,10 +70,6 @@ int multitasking_init(void)
|
|||
|
||||
task_table[0].prio = IDLE_PRIO;
|
||||
task_table[0].stack = (void*) &boot_stack;
|
||||
task_table[0].page_map = read_cr3();
|
||||
|
||||
// register idle task
|
||||
register_task();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -122,16 +113,14 @@ static void NORETURN do_exit(int arg)
|
|||
|
||||
kprintf("Terminate task: %u, return value %d\n", curr_task->id, arg);
|
||||
|
||||
page_map_drop();
|
||||
curr_task->status = TASK_FINISHED;
|
||||
reschedule();
|
||||
|
||||
// decrease the number of active tasks
|
||||
spinlock_irqsave_lock(&readyqueues.lock);
|
||||
readyqueues.nr_tasks--;
|
||||
spinlock_irqsave_unlock(&readyqueues.lock);
|
||||
|
||||
curr_task->status = TASK_FINISHED;
|
||||
reschedule();
|
||||
|
||||
kprintf("Kernel panic: scheduler found no valid task\n");
|
||||
while(1) {
|
||||
HALT;
|
||||
|
@ -146,28 +135,12 @@ void NORETURN leave_kernel_task(void) {
|
|||
do_exit(result);
|
||||
}
|
||||
|
||||
/** @brief This function shall be called by leaving user-level tasks */
|
||||
void NORETURN leave_user_task(void)
|
||||
{
|
||||
SYSCALL1(__NR_exit, 0);
|
||||
|
||||
// this point should never reached
|
||||
while(1) {}
|
||||
}
|
||||
|
||||
/** @brief To be called by the systemcall to exit tasks */
|
||||
void NORETURN sys_exit(int arg) {
|
||||
do_exit(arg);
|
||||
}
|
||||
|
||||
/** @brief Aborting a task is like exiting it with result -1 */
|
||||
void NORETURN abort(void) {
|
||||
do_exit(-1);
|
||||
}
|
||||
|
||||
/** @brief Create a task with a specific entry point
|
||||
*
|
||||
* @todo Dont aquire table_lock for the whole task creation.
|
||||
*
|
||||
* @param id Pointer to a tid_t struct were the id shall be set
|
||||
* @param ep Pointer to the function the task shall start with
|
||||
|
@ -201,17 +174,6 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg, uint8_t prio)
|
|||
task_table[i].stack = create_stack(i);
|
||||
task_table[i].prio = prio;
|
||||
|
||||
spinlock_irqsave_init(&task_table[i].page_lock);
|
||||
atomic_int32_set(&task_table[i].user_usage, 0);
|
||||
|
||||
/* Allocated new PGD or PML4 and copy page table */
|
||||
task_table[i].page_map = get_pages(1);
|
||||
if (BUILTIN_EXPECT(!task_table[i].page_map, 0))
|
||||
goto out;
|
||||
|
||||
/* Copy page tables & user frames of current task to new one */
|
||||
page_map_copy(&task_table[i]);
|
||||
|
||||
if (id)
|
||||
*id = i;
|
||||
|
||||
|
@ -236,7 +198,6 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg, uint8_t prio)
|
|||
}
|
||||
}
|
||||
|
||||
out:
|
||||
spinlock_irqsave_unlock(&table_lock);
|
||||
|
||||
return ret;
|
||||
|
@ -286,7 +247,7 @@ int wakeup_task(tid_t id)
|
|||
task->next = NULL;
|
||||
readyqueues.queue[prio-1].last->next = task;
|
||||
readyqueues.queue[prio-1].last = task;
|
||||
}
|
||||
}
|
||||
spinlock_irqsave_unlock(&readyqueues.lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
C_source := string.c stdio.c printf.c sprintf.c moddi3.c umoddi3.c divdi3.c udivdi3.c qdivrem.c
|
||||
C_source := string.c stdio.c printf.c moddi3.c umoddi3.c divdi3.c udivdi3.c qdivrem.c
|
||||
MODULE := libkern
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
||||
|
|
|
@ -1,82 +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 <eduos/stdio.h>
|
||||
|
||||
typedef struct {
|
||||
char *str;
|
||||
size_t pos;
|
||||
size_t max;
|
||||
} sputchar_arg_t;
|
||||
|
||||
static void sputchar(int c, void *arg)
|
||||
{
|
||||
sputchar_arg_t *dest = (sputchar_arg_t *) arg;
|
||||
|
||||
if (dest->pos < dest->max) {
|
||||
dest->str[dest->pos] = (char)c;
|
||||
dest->pos++;
|
||||
}
|
||||
}
|
||||
|
||||
int ksnprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
sputchar_arg_t dest;
|
||||
|
||||
dest.str = str;
|
||||
dest.pos = 0;
|
||||
dest.max = size;
|
||||
|
||||
va_start(ap, format);
|
||||
ret = kvprintf(format, sputchar, &dest, 10, ap);
|
||||
va_end(ap);
|
||||
|
||||
str[ret] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ksprintf(char *str, const char *format, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
sputchar_arg_t dest;
|
||||
|
||||
dest.str = str;
|
||||
dest.pos = 0;
|
||||
dest.max = (size_t) -1;
|
||||
|
||||
va_start(ap, format);
|
||||
ret = kvprintf(format, sputchar, &dest, 10, ap);
|
||||
va_end(ap);
|
||||
|
||||
str[ret] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -29,27 +29,9 @@
|
|||
#include <eduos/string.h>
|
||||
#include <eduos/stdarg.h>
|
||||
#include <eduos/spinlock.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/processor.h>
|
||||
#ifdef CONFIG_VGA
|
||||
#include <asm/vga.h>
|
||||
#endif
|
||||
#ifdef CONFIG_UART
|
||||
#include <asm/uart.h>
|
||||
#endif
|
||||
|
||||
#define NO_EARLY_PRINT 0x00
|
||||
#define VGA_EARLY_PRINT 0x01
|
||||
#define UART_EARLY_PRINT 0x02
|
||||
|
||||
#ifdef CONFIG_VGA
|
||||
static uint32_t early_print = VGA_EARLY_PRINT;
|
||||
#else
|
||||
static uint32_t early_print = NO_EARLY_PRINT;
|
||||
#endif
|
||||
static spinlock_irqsave_t olock = SPINLOCK_IRQSAVE_INIT;
|
||||
static atomic_int32_t kmsg_counter = ATOMIC_INIT(0);
|
||||
static unsigned char kmessages[KMSG_SIZE] __attribute__ ((section(".kmsg"))) = {[0 ... KMSG_SIZE-1] = 0x00};
|
||||
|
||||
int koutput_init(void)
|
||||
{
|
||||
|
@ -62,67 +44,23 @@ int koutput_init(void)
|
|||
|
||||
int kputchar(int c)
|
||||
{
|
||||
int pos;
|
||||
|
||||
if (early_print != NO_EARLY_PRINT)
|
||||
spinlock_irqsave_lock(&olock);
|
||||
|
||||
pos = atomic_int32_inc(&kmsg_counter);
|
||||
kmessages[pos % KMSG_SIZE] = (unsigned char) c;
|
||||
|
||||
spinlock_irqsave_lock(&olock);
|
||||
#ifdef CONFIG_VGA
|
||||
if (early_print & VGA_EARLY_PRINT)
|
||||
vga_putchar(c);
|
||||
vga_putchar(c);
|
||||
#endif
|
||||
#ifdef CONFIG_UART
|
||||
if (early_print & UART_EARLY_PRINT)
|
||||
uart_putchar(c);
|
||||
#endif
|
||||
|
||||
if (early_print != NO_EARLY_PRINT)
|
||||
spinlock_irqsave_unlock(&olock);
|
||||
spinlock_irqsave_unlock(&olock);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int kputs(const char *str)
|
||||
{
|
||||
int pos, i, len = strlen(str);
|
||||
|
||||
if (early_print != NO_EARLY_PRINT)
|
||||
spinlock_irqsave_lock(&olock);
|
||||
|
||||
for(i=0; i<len; i++) {
|
||||
pos = atomic_int32_inc(&kmsg_counter);
|
||||
kmessages[pos % KMSG_SIZE] = str[i];
|
||||
#ifdef CONFIG_VGA
|
||||
if (early_print & VGA_EARLY_PRINT)
|
||||
vga_putchar(str[i]);
|
||||
#endif
|
||||
#ifdef CONFIG_UART
|
||||
if (early_print & UART_EARLY_PRINT)
|
||||
uart_putchar(str[i]);
|
||||
#endif
|
||||
}
|
||||
int i;
|
||||
for(i=0; str[i] != '\0'; i++)
|
||||
vga_putchar((int) str[i]);
|
||||
|
||||
if (early_print != NO_EARLY_PRINT)
|
||||
spinlock_irqsave_unlock(&olock);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int koutput_add_uart(void)
|
||||
{
|
||||
#ifdef CONFIG_UART
|
||||
uint32_t i;
|
||||
|
||||
early_print |= UART_EARLY_PRINT;
|
||||
|
||||
for(i=0; i<atomic_int32_read(&kmsg_counter); i++)
|
||||
uart_putchar(kmessages[i % KMSG_SIZE]);
|
||||
|
||||
return 0;
|
||||
return i;
|
||||
#else
|
||||
return -EINVAL;
|
||||
#endif
|
||||
}
|
||||
|
|
204
mm/memory.c
204
mm/memory.c
|
@ -27,29 +27,8 @@
|
|||
|
||||
#include <eduos/stddef.h>
|
||||
#include <eduos/stdlib.h>
|
||||
#include <eduos/stdio.h>
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/spinlock.h>
|
||||
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/multiboot.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
static char stack[MAX_TASKS-1][KERNEL_STACK_SIZE];
|
||||
static char bitmap[BITMAP_SIZE];
|
||||
|
||||
static spinlock_t bitmap_lock = SPINLOCK_INIT;
|
||||
|
||||
atomic_int32_t total_pages = ATOMIC_INIT(0);
|
||||
atomic_int32_t total_allocated_pages = ATOMIC_INIT(0);
|
||||
atomic_int32_t total_available_pages = ATOMIC_INIT(0);
|
||||
|
||||
void* create_stack(tid_t id)
|
||||
{
|
||||
|
@ -62,186 +41,3 @@ void* create_stack(tid_t id)
|
|||
|
||||
return (void*) stack[id-1];
|
||||
}
|
||||
|
||||
inline static int page_marked(size_t i)
|
||||
{
|
||||
size_t index = i >> 3;
|
||||
size_t mod = i & 0x7;
|
||||
|
||||
return (bitmap[index] & (1 << mod));
|
||||
}
|
||||
|
||||
inline static void page_set_mark(size_t i)
|
||||
{
|
||||
size_t index = i >> 3;
|
||||
size_t mod = i & 0x7;
|
||||
|
||||
bitmap[index] = bitmap[index] | (1 << mod);
|
||||
}
|
||||
|
||||
inline static void page_clear_mark(size_t i)
|
||||
{
|
||||
size_t index = i / 8;
|
||||
size_t mod = i % 8;
|
||||
|
||||
bitmap[index] = bitmap[index] & ~(1 << mod);
|
||||
}
|
||||
|
||||
size_t get_pages(size_t npages)
|
||||
{
|
||||
size_t cnt, off;
|
||||
static size_t alloc_start = (size_t) -1;
|
||||
|
||||
if (BUILTIN_EXPECT(!npages, 0))
|
||||
return 0;
|
||||
if (BUILTIN_EXPECT(npages > atomic_int32_read(&total_available_pages), 0))
|
||||
return 0;
|
||||
|
||||
spinlock_lock(&bitmap_lock);
|
||||
|
||||
if (alloc_start == (size_t)-1)
|
||||
alloc_start = ((size_t) &kernel_end >> PAGE_BITS);
|
||||
off = 1;
|
||||
while (off <= BITMAP_SIZE*8 - npages) {
|
||||
for (cnt=0; cnt<npages; cnt++) {
|
||||
if (page_marked(((off+alloc_start)%(BITMAP_SIZE*8 - npages))+cnt))
|
||||
goto next;
|
||||
}
|
||||
|
||||
off = (off+alloc_start) % (BITMAP_SIZE*8 - npages);
|
||||
alloc_start = off+npages;
|
||||
|
||||
for (cnt=0; cnt<npages; cnt++) {
|
||||
page_set_mark(off+cnt);
|
||||
}
|
||||
|
||||
spinlock_unlock(&bitmap_lock);
|
||||
|
||||
atomic_int32_add(&total_allocated_pages, npages);
|
||||
atomic_int32_sub(&total_available_pages, npages);
|
||||
|
||||
return off << PAGE_BITS;
|
||||
|
||||
next: off += cnt+1;
|
||||
}
|
||||
|
||||
spinlock_unlock(&bitmap_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int put_pages(size_t phyaddr, size_t npages)
|
||||
{
|
||||
size_t i, ret = 0;
|
||||
size_t base = phyaddr >> PAGE_BITS;
|
||||
|
||||
if (BUILTIN_EXPECT(!phyaddr, 0))
|
||||
return -EINVAL;
|
||||
if (BUILTIN_EXPECT(!npages, 0))
|
||||
return -EINVAL;
|
||||
|
||||
spinlock_lock(&bitmap_lock);
|
||||
|
||||
for (i=0; i<npages; i++) {
|
||||
if (page_marked(base+i)) {
|
||||
page_clear_mark(base+i);
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
spinlock_unlock(&bitmap_lock);
|
||||
|
||||
atomic_int32_sub(&total_allocated_pages, ret);
|
||||
atomic_int32_add(&total_available_pages, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int memory_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t addr;
|
||||
int ret = 0;
|
||||
|
||||
// mark all memory as used
|
||||
memset(bitmap, 0xff, BITMAP_SIZE);
|
||||
|
||||
// parse multiboot information for available memory
|
||||
if (mb_info) {
|
||||
if (mb_info->flags & MULTIBOOT_INFO_MEM_MAP) {
|
||||
multiboot_memory_map_t* mmap = (multiboot_memory_map_t*) ((size_t) mb_info->mmap_addr);
|
||||
multiboot_memory_map_t* mmap_end = (void*) ((size_t) mb_info->mmap_addr + mb_info->mmap_length);
|
||||
|
||||
// mark available memory as free
|
||||
while (mmap < mmap_end) {
|
||||
if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE) {
|
||||
for (addr=mmap->addr; addr < mmap->addr + mmap->len; addr += PAGE_SIZE) {
|
||||
page_clear_mark(addr >> PAGE_BITS);
|
||||
atomic_int32_inc(&total_pages);
|
||||
atomic_int32_inc(&total_available_pages);
|
||||
}
|
||||
}
|
||||
mmap++;
|
||||
}
|
||||
}
|
||||
else if (mb_info->flags & MULTIBOOT_INFO_MEM) {
|
||||
size_t page;
|
||||
size_t pages_lower = mb_info->mem_lower >> 2; /* KiB to page number */
|
||||
size_t pages_upper = mb_info->mem_upper >> 2;
|
||||
|
||||
for (page=0; page<pages_lower; page++)
|
||||
page_clear_mark(page);
|
||||
|
||||
for (page=0; page<pages_upper; page++)
|
||||
page_clear_mark(page + 256); /* 1 MiB == 256 pages offset */
|
||||
|
||||
atomic_int32_add(&total_pages, pages_lower + pages_upper);
|
||||
atomic_int32_add(&total_available_pages, pages_lower + pages_upper);
|
||||
}
|
||||
else {
|
||||
kputs("Unable to initialize the memory management subsystem\n");
|
||||
while (1) HALT;
|
||||
}
|
||||
|
||||
// mark mb_info as used
|
||||
page_set_mark((size_t) mb_info >> PAGE_BITS);
|
||||
atomic_int32_inc(&total_allocated_pages);
|
||||
atomic_int32_dec(&total_available_pages);
|
||||
|
||||
|
||||
if (mb_info->flags & MULTIBOOT_INFO_MODS) {
|
||||
// mark modules list as used
|
||||
for(addr=mb_info->mods_addr; addr<mb_info->mods_addr+mb_info->mods_count*sizeof(multiboot_module_t); addr+=PAGE_SIZE) {
|
||||
page_set_mark(addr >> PAGE_BITS);
|
||||
atomic_int32_inc(&total_allocated_pages);
|
||||
atomic_int32_dec(&total_available_pages);
|
||||
}
|
||||
|
||||
// mark modules as used
|
||||
multiboot_module_t* mmodule = (multiboot_module_t*) ((size_t) mb_info->mods_addr);
|
||||
for(i=0; i<mb_info->mods_count; i++) {
|
||||
for(addr=mmodule[i].mod_start; addr<mmodule[i].mod_end; addr+=PAGE_SIZE) {
|
||||
page_set_mark(addr >> PAGE_BITS);
|
||||
atomic_int32_inc(&total_allocated_pages);
|
||||
atomic_int32_dec(&total_available_pages);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mark kernel as used
|
||||
for(addr=(size_t) &kernel_start; addr<(size_t) &kernel_end; addr+=PAGE_SIZE) {
|
||||
page_set_mark(addr >> PAGE_BITS);
|
||||
atomic_int32_inc(&total_allocated_pages);
|
||||
atomic_int32_dec(&total_available_pages);
|
||||
}
|
||||
|
||||
// enable paging and map SMP, VGA, Multiboot modules etc.
|
||||
ret = page_init();
|
||||
if (BUILTIN_EXPECT(ret, 0)) {
|
||||
kputs("Failed to initialize paging!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue