Compare commits

..

1 commit

Author SHA1 Message Date
Stefan Lankes
ba7fe04291 remove typo 2014-01-23 22:48:37 +01:00
36 changed files with 233 additions and 4406 deletions

100
Doxyfile
View file

@ -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
@ -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

View file

@ -1,8 +1,7 @@
TERM = xterm
TOPDIR = $(shell pwd)
ARCH = x86
NAME = eduos
KERNDIRS = libkern kernel mm arch/$(ARCH)/kernel arch/$(ARCH)/mm
KERNDIRS = libkern kernel mm arch/$(ARCH)/kernel
SUBDIRS = $(KERNDIRS)
# Set your own cross compiler tool chain prefix here
@ -21,26 +20,14 @@ OBJCOPY_FOR_TARGET = $(CROSSCOMPREFIX)objcopy
RANLIB_FOR_TARGET = $(CROSSCOMPREFIX)ranlib
STRIP_FOR_TARGET = $(CROSSCOMPREFIX)strip
READELF_FOR_TARGET = $(CROSSCOMPREFIX)readelf
NASM = nasm
NASMFLAGS = -felf32 -g -i$(TOPDIR)/include/eduos/
GDB = $(CROSSCOMPREFIX)gdb
GDBFLAGS = -x debug.gdb
QEMU = qemu-system-i386
QEMUFLAGS = -smp 2 -monitor stdio \
-net nic,model=rtl8139 \
-net user,hostfwd=tcp::12345-:7
QEMUDEBUGFLAGS = -monitor none -daemonize \
-net nic,model=rtl8139 \
-net user,hostfwd=tcp::12345-:7
QEMUSERIALFLAGS = -device pci-serial,chardev=tS0 \
-chardev socket,host=localhost,port=4555,server,id=tS0
NASMFLAGS = -felf32 -g -i$(TOPDIR)/include/eduos/
INCLUDE = -I$(TOPDIR)/include -I$(TOPDIR)/arch/$(ARCH)/include
# Compiler options for final code
CFLAGS = -g -m32 -march=i586 -Wall -O2 -fno-builtin -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc $(INCLUDE) -fno-stack-protector
# Compiler options for debugging
debug debug-eclipse : CFLAGS = -g -O0 -m32 -march=i586 -Wall -fno-builtin -DWITH_FRAME_POINTER -nostdinc $(INCLUDE) -fno-stack-protector
#CFLAGS = -g -O -m32 -march=i586 -Wall -fno-builtin -DWITH_FRAME_POINTER -nostdinc $(INCLUDE) -fno-stack-protector
AR = ar
ARFLAGS = rsv
RM = rm -rf
@ -63,8 +50,8 @@ $(NAME).elf:
$Q$(LD_FOR_TARGET) $(LDFLAGS) -o $(NAME).elf $^
@echo [OBJCOPY] $(NAME).sym
$Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $(NAME).elf $(NAME).sym
#@echo [OBJCOPY] $(NAME).elf
#$Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $(NAME).elf
@echo [OBJCOPY] $(NAME).elf
$Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $(NAME).elf
clean:
$Q$(RM) $(NAME).elf $(NAME).sym *~
@ -75,22 +62,14 @@ veryclean: clean
@echo Very cleaned
qemu: $(NAME).elf
$(QEMU) $(QEMUFLAGS) -kernel $(NAME).elf
qemu-system-i386 -monitor stdio -smp 2 -net nic,model=rtl8139 -net user,hostfwd=tcp::12345-:7 -net dump -kernel $(NAME).elf
uart: $(NAME).elf
$(QEMU) $(QEMUFLAGS) $(QEMUSERIALFLAGS) -kernel $(NAME).elf
debug: $(NAME).elf
$(TERM) -e $(GDB) $(GDBFLAGS) &
$(QEMU) $(QEMUDEBUGFLAGS) -s -S -kernel $(NAME).elf
debug-eclipse: clean $(NAME).elf
killall $(QEMU) &
( ( $(QEMU) $(QEMUDEBUGFLAGS) $(QEMUSERIALFLAGS) -s -S -kernel $(NAME).elf & ) & )
qemu-dbg: $(NAME).elf
qemu-system-i386 -monitor stdio -s -S -smp 2 -net nic,model=rtl8139 -net user,hostfwd=tcp::12345-:7 -net dump -kernel $(NAME).elf
doc:
@echo Create documentation...
@doxygen
@echo Create documentation...
%.o : %.c
@echo [CC] $@
@ -112,5 +91,5 @@ include/eduos/config.inc: include/eduos/config.h
$Q$(CC_FOR_TARGET) $(CFLAGS) -c -o $@ $<
.PHONY: default all clean emu gdb newlib tools
include $(addsuffix /Makefile,$(SUBDIRS))

View file

@ -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>
@ -83,20 +83,9 @@ Overview of all branches
Add support of user-level tasks with an small interface for basic system calls
5. stage5 - Enabling paging
Add support of paging. See http://www.noteblok.net/2014/06/14/bachelor
for a detailed description.
6. stage6 - Add UART support
Add basic support of a serial device
Usefull Links
-------------
0. http://www.gnu.org/software/grub/manual/multiboot/
1. http://www.osdever.net/tutorials/view/brans-kernel-development-tutorial
2. http://www.jamesmolloy.co.uk/tutorial_html/index.html
3. http://techblog.lankes.org/tutorials/
4. http://www.os.rwth-aachen.de
5. http://www.noteblok.net/2014/06/14/bachelor
1. http://www.gnu.org/software/grub/manual/multiboot/
2. http://www.osdever.net/tutorials/view/brans-kernel-development-tutorial
3. http://www.jamesmolloy.co.uk/tutorial_html/index.html
4. http://techblog.lankes.org/tutorials/

View file

@ -122,8 +122,8 @@ inline static int32_t atomic_int32_sub(atomic_int32_t *d, int32_t i)
*
* @param d The atomic_int32_t var you want to increment
*/
inline static int32_t atomic_int32_inc(atomic_int32_t* d) {
return atomic_int32_add(d, 1);
inline static void atomic_int32_inc(atomic_int32_t* d) {
asm volatile(LOCK "incl %0" : "+m" (d->counter));
}
/** @brief Atomic decrement by one
@ -132,8 +132,8 @@ inline static int32_t atomic_int32_inc(atomic_int32_t* d) {
*
* @param d The atomic_int32_t var you want to decrement
*/
inline static int32_t atomic_int32_dec(atomic_int32_t* d) {
return atomic_int32_add(d, -1);
inline static void atomic_int32_dec(atomic_int32_t* d) {
asm volatile(LOCK "decl %0" : "+m" (d->counter));
}
/** @brief Read out an atomic_int32_t var

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -38,73 +38,11 @@
#include <eduos/stddef.h>
#include <asm/gdt.h>
#ifdef CONFIG_PCI
#include <asm/pci.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
// feature list 1
#define CPU_FEATURE_FPU (1 << 0)
#define CPU_FEATURE_MSR (1 << 5)
#define CPU_FEATURE_APIC (1 << 9)
#define CPU_FEATURE_MMX (1 << 23)
#define CPU_FEATURE_FXSR (1 << 24)
#define CPU_FEATURE_SSE (1 << 25)
#define CPU_FEATURE_SSE2 (1 << 26)
// feature list 2
#define CPU_FEATURE_X2APIC (1 << 21)
#define CPU_FEATURE_AVX (1 << 28)
#define CPU_FEATURE_HYPERVISOR (1 << 31)
typedef struct {
uint32_t feature1, feature2;
} cpu_info_t;
extern cpu_info_t cpu_info;
// determine the cpu features
int cpu_detection(void);
inline static uint32_t has_fpu(void) {
return (cpu_info.feature1 & CPU_FEATURE_FPU);
}
inline static uint32_t has_msr(void) {
return (cpu_info.feature1 & CPU_FEATURE_MSR);
}
inline static uint32_t has_apic(void) {
return (cpu_info.feature1 & CPU_FEATURE_APIC);
}
inline static uint32_t has_fxsr(void) {
return (cpu_info.feature1 & CPU_FEATURE_FXSR);
}
inline static uint32_t has_sse(void) {
return (cpu_info.feature1 & CPU_FEATURE_SSE);
}
inline static uint32_t has_sse2(void) {
return (cpu_info.feature1 & CPU_FEATURE_SSE2);
}
inline static uint32_t has_x2apic(void) {
return (cpu_info.feature2 & CPU_FEATURE_X2APIC);
}
inline static uint32_t has_avx(void) {
return (cpu_info.feature2 & CPU_FEATURE_AVX);
}
inline static uint32_t on_hypervisor(void) {
return (cpu_info.feature2 & CPU_FEATURE_HYPERVISOR);
}
/** @brief Read out time stamp counter
*
* The rdtsc asm command puts a 64 bit time stamp value
@ -119,102 +57,6 @@ inline static uint64_t rdtsc(void)
return x;
}
/** @brief Read MSR
*
* The asm instruction rdmsr which stands for "Read from model specific register"
* is used here.
*
* @param msr The parameter which rdmsr assumes in ECX
* @return The value rdmsr put into EDX:EAX
*/
inline static uint64_t rdmsr(uint32_t msr) {
uint32_t low, high;
asm volatile ("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
return ((uint64_t)high << 32) | low;
}
/** @brief Write a value to a Machine-Specific Registers (MSR)
*
* The asm instruction wrmsr which stands for "Write to model specific register"
* is used here.
*
* @param msr The MSR identifier
* @param value Value, which will be store in the MSR
*/
inline static void wrmsr(uint32_t msr, uint64_t value)
{
uint32_t low = value & 0xFFFFFFFF;
uint32_t high = value >> 32;
asm volatile("wrmsr" :: "a"(low), "c"(msr), "d"(high));
}
/** @brief Read cr0 register
* @return cr0's value
*/
static inline size_t read_cr0(void) {
size_t val;
asm volatile("mov %%cr0, %0" : "=r"(val));
return val;
}
/** @brief Write a value into cr0 register
* @param val The value you want to write into cr0
*/
static inline void write_cr0(size_t val) {
asm volatile("mov %0, %%cr0" : : "r"(val));
}
/** @brief Read cr2 register
* @return cr2's value
*/
static inline size_t read_cr2(void) {
size_t val;
asm volatile("mov %%cr2, %0" : "=r"(val));
return val;
}
/** @brief Write a value into cr2 register
* @param val The value you want to write into cr2
*/
static inline void write_cr2(size_t val) {
asm volatile("mov %0, %%cr2" : : "r"(val));
}
/** @brief Read cr3 register
* @return cr3's value
*/
static inline size_t read_cr3(void) {
size_t val;
asm volatile("mov %%cr3, %0" : "=r"(val));
return val;
}
/** @brief Write a value into cr3 register
* @param val The value you want to write into cr3
*/
static inline void write_cr3(size_t val) {
asm volatile("mov %0, %%cr3" : : "r"(val));
}
/** @brief Read cr4 register
* @return cr4's value
*/
static inline size_t read_cr4(void) {
size_t val;
asm volatile("mov %%cr4, %0" : "=r"(val));
return val;
}
/** @brief Write a value into cr4 register
* @param val The value you want to write into cr4
*/
static inline void write_cr4(size_t val) {
asm volatile("mov %0, %%cr4" : : "r"(val));
}
/** @brief Flush cache
*
* The wbinvd asm instruction which stands for "Write back and invalidate"
@ -224,26 +66,6 @@ inline static void flush_cache(void) {
asm volatile ("wbinvd" : : : "memory");
}
/** @brief Flush Translation Lookaside Buffer
*
* Just reads cr3 and writes the same value back into it.
*/
static inline void flush_tlb(void)
{
size_t val = read_cr3();
if (val)
write_cr3(val);
}
/** @brief Flush a specific page entry in TLB
* @param addr The (virtual) address of the page to flush
*/
static inline void tlb_flush_one_page(size_t addr)
{
asm volatile("invlpg (%0)" : : "r"(addr) : "memory");
}
/** @brief Invalidate cache
*
* The invd asm instruction which invalidates cache without writing back
@ -253,30 +75,12 @@ inline static void invalid_cache(void) {
asm volatile ("invd");
}
/* Force strict CPU ordering */
typedef void (*func_memory_barrier)(void);
/// Force strict CPU ordering, serializes load and store operations.
extern func_memory_barrier mb;
inline static void mb(void) { asm volatile("mfence" ::: "memory"); }
/// Force strict CPU ordering, serializes load operations.
extern func_memory_barrier rmb;
inline static void rmb(void) { asm volatile("lfence" ::: "memory"); }
/// Force strict CPU ordering, serializes store operations.
extern func_memory_barrier wmb;
/** @brief Read out CPU ID
*
* The cpuid asm-instruction does fill some information into registers and
* this function fills those register values into the given uint32_t vars.\n
*
* @param code Input parameter for the cpuid instruction. Take a look into the intel manual.
* @param a EAX value will be stores here
* @param b EBX value will be stores here
* @param c ECX value will be stores here
* @param d EDX value will be stores here
*/
inline static void cpuid(uint32_t code, uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d) {
asm volatile ("cpuid" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "0"(code), "2"(*c));
}
inline static void wmb(void) { asm volatile("sfence" ::: "memory"); }
/** @brief Read EFLAGS
*
@ -350,10 +154,6 @@ static inline size_t lsb(size_t i)
inline static int system_init(void)
{
gdt_install();
cpu_detection();
#ifdef CONFIG_PCI
pci_init();
#endif
return 0;
}

View file

@ -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

View file

@ -1,4 +1,4 @@
C_source := tasks.c vga.c gdt.c irq.c idt.c isrs.c timer.c processor.c uart.c pci.c
C_source := tasks.c multiboot.c vga.c gdt.c irq.c idt.c isrs.c timer.c processor.c
ASM_source := entry.asm string32.asm
MODULE := arch_x86_kernel

View file

@ -1,4 +1,4 @@
;
; Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
; All rights reserved.
;
@ -32,20 +32,19 @@
%include "config.inc"
[BITS 32]
; We use a special name to map this section at the begin of our kernel
; => Multiboot expects its magic number at the beginning of the kernel.
; => Multiboot needs its magic number at the begin of the kernel
SECTION .mboot
global start
start:
jmp stublet
; This part MUST be 4 byte aligned, so we solve that issue using 'ALIGN 4'.
; This part MUST be 4byte aligned, so we solve that issue using 'ALIGN 4'
ALIGN 4
mboot:
; Multiboot macros to make a few lines more readable later
MULTIBOOT_PAGE_ALIGN equ (1 << 0)
MULTIBOOT_MEMORY_INFO equ (1 << 1)
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
@ -58,43 +57,37 @@ mboot:
SECTION .text
ALIGN 4
stublet:
; Initialize stack pointer
; initialize stack pointer
mov esp, boot_stack
add esp, KERNEL_STACK_SIZE-16
; Initialize CPU features
; initialize cpu features
call cpu_init
; Interpret multiboot information
mov DWORD [mb_info], ebx
; interpret multiboot information
extern multiboot_init
push ebx
call multiboot_init
add esp, 4
; Jump to the boot processors's C code
; jump to the boot processors's C code
extern main
call main
jmp $
; This will set up the x86 control registers:
; Caching and the floating point unit are enabled
; Bootstrap page tables are loaded and page size
; extensions (huge pages) enabled.
global cpu_init
cpu_init:
; Set CR3
mov eax, boot_pgd
mov cr3, eax
; Set CR4
mov cr4, eax
and eax, ~(1 << 9) ; disable SSE
or eax, (1 << 4) ; enable PSE
mov cr4, eax
; Set CR0
mov eax, cr0
and eax, ~(1 << 2) ; disable FPU emulation
and eax, ~(1 << 30) ; enable caching
or eax, (1 << 31) ; enable paging
or eax, (1 << 5) ; enable FPU exceptions
; enable caching, disable paging and fpu emulation
and eax, 0x1ffffffb
; ...and turn on FPU exceptions
or eax, 0x22
mov cr0, eax
; clears the current pgd entry
xor eax, eax
mov cr3, eax
; at this stage, we disable the SSE support
mov eax, cr4
and eax, 0xfffbf9ff
mov cr4, eax
ret
; This will set up our new segment registers. We need to do
@ -115,12 +108,12 @@ gdt_flush:
flush2:
ret
; The first 32 interrupt service routines (ISR) entries correspond to exceptions.
; Some exceptions will push an error code onto the stack which is specific to
; The first 32 interrupt service routines (isr) entries correspond to exceptions.
; Some exceptions will push an error code onto the stack which is specific to
; the exception caused. To decrease the complexity, we handle this by pushing a
; Dummy error code of 0 onto the stack for any ISR that doesn't push an error
; code already.
;
; dummy error code of 0 onto the stack for any ISR that doesn't push an error
; code already.
;
; ISRs are registered as "Interrupt Gate".
; Therefore, the interrupt flag (IF) is already cleared.
@ -143,8 +136,8 @@ flush2:
jmp common_stub
%endmacro
; Create isr entries, where the number after the
; pseudo error code represents following interrupts:
; create isr entries, where the number after the
; pseudo error code represents following interrupts
; 0: Divide By Zero Exception
; 1: Debug Exception
; 2: Non Maskable Interrupt Exception
@ -153,10 +146,10 @@ flush2:
; 5: Out of Bounds Exception
; 6: Invalid Opcode Exception
; 7: Coprocessor Not Available Exception
%assign i 0
%assign i 0
%rep 8
isrstub_pseudo_error i
%assign i i+1
%assign i i+1
%endrep
; 8: Double Fault Exception (With Error Code!)
@ -196,16 +189,18 @@ isrstub_pseudo_error 9
jmp common_stub
%endmacro
; Create entries for the interrupts 0 to 23
; create entries for the interrupts 0 to 23
%assign i 0
%rep 24
irqstub i
%assign i i+1
%endrep
; Used to realize system calls.
; By entering the handler, the interrupt flag is not cleared.
extern syscall_handler
global isrsyscall
; used to realize system calls
; by entering the handler, the interrupt flag is not cleared
isrsyscall:
cli
push es
@ -218,14 +213,13 @@ isrsyscall:
push ebx
push eax
; Set kernel data segmenets
; set kernel data segmenets
mov ax, 0x10
mov ds, ax
mov es, ax
mov eax, [esp]
sti
extern syscall_handler
call syscall_handler
cli
@ -247,12 +241,12 @@ 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:
; create on the stack a pseudo interrupt
; afterwards, we switch to the task with iret
; we already in kernel space => no pushing of SS required
mov eax, [esp+4] ; on the stack is already the address to store the old esp
pushf ; push controll register
push DWORD 0x8 ; CS
@ -269,6 +263,8 @@ ALIGN 4
rollback:
ret
extern set_kernel_stack
ALIGN 4
common_stub:
pusha
@ -278,10 +274,8 @@ common_stub:
mov es, ax
mov ds, ax
; Use the same handler for interrupts and exceptions
; use the same handler for interrupts and exceptions
push esp
extern set_kernel_stack
call irq_handler
add esp, 4
@ -293,15 +287,15 @@ common_switch:
call get_current_stack ; get new esp
xchg eax, esp
; Set task switched flag
; set task switched flag
mov eax, cr0
or eax, 8
mov cr0, eax
; Set esp0 in the task state segment
; set esp0 in the task state segment
call set_kernel_stack
; Call cleanup code
; call cleanup code
call finish_task_switch
no_context_switch:
@ -311,34 +305,9 @@ no_context_switch:
add esp, 8
iret
SECTION .data
global mb_info:
ALIGN 4
mb_info:
DD 0
ALIGN 4096
global boot_stack
boot_stack:
TIMES (KERNEL_STACK_SIZE) DB 0xcd
; Bootstrap page tables are used during the initialization.
; These tables do a simple identity paging and will
; be replaced in page_init() by more fine-granular mappings.
ALIGN 4096
global boot_map
boot_map:
boot_pgd:
DD boot_pgt + 0x107 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_USER
times 1022 DD 0 ; PAGE_MAP_ENTRIES - 2
DD boot_pgd + 0x303 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_SELF (self-reference)
boot_pgt:
%assign i 0
%rep 1024 ; PAGE_MAP_ENTRIES
DD i + 0x203 ; PG_PRESENT | PG_BOOT | PG_RW
%assign i i + 4096 ; PAGE_SIZE
%endrep
boot_stack:
TIMES (KERNEL_STACK_SIZE) DB 0xcd
; add some hints to the ELF file
SECTION .note.GNU-stack noalloc noexec nowrite progbits

View file

@ -34,9 +34,8 @@
#include <eduos/time.h>
#include <asm/gdt.h>
#include <asm/tss.h>
#include <asm/page.h>
gdt_ptr_t gp;
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}};

View file

@ -25,24 +25,17 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @author Steffen Vogel
* @file include/memory.h
* @brief Memory related functions
*
* This file contains platform independent memory functions
#include <eduos/stddef.h>
#include <asm/multiboot.h>
/*
* eduOS is able to use Multiboot (http://www.gnu.org/software/grub/manual/multiboot/),
* which specifies an interface between a boot loader and a operating system
*/
#ifndef __MEMORY_H__
#define __MEMORY_H__
multiboot_info_t* mb_info __attribute__ ((section (".data"))) = NULL;
/** @brief Initialize the memory subsystem */
int memory_init();
/** @brief Request physical page frames */
size_t get_pages(size_t npages);
/** @brief release physical page frames */
int put_pages(size_t phyaddr, size_t npages);
#endif
void multiboot_init(void* mb)
{
mb_info = (multiboot_info_t*) mb;
}

View file

@ -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

View file

@ -32,22 +32,8 @@
#include <eduos/processor.h>
#include <eduos/tasks.h>
cpu_info_t cpu_info = { 0, 0 };
static uint32_t cpu_freq = 0;
static void default_mb(void)
{
asm volatile ("lock; addl $0,0(%%esp)" ::: "memory", "cc");
}
func_memory_barrier mb = default_mb;
func_memory_barrier rmb = default_mb;
func_memory_barrier wmb = default_mb;
static void mfence(void) { asm volatile("mfence" ::: "memory"); }
static void lfence(void) { asm volatile("lfence" ::: "memory"); }
static void sfence(void) { asm volatile("sfence" ::: "memory"); }
uint32_t detect_cpu_frequency(void)
{
uint64_t start, end, diff;
@ -76,61 +62,6 @@ uint32_t detect_cpu_frequency(void)
return cpu_freq;
}
int cpu_detection(void) {
uint32_t a, b;
size_t cr4;
uint8_t first_time = 0;
if (!cpu_info.feature1) {
first_time = 1;
cpuid(1, &a, &b, &cpu_info.feature2, &cpu_info.feature1);
}
cr4 = read_cr4();
if (has_fxsr())
cr4 |= 0x200; // set the OSFXSR bit
if (has_sse())
cr4 |= 0x400; // set the OSXMMEXCPT bit
write_cr4(cr4);
if (first_time && has_sse())
wmb = sfence;
if (first_time && has_sse2()) {
rmb = lfence;
mb = mfence;
}
if (first_time && has_avx())
kprintf(
"The CPU owns the Advanced Vector Extensions (AVX). However, eduOS doesn't support AVX!\n");
if (has_fpu()) {
if (first_time)
kputs("Found and initialized FPU!\n");
asm volatile ("fninit");
}
if (first_time && on_hypervisor()) {
uint32_t c, d;
char vendor_id[13];
kprintf("eduOS is running on a hypervisor!\n");
cpuid(0x40000000, &a, &b, &c, &d);
memcpy(vendor_id, &b, 4);
memcpy(vendor_id + 4, &c, 4);
memcpy(vendor_id + 8, &d, 4);
vendor_id[12] = '\0';
kprintf("Hypervisor Vendor Id: %s\n", vendor_id);
kprintf("Maximum input value for hypervisor: 0x%x\n", a);
}
return 0;
}
uint32_t get_cpu_frequency(void)
{
if (cpu_freq > 0)

View file

@ -36,9 +36,6 @@ size_t* get_current_stack(void)
{
task_t* curr_task = current_task;
// use new page table
write_cr3(curr_task->page_map);
return curr_task->last_stack_pointer;
}

View file

@ -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

View file

@ -1,4 +0,0 @@
C_source := page.c
MODULE := arch_x86_mm
include $(TOPDIR)/Makefile.inc

View file

@ -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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_task->user_usage);
}
}
}
spinlock_irqsave_lock(&current_task->page_lock);
traverse(PAGE_LEVELS-1, 0);
spinlock_irqsave_unlock(&current_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(&current_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(&current_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;
}

View file

@ -1,7 +0,0 @@
# Constant part of the script
symbol-file eduos.elf
target remote localhost:1234
set architecture i386
break main
continue

View file

@ -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
*

View file

@ -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 &#160;<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-->

View file

@ -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-->&#160;<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-->

View file

@ -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; }

View file

@ -34,21 +34,17 @@ extern "C" {
#define EDUOS_VERSION "0.1"
#define MAX_TASKS 16
#define TIMER_FREQ 100 /* in HZ */
#define CLOCK_TICK_RATE 1193182 /* 8254 chip's internal oscillator frequency */
#define VIDEO_MEM_ADDR 0xB8000 /* the video memory address */
#define TIMER_FREQ 100 /* in HZ */
#define CLOCK_TICK_RATE 1193182 /* 8254 chip's internal oscillator frequency */
#define VIDEO_MEM_ADDR 0xB8000 // the video memora address
#define CACHE_LINE 64
#define KERNEL_STACK_SIZE (8<<10) /* 8 KiB */
#define BITMAP_SIZE (128<<5) /* for 128 MiB of RAM */
#define KMSG_SIZE (8*1024)
#define KERNEL_STACK_SIZE (8*1024)
#define PAGE_SHIFT 12
#define INT_SYSCALL 0x80
#define MAILBOX_SIZE 32
#define BYTE_ORDER LITTLE_ENDIAN
#define BYTE_ORDER LITTLE_ENDIAN
#define CONFIG_VGA
#define CONFIG_PCI
#define CONFIG_UART
#define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b))
//#define BUILTIN_EXPECT(exp, b) (exp)

View file

@ -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

View file

@ -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

View file

@ -35,7 +35,6 @@
#define __SEMAPHORE_H__
#include <eduos/string.h>
#include <eduos/tasks.h>
#include <eduos/semaphore_types.h>
#include <eduos/spinlock.h>
#include <eduos/errno.h>

View file

@ -46,6 +46,10 @@ extern "C" {
/// represents a task identifier
typedef unsigned int tid_t;
#define PAGE_SIZE (1 << PAGE_SHIFT)
#define PAGE_MASK ~(PAGE_SIZE - 1)
#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
struct task;
/// pointer to the current (running) task
extern struct task* current_task;

View file

@ -77,11 +77,6 @@ int ksnprintf(char *str, size_t size, const char *format, ...);
*/
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

View file

@ -39,9 +39,7 @@
#include <eduos/stddef.h>
#include <eduos/spinlock_types.h>
#include <asm/tasks_types.h>
#include <asm/atomic.h>
#ifdef __cplusplus
extern "C" {
@ -75,12 +73,6 @@ typedef struct task {
void* stack;
/// Task priority
uint8_t prio;
/// Physical address of root page table
size_t page_map;
/// Lock for page tables
spinlock_irqsave_t page_lock;
/// usage in number of pages (including page map tables)
atomic_int32_t user_usage;
/// next task in the queue
struct task* next;
/// previous task in the queue

View file

@ -33,15 +33,10 @@
#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,21 +47,17 @@ 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)
static void userfoo(void* arg)
{
char str[256];
ksnprintf(str, 256, "hello from %s\n", (char*) arg);
SYSCALL1(__NR_write, "hello from userfoo\n");
SYSCALL1(__NR_exit, 0);
while(1) ;
//kprintf("hello from %s\n", (char*) arg);
}
static char ustack[KERNEL_STACK_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
static char ustack[KERNEL_STACK_SIZE];
static int wrapper(void* arg)
{
@ -74,26 +65,9 @@ static int wrapper(void* arg)
memset(ustack, 0xCD, KERNEL_STACK_SIZE);
*stack-- = (size_t) arg;
*stack = (size_t) NULL; // put exit function as caller on the stack
*stack = (size_t) leave_user_task; // 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)
@ -117,15 +91,11 @@ static int eduos_init(void)
// initialize .bss section
memset((void*)&bss_start, 0x00, ((size_t) &bss_end - (size_t) &bss_start));
koutput_init();
system_init();
irq_init();
timer_init();
koutput_init();
multitasking_init();
memory_init();
#ifdef CONFIG_UART
uart_init();
#endif
return 0;
}
@ -134,18 +104,16 @@ int main(void)
{
tid_t id1;
tid_t id2;
eduos_init();
irq_enable();
system_calibration();
kprintf("This is eduOS %s Build %u, %u\n", EDUOS_VERSION, &__BUILD_DATE, &__BUILD_TIME);
kprintf("Kernel starts at %p and ends at %p\n", &kernel_start, &kernel_end);
irq_enable();
system_calibration();
kprintf("Processor frequency: %u MHz\n", get_cpu_frequency());
kprintf("Total memory: %lu KiB\n", atomic_int32_read(&total_pages) * PAGE_SIZE / 1024);
kprintf("Total memory available: %lu KiB\n", atomic_int32_read(&total_available_pages) * PAGE_SIZE / 1024);
create_kernel_task(&id1, foo, "foo1", NORMAL_PRIO);
create_kernel_task(&id2, wrapper, "userfoo", NORMAL_PRIO);

View file

@ -34,17 +34,14 @@
#include <eduos/spinlock.h>
#include <eduos/errno.h>
#include <eduos/syscall.h>
#include <eduos/memory.h>
#include <asm/page.h>
/** @brief Array of task structures (aka PCB)
*
* A task's id will be its position in this array.
*/
static task_t task_table[MAX_TASKS] = { \
[0] = {0, TASK_IDLE, NULL, NULL, 0, 0, SPINLOCK_IRQSAVE_INIT, ATOMIC_INIT(0), NULL, NULL}, \
[1 ... MAX_TASKS-1] = {0, TASK_INVALID, NULL, NULL, 0, 0, SPINLOCK_IRQSAVE_INIT, ATOMIC_INIT(0), NULL, NULL}};
[0] = {0, TASK_IDLE, NULL, NULL, 0, NULL, NULL}, \
[1 ... MAX_TASKS-1] = {0, TASK_INVALID, NULL, NULL, 0, NULL, NULL}};
static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT;
@ -56,7 +53,7 @@ extern const void boot_stack;
/** @brief helper function for the assembly code to determine the current task
* @return Pointer to the task_t structure of current task
*/
task_t* get_current_task(void)
task_t* get_current_task(void)
{
return current_task;
}
@ -75,7 +72,6 @@ int multitasking_init(void)
task_table[0].prio = IDLE_PRIO;
task_table[0].stack = (void*) &boot_stack;
task_table[0].page_map = read_cr3();
// register idle task
register_task();
@ -122,16 +118,14 @@ static void NORETURN do_exit(int arg)
kprintf("Terminate task: %u, return value %d\n", curr_task->id, arg);
page_map_drop();
curr_task->status = TASK_FINISHED;
reschedule();
// decrease the number of active tasks
spinlock_irqsave_lock(&readyqueues.lock);
readyqueues.nr_tasks--;
spinlock_irqsave_unlock(&readyqueues.lock);
curr_task->status = TASK_FINISHED;
reschedule();
kprintf("Kernel panic: scheduler found no valid task\n");
while(1) {
HALT;
@ -166,8 +160,6 @@ void NORETURN abort(void) {
}
/** @brief Create a task with a specific entry point
*
* @todo Dont aquire table_lock for the whole task creation.
*
* @param id Pointer to a tid_t struct were the id shall be set
* @param ep Pointer to the function the task shall start with
@ -201,17 +193,6 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg, uint8_t prio)
task_table[i].stack = create_stack(i);
task_table[i].prio = prio;
spinlock_irqsave_init(&task_table[i].page_lock);
atomic_int32_set(&task_table[i].user_usage, 0);
/* Allocated new PGD or PML4 and copy page table */
task_table[i].page_map = get_pages(1);
if (BUILTIN_EXPECT(!task_table[i].page_map, 0))
goto out;
/* Copy page tables & user frames of current task to new one */
page_map_copy(&task_table[i]);
if (id)
*id = i;
@ -236,7 +217,6 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg, uint8_t prio)
}
}
out:
spinlock_irqsave_unlock(&table_lock);
return ret;
@ -397,7 +377,7 @@ 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);
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);
}

View file

@ -29,27 +29,9 @@
#include <eduos/string.h>
#include <eduos/stdarg.h>
#include <eduos/spinlock.h>
#include <asm/atomic.h>
#include <asm/processor.h>
#ifdef CONFIG_VGA
#include <asm/vga.h>
#endif
#ifdef CONFIG_UART
#include <asm/uart.h>
#endif
#define NO_EARLY_PRINT 0x00
#define VGA_EARLY_PRINT 0x01
#define UART_EARLY_PRINT 0x02
#ifdef CONFIG_VGA
static uint32_t early_print = VGA_EARLY_PRINT;
#else
static uint32_t early_print = NO_EARLY_PRINT;
#endif
static spinlock_irqsave_t olock = SPINLOCK_IRQSAVE_INIT;
static atomic_int32_t kmsg_counter = ATOMIC_INIT(0);
static unsigned char kmessages[KMSG_SIZE] __attribute__ ((section(".kmsg"))) = {[0 ... KMSG_SIZE-1] = 0x00};
int koutput_init(void)
{
@ -62,67 +44,23 @@ int koutput_init(void)
int kputchar(int c)
{
int pos;
if (early_print != NO_EARLY_PRINT)
spinlock_irqsave_lock(&olock);
pos = atomic_int32_inc(&kmsg_counter);
kmessages[pos % KMSG_SIZE] = (unsigned char) c;
spinlock_irqsave_lock(&olock);
#ifdef CONFIG_VGA
if (early_print & VGA_EARLY_PRINT)
vga_putchar(c);
vga_putchar(c);
#endif
#ifdef CONFIG_UART
if (early_print & UART_EARLY_PRINT)
uart_putchar(c);
#endif
if (early_print != NO_EARLY_PRINT)
spinlock_irqsave_unlock(&olock);
spinlock_irqsave_unlock(&olock);
return 1;
}
int kputs(const char *str)
{
int pos, i, len = strlen(str);
if (early_print != NO_EARLY_PRINT)
spinlock_irqsave_lock(&olock);
for(i=0; i<len; i++) {
pos = atomic_int32_inc(&kmsg_counter);
kmessages[pos % KMSG_SIZE] = str[i];
#ifdef CONFIG_VGA
if (early_print & VGA_EARLY_PRINT)
vga_putchar(str[i]);
#endif
#ifdef CONFIG_UART
if (early_print & UART_EARLY_PRINT)
uart_putchar(str[i]);
#endif
}
int i;
for(i=0; str[i] != '\0'; i++)
vga_putchar((int) str[i]);
if (early_print != NO_EARLY_PRINT)
spinlock_irqsave_unlock(&olock);
return len;
}
int koutput_add_uart(void)
{
#ifdef CONFIG_UART
uint32_t i;
early_print |= UART_EARLY_PRINT;
for(i=0; i<atomic_int32_read(&kmsg_counter); i++)
uart_putchar(kmessages[i % KMSG_SIZE]);
return 0;
return i;
#else
return -EINVAL;
#endif
}

View file

@ -27,29 +27,8 @@
#include <eduos/stddef.h>
#include <eduos/stdlib.h>
#include <eduos/stdio.h>
#include <eduos/string.h>
#include <eduos/spinlock.h>
#include <asm/atomic.h>
#include <asm/multiboot.h>
#include <asm/page.h>
/*
* Note that linker symbols are not variables, they have no memory allocated for
* maintaining a value, rather their address is their value.
*/
extern const void kernel_start;
extern const void kernel_end;
static char stack[MAX_TASKS-1][KERNEL_STACK_SIZE];
static char bitmap[BITMAP_SIZE];
static spinlock_t bitmap_lock = SPINLOCK_INIT;
atomic_int32_t total_pages = ATOMIC_INIT(0);
atomic_int32_t total_allocated_pages = ATOMIC_INIT(0);
atomic_int32_t total_available_pages = ATOMIC_INIT(0);
void* create_stack(tid_t id)
{
@ -62,186 +41,3 @@ void* create_stack(tid_t id)
return (void*) stack[id-1];
}
inline static int page_marked(size_t i)
{
size_t index = i >> 3;
size_t mod = i & 0x7;
return (bitmap[index] & (1 << mod));
}
inline static void page_set_mark(size_t i)
{
size_t index = i >> 3;
size_t mod = i & 0x7;
bitmap[index] = bitmap[index] | (1 << mod);
}
inline static void page_clear_mark(size_t i)
{
size_t index = i / 8;
size_t mod = i % 8;
bitmap[index] = bitmap[index] & ~(1 << mod);
}
size_t get_pages(size_t npages)
{
size_t cnt, off;
static size_t alloc_start = (size_t) -1;
if (BUILTIN_EXPECT(!npages, 0))
return 0;
if (BUILTIN_EXPECT(npages > atomic_int32_read(&total_available_pages), 0))
return 0;
spinlock_lock(&bitmap_lock);
if (alloc_start == (size_t)-1)
alloc_start = ((size_t) &kernel_end >> PAGE_BITS);
off = 1;
while (off <= BITMAP_SIZE*8 - npages) {
for (cnt=0; cnt<npages; cnt++) {
if (page_marked(((off+alloc_start)%(BITMAP_SIZE*8 - npages))+cnt))
goto next;
}
off = (off+alloc_start) % (BITMAP_SIZE*8 - npages);
alloc_start = off+npages;
for (cnt=0; cnt<npages; cnt++) {
page_set_mark(off+cnt);
}
spinlock_unlock(&bitmap_lock);
atomic_int32_add(&total_allocated_pages, npages);
atomic_int32_sub(&total_available_pages, npages);
return off << PAGE_BITS;
next: off += cnt+1;
}
spinlock_unlock(&bitmap_lock);
return 0;
}
int put_pages(size_t phyaddr, size_t npages)
{
size_t i, ret = 0;
size_t base = phyaddr >> PAGE_BITS;
if (BUILTIN_EXPECT(!phyaddr, 0))
return -EINVAL;
if (BUILTIN_EXPECT(!npages, 0))
return -EINVAL;
spinlock_lock(&bitmap_lock);
for (i=0; i<npages; i++) {
if (page_marked(base+i)) {
page_clear_mark(base+i);
ret++;
}
}
spinlock_unlock(&bitmap_lock);
atomic_int32_sub(&total_allocated_pages, ret);
atomic_int32_add(&total_available_pages, ret);
return ret;
}
int memory_init(void)
{
unsigned int i;
size_t addr;
int ret = 0;
// mark all memory as used
memset(bitmap, 0xff, BITMAP_SIZE);
// parse multiboot information for available memory
if (mb_info) {
if (mb_info->flags & MULTIBOOT_INFO_MEM_MAP) {
multiboot_memory_map_t* mmap = (multiboot_memory_map_t*) ((size_t) mb_info->mmap_addr);
multiboot_memory_map_t* mmap_end = (void*) ((size_t) mb_info->mmap_addr + mb_info->mmap_length);
// mark available memory as free
while (mmap < mmap_end) {
if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE) {
for (addr=mmap->addr; addr < mmap->addr + mmap->len; addr += PAGE_SIZE) {
page_clear_mark(addr >> PAGE_BITS);
atomic_int32_inc(&total_pages);
atomic_int32_inc(&total_available_pages);
}
}
mmap++;
}
}
else if (mb_info->flags & MULTIBOOT_INFO_MEM) {
size_t page;
size_t pages_lower = mb_info->mem_lower >> 2; /* KiB to page number */
size_t pages_upper = mb_info->mem_upper >> 2;
for (page=0; page<pages_lower; page++)
page_clear_mark(page);
for (page=0; page<pages_upper; page++)
page_clear_mark(page + 256); /* 1 MiB == 256 pages offset */
atomic_int32_add(&total_pages, pages_lower + pages_upper);
atomic_int32_add(&total_available_pages, pages_lower + pages_upper);
}
else {
kputs("Unable to initialize the memory management subsystem\n");
while (1) HALT;
}
// mark mb_info as used
page_set_mark((size_t) mb_info >> PAGE_BITS);
atomic_int32_inc(&total_allocated_pages);
atomic_int32_dec(&total_available_pages);
if (mb_info->flags & MULTIBOOT_INFO_MODS) {
// mark modules list as used
for(addr=mb_info->mods_addr; addr<mb_info->mods_addr+mb_info->mods_count*sizeof(multiboot_module_t); addr+=PAGE_SIZE) {
page_set_mark(addr >> PAGE_BITS);
atomic_int32_inc(&total_allocated_pages);
atomic_int32_dec(&total_available_pages);
}
// mark modules as used
multiboot_module_t* mmodule = (multiboot_module_t*) ((size_t) mb_info->mods_addr);
for(i=0; i<mb_info->mods_count; i++) {
for(addr=mmodule[i].mod_start; addr<mmodule[i].mod_end; addr+=PAGE_SIZE) {
page_set_mark(addr >> PAGE_BITS);
atomic_int32_inc(&total_allocated_pages);
atomic_int32_dec(&total_available_pages);
}
}
}
}
// mark kernel as used
for(addr=(size_t) &kernel_start; addr<(size_t) &kernel_end; addr+=PAGE_SIZE) {
page_set_mark(addr >> PAGE_BITS);
atomic_int32_inc(&total_allocated_pages);
atomic_int32_dec(&total_available_pages);
}
// enable paging and map SMP, VGA, Multiboot modules etc.
ret = page_init();
if (BUILTIN_EXPECT(ret, 0)) {
kputs("Failed to initialize paging!\n");
return ret;
}
return ret;
}