Compare commits
2 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ecc50893a1 | ||
![]() |
b87aa02d7b |
67 changed files with 193 additions and 8582 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -3,6 +3,4 @@
|
|||
*~
|
||||
*.elf
|
||||
*.sym
|
||||
documentation/html/
|
||||
include/eduos/config.h
|
||||
include/eduos/config.inc
|
||||
|
|
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 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
|
||||
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] $@
|
||||
|
@ -98,12 +77,7 @@ doc:
|
|||
@echo [DEP] $*.dep
|
||||
$Q$(CC_FOR_TARGET) -MF $*.dep -MT $*.o -MM $(CFLAGS) $<
|
||||
|
||||
include/eduos/config.inc: include/eduos/config.h
|
||||
@echo "; This file is generated automatically from the config.h file." > include/eduos/config.inc
|
||||
@echo "; Before editing this, you should consider editing config.h." >> include/eduos/config.inc
|
||||
@awk '/^#define KERNEL_STACK_SIZE/{ print "%define KERNEL_STACK_SIZE", $$3 }' include/eduos/config.h >> include/eduos/config.inc
|
||||
|
||||
%.o : %.asm include/eduos/config.inc
|
||||
%.o : %.asm
|
||||
@echo [ASM] $@
|
||||
$Q$(NASM) $(NASMFLAGS) -o $@ $<
|
||||
|
||||
|
@ -112,5 +86,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))
|
||||
|
|
60
README.md
60
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>
|
||||
|
@ -60,43 +60,7 @@ Boot eduOS via grub
|
|||
}
|
||||
</pre>
|
||||
|
||||
Overview of all branches
|
||||
------------------------
|
||||
0. stage0 - Smallest HelloWorld of the World
|
||||
|
||||
Description of loading a minimal 32bit kernel
|
||||
|
||||
1. stage1 - Non-preemptive multitasking
|
||||
|
||||
Introduction into a simple form of multitasking, where no interrupts are
|
||||
required.
|
||||
|
||||
2. stage2 - Synchronisation primitives
|
||||
|
||||
Description of basic synchronization primitives
|
||||
|
||||
3. 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://techblog.lankes.org/tutorials/
|
||||
|
|
|
@ -1,167 +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/atomic.h
|
||||
* @brief Functions for atomic operations
|
||||
*
|
||||
* This file defines functions for atomic operations on int32 variables
|
||||
* which will be used in locking-mechanisms.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ATOMIC_H__
|
||||
#define __ARCH_ATOMIC_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if MAX_CORES > 1
|
||||
#define LOCK "lock ; "
|
||||
#else
|
||||
#define LOCK ""
|
||||
#endif
|
||||
|
||||
/** @brief Makro for initialization of atomic_int32_t vars
|
||||
*
|
||||
* Whenever you use an atomic_int32_t variable, init it with
|
||||
* this macro first.\n
|
||||
* Example: atomic_int32_t myAtomicVar = ATOMIC_INIT(123);
|
||||
*
|
||||
* @param i The number value you want to init it with.
|
||||
*/
|
||||
#define ATOMIC_INIT(i) { (i) }
|
||||
|
||||
/** @brief Standard-datatype for atomic operations
|
||||
*
|
||||
* It just consists of an int32_t variable internally, marked as volatile.
|
||||
*/
|
||||
typedef struct { volatile int32_t counter; } atomic_int32_t;
|
||||
|
||||
/** @brief Atomic test and set operation for int32 vars.
|
||||
*
|
||||
* This function will atomically exchange the value of an atomic variable and
|
||||
* return its old value. Is used in locking-operations.\n
|
||||
* \n
|
||||
* Intel manuals: If a memory operand is referenced, the processor's locking
|
||||
* protocol is automatically implemented for the duration of the exchange
|
||||
* operation, regardless of the presence or absence of the LOCK prefix.
|
||||
*
|
||||
* @param d Pointer to the atomic_int_32_t with the value you want to exchange
|
||||
* @param ret the value you want the var test for
|
||||
*
|
||||
* @return The old value of the atomic_int_32_t var before exchange
|
||||
*/
|
||||
inline static int32_t atomic_int32_test_and_set(atomic_int32_t* d, int32_t ret)
|
||||
{
|
||||
asm volatile ("xchgl %0, %1" : "=r"(ret) : "m"(d->counter), "0"(ret) : "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Atomic addition of values to atomic_int32_t vars
|
||||
*
|
||||
* This function lets you add values in an atomic operation
|
||||
*
|
||||
* @param d Pointer to the atomit_int32_t var you want do add a value to
|
||||
* @param i The value you want to increment by
|
||||
*
|
||||
* @return The mathematical result
|
||||
*/
|
||||
inline static int32_t atomic_int32_add(atomic_int32_t *d, int32_t i)
|
||||
{
|
||||
int32_t res = i;
|
||||
asm volatile(LOCK "xaddl %0, %1" : "=r"(i) : "m"(d->counter), "0"(i) : "memory", "cc");
|
||||
return res+i;
|
||||
}
|
||||
|
||||
/** @brief Atomic subtraction of values from atomic_int32_t vars
|
||||
*
|
||||
* This function lets you subtract values in an atomic operation.\n
|
||||
* This function is just for convenience. It uses atomic_int32_add(d, -i)
|
||||
*
|
||||
* @param d Pointer to the atomic_int32_t var you want to subtract from
|
||||
* @param i The value you want to subtract by
|
||||
*
|
||||
* @return The mathematical result
|
||||
*/
|
||||
inline static int32_t atomic_int32_sub(atomic_int32_t *d, int32_t i)
|
||||
{
|
||||
return atomic_int32_add(d, -i);
|
||||
}
|
||||
|
||||
/** @brief Atomic increment by one
|
||||
*
|
||||
* The atomic_int32_t var will be atomically incremented by one.\n
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/** @brief Atomic decrement by one
|
||||
*
|
||||
* The atomic_int32_t var will be atomically decremented by one.\n
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/** @brief Read out an atomic_int32_t var
|
||||
*
|
||||
* This function is for convenience: It looks into the atomic_int32_t struct
|
||||
* and returns the internal value for you.
|
||||
*
|
||||
* @param d Pointer to the atomic_int32_t var you want to read out
|
||||
* @return It's number value
|
||||
*/
|
||||
inline static int32_t atomic_int32_read(atomic_int32_t *d) {
|
||||
return d->counter;
|
||||
}
|
||||
|
||||
/** @brief Set the value of an atomic_int32_t var
|
||||
*
|
||||
* This function is for convenience: It sets the internal value of
|
||||
* an atomic_int32_t var for you.
|
||||
*
|
||||
* @param d Pointer to the atomic_int32_t var you want to set
|
||||
* @param v The value to set
|
||||
*/
|
||||
inline static void atomic_int32_set(atomic_int32_t *d, int32_t v) {
|
||||
atomic_int32_test_and_set(d, v);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,163 +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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file arch/x86/include/asm/gdt.h
|
||||
* @brief Definitions and functions related to segmentation
|
||||
* @author Stefan Lankes
|
||||
*
|
||||
* This file defines the interface for segmentation as like structures to describe segments.\n
|
||||
* There are also some other gdt-private functions in the gdt.c file defined.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_GDT_H__
|
||||
#define __ARCH_GDT_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// This segment is a data segment
|
||||
#define GDT_FLAG_DATASEG 0x02
|
||||
/// This segment is a code segment
|
||||
#define GDT_FLAG_CODESEG 0x0a
|
||||
#define GDT_FLAG_TSS 0x09
|
||||
#define GDT_FLAG_TSS_BUSY 0x02
|
||||
|
||||
#define GDT_FLAG_SEGMENT 0x10
|
||||
/// Privilege level: Ring 0
|
||||
#define GDT_FLAG_RING0 0x00
|
||||
/// Privilege level: Ring 1
|
||||
#define GDT_FLAG_RING1 0x20
|
||||
/// Privilege level: Ring 2
|
||||
#define GDT_FLAG_RING2 0x40
|
||||
/// Privilege level: Ring 3
|
||||
#define GDT_FLAG_RING3 0x60
|
||||
/// Segment is present
|
||||
#define GDT_FLAG_PRESENT 0x80
|
||||
/// Segment was accessed
|
||||
#define GDT_FLAG_ACCESSED 0x01
|
||||
/**
|
||||
* @brief Granularity of segment limit
|
||||
* - set: segment limit unit is 4 KB (page size)
|
||||
* - not set: unit is bytes
|
||||
*/
|
||||
#define GDT_FLAG_4K_GRAN 0x80
|
||||
/**
|
||||
* @brief Default operand size
|
||||
* - set: 32 bit
|
||||
* - not set: 16 bit
|
||||
*/
|
||||
#define GDT_FLAG_16_BIT 0x00
|
||||
#define GDT_FLAG_32_BIT 0x40
|
||||
#define GDT_FLAG_64_BIT 0x20
|
||||
|
||||
/** @brief Defines a GDT entry
|
||||
*
|
||||
* A global descriptor table entry consists of:
|
||||
* - 32 bit base address (chunkwise embedded into this structure)
|
||||
* - 20 bit limit
|
||||
*/
|
||||
typedef struct {
|
||||
/// Lower 16 bits of limit range
|
||||
uint16_t limit_low;
|
||||
/// Lower 16 bits of base address
|
||||
uint16_t base_low;
|
||||
/// middle 8 bits of base address
|
||||
uint8_t base_middle;
|
||||
/// Access bits
|
||||
uint8_t access;
|
||||
/// Granularity bits
|
||||
uint8_t granularity;
|
||||
/// Higher 8 bits of base address
|
||||
uint8_t base_high;
|
||||
} __attribute__ ((packed)) gdt_entry_t;
|
||||
|
||||
/** @brief defines the GDT pointer structure
|
||||
*
|
||||
* This structure tells the address and size of the table.
|
||||
*/
|
||||
typedef struct {
|
||||
/// Size of the table in bytes (not the number of entries!)
|
||||
uint16_t limit;
|
||||
/// Address of the table
|
||||
size_t base;
|
||||
} __attribute__ ((packed)) gdt_ptr_t;
|
||||
|
||||
#ifdef CONFIG_LGUEST
|
||||
|
||||
// TODO TODO: Just hacked in
|
||||
#define GDT_ENTRIES 32
|
||||
|
||||
#else
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
#define GDT_ENTRIES (5+MAX_TASKS)
|
||||
#else
|
||||
// a TSS descriptor is twice larger than a code/data descriptor
|
||||
#define GDT_ENTRIES (5+MAX_TASKS*2)
|
||||
#endif
|
||||
|
||||
#if GDT_ENTRIES > 8192
|
||||
#error Too many GDT entries!
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @brief Installs the global descriptor table
|
||||
*
|
||||
* The installation involves the following steps:
|
||||
* - set up the special GDT pointer
|
||||
* - set up the entries in our GDT
|
||||
* - finally call gdt_flush() in our assembler file
|
||||
* in order to tell the processor where the new GDT is
|
||||
* - update the new segment registers
|
||||
*/
|
||||
void gdt_install(void);
|
||||
|
||||
/** @brief Set gate with chosen attributes
|
||||
*/
|
||||
void gdt_set_gate(int num, unsigned long base, unsigned long limit,
|
||||
unsigned char access, unsigned char gran);
|
||||
|
||||
/** @brief Configures and returns a GDT descriptor with chosen attributes
|
||||
*
|
||||
* Just feed this function with address, limit and the flags
|
||||
* you have seen in idt.h
|
||||
*
|
||||
* @return a preconfigured gdt descriptor
|
||||
*/
|
||||
void configure_gdt_entry(gdt_entry_t *dest_entry, unsigned long base, unsigned long limit,
|
||||
unsigned char access, unsigned char gran);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,138 +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/idt.h
|
||||
* @brief Definition of IDT flags and functions to set interrupts
|
||||
*
|
||||
* This file contains define-constants for interrupt flags
|
||||
* and installer functions for interrupt gates.\n
|
||||
* See idt.c for structure definitions.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_IDT_H__
|
||||
#define __ARCH_IDT_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
|
||||
/// This bit shall be set to 0 if the IDT slot is empty
|
||||
#define IDT_FLAG_PRESENT 0x80
|
||||
/// Interrupt can be called from within RING0
|
||||
#define IDT_FLAG_RING0 0x00
|
||||
/// Interrupt can be called from within RING1 and lower
|
||||
#define IDT_FLAG_RING1 0x20
|
||||
/// Interrupt can be called from within RING2 and lower
|
||||
#define IDT_FLAG_RING2 0x40
|
||||
/// Interrupt can be called from within RING3 and lower
|
||||
#define IDT_FLAG_RING3 0x60
|
||||
/// Size of gate is 16 bit
|
||||
#define IDT_FLAG_16BIT 0x00
|
||||
/// Size of gate is 32 bit
|
||||
#define IDT_FLAG_32BIT 0x08
|
||||
/// The entry describes an interrupt gate
|
||||
#define IDT_FLAG_INTTRAP 0x06
|
||||
/// The entry describes a trap gate
|
||||
#define IDT_FLAG_TRAPGATE 0x07
|
||||
/// The entry describes a task gate
|
||||
#define IDT_FLAG_TASKGATE 0x05
|
||||
|
||||
/*
|
||||
* This is not IDT-flag related. It's the segment selectors for kernel code and data.
|
||||
*/
|
||||
#define KERNEL_CODE_SELECTOR 0x08
|
||||
#define KERNEL_DATA_SELECTOR 0x10
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Defines an IDT entry
|
||||
*
|
||||
* This structure defines interrupt descriptor table entries.\n
|
||||
* They consist of the handling function's base address, some flags
|
||||
* and a segment selector.
|
||||
*/
|
||||
typedef struct {
|
||||
/// Handler function's lower 16 address bits
|
||||
uint16_t base_lo;
|
||||
/// Handler function's segment selector.
|
||||
uint16_t sel;
|
||||
/// These bits are reserved by Intel
|
||||
uint8_t always0;
|
||||
/// These 8 bits contain flags. Exact use depends on the type of interrupt gate.
|
||||
uint8_t flags;
|
||||
/// Higher 16 bits of handler function's base address
|
||||
uint16_t base_hi;
|
||||
} __attribute__ ((packed)) idt_entry_t;
|
||||
|
||||
/** @brief Defines the idt pointer structure.
|
||||
*
|
||||
* This structure keeps information about
|
||||
* base address and size of the interrupt descriptor table.
|
||||
*/
|
||||
typedef struct {
|
||||
/// Size of the IDT in bytes (not the number of entries!)
|
||||
uint16_t limit;
|
||||
/// Base address of the IDT
|
||||
size_t base;
|
||||
} __attribute__ ((packed)) idt_ptr_t;
|
||||
|
||||
/** @brief Installs IDT
|
||||
*
|
||||
* The installation involves the following steps:
|
||||
* - Set up the IDT pointer
|
||||
* - Set up int 0x80 for syscalls
|
||||
* - process idt_load()
|
||||
*/
|
||||
void idt_install(void);
|
||||
|
||||
/** @brief Set an entry in the IDT
|
||||
*
|
||||
* @param num index in the IDT
|
||||
* @param base base-address of the handler function being installed
|
||||
* @param sel Segment the IDT will use
|
||||
* @param flags Flags this entry will have
|
||||
*/
|
||||
void idt_set_gate(unsigned char num, size_t base, unsigned short sel,
|
||||
unsigned char flags);
|
||||
|
||||
/** @brief Configures and returns a IDT entry with chosen attributes
|
||||
*
|
||||
* Just feed this function with base, selector and the flags
|
||||
* you have seen in idt.h
|
||||
*
|
||||
* @return a preconfigured idt descriptor
|
||||
*/
|
||||
void configure_idt_entry(idt_entry_t *dest_entry, size_t base,
|
||||
unsigned short sel, unsigned char flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,80 +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/irq.h
|
||||
* @brief Functions related to IRQs
|
||||
*
|
||||
* This file contains functions and a pointer type related to interrupt requests.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_IRQ_H__
|
||||
#define __ARCH_IRQ_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
#include <eduos/tasks_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Pointer-type to IRQ-handling functions
|
||||
*
|
||||
* Whenever you write a IRQ-handling function it has to match this signature.
|
||||
*/
|
||||
typedef void (*irq_handler_t)(struct state *);
|
||||
|
||||
/** @brief Install a custom IRQ handler for a given IRQ
|
||||
*
|
||||
* @param irq The desired irq
|
||||
* @param handler The handler to install
|
||||
*/
|
||||
int irq_install_handler(unsigned int irq, irq_handler_t handler);
|
||||
|
||||
/** @brief Clear the handler for a given IRQ
|
||||
*
|
||||
* @param irq The handler's IRQ
|
||||
*/
|
||||
int irq_uninstall_handler(unsigned int irq);
|
||||
|
||||
/** @brief Procedure to initialize IRQ
|
||||
*
|
||||
* This procedure is just a small collection of calls:
|
||||
* - idt_install();
|
||||
* - isrs_install();
|
||||
* - irq_install();
|
||||
*
|
||||
* @return Just returns 0 in any case
|
||||
*/
|
||||
int irq_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,105 +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/irqflags.h
|
||||
* @brief Functions related to IRQ configuration
|
||||
*
|
||||
* This file contains definitions of inline functions
|
||||
* for enabling and disabling IRQ handling.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_IRQFLAGS_H__
|
||||
#define __ARCH_IRQFLAGS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Disable IRQs
|
||||
*
|
||||
* This inline function just clears out the interrupt bit
|
||||
*/
|
||||
inline static void irq_disable(void) {
|
||||
asm volatile("cli" ::: "memory");
|
||||
}
|
||||
|
||||
/** @brief Disable IRQs (nested)
|
||||
*
|
||||
* Disable IRQs when unsure if IRQs were enabled at all.\n
|
||||
* This function together with irq_nested_enable can be used
|
||||
* in situations when interrupts shouldn't be activated if they
|
||||
* were not activated before calling this function.
|
||||
*
|
||||
* @return The set of flags which have been set until now
|
||||
*/
|
||||
inline static uint8_t irq_nested_disable(void) {
|
||||
size_t flags;
|
||||
asm volatile("pushf; cli; pop %0": "=r"(flags) : : "memory");
|
||||
if (flags & (1 << 9))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Enable IRQs */
|
||||
inline static void irq_enable(void) {
|
||||
asm volatile("sti" ::: "memory");
|
||||
}
|
||||
|
||||
/** @brief Enable IRQs (nested)
|
||||
*
|
||||
* If called after calling irq_nested_disable, this function will
|
||||
* not activate IRQs if they were not active before.
|
||||
*
|
||||
* @param flags Flags to set. Could be the old ones you got from irq_nested_disable.
|
||||
*/
|
||||
inline static void irq_nested_enable(uint8_t flags) {
|
||||
if (flags)
|
||||
irq_enable();
|
||||
}
|
||||
|
||||
/** @brief Determines, if the interrupt flags (IF) is ser
|
||||
*
|
||||
* @return
|
||||
* - 1 interrupt flag is set
|
||||
* - 0 interrupt flag is cleared
|
||||
*/
|
||||
inline static uint8_t is_irq_enabled(void)
|
||||
{
|
||||
size_t flags;
|
||||
asm volatile("pushf; pop %0": "=r"(flags) : : "memory");
|
||||
if (flags & (1 << 9))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,59 +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/isrs.h
|
||||
* @brief Installation of interrupt service routines
|
||||
*
|
||||
* This file contains the declaration of the ISR installer procedure.\n
|
||||
* There is more interesting code related to ISRs in the isrs.c file.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ISRS_H__
|
||||
#define __ARCH_ISRS_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief ISR installer procedure
|
||||
*
|
||||
* This procedure sets the first 32 entries in the IDT
|
||||
* to the first 32 ISRs to call one general fault handler
|
||||
* which will do some dispatching and exception message logging.\n
|
||||
* The access flags are set to 0x8E (PRESENT, privilege: RING0, size: 32bit gate, type: interrupt gate).
|
||||
*/
|
||||
void isrs_install(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -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
|
|
@ -37,74 +37,11 @@
|
|||
#define __ARCH_PROCESSOR_H__
|
||||
|
||||
#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 +56,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 +65,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,77 +74,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;
|
||||
}
|
||||
|
||||
/** @brief search the first most significant bit
|
||||
*
|
||||
* @param i source operand
|
||||
* @return
|
||||
* - first bit, which is set in the source operand
|
||||
* - invalid value, if not bit ist set
|
||||
*/
|
||||
static inline size_t msb(size_t i)
|
||||
{
|
||||
size_t ret;
|
||||
|
||||
if (!i)
|
||||
return (sizeof(size_t)*8);
|
||||
asm volatile ("bsr %1, %0" : "=r"(ret) : "r"(i) : "cc");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief search the least significant bit
|
||||
*
|
||||
* @param i source operand
|
||||
* @return
|
||||
* - first bit, which is set in the source operand
|
||||
* - invalid value, if not bit ist set
|
||||
*/
|
||||
static inline size_t lsb(size_t i)
|
||||
{
|
||||
size_t ret;
|
||||
|
||||
if (!i)
|
||||
return (sizeof(size_t)*8);
|
||||
asm volatile ("bsf %1, %0" : "=r"(ret) : "r"(i) : "cc");
|
||||
|
||||
return ret;
|
||||
}
|
||||
inline static void wmb(void) { asm volatile("sfence" ::: "memory"); }
|
||||
|
||||
/// A one-instruction-do-nothing
|
||||
#define NOP1 asm volatile ("nop")
|
||||
|
@ -333,63 +89,6 @@ static inline size_t lsb(size_t i)
|
|||
#define NOP4 asm volatile ("nop;nop;nop;nop")
|
||||
/// A eight-instruction-do-nothing
|
||||
#define NOP8 asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop")
|
||||
/// The PAUSE instruction provides a hint to the processor that the code sequence is a spin-wait loop.
|
||||
#define PAUSE asm volatile ("pause")
|
||||
/// The HALT instruction stops the processor until the next interrupt arrives
|
||||
#define HALT asm volatile ("hlt")
|
||||
|
||||
/** @brief Init several subsystems
|
||||
*
|
||||
* This function calls the initialization procedures for:
|
||||
* - GDT
|
||||
* - APIC
|
||||
* - PCI [if configured]
|
||||
*
|
||||
* @return 0 in any case
|
||||
*/
|
||||
inline static int system_init(void)
|
||||
{
|
||||
gdt_install();
|
||||
cpu_detection();
|
||||
#ifdef CONFIG_PCI
|
||||
pci_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Detect and read out CPU frequency
|
||||
*
|
||||
* @return The CPU frequency in MHz
|
||||
*/
|
||||
uint32_t detect_cpu_frequency(void);
|
||||
|
||||
/** @brief Read out CPU frequency if detected before
|
||||
*
|
||||
* If you did not issue the detect_cpu_frequency() function before,
|
||||
* this function will call it implicitly.
|
||||
*
|
||||
* @return The CPU frequency in MHz
|
||||
*/
|
||||
uint32_t get_cpu_frequency(void);
|
||||
|
||||
/** @brief Busywait an microseconds interval of time
|
||||
* @param usecs The time to wait in microseconds
|
||||
*/
|
||||
void udelay(uint32_t usecs);
|
||||
|
||||
/** @brief System calibration
|
||||
*
|
||||
* This procedure will detect the CPU frequency and calibrate the APIC timer.
|
||||
*
|
||||
* @return 0 in any case.
|
||||
*/
|
||||
inline static int system_calibration(void)
|
||||
{
|
||||
detect_cpu_frequency();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -69,41 +69,6 @@ typedef char int8_t;
|
|||
/// 16 bit wide char type
|
||||
typedef unsigned short wchar_t;
|
||||
|
||||
/// This defines what the stack looks like after the task context is saved.
|
||||
struct state {
|
||||
/// ds register
|
||||
uint32_t ds;
|
||||
/// es register
|
||||
uint32_t es;
|
||||
/// EDI register
|
||||
uint32_t edi;
|
||||
/// ESI register
|
||||
uint32_t esi;
|
||||
/// EBP register
|
||||
uint32_t ebp;
|
||||
/// ESP register
|
||||
uint32_t esp;
|
||||
/// EBX register
|
||||
uint32_t ebx;
|
||||
/// EDX register
|
||||
uint32_t edx;
|
||||
/// ECX register
|
||||
uint32_t ecx;
|
||||
/// EAX register
|
||||
uint32_t eax; /* pushed by 'pusha' */
|
||||
|
||||
/// Interrupt number
|
||||
uint32_t int_no;
|
||||
|
||||
// pushed by the processor automatically
|
||||
uint32_t error;
|
||||
uint32_t eip;
|
||||
uint32_t cs;
|
||||
uint32_t eflags;
|
||||
uint32_t useresp;
|
||||
uint32_t ss;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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
|
|
@ -1,98 +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/tasks.h
|
||||
* @brief Task related structure definitions
|
||||
*
|
||||
* This file contains the task_t structure definition
|
||||
* and task state define constants
|
||||
*/
|
||||
|
||||
#ifndef __ASM_TASKS_H__
|
||||
#define __ASM_TASKS_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Switch to current task
|
||||
*
|
||||
* @param stack Pointer to the old stack pointer
|
||||
*/
|
||||
void switch_context(size_t** stack);
|
||||
|
||||
/** @brief Setup a default frame for a new task
|
||||
*
|
||||
* @param task Pointer to the task structure
|
||||
* @param ep The entry point for code execution
|
||||
* @param arg Arguments list pointer for the task's stack
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
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
|
||||
|
||||
#endif
|
|
@ -1,72 +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/tss.h
|
||||
* @brief Task state segment structure definition
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_TSS_H__
|
||||
#define __ARCH_TSS_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief The tast state segment structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t backlink, __blh;
|
||||
uint32_t esp0;
|
||||
uint16_t ss0, __ss0h;
|
||||
uint32_t esp1;
|
||||
uint16_t ss1, __ss1h;
|
||||
uint32_t esp2;
|
||||
uint16_t ss2, __ss2h;
|
||||
uint32_t cr3;
|
||||
uint32_t eip;
|
||||
uint32_t eflags;
|
||||
uint32_t eax, ecx, edx, ebx;
|
||||
uint32_t esp, ebp, esi, edi;
|
||||
uint16_t es, __esh;
|
||||
uint16_t cs, __csh;
|
||||
uint16_t ss, __ssh;
|
||||
uint16_t ds, __dsh;
|
||||
uint16_t fs, __fsh;
|
||||
uint16_t gs, __gsh;
|
||||
uint16_t ldt, __ldth;
|
||||
uint16_t trace, bitmap;
|
||||
} __attribute__ ((packed)) tss_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#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 := multiboot.c vga.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.
|
||||
;
|
||||
|
@ -24,28 +24,20 @@
|
|||
; (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 the kernel's entry point. We could either call main here,
|
||||
; or we can use this to setup the stack or other nice stuff, like
|
||||
; perhaps setting up the GDT and segments. Please note that interrupts
|
||||
; are disabled at this point: More on interrupts later!
|
||||
|
||||
%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,287 +50,43 @@ mboot:
|
|||
SECTION .text
|
||||
ALIGN 4
|
||||
stublet:
|
||||
; Initialize stack pointer
|
||||
mov esp, boot_stack
|
||||
add esp, KERNEL_STACK_SIZE-16
|
||||
; Initialize CPU features
|
||||
; initialize stack pointer.
|
||||
mov esp, default_stack_pointer
|
||||
; 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 eax, cr0
|
||||
; 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
|
||||
|
||||
; Set CR4
|
||||
; at this stage, we disable the SSE support
|
||||
mov eax, cr4
|
||||
and eax, 0xfffbf9ff
|
||||
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
|
||||
mov cr0, eax
|
||||
|
||||
ret
|
||||
|
||||
; This will set up our new segment registers. We need to do
|
||||
; something special in order to set CS. We do what is called a
|
||||
; far jump. A jump that includes a segment as well as an offset.
|
||||
; This is declared in C as 'extern void gdt_flush();'
|
||||
global gdt_flush
|
||||
extern gp
|
||||
gdt_flush:
|
||||
lgdt [gp]
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
jmp 0x08:flush2
|
||||
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 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.
|
||||
;
|
||||
; ISRs are registered as "Interrupt Gate".
|
||||
; Therefore, the interrupt flag (IF) is already cleared.
|
||||
|
||||
; NASM macro which pushs also an pseudo error code
|
||||
%macro isrstub_pseudo_error 1
|
||||
global isr%1
|
||||
isr%1:
|
||||
push byte 0 ; pseudo error code
|
||||
push byte %1
|
||||
jmp common_stub
|
||||
%endmacro
|
||||
|
||||
; Similar to isrstub_pseudo_error, but without pushing
|
||||
; a pseudo error code => The error code is already
|
||||
; on the stack.
|
||||
%macro isrstub 1
|
||||
global isr%1
|
||||
isr%1:
|
||||
push byte %1
|
||||
jmp common_stub
|
||||
%endmacro
|
||||
|
||||
; 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
|
||||
; 3: Int 3 Exception
|
||||
; 4: INTO Exception
|
||||
; 5: Out of Bounds Exception
|
||||
; 6: Invalid Opcode Exception
|
||||
; 7: Coprocessor Not Available Exception
|
||||
%assign i 0
|
||||
%rep 8
|
||||
isrstub_pseudo_error i
|
||||
%assign i i+1
|
||||
%endrep
|
||||
|
||||
; 8: Double Fault Exception (With Error Code!)
|
||||
isrstub 8
|
||||
|
||||
; 9: Coprocessor Segment Overrun Exception
|
||||
isrstub_pseudo_error 9
|
||||
|
||||
; 10: Bad TSS Exception (With Error Code!)
|
||||
; 11: Segment Not Present Exception (With Error Code!)
|
||||
; 12: Stack Fault Exception (With Error Code!)
|
||||
; 13: General Protection Fault Exception (With Error Code!)
|
||||
; 14: Page Fault Exception (With Error Code!)
|
||||
%assign i 10
|
||||
%rep 5
|
||||
isrstub i
|
||||
%assign i i+1
|
||||
%endrep
|
||||
|
||||
; 15: Reserved Exception
|
||||
; 16: Floating Point Exception
|
||||
; 17: Alignment Check Exception
|
||||
; 18: Machine Check Exceptio
|
||||
; 19-31: Reserved
|
||||
%assign i 15
|
||||
%rep 17
|
||||
isrstub_pseudo_error i
|
||||
%assign i i+1
|
||||
%endrep
|
||||
|
||||
; NASM macro for asynchronous interrupts (no exceptions)
|
||||
%macro irqstub 1
|
||||
global irq%1
|
||||
irq%1:
|
||||
push byte 0 ; pseudo error code
|
||||
push byte 32+%1
|
||||
jmp common_stub
|
||||
%endmacro
|
||||
|
||||
; 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
|
||||
|
||||
; 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:
|
||||
mov eax, [esp+4] ; on the stack is already the address to store the old esp
|
||||
pushf ; push controll register
|
||||
push DWORD 0x8 ; CS
|
||||
push DWORD rollback ; EIP
|
||||
push DWORD 0x0 ; Interrupt number
|
||||
push DWORD 0x00edbabe ; Error code
|
||||
pusha ; push all general purpose registers...
|
||||
push 0x10 ; kernel data segment
|
||||
push 0x10 ; kernel data segment
|
||||
|
||||
jmp common_switch
|
||||
|
||||
ALIGN 4
|
||||
rollback:
|
||||
ret
|
||||
|
||||
ALIGN 4
|
||||
common_stub:
|
||||
pusha
|
||||
push es
|
||||
push ds
|
||||
mov ax, 0x10
|
||||
mov es, ax
|
||||
mov ds, ax
|
||||
|
||||
; Use the same handler for interrupts and exceptions
|
||||
push esp
|
||||
|
||||
extern set_kernel_stack
|
||||
call irq_handler
|
||||
add esp, 4
|
||||
|
||||
cmp eax, 0
|
||||
je no_context_switch
|
||||
|
||||
common_switch:
|
||||
mov [eax], esp ; store old esp
|
||||
call get_current_stack ; get new esp
|
||||
xchg eax, esp
|
||||
|
||||
; Set task switched flag
|
||||
mov eax, cr0
|
||||
or eax, 8
|
||||
mov cr0, eax
|
||||
|
||||
; Set esp0 in the task state segment
|
||||
call set_kernel_stack
|
||||
|
||||
; Call cleanup code
|
||||
call finish_task_switch
|
||||
|
||||
no_context_switch:
|
||||
pop ds
|
||||
pop es
|
||||
popa
|
||||
add esp, 8
|
||||
iret
|
||||
|
||||
; Here is the definition of our stack. Remember that a stack actually grows
|
||||
; downwards, so we declare the size of the data before declaring
|
||||
; the identifier 'default_stack_pointer'
|
||||
SECTION .data
|
||||
resb 8192 ; This reserves 8KBytes of memory here
|
||||
default_stack_pointer:
|
||||
|
||||
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
|
||||
|
||||
; add some hints to the ELF file
|
||||
SECTION .note.GNU-stack noalloc noexec nowrite progbits
|
||||
|
|
|
@ -1,147 +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/stdlib.h>
|
||||
#include <eduos/tasks.h>
|
||||
#include <eduos/errno.h>
|
||||
#include <eduos/processor.h>
|
||||
#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)));
|
||||
// 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}};
|
||||
|
||||
/*
|
||||
* This is defined in entry.asm. We use this to properly reload
|
||||
* the new segment registers
|
||||
*/
|
||||
extern void gdt_flush(void);
|
||||
|
||||
void set_kernel_stack(void)
|
||||
{
|
||||
task_t* curr_task = current_task;
|
||||
|
||||
task_state_segment.esp0 = (size_t) curr_task->stack + KERNEL_STACK_SIZE-16;
|
||||
}
|
||||
|
||||
/* Setup a descriptor in the Global Descriptor Table */
|
||||
void gdt_set_gate(int num, unsigned long base, unsigned long limit,
|
||||
unsigned char access, unsigned char gran)
|
||||
{
|
||||
configure_gdt_entry(&gdt[num], base, limit, access, gran);
|
||||
}
|
||||
|
||||
void configure_gdt_entry(gdt_entry_t *dest_entry, unsigned long base, unsigned long limit,
|
||||
unsigned char access, unsigned char gran)
|
||||
{
|
||||
/* Setup the descriptor base address */
|
||||
dest_entry->base_low = (base & 0xFFFF);
|
||||
dest_entry->base_middle = (base >> 16) & 0xFF;
|
||||
dest_entry->base_high = (base >> 24) & 0xFF;
|
||||
|
||||
/* Setup the descriptor limits */
|
||||
dest_entry->limit_low = (limit & 0xFFFF);
|
||||
dest_entry->granularity = ((limit >> 16) & 0x0F);
|
||||
|
||||
/* Finally, set up the granularity and access flags */
|
||||
dest_entry->granularity |= (gran & 0xF0);
|
||||
dest_entry->access = access;
|
||||
}
|
||||
|
||||
/*
|
||||
* This will setup the special GDT
|
||||
* pointer, set up the entries in our GDT, and then
|
||||
* finally call gdt_flush() in our assembler file in order
|
||||
* to tell the processor where the new GDT is and update the
|
||||
* new segment registers
|
||||
*/
|
||||
void gdt_install(void)
|
||||
{
|
||||
unsigned long mode, limit;
|
||||
|
||||
memset(&task_state_segment, 0x00, sizeof(tss_t));
|
||||
|
||||
mode = GDT_FLAG_32_BIT;
|
||||
limit = 0xFFFFFFFF;
|
||||
|
||||
/* Setup the GDT pointer and limit */
|
||||
gp.limit = (sizeof(gdt_entry_t) * GDT_ENTRIES) - 1;
|
||||
gp.base = (size_t) &gdt;
|
||||
|
||||
/* Our NULL descriptor */
|
||||
gdt_set_gate(0, 0, 0, 0, 0);
|
||||
|
||||
/*
|
||||
* The second entry is our Code Segment. The base address
|
||||
* is 0, the limit is 4 GByte, it uses 4KByte granularity,
|
||||
* uses 32-bit opcodes, and is a Code Segment descriptor.
|
||||
*/
|
||||
gdt_set_gate(1, 0, limit,
|
||||
GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT,
|
||||
GDT_FLAG_4K_GRAN | mode);
|
||||
|
||||
/*
|
||||
* The third entry is our Data Segment. It's EXACTLY the
|
||||
* same as our code segment, but the descriptor type in
|
||||
* this entry's access byte says it's a Data Segment
|
||||
*/
|
||||
gdt_set_gate(2, 0, limit,
|
||||
GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT,
|
||||
GDT_FLAG_4K_GRAN | mode);
|
||||
|
||||
/*
|
||||
* Create code segement for userspace applications (ring 3)
|
||||
*/
|
||||
gdt_set_gate(3, 0, limit,
|
||||
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT,
|
||||
GDT_FLAG_4K_GRAN | mode);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/* set default values */
|
||||
task_state_segment.eflags = 0x1202;
|
||||
task_state_segment.ss0 = 0x10; // data segment
|
||||
task_state_segment.esp0 = 0xDEADBEEF; // invalid pseudo address
|
||||
task_state_segment.cs = 0x0b;
|
||||
task_state_segment.ss = task_state_segment.ds = task_state_segment.es = task_state_segment.fs = task_state_segment.gs = 0x13;
|
||||
gdt_set_gate(5, (unsigned long) (&task_state_segment), sizeof(tss_t)-1,
|
||||
GDT_FLAG_PRESENT | GDT_FLAG_TSS | GDT_FLAG_RING0, mode);
|
||||
|
||||
/* Flush out the old GDT and install the new changes! */
|
||||
gdt_flush();
|
||||
}
|
|
@ -1,98 +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/kernel/idt.c
|
||||
* @brief Definitions and functions related to IDT
|
||||
*
|
||||
*
|
||||
* This file defines the interface for interrupts as like
|
||||
* structures to describe interrupt descriptor table entries.\n
|
||||
* See idt.h for flag definitions.
|
||||
*/
|
||||
|
||||
#include <eduos/string.h>
|
||||
#include <asm/idt.h>
|
||||
|
||||
/*
|
||||
* Declare an IDT of 256 entries. Although we will only use the
|
||||
* first 32 entries in this tutorial, the rest exists as a bit
|
||||
* of a trap. If any undefined IDT entry is hit, it normally
|
||||
* will cause an "Unhandled Interrupt" exception. Any descriptor
|
||||
* for which the 'presence' bit is cleared (0) will generate an
|
||||
* "Unhandled Interrupt" exception
|
||||
*/
|
||||
static idt_entry_t idt[256] = {[0 ... 255] = {0, 0, 0, 0, 0}};
|
||||
static idt_ptr_t idtp;
|
||||
|
||||
void configure_idt_entry(idt_entry_t *dest_entry, size_t base,
|
||||
unsigned short sel, unsigned char flags)
|
||||
{
|
||||
/* The interrupt routine's base address */
|
||||
dest_entry->base_lo = (base & 0xFFFF);
|
||||
dest_entry->base_hi = (base >> 16) & 0xFFFF;
|
||||
|
||||
/* The segment or 'selector' that this IDT entry will use
|
||||
* is set here, along with any access flags */
|
||||
dest_entry->sel = sel;
|
||||
dest_entry->always0 = 0;
|
||||
dest_entry->flags = flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use this function to set an entry in the IDT. Alot simpler
|
||||
* than twiddling with the GDT ;)
|
||||
*/
|
||||
void idt_set_gate(unsigned char num, size_t base, unsigned short sel,
|
||||
unsigned char flags)
|
||||
{
|
||||
configure_idt_entry(&idt[num], base, sel, flags);
|
||||
}
|
||||
|
||||
extern void isrsyscall(void);
|
||||
|
||||
/* Installs the IDT */
|
||||
void idt_install(void)
|
||||
{
|
||||
static int initialized = 0;
|
||||
|
||||
if (!initialized) {
|
||||
initialized = 1;
|
||||
|
||||
/* Sets the special IDT pointer up, just like in 'gdt.c' */
|
||||
idtp.limit = (sizeof(idt_entry_t) * 256) - 1;
|
||||
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 */
|
||||
asm volatile("lidt %0" : : "m" (idtp));
|
||||
}
|
|
@ -1,255 +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/kernel/irq.c
|
||||
* @brief Function definitions for irq.h and a standard IRQ-handler
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <eduos/stdio.h>
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/tasks.h>
|
||||
#include <eduos/errno.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/idt.h>
|
||||
#include <asm/isrs.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/*
|
||||
* These are our own ISRs that point to our special IRQ handler
|
||||
* instead of the regular 'fault_handler' function
|
||||
*/
|
||||
extern void irq0(void);
|
||||
extern void irq1(void);
|
||||
extern void irq2(void);
|
||||
extern void irq3(void);
|
||||
extern void irq4(void);
|
||||
extern void irq5(void);
|
||||
extern void irq6(void);
|
||||
extern void irq7(void);
|
||||
extern void irq8(void);
|
||||
extern void irq9(void);
|
||||
extern void irq10(void);
|
||||
extern void irq11(void);
|
||||
extern void irq12(void);
|
||||
extern void irq13(void);
|
||||
extern void irq14(void);
|
||||
extern void irq15(void);
|
||||
extern void irq16(void);
|
||||
extern void irq17(void);
|
||||
extern void irq18(void);
|
||||
extern void irq19(void);
|
||||
extern void irq20(void);
|
||||
extern void irq21(void);
|
||||
extern void irq22(void);
|
||||
extern void irq23(void);
|
||||
|
||||
#define MAX_HANDLERS 256
|
||||
|
||||
/** @brief IRQ handle pointers
|
||||
*
|
||||
* This array is actually an array of function pointers. We use
|
||||
* this to handle custom IRQ handlers for a given IRQ
|
||||
*/
|
||||
static void* irq_routines[MAX_HANDLERS] = {[0 ... MAX_HANDLERS-1] = NULL };
|
||||
|
||||
/* This installs a custom IRQ handler for the given IRQ */
|
||||
int irq_install_handler(unsigned int irq, irq_handler_t handler)
|
||||
{
|
||||
if (irq >= MAX_HANDLERS)
|
||||
return -EINVAL;
|
||||
|
||||
irq_routines[irq] = handler;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This clears the handler for a given IRQ */
|
||||
int irq_uninstall_handler(unsigned int irq)
|
||||
{
|
||||
if (irq >= MAX_HANDLERS)
|
||||
return -EINVAL;
|
||||
|
||||
irq_routines[irq] = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Remapping IRQs with a couple of IO output operations
|
||||
*
|
||||
* Normally, IRQs 0 to 7 are mapped to entries 8 to 15. This
|
||||
* is a problem in protected mode, because IDT entry 8 is a
|
||||
* Double Fault! Without remapping, every time IRQ0 fires,
|
||||
* you get a Double Fault Exception, which is NOT what's
|
||||
* actually happening. We send commands to the Programmable
|
||||
* Interrupt Controller (PICs - also called the 8259's) in
|
||||
* order to make IRQ0 to 15 be remapped to IDT entries 32 to
|
||||
* 47
|
||||
*/
|
||||
static int irq_remap(void)
|
||||
{
|
||||
outportb(0x20, 0x11);
|
||||
outportb(0xA0, 0x11);
|
||||
outportb(0x21, 0x20);
|
||||
outportb(0xA1, 0x28);
|
||||
outportb(0x21, 0x04);
|
||||
outportb(0xA1, 0x02);
|
||||
outportb(0x21, 0x01);
|
||||
outportb(0xA1, 0x01);
|
||||
outportb(0x21, 0x0);
|
||||
outportb(0xA1, 0x0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Remap IRQs and install ISRs in IDT
|
||||
*
|
||||
* We first remap the interrupt controllers, and then we install
|
||||
* the appropriate ISRs to the correct entries in the IDT.\n
|
||||
* This is just like installing the exception handlers
|
||||
*/
|
||||
static int irq_install(void)
|
||||
{
|
||||
irq_remap();
|
||||
|
||||
idt_set_gate(32, (size_t)irq0, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(33, (size_t)irq1, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(34, (size_t)irq2, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(35, (size_t)irq3, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(36, (size_t)irq4, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(37, (size_t)irq5, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(38, (size_t)irq6, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(39, (size_t)irq7, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(40, (size_t)irq8, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(41, (size_t)irq9, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(42, (size_t)irq10, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(43, (size_t)irq11, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(44, (size_t)irq12, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(45, (size_t)irq13, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(46, (size_t)irq14, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(47, (size_t)irq15, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(48, (size_t)irq16, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(49, (size_t)irq17, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(50, (size_t)irq18, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(51, (size_t)irq19, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(52, (size_t)irq20, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(53, (size_t)irq21, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(54, (size_t)irq22, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(55, (size_t)irq23, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int irq_init(void)
|
||||
{
|
||||
idt_install();
|
||||
isrs_install();
|
||||
irq_install();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Default IRQ handler
|
||||
*
|
||||
* Each of the IRQ ISRs point to this function, rather than
|
||||
* the 'fault_handler' in 'isrs.c'. The IRQ Controllers need
|
||||
* to be told when you are done servicing them, so you need
|
||||
* to send them an "End of Interrupt" command. If we use the PIC
|
||||
* instead of the APIC, we have two 8259 chips: The first one
|
||||
* exists at 0x20, the second one exists at 0xA0. If the second
|
||||
* controller (an IRQ from 8 to 15) gets an interrupt, you need to
|
||||
* acknowledge the interrupt at BOTH controllers, otherwise, you
|
||||
* only send an EOI command to the first controller. If you don't send
|
||||
* an EOI, it won't raise any more IRQs.
|
||||
*
|
||||
* Note: If we enabled the APIC, we also disabled the PIC. Afterwards,
|
||||
* we get no interrupts between 0 and 15.
|
||||
*/
|
||||
size_t** irq_handler(struct state *s)
|
||||
{
|
||||
/* This is a blank function pointer */
|
||||
void (*handler) (struct state * s);
|
||||
|
||||
/*
|
||||
* Find out if we have a custom handler to run for this
|
||||
* IRQ and then finally, run it
|
||||
*/
|
||||
if (BUILTIN_EXPECT(s->int_no < MAX_HANDLERS, 1)) {
|
||||
handler = irq_routines[s->int_no];
|
||||
if (handler)
|
||||
handler(s);
|
||||
} else kprintf("Invalid interrupt number %d\n", s->int_no);
|
||||
|
||||
/*
|
||||
* If the IDT entry that was invoked was greater-than-or-equal to 40
|
||||
* and lower than 48 (meaning IRQ8 - 15), then we need to
|
||||
* send an EOI to the slave controller of the PIC
|
||||
*/
|
||||
if (s->int_no >= 40)
|
||||
outportb(0xA0, 0x20);
|
||||
|
||||
/*
|
||||
* In either case, we need to send an EOI to the master
|
||||
* interrupt controller of the PIC, too
|
||||
*/
|
||||
outportb(0x20, 0x20);
|
||||
|
||||
// timer interrupt?
|
||||
if (s->int_no == 32)
|
||||
return scheduler(); // switch to a new task
|
||||
else if ((s->int_no >= 32) && (get_highest_priority() > current_task->prio))
|
||||
return scheduler();
|
||||
|
||||
return NULL;
|
||||
}
|
|
@ -1,207 +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/kernel/isrs.c
|
||||
* @brief Installation of interrupt service routines and definition of fault handler.
|
||||
*
|
||||
* This file contains prototypes for the first 32 entries of the IDT,
|
||||
* an ISR installer procedure and a fault handler.\n
|
||||
*/
|
||||
|
||||
#include <eduos/stdio.h>
|
||||
#include <eduos/tasks.h>
|
||||
#include <asm/irqflags.h>
|
||||
#include <asm/isrs.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/idt.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/*
|
||||
* These are function prototypes for all of the exception
|
||||
* handlers: The first 32 entries in the IDT are reserved
|
||||
* by Intel and are designed to service exceptions!
|
||||
*/
|
||||
extern void isr0(void);
|
||||
extern void isr1(void);
|
||||
extern void isr2(void);
|
||||
extern void isr3(void);
|
||||
extern void isr4(void);
|
||||
extern void isr5(void);
|
||||
extern void isr6(void);
|
||||
extern void isr7(void);
|
||||
extern void isr8(void);
|
||||
extern void isr9(void);
|
||||
extern void isr10(void);
|
||||
extern void isr11(void);
|
||||
extern void isr12(void);
|
||||
extern void isr13(void);
|
||||
extern void isr14(void);
|
||||
extern void isr15(void);
|
||||
extern void isr16(void);
|
||||
extern void isr17(void);
|
||||
extern void isr18(void);
|
||||
extern void isr19(void);
|
||||
extern void isr20(void);
|
||||
extern void isr21(void);
|
||||
extern void isr22(void);
|
||||
extern void isr23(void);
|
||||
extern void isr24(void);
|
||||
extern void isr25(void);
|
||||
extern void isr26(void);
|
||||
extern void isr27(void);
|
||||
extern void isr28(void);
|
||||
extern void isr29(void);
|
||||
extern void isr30(void);
|
||||
extern void isr31(void);
|
||||
|
||||
static void fault_handler(struct state *s);
|
||||
|
||||
/*
|
||||
* This is a very repetitive function... it's not hard, it's
|
||||
* just annoying. As you can see, we set the first 32 entries
|
||||
* in the IDT to the first 32 ISRs. We can't use a for loop
|
||||
* for this, because there is no way to get the function names
|
||||
* that correspond to that given entry. We set the access
|
||||
* flags to 0x8E. This means that the entry is present, is
|
||||
* running in ring 0 (kernel level), and has the lower 5 bits
|
||||
* set to the required '14', which is represented by 'E' in
|
||||
* hex.
|
||||
*/
|
||||
void isrs_install(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
idt_set_gate(0, (size_t)isr0, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(1, (size_t)isr1, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(2, (size_t)isr2, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(3, (size_t)isr3, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(4, (size_t)isr4, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(5, (size_t)isr5, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(6, (size_t)isr6, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(7, (size_t)isr7, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(8, (size_t)isr8, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(9, (size_t)isr9, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(10, (size_t)isr10, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(11, (size_t)isr11, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(12, (size_t)isr12, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(13, (size_t)isr13, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(14, (size_t)isr14, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(15, (size_t)isr15, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(16, (size_t)isr16, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(17, (size_t)isr17, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(18, (size_t)isr18, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(19, (size_t)isr19, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(20, (size_t)isr20, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(21, (size_t)isr21, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(22, (size_t)isr22, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(23, (size_t)isr23, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(24, (size_t)isr24, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(25, (size_t)isr25, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(26, (size_t)isr26, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(27, (size_t)isr27, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(28, (size_t)isr28, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(29, (size_t)isr29, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(30, (size_t)isr30, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
idt_set_gate(31, (size_t)isr31, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
||||
|
||||
// install the default handler
|
||||
for(i=0; i<32; i++)
|
||||
irq_install_handler(i, fault_handler);
|
||||
}
|
||||
|
||||
/** @brief Exception messages
|
||||
*
|
||||
* This is a simple string array. It contains the message that
|
||||
* corresponds to each and every exception. We get the correct
|
||||
* message by accessing it like this:
|
||||
* exception_message[interrupt_number]
|
||||
*/
|
||||
static const char *exception_messages[] = {
|
||||
"Division By Zero", "Debug", "Non Maskable Interrupt",
|
||||
"Breakpoint", "Into Detected Overflow", "Out of Bounds", "Invalid Opcode",
|
||||
"No Coprocessor", "Double Fault", "Coprocessor Segment Overrun", "Bad TSS",
|
||||
"Segment Not Present", "Stack Fault", "General Protection Fault", "Page Fault",
|
||||
"Unknown Interrupt", "Coprocessor Fault", "Alignment Check", "Machine Check",
|
||||
"Reserved", "Reserved", "Reserved", "Reserved", "Reserved",
|
||||
"Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved",
|
||||
"Reserved", "Reserved" };
|
||||
|
||||
/*
|
||||
* All of our Exception handling Interrupt Service Routines will
|
||||
* point to this function. This will tell us what exception has
|
||||
* occured! Right now, we simply abort the current task.
|
||||
* All ISRs disable interrupts while they are being
|
||||
* serviced as a 'locking' mechanism to prevent an IRQ from
|
||||
* happening and messing up kernel data structures
|
||||
*/
|
||||
static void fault_handler(struct state *s)
|
||||
{
|
||||
if (s->int_no < 32) {
|
||||
kputs(exception_messages[s->int_no]);
|
||||
kprintf(" Exception (%d) at 0x%x:0x%x, error code 0x%x, eflags 0x%x\n",
|
||||
s->int_no, s->cs, s->eip, s->error, s->eflags);
|
||||
|
||||
outportb(0x20, 0x20);
|
||||
|
||||
irq_enable();
|
||||
abort();
|
||||
}
|
||||
}
|
|
@ -25,27 +25,17 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file arch/x86/include/asm/tasks_types.h
|
||||
* @brief Task related structure definitions
|
||||
*
|
||||
* This file contains the task_t structure definition
|
||||
* and task state define constants
|
||||
#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 __ASM_TASKS_TYPES_H__
|
||||
#define __ASM_TASKS_TYPES_H__
|
||||
multiboot_info_t* mb_info __attribute__ ((section (".data"))) = NULL;
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
void multiboot_init(void* mb)
|
||||
{
|
||||
mb_info = (multiboot_info_t*) mb;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -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
|
@ -1,141 +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/string.h>
|
||||
#include <eduos/time.h>
|
||||
#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;
|
||||
uint64_t ticks, old;
|
||||
|
||||
if (BUILTIN_EXPECT(cpu_freq > 0, 0))
|
||||
return cpu_freq;
|
||||
|
||||
old = get_clock_tick();
|
||||
|
||||
/* wait for the next time slice */
|
||||
while((ticks = get_clock_tick()) - old == 0)
|
||||
HALT;
|
||||
|
||||
rmb();
|
||||
start = rdtsc();
|
||||
/* wait a second to determine the frequency */
|
||||
while(get_clock_tick() - ticks < TIMER_FREQ)
|
||||
HALT;
|
||||
rmb();
|
||||
end = rdtsc();
|
||||
|
||||
diff = end > start ? end - start : start - end;
|
||||
cpu_freq = (uint32_t) (diff / (uint64_t) 1000000);
|
||||
|
||||
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)
|
||||
return cpu_freq;
|
||||
|
||||
return detect_cpu_frequency();
|
||||
}
|
||||
|
|
@ -1,102 +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/stdlib.h>
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/tasks.h>
|
||||
#include <eduos/errno.h>
|
||||
#include <eduos/processor.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int create_default_frame(task_t* task, entry_point_t ep, void* arg)
|
||||
{
|
||||
size_t *stack;
|
||||
struct state *stptr;
|
||||
size_t state_size;
|
||||
|
||||
if (BUILTIN_EXPECT(!task, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (BUILTIN_EXPECT(!task->stack, 0))
|
||||
return -EINVAL;
|
||||
|
||||
memset(task->stack, 0xCD, KERNEL_STACK_SIZE);
|
||||
|
||||
/* The difference between setting up a task for SW-task-switching
|
||||
* 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
|
||||
|
||||
/* Only marker for debugging purposes, ... */
|
||||
*stack-- = 0xDEADBEEF;
|
||||
/* the first-function-to-be-called's arguments, ... */
|
||||
*stack-- = (size_t) arg;
|
||||
|
||||
/* and the "caller" we shall return to.
|
||||
* This procedure cleans the task after exit. */
|
||||
*stack = (size_t) leave_kernel_task;
|
||||
|
||||
/* Next bunch on the stack is the initial register state.
|
||||
* The stack must look like the stack of a task which was
|
||||
* scheduled away previously. */
|
||||
|
||||
state_size = sizeof(struct state) - 2*sizeof(size_t);
|
||||
stack = (size_t*) ((size_t) stack - state_size);
|
||||
|
||||
stptr = (struct state *) stack;
|
||||
memset(stptr, 0x00, state_size);
|
||||
stptr->esp = (size_t)stack + state_size;
|
||||
|
||||
stptr->int_no = 0xB16B00B5;
|
||||
stptr->error = 0xC03DB4B3;
|
||||
|
||||
/* The instruction pointer shall be set on the first function to be called
|
||||
after IRETing */
|
||||
stptr->eip = (size_t)ep;
|
||||
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
|
||||
|
||||
/* Set the task's stack pointer entry to the stack we have crafted right now. */
|
||||
task->last_stack_pointer = (size_t*)stack;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,110 +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/tasks.h>
|
||||
#include <eduos/time.h>
|
||||
#include <eduos/errno.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/irqflags.h>
|
||||
#include <asm/vga.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/*
|
||||
* This will keep track of how many ticks the system
|
||||
* has been running for
|
||||
*/
|
||||
static volatile uint64_t timer_ticks = 0;
|
||||
|
||||
uint64_t get_clock_tick(void)
|
||||
{
|
||||
return timer_ticks;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles the timer. In this case, it's very simple: We
|
||||
* increment the 'timer_ticks' variable every time the
|
||||
* timer fires.
|
||||
*/
|
||||
static void timer_handler(struct state *s)
|
||||
{
|
||||
/* Increment our 'tick counter' */
|
||||
timer_ticks++;
|
||||
|
||||
/*
|
||||
* 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");
|
||||
//}
|
||||
}
|
||||
|
||||
#define LATCH(f) ((CLOCK_TICK_RATE + f/2) / f)
|
||||
#define WAIT_SOME_TIME() do { uint64_t start = rdtsc(); \
|
||||
while(rdtsc() - start < 1000000) ; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Sets up the system clock by installing the timer handler
|
||||
* into IRQ0
|
||||
*/
|
||||
int timer_init(void)
|
||||
{
|
||||
/*
|
||||
* Installs 'timer_handler' for the PIC and APIC timer,
|
||||
* only one handler will be later used.
|
||||
*/
|
||||
irq_install_handler(32, timer_handler);
|
||||
irq_install_handler(123, timer_handler);
|
||||
|
||||
/*
|
||||
* Port 0x43 is for initializing the PIT:
|
||||
*
|
||||
* 0x34 means the following:
|
||||
* 0b... (step-by-step binary representation)
|
||||
* ... 00 - channel 0
|
||||
* ... 11 - write two values to counter register:
|
||||
* first low-, then high-byte
|
||||
* ... 010 - mode number 2: "rate generator" / frequency divider
|
||||
* ... 0 - binary counter (the alternative is BCD)
|
||||
*/
|
||||
outportb(0x43, 0x34);
|
||||
|
||||
WAIT_SOME_TIME();
|
||||
|
||||
/* Port 0x40 is for the counter register of channel 0 */
|
||||
|
||||
outportb(0x40, LATCH(TIMER_FREQ) & 0xFF); /* low byte */
|
||||
|
||||
WAIT_SOME_TIME();
|
||||
|
||||
outportb(0x40, LATCH(TIMER_FREQ) >> 8); /* high byte */
|
||||
|
||||
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
|
|
@ -29,8 +29,6 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/vga.h>
|
||||
|
||||
#ifdef CONFIG_VGA
|
||||
|
||||
/*
|
||||
* These define our textpointer, our background and foreground
|
||||
* colors (attributes), and x and y cursor coordinates
|
||||
|
@ -235,5 +233,3 @@ void vga_init(void)
|
|||
textmemptr = (unsigned short *)VIDEO_MEM_ADDR;
|
||||
vga_clear();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
C_source := page.c
|
||||
MODULE := arch_x86_mm
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
|
@ -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; }
|
||||
|
|
|
@ -33,22 +33,9 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#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 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 VIDEO_MEM_ADDR 0xB8000 // the video memora address
|
||||
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
#define CONFIG_VGA
|
||||
#define CONFIG_PCI
|
||||
#define CONFIG_UART
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
#define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b))
|
||||
//#define BUILTIN_EXPECT(exp, b) (exp)
|
||||
|
|
|
@ -1,180 +0,0 @@
|
|||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file include/eduos/errno.h
|
||||
* @brief Error number define constants
|
||||
*
|
||||
* This file just contains the full list of error numbers which can
|
||||
* be returned somewhere. In principle, we use the same error codes
|
||||
* than newlib.
|
||||
*/
|
||||
|
||||
#ifndef __ERRNO_H__
|
||||
#define __ERRNO_H__
|
||||
|
||||
#include <eduos/config.h>
|
||||
#include <asm/stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define EPERM 1 /* Not super-user */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Arg list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No children */
|
||||
#define EAGAIN 11 /* No more processes */
|
||||
#define ENOMEM 12 /* Not enough core */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#ifdef __LINUX_ERRNO_EXTENSIONS__
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#endif
|
||||
#define EBUSY 16 /* Mount device busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* Too many open files in system */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math arg out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
#define ENOMSG 35 /* No message of desired type */
|
||||
#define EIDRM 36 /* Identifier removed */
|
||||
#ifdef __LINUX_ERRNO_EXTENSIONS__
|
||||
#define ECHRNG 37 /* Channel number out of range */
|
||||
#define EL2NSYNC 38 /* Level 2 not synchronized */
|
||||
#define EL3HLT 39 /* Level 3 halted */
|
||||
#define EL3RST 40 /* Level 3 reset */
|
||||
#define ELNRNG 41 /* Link number out of range */
|
||||
#define EUNATCH 42 /* Protocol driver not attached */
|
||||
#define ENOCSI 43 /* No CSI structure available */
|
||||
#define EL2HLT 44 /* Level 2 halted */
|
||||
#endif
|
||||
#define EDEADLK 45 /* Deadlock condition */
|
||||
#define ENOLCK 46 /* No record locks available */
|
||||
#ifdef __LINUX_ERRNO_EXTENSIONS__
|
||||
#define EBADE 50 /* Invalid exchange */
|
||||
#define EBADR 51 /* Invalid request descriptor */
|
||||
#define EXFULL 52 /* Exchange full */
|
||||
#define ENOANO 53 /* No anode */
|
||||
#define EBADRQC 54 /* Invalid request code */
|
||||
#define EBADSLT 55 /* Invalid slot */
|
||||
#define EDEADLOCK 56 /* File locking deadlock error */
|
||||
#define EBFONT 57 /* Bad font file fmt */
|
||||
#endif
|
||||
#define ENOSTR 60 /* Device not a stream */
|
||||
#define ENODATA 61 /* No data (for no delay io) */
|
||||
#define ETIME 62 /* Timer expired */
|
||||
#define ENOSR 63 /* Out of streams resources */
|
||||
#ifdef __LINUX_ERRNO_EXTENSIONS__
|
||||
#define ENONET 64 /* Machine is not on the network */
|
||||
#define ENOPKG 65 /* Package not installed */
|
||||
#define EREMOTE 66 /* The object is remote */
|
||||
#endif
|
||||
#define ENOLINK 67 /* The link has been severed */
|
||||
#ifdef __LINUX_ERRNO_EXTENSIONS__
|
||||
#define EADV 68 /* Advertise error */
|
||||
#define ESRMNT 69 /* Srmount error */
|
||||
#define ECOMM 70 /* Communication error on send */
|
||||
#endif
|
||||
#define EPROTO 71 /* Protocol error */
|
||||
#define EMULTIHOP 74 /* Multihop attempted */
|
||||
#ifdef __LINUX_ERRNO_EXTENSIONS__
|
||||
#define ELBIN 75 /* Inode is remote (not really error) */
|
||||
#define EDOTDOT 76 /* Cross mount point (not really error) */
|
||||
#endif
|
||||
#define EBADMSG 77 /* Trying to read unreadable message */
|
||||
#define EFTYPE 79 /* Inappropriate file type or format */
|
||||
#ifdef __LINUX_ERRNO_EXTENSIONS__
|
||||
#define ENOTUNIQ 80 /* Given log. name not unique */
|
||||
#define EBADFD 81 /* f.d. invalid for this operation */
|
||||
#define EREMCHG 82 /* Remote address changed */
|
||||
#define ELIBACC 83 /* Can't access a needed shared lib */
|
||||
#define ELIBBAD 84 /* Accessing a corrupted shared lib */
|
||||
#define ELIBSCN 85 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 86 /* Attempting to link in too many libs */
|
||||
#define ELIBEXEC 87 /* Attempting to exec a shared library */
|
||||
#endif
|
||||
#define ENOSYS 88 /* Function not implemented */
|
||||
#ifdef __CYGWIN__
|
||||
#define ENMFILE 89 /* No more files */
|
||||
#endif
|
||||
#define ENOTEMPTY 90 /* Directory not empty */
|
||||
#define ENAMETOOLONG 91 /* File or path name too long */
|
||||
#define ELOOP 92 /* Too many symbolic links */
|
||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||
#define ECONNRESET 104 /* Connection reset by peer */
|
||||
#define ENOBUFS 105 /* No buffer space available */
|
||||
#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */
|
||||
#define EPROTOTYPE 107 /* Protocol wrong type for socket */
|
||||
#define ENOTSOCK 108 /* Socket operation on non-socket */
|
||||
#define ENOPROTOOPT 109 /* Protocol not available */
|
||||
#ifdef __LINUX_ERRNO_EXTENSIONS__
|
||||
#define ESHUTDOWN 110 /* Can't send after socket shutdown */
|
||||
#endif
|
||||
#define ECONNREFUSED 111 /* Connection refused */
|
||||
#define EADDRINUSE 112 /* Address already in use */
|
||||
#define ECONNABORTED 113 /* Connection aborted */
|
||||
#define ENETUNREACH 114 /* Network is unreachable */
|
||||
#define ENETDOWN 115 /* Network interface is not configured */
|
||||
#define ETIMEDOUT 116 /* Connection timed out */
|
||||
#define EHOSTDOWN 117 /* Host is down */
|
||||
#define EHOSTUNREACH 118 /* Host is unreachable */
|
||||
#define EINPROGRESS 119 /* Connection already in progress */
|
||||
#define EALREADY 120 /* Socket already connected */
|
||||
#define EDESTADDRREQ 121 /* Destination address required */
|
||||
#define EMSGSIZE 122 /* Message too long */
|
||||
#define EPROTONOSUPPORT 123 /* Unknown protocol */
|
||||
#ifdef __LINUX_ERRNO_EXTENSIONS__
|
||||
#define ESOCKTNOSUPPORT 124 /* Socket type not supported */
|
||||
#endif
|
||||
#define EADDRNOTAVAIL 125 /* Address not available */
|
||||
#define ENETRESET 126
|
||||
#define EISCONN 127 /* Socket is already connected */
|
||||
#define ENOTCONN 128 /* Socket is not connected */
|
||||
#define ETOOMANYREFS 129
|
||||
#ifdef __LINUX_ERRNO_EXTENSIONS__
|
||||
#define EPROCLIM 130
|
||||
#define EUSERS 131
|
||||
#endif
|
||||
#define EDQUOT 132
|
||||
#define ESTALE 133
|
||||
#define ENOTSUP 134 /* Not supported */
|
||||
#ifdef __LINUX_ERRNO_EXTENSIONS__
|
||||
#define ENOMEDIUM 135 /* No medium (in tape drive) */
|
||||
#endif
|
||||
#ifdef __CYGWIN__
|
||||
#define ENOSHARE 136 /* No such host or network path */
|
||||
#define ECASECLASH 137 /* Filename exists with different case */
|
||||
#endif
|
||||
#define EILSEQ 138
|
||||
#define EOVERFLOW 139 /* Value too large for defined data type */
|
||||
#define ECANCELED 140 /* Operation canceled */
|
||||
#define ENOTRECOVERABLE 141 /* State not recoverable */
|
||||
#define EOWNERDEAD 142 /* Previous owner died */
|
||||
#ifdef __LINUX_ERRNO_EXTENSIONS__
|
||||
#define ESTRPIPE 143 /* Streams pipe error */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -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
|
|
@ -1,48 +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 Steffen Vogel
|
||||
* @file include/memory.h
|
||||
* @brief Memory related functions
|
||||
*
|
||||
* This file contains platform independent memory functions
|
||||
*/
|
||||
|
||||
#ifndef __MEMORY_H__
|
||||
#define __MEMORY_H__
|
||||
|
||||
/** @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
|
|
@ -1,177 +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/eduos/semaphore.h
|
||||
* @brief semaphore functions definition
|
||||
*/
|
||||
|
||||
#ifndef __SEMAPHORE_H__
|
||||
#define __SEMAPHORE_H__
|
||||
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/tasks.h>
|
||||
#include <eduos/semaphore_types.h>
|
||||
#include <eduos/spinlock.h>
|
||||
#include <eduos/errno.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Semaphore initialization
|
||||
*
|
||||
* Always init semaphores before use!
|
||||
*
|
||||
* @param s Pointer to semaphore structure to initialize
|
||||
* @param v Resource count
|
||||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL on invalid argument
|
||||
*/
|
||||
inline static int sem_init(sem_t* s, unsigned int v) {
|
||||
unsigned int i;
|
||||
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
s->value = v;
|
||||
s->pos = 0;
|
||||
for(i=0; i<MAX_TASKS; i++)
|
||||
s->queue[i] = MAX_TASKS;
|
||||
spinlock_irqsave_init(&s->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Destroy semaphore
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL on invalid argument
|
||||
*/
|
||||
inline static int sem_destroy(sem_t* s) {
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
spinlock_irqsave_destroy(&s->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Nonblocking trywait for sempahore
|
||||
*
|
||||
* Will return immediately if not available
|
||||
*
|
||||
* @return
|
||||
* - 0 on success (You got the semaphore)
|
||||
* - -EINVAL on invalid argument
|
||||
* - -ECANCELED on failure (You still have to wait)
|
||||
*/
|
||||
inline static int sem_trywait(sem_t* s) {
|
||||
int ret = -ECANCELED;
|
||||
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
spinlock_irqsave_lock(&s->lock);
|
||||
if (s->value > 0) {
|
||||
s->value--;
|
||||
ret = 0;
|
||||
}
|
||||
spinlock_irqsave_unlock(&s->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Blocking wait for semaphore
|
||||
*
|
||||
* @param s Address of the according sem_t structure
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL on invalid argument
|
||||
* - -ETIME on timer expired
|
||||
*/
|
||||
inline static int sem_wait(sem_t* s) {
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
next_try1:
|
||||
spinlock_irqsave_lock(&s->lock);
|
||||
if (s->value > 0) {
|
||||
s->value--;
|
||||
spinlock_irqsave_unlock(&s->lock);
|
||||
} else {
|
||||
s->queue[s->pos] = current_task->id;
|
||||
s->pos = (s->pos + 1) % MAX_TASKS;
|
||||
block_current_task();
|
||||
spinlock_irqsave_unlock(&s->lock);
|
||||
reschedule();
|
||||
goto next_try1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Give back resource
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL on invalid argument
|
||||
*/
|
||||
inline static int sem_post(sem_t* s) {
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
spinlock_irqsave_lock(&s->lock);
|
||||
if (s->value > 0) {
|
||||
s->value++;
|
||||
spinlock_irqsave_unlock(&s->lock);
|
||||
} else {
|
||||
unsigned int k, i;
|
||||
|
||||
s->value++;
|
||||
i = s->pos;
|
||||
for(k=0; k<MAX_TASKS; k++) {
|
||||
if (s->queue[i] < MAX_TASKS) {
|
||||
wakeup_task(s->queue[i]);
|
||||
s->queue[i] = MAX_TASKS;
|
||||
break;
|
||||
}
|
||||
i = (i + 1) % MAX_TASKS;
|
||||
}
|
||||
spinlock_irqsave_unlock(&s->lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,62 +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/eduos/semaphore_types.h
|
||||
* @brief semaphore type definition
|
||||
*/
|
||||
|
||||
#ifndef __SEMAPHORE_TYPES_H__
|
||||
#define __SEMAPHORE_TYPES_H__
|
||||
|
||||
#include <eduos/spinlock_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Semaphore structure */
|
||||
typedef struct {
|
||||
/// Resource available count
|
||||
unsigned int value;
|
||||
/// Queue of waiting tasks
|
||||
tid_t queue[MAX_TASKS];
|
||||
/// Position in queue
|
||||
unsigned int pos;
|
||||
/// Access lock
|
||||
spinlock_irqsave_t lock;
|
||||
} sem_t;
|
||||
|
||||
/// Macro for initialization of semaphore
|
||||
#define SEM_INIT(v) {v, {[0 ... MAX_TASKS-1] = MAX_TASKS}, 0, SPINLOCK_IRQSAVE_INIT}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,219 +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/spinlock.h
|
||||
* @brief Spinlock functions
|
||||
*/
|
||||
|
||||
#ifndef __SPINLOCK_H__
|
||||
#define __SPINLOCK_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
#include <eduos/spinlock_types.h>
|
||||
#include <eduos/tasks_types.h>
|
||||
#include <eduos/errno.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/irqflags.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Initialization of a spinlock
|
||||
*
|
||||
* Initialize each spinlock before use!
|
||||
*
|
||||
* @param s Pointer to the spinlock structure to initialize.
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
inline static int spinlock_init(spinlock_t* s) {
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
atomic_int32_set(&s->queue, 0);
|
||||
atomic_int32_set(&s->dequeue, 1);
|
||||
s->owner = MAX_TASKS;
|
||||
s->counter = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Destroy spinlock after use
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
inline static int spinlock_destroy(spinlock_t* s) {
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
s->owner = MAX_TASKS;
|
||||
s->counter = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Lock spinlock at entry of critical section
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
inline static int spinlock_lock(spinlock_t* s) {
|
||||
int32_t ticket;
|
||||
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (s->owner == current_task->id) {
|
||||
s->counter++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ticket = atomic_int32_add(&s->queue, 1);
|
||||
while(atomic_int32_read(&s->dequeue) != ticket) {
|
||||
PAUSE;
|
||||
}
|
||||
s->owner = current_task->id;
|
||||
s->counter = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Unlock spinlock on exit of critical section
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
inline static int spinlock_unlock(spinlock_t* s) {
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
s->counter--;
|
||||
if (!s->counter) {
|
||||
s->owner = MAX_TASKS;
|
||||
atomic_int32_inc(&s->dequeue);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Initialization of a irqsave spinlock
|
||||
*
|
||||
* Initialize each irqsave spinlock before use!
|
||||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
inline static int spinlock_irqsave_init(spinlock_irqsave_t* s) {
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
atomic_int32_set(&s->queue, 0);
|
||||
atomic_int32_set(&s->dequeue, 1);
|
||||
s->flags = 0;
|
||||
s->counter = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Destroy irqsave spinlock after use
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
inline static int spinlock_irqsave_destroy(spinlock_irqsave_t* s) {
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
s->flags = 0;
|
||||
s->counter = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Unlock an irqsave spinlock on exit of critical section
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
inline static int spinlock_irqsave_lock(spinlock_irqsave_t* s) {
|
||||
int32_t ticket;
|
||||
uint8_t flags;
|
||||
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
flags = irq_nested_disable();
|
||||
if (s->counter == 1) {
|
||||
s->counter++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ticket = atomic_int32_add(&s->queue, 1);
|
||||
while (atomic_int32_read(&s->dequeue) != ticket) {
|
||||
PAUSE;
|
||||
}
|
||||
|
||||
s->flags = flags;
|
||||
s->counter = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Unlock irqsave spinlock on exit of critical section and re-enable interrupts
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
inline static int spinlock_irqsave_unlock(spinlock_irqsave_t* s) {
|
||||
uint8_t flags;
|
||||
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
s->counter--;
|
||||
if (!s->counter) {
|
||||
flags = s->flags;
|
||||
s->flags = 0;
|
||||
atomic_int32_inc(&s->dequeue);
|
||||
irq_nested_enable(flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,77 +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/spinlock_types.h
|
||||
* @brief Spinlock type definition
|
||||
*/
|
||||
|
||||
#ifndef __SPINLOCK_TYPES_H__
|
||||
#define __SPINLOCK_TYPES_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Spinlock structure */
|
||||
typedef struct spinlock {
|
||||
/// Internal queue
|
||||
atomic_int32_t queue;
|
||||
/// Internal dequeue
|
||||
atomic_int32_t dequeue;
|
||||
/// Owner of this spinlock structure
|
||||
tid_t owner;
|
||||
/// Internal counter var
|
||||
uint32_t counter;
|
||||
} spinlock_t;
|
||||
|
||||
typedef struct spinlock_irqsave {
|
||||
/// Internal queue
|
||||
atomic_int32_t queue;
|
||||
/// Internal dequeue
|
||||
atomic_int32_t dequeue;
|
||||
/// Internal counter var
|
||||
uint32_t counter;
|
||||
/// Interrupt flag
|
||||
uint8_t flags;
|
||||
} spinlock_irqsave_t;
|
||||
|
||||
/// Macro for spinlock initialization
|
||||
#define SPINLOCK_INIT { ATOMIC_INIT(0), ATOMIC_INIT(1), MAX_TASKS, 0}
|
||||
/// Macro for irqsave spinlock initialization
|
||||
#define SPINLOCK_IRQSAVE_INIT { ATOMIC_INIT(0), ATOMIC_INIT(1), 0, 0}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -28,27 +28,17 @@
|
|||
#ifndef __STDARG_H__
|
||||
#define __STDARG_H__
|
||||
|
||||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file include/eduos/stdarg.h
|
||||
* @brief Definition of variable argument lists
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef __builtin_va_list va_list;
|
||||
|
||||
/// Initialize a variable argument list
|
||||
#define va_start __builtin_va_start
|
||||
/// Retrieve next argument
|
||||
#define va_arg __builtin_va_arg
|
||||
/// End using variable argument list
|
||||
#define va_end __builtin_va_end
|
||||
/// copies the (previously initialized) variable argument list
|
||||
#define va_end __builtin_va_end
|
||||
#define va_copy __builtin_va_copy
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -28,12 +28,6 @@
|
|||
#ifndef __STDDEF_H__
|
||||
#define __STDDEF_H__
|
||||
|
||||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file include/eduos/stddef.h
|
||||
* @brief Definition of basic data types
|
||||
*/
|
||||
|
||||
#include <eduos/config.h>
|
||||
#include <asm/stddef.h>
|
||||
|
||||
|
@ -43,12 +37,12 @@ extern "C" {
|
|||
|
||||
#define NULL ((void*) 0)
|
||||
|
||||
/// represents a task identifier
|
||||
typedef unsigned int tid_t;
|
||||
|
||||
struct task;
|
||||
/// pointer to the current (running) task
|
||||
extern struct task* current_task;
|
||||
/*
|
||||
* macros, which are later used to determine the core id
|
||||
* and their "private" data
|
||||
*/
|
||||
#define per_core(name) name
|
||||
#define CORE_ID 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -44,12 +44,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Create a new stack for a new task
|
||||
*
|
||||
* @return start address of the new stack
|
||||
*/
|
||||
void* create_stack(tid_t id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -28,12 +28,6 @@
|
|||
#ifndef __STRING_H__
|
||||
#define __STRING_H__
|
||||
|
||||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file include/eduos/string.h
|
||||
* @brief Definition of basic string and memory opeations
|
||||
*/
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
#include <asm/string.h>
|
||||
|
||||
|
|
|
@ -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
|
|
@ -1,131 +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/eduos/tasks.h
|
||||
* @brief Task related
|
||||
*
|
||||
* Create and leave tasks or fork them.
|
||||
*/
|
||||
|
||||
#ifndef __TASKS_H__
|
||||
#define __TASKS_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
#include <eduos/tasks_types.h>
|
||||
#include <asm/tasks.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
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
|
||||
*
|
||||
* @return
|
||||
* - 0 no context switch
|
||||
* - !0 address of the old stack pointer
|
||||
*/
|
||||
size_t** scheduler(void);
|
||||
|
||||
/** @brief Initialize the multitasking subsystem
|
||||
*
|
||||
* This procedure sets the current task to the
|
||||
* current "task" (there are no tasks, yet) and that was it.
|
||||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -ENOMEM (-12) on failure
|
||||
*/
|
||||
int multitasking_init(void);
|
||||
|
||||
/** @brief create a kernel-level 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
|
||||
* @param args Arguments the task shall start with
|
||||
* @param prio Desired priority of the new kernel task
|
||||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
int create_kernel_task(tid_t* id, entry_point_t ep, void* args, uint8_t prio);
|
||||
|
||||
/** @brief determine the highest priority of all tasks, which are ready
|
||||
*
|
||||
* @return
|
||||
* - return highest priority
|
||||
* - if no task is ready, the function returns an invalid value (> MAX_PRIO)
|
||||
*/
|
||||
uint32_t get_highest_priority(void);
|
||||
|
||||
/** @brief Call to rescheduling
|
||||
*
|
||||
* This is a purely assembled procedure for rescheduling
|
||||
*/
|
||||
void reschedule(void);
|
||||
|
||||
/** @brief Wake up a blocked task
|
||||
*
|
||||
* The task's status will be changed to TASK_READY
|
||||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
int wakeup_task(tid_t);
|
||||
|
||||
/** @brief Block current task
|
||||
*
|
||||
* The current task's status will be changed to TASK_BLOCKED
|
||||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
int block_current_task(void);
|
||||
|
||||
/** @brief Abort current task */
|
||||
void NORETURN abort(void);
|
||||
|
||||
/** @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
|
||||
|
||||
#endif
|
|
@ -1,115 +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/eduos/tasks_types.h
|
||||
* @brief Task related structure definitions
|
||||
*
|
||||
* This file contains the task_t structure definition
|
||||
* and task state define constants
|
||||
*/
|
||||
|
||||
#ifndef __TASKS_TYPES_H__
|
||||
#define __TASKS_TYPES_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
#include <eduos/spinlock_types.h>
|
||||
|
||||
#include <asm/tasks_types.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TASK_INVALID 0
|
||||
#define TASK_READY 1
|
||||
#define TASK_RUNNING 2
|
||||
#define TASK_BLOCKED 3
|
||||
#define TASK_FINISHED 4
|
||||
#define TASK_IDLE 5
|
||||
|
||||
#define MAX_PRIO 31
|
||||
#define REALTIME_PRIO 31
|
||||
#define HIGH_PRIO 16
|
||||
#define NORMAL_PRIO 8
|
||||
#define LOW_PRIO 1
|
||||
#define IDLE_PRIO 0
|
||||
|
||||
typedef int (*entry_point_t)(void*);
|
||||
|
||||
/** @brief Represents a the process control block */
|
||||
typedef struct task {
|
||||
/// Task id = position in the task table
|
||||
tid_t id __attribute__ ((aligned (CACHE_LINE)));
|
||||
/// Task status (INVALID, READY, RUNNING, ...)
|
||||
uint32_t status;
|
||||
/// copy of the stack pointer before a context switch
|
||||
size_t* last_stack_pointer;
|
||||
/// start address of the stack
|
||||
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
|
||||
struct task* prev;
|
||||
} task_t;
|
||||
|
||||
typedef struct {
|
||||
task_t* first;
|
||||
task_t* last;
|
||||
} task_list_t;
|
||||
|
||||
/** @brief Represents a queue for all runable tasks */
|
||||
typedef struct {
|
||||
/// idle task
|
||||
task_t* idle __attribute__ ((aligned (CACHE_LINE)));
|
||||
/// previous task
|
||||
task_t* old_task;
|
||||
/// total number of tasks in the queue
|
||||
uint32_t nr_tasks;
|
||||
/// indicates the used priority queues
|
||||
uint32_t prio_bitmap;
|
||||
/// a queue for each priority
|
||||
task_list_t queue[MAX_PRIO-1];
|
||||
/// lock for this runqueue
|
||||
spinlock_irqsave_t lock;
|
||||
} readyqueues_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,56 +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/eduos/time.h
|
||||
* @brief Time related functions
|
||||
*/
|
||||
|
||||
#ifndef __TIME_H__
|
||||
#define __TIME_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Initialize Timer interrupts
|
||||
*
|
||||
* This procedure installs IRQ handlers for timer interrupts
|
||||
*/
|
||||
int timer_init(void);
|
||||
|
||||
/** @brief Returns the current number of ticks.
|
||||
* @return Current number of ticks
|
||||
*/
|
||||
uint64_t get_clock_tick(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
C_source := main.c tasks.c syscall.c
|
||||
C_source := main.c
|
||||
MODULE := kernel
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
||||
|
|
|
@ -28,20 +28,9 @@
|
|||
#include <eduos/stddef.h>
|
||||
#include <eduos/stdio.h>
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/time.h>
|
||||
#include <eduos/tasks.h>
|
||||
#include <eduos/processor.h>
|
||||
#include <eduos/tasks.h>
|
||||
#include <eduos/syscall.h>
|
||||
#include <eduos/memory.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,105 +41,26 @@ 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 int foo(void* arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<10; i++) {
|
||||
kprintf("hello from %s\n", (char*) arg);
|
||||
}
|
||||
|
||||
// demo of an exception
|
||||
/*i = 0;
|
||||
i = 32 / i;
|
||||
kprintf("i = %d\n", i);*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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();
|
||||
multitasking_init();
|
||||
memory_init();
|
||||
#ifdef CONFIG_UART
|
||||
uart_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
|
||||
create_kernel_task(&id1, foo, "foo1", NORMAL_PRIO);
|
||||
create_kernel_task(&id2, wrapper, "userfoo", NORMAL_PRIO);
|
||||
|
||||
kprintf("\nHello World!\n");
|
||||
|
||||
while(1) {
|
||||
HALT;
|
||||
NOP8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -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;
|
||||
}
|
417
kernel/tasks.c
417
kernel/tasks.c
|
@ -1,417 +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/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}};
|
||||
|
||||
static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT;
|
||||
|
||||
static readyqueues_t readyqueues = {task_table+0, NULL, 0, 0, {[0 ... MAX_PRIO-2] = {NULL, NULL}}, SPINLOCK_IRQSAVE_INIT};
|
||||
|
||||
task_t* current_task = task_table+0;
|
||||
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)
|
||||
{
|
||||
return current_task;
|
||||
}
|
||||
|
||||
uint32_t get_highest_priority(void)
|
||||
{
|
||||
return msb(readyqueues.prio_bitmap);
|
||||
}
|
||||
|
||||
int multitasking_init(void)
|
||||
{
|
||||
if (BUILTIN_EXPECT(task_table[0].status != TASK_IDLE, 0)) {
|
||||
kputs("Task 0 is not an idle task\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void finish_task_switch(void)
|
||||
{
|
||||
task_t* old;
|
||||
uint8_t prio;
|
||||
|
||||
spinlock_irqsave_lock(&readyqueues.lock);
|
||||
|
||||
if ((old = readyqueues.old_task) != NULL) {
|
||||
if (old->status == TASK_INVALID) {
|
||||
old->stack = NULL;
|
||||
old->last_stack_pointer = NULL;
|
||||
readyqueues.old_task = NULL;
|
||||
} else {
|
||||
prio = old->prio;
|
||||
if (!readyqueues.queue[prio-1].first) {
|
||||
old->next = old->prev = NULL;
|
||||
readyqueues.queue[prio-1].first = readyqueues.queue[prio-1].last = old;
|
||||
} else {
|
||||
old->next = NULL;
|
||||
old->prev = readyqueues.queue[prio-1].last;
|
||||
readyqueues.queue[prio-1].last->next = old;
|
||||
readyqueues.queue[prio-1].last = old;
|
||||
}
|
||||
readyqueues.old_task = NULL;
|
||||
readyqueues.prio_bitmap |= (1 << prio);
|
||||
}
|
||||
}
|
||||
|
||||
spinlock_irqsave_unlock(&readyqueues.lock);
|
||||
}
|
||||
|
||||
/** @brief A procedure to be called by
|
||||
* procedures which are called by exiting tasks. */
|
||||
static void NORETURN do_exit(int arg)
|
||||
{
|
||||
task_t* curr_task = current_task;
|
||||
|
||||
kprintf("Terminate task: %u, return value %d\n", curr_task->id, arg);
|
||||
|
||||
page_map_drop();
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief A procedure to be called by kernel tasks */
|
||||
void NORETURN leave_kernel_task(void) {
|
||||
int result;
|
||||
|
||||
result = 0; //get_return_value();
|
||||
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
|
||||
* @param arg Arguments list
|
||||
* @param prio Desired priority of the new task
|
||||
* @param core_id Start the new task on the core with this id
|
||||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -ENOMEM (-12) or -EINVAL (-22) on failure
|
||||
*/
|
||||
static int create_task(tid_t* id, entry_point_t ep, void* arg, uint8_t prio)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
uint32_t i;
|
||||
|
||||
if (BUILTIN_EXPECT(!ep, 0))
|
||||
return -EINVAL;
|
||||
if (BUILTIN_EXPECT(prio == IDLE_PRIO, 0))
|
||||
return -EINVAL;
|
||||
if (BUILTIN_EXPECT(prio > MAX_PRIO, 0))
|
||||
return -EINVAL;
|
||||
|
||||
spinlock_irqsave_lock(&table_lock);
|
||||
|
||||
for(i=0; i<MAX_TASKS; i++) {
|
||||
if (task_table[i].status == TASK_INVALID) {
|
||||
task_table[i].id = i;
|
||||
task_table[i].status = TASK_READY;
|
||||
task_table[i].last_stack_pointer = NULL;
|
||||
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;
|
||||
|
||||
ret = create_default_frame(task_table+i, ep, arg);
|
||||
|
||||
// add task in the readyqueues
|
||||
spinlock_irqsave_lock(&readyqueues.lock);
|
||||
readyqueues.prio_bitmap |= (1 << prio);
|
||||
readyqueues.nr_tasks++;
|
||||
if (!readyqueues.queue[prio-1].first) {
|
||||
task_table[i].next = task_table[i].prev = NULL;
|
||||
readyqueues.queue[prio-1].first = task_table+i;
|
||||
readyqueues.queue[prio-1].last = task_table+i;
|
||||
} else {
|
||||
task_table[i].prev = readyqueues.queue[prio-1].last;
|
||||
task_table[i].next = NULL;
|
||||
readyqueues.queue[prio-1].last->next = task_table+i;
|
||||
readyqueues.queue[prio-1].last = task_table+i;
|
||||
}
|
||||
spinlock_irqsave_unlock(&readyqueues.lock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
spinlock_irqsave_unlock(&table_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int create_kernel_task(tid_t* id, entry_point_t ep, void* args, uint8_t prio)
|
||||
{
|
||||
if (prio > MAX_PRIO)
|
||||
prio = NORMAL_PRIO;
|
||||
|
||||
return create_task(id, ep, args, prio);
|
||||
}
|
||||
|
||||
/** @brief Wakeup a blocked task
|
||||
* @param id The task's tid_t structure
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
int wakeup_task(tid_t id)
|
||||
{
|
||||
task_t* task;
|
||||
uint32_t prio;
|
||||
int ret = -EINVAL;
|
||||
uint8_t flags;
|
||||
|
||||
flags = irq_nested_disable();
|
||||
|
||||
task = task_table + id;
|
||||
prio = task->prio;
|
||||
|
||||
if (task->status == TASK_BLOCKED) {
|
||||
task->status = TASK_READY;
|
||||
ret = 0;
|
||||
|
||||
spinlock_irqsave_lock(&readyqueues.lock);
|
||||
// increase the number of ready tasks
|
||||
readyqueues.nr_tasks++;
|
||||
|
||||
// add task to the runqueue
|
||||
if (!readyqueues.queue[prio-1].last) {
|
||||
readyqueues.queue[prio-1].last = readyqueues.queue[prio-1].first = task;
|
||||
task->next = task->prev = NULL;
|
||||
readyqueues.prio_bitmap |= (1 << prio);
|
||||
} else {
|
||||
task->prev = readyqueues.queue[prio-1].last;
|
||||
task->next = NULL;
|
||||
readyqueues.queue[prio-1].last->next = task;
|
||||
readyqueues.queue[prio-1].last = task;
|
||||
}
|
||||
spinlock_irqsave_unlock(&readyqueues.lock);
|
||||
}
|
||||
|
||||
irq_nested_enable(flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Block current task
|
||||
*
|
||||
* The current task's status will be changed to TASK_BLOCKED
|
||||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
int block_current_task(void)
|
||||
{
|
||||
tid_t id;
|
||||
uint32_t prio;
|
||||
int ret = -EINVAL;
|
||||
uint8_t flags;
|
||||
|
||||
flags = irq_nested_disable();
|
||||
|
||||
id = current_task->id;
|
||||
prio = current_task->prio;
|
||||
|
||||
if (task_table[id].status == TASK_RUNNING) {
|
||||
task_table[id].status = TASK_BLOCKED;
|
||||
ret = 0;
|
||||
|
||||
spinlock_irqsave_lock(&readyqueues.lock);
|
||||
// reduce the number of ready tasks
|
||||
readyqueues.nr_tasks--;
|
||||
|
||||
// remove task from queue
|
||||
if (task_table[id].prev)
|
||||
task_table[id].prev->next = task_table[id].next;
|
||||
if (task_table[id].next)
|
||||
task_table[id].next->prev = task_table[id].prev;
|
||||
if (readyqueues.queue[prio-1].first == task_table+id)
|
||||
readyqueues.queue[prio-1].first = task_table[id].next;
|
||||
if (readyqueues.queue[prio-1].last == task_table+id) {
|
||||
readyqueues.queue[prio-1].last = task_table[id].prev;
|
||||
if (!readyqueues.queue[prio-1].last)
|
||||
readyqueues.queue[prio-1].last = readyqueues.queue[prio-1].first;
|
||||
}
|
||||
|
||||
// No valid task in queue => update prio_bitmap
|
||||
if (!readyqueues.queue[prio-1].first)
|
||||
readyqueues.prio_bitmap &= ~(1 << prio);
|
||||
spinlock_irqsave_unlock(&readyqueues.lock);
|
||||
}
|
||||
|
||||
irq_nested_enable(flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t** scheduler(void)
|
||||
{
|
||||
task_t* orig_task;
|
||||
uint32_t prio;
|
||||
|
||||
orig_task = current_task;
|
||||
|
||||
spinlock_irqsave_lock(&readyqueues.lock);
|
||||
|
||||
/* signalizes that this task could be reused */
|
||||
if (current_task->status == TASK_FINISHED) {
|
||||
current_task->status = TASK_INVALID;
|
||||
readyqueues.old_task = current_task;
|
||||
} else readyqueues.old_task = NULL; // reset old task
|
||||
|
||||
prio = msb(readyqueues.prio_bitmap); // determines highest priority
|
||||
if (prio > MAX_PRIO) {
|
||||
if ((current_task->status == TASK_RUNNING) || (current_task->status == TASK_IDLE))
|
||||
goto get_task_out;
|
||||
current_task = readyqueues.idle;
|
||||
} else {
|
||||
// Does the current task have an higher priority? => no task switch
|
||||
if ((current_task->prio > prio) && (current_task->status == TASK_RUNNING))
|
||||
goto get_task_out;
|
||||
|
||||
if (current_task->status == TASK_RUNNING) {
|
||||
current_task->status = TASK_READY;
|
||||
readyqueues.old_task = current_task;
|
||||
}
|
||||
|
||||
current_task = readyqueues.queue[prio-1].first;
|
||||
if (BUILTIN_EXPECT(current_task->status == TASK_INVALID, 0)) {
|
||||
kprintf("Upps!!!!!!! Got invalid task %d, orig task %d\n", current_task->id, orig_task->id);
|
||||
}
|
||||
current_task->status = TASK_RUNNING;
|
||||
|
||||
// remove new task from queue
|
||||
// by the way, priority 0 is only used by the idle task and doesn't need own queue
|
||||
readyqueues.queue[prio-1].first = current_task->next;
|
||||
if (!current_task->next) {
|
||||
readyqueues.queue[prio-1].last = NULL;
|
||||
readyqueues.prio_bitmap &= ~(1 << prio);
|
||||
}
|
||||
current_task->next = current_task->prev = NULL;
|
||||
}
|
||||
|
||||
get_task_out:
|
||||
spinlock_irqsave_unlock(&readyqueues.lock);
|
||||
|
||||
if (current_task != orig_task) {
|
||||
//kprintf("schedule from %u to %u with prio %u\n", orig_task->id, current_task->id, (uint32_t)current_task->prio);
|
||||
|
||||
return (size_t**) &(orig_task->last_stack_pointer);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void reschedule(void)
|
||||
{
|
||||
size_t** stack;
|
||||
uint8_t flags;
|
||||
|
||||
flags = irq_nested_disable();
|
||||
if ((stack = scheduler()))
|
||||
switch_context(stack);
|
||||
irq_nested_enable(flags);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -28,101 +28,28 @@
|
|||
#include <eduos/stdio.h>
|
||||
#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)
|
||||
{
|
||||
#ifdef CONFIG_VGA
|
||||
vga_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
#ifdef CONFIG_VGA
|
||||
if (early_print & VGA_EARLY_PRINT)
|
||||
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);
|
||||
vga_putchar(c);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int kputs(const char *str)
|
||||
{
|
||||
int pos, i, len = strlen(str);
|
||||
int i;
|
||||
|
||||
if (early_print != NO_EARLY_PRINT)
|
||||
spinlock_irqsave_lock(&olock);
|
||||
for(i=0; str[i] != '\0'; i++)
|
||||
vga_putchar((int) str[i]);
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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;
|
||||
#else
|
||||
return -EINVAL;
|
||||
#endif
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
C_source := memory.c
|
||||
MODULE := mm
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
247
mm/memory.c
247
mm/memory.c
|
@ -1,247 +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/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)
|
||||
{
|
||||
// idle task uses stack, which is defined in entry.asm
|
||||
if (BUILTIN_EXPECT(!id, 0))
|
||||
return NULL;
|
||||
// do we have a valid task id?
|
||||
if (BUILTIN_EXPECT(id >= MAX_TASKS, 0))
|
||||
return NULL;
|
||||
|
||||
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