Compare commits

..

No commits in common. "master" and "paging-fork" have entirely different histories.

27 changed files with 126 additions and 3227 deletions

View file

@ -1,4 +1,3 @@
TERM = xterm
TOPDIR = $(shell pwd) TOPDIR = $(shell pwd)
ARCH = x86 ARCH = x86
NAME = eduos NAME = eduos
@ -23,24 +22,21 @@ STRIP_FOR_TARGET = $(CROSSCOMPREFIX)strip
READELF_FOR_TARGET = $(CROSSCOMPREFIX)readelf READELF_FOR_TARGET = $(CROSSCOMPREFIX)readelf
NASM = nasm NASM = nasm
NASMFLAGS = -felf32 -g -i$(TOPDIR)/include/eduos/ GDB = gdb
GDB = $(CROSSCOMPREFIX)gdb
GDBFLAGS = -x debug.gdb
QEMU = qemu-system-i386 QEMU = qemu-system-i386
NASMFLAGS = -felf32 -g -i$(TOPDIR)/include/eduos/
GDBFLAGS = -x debug.gdb
QEMUFLAGS = -smp 2 -monitor stdio \ QEMUFLAGS = -smp 2 -monitor stdio \
-net nic,model=rtl8139 \ -net nic,model=rtl8139 \
-net user,hostfwd=tcp::12345-:7 -net user,hostfwd=tcp::12345-:7 \
QEMUDEBUGFLAGS = -monitor none -daemonize \ -serial tcp::12346,server,nowait
-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
INCLUDE = -I$(TOPDIR)/include -I$(TOPDIR)/arch/$(ARCH)/include INCLUDE = -I$(TOPDIR)/include -I$(TOPDIR)/arch/$(ARCH)/include
# Compiler options for final code # 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 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 # 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 AR = ar
ARFLAGS = rsv ARFLAGS = rsv
RM = rm -rf RM = rm -rf
@ -63,8 +59,8 @@ $(NAME).elf:
$Q$(LD_FOR_TARGET) $(LDFLAGS) -o $(NAME).elf $^ $Q$(LD_FOR_TARGET) $(LDFLAGS) -o $(NAME).elf $^
@echo [OBJCOPY] $(NAME).sym @echo [OBJCOPY] $(NAME).sym
$Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $(NAME).elf $(NAME).sym $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $(NAME).elf $(NAME).sym
#@echo [OBJCOPY] $(NAME).elf @echo [OBJCOPY] $(NAME).elf
#$Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $(NAME).elf $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $(NAME).elf
clean: clean:
$Q$(RM) $(NAME).elf $(NAME).sym *~ $Q$(RM) $(NAME).elf $(NAME).sym *~
@ -77,16 +73,9 @@ veryclean: clean
qemu: $(NAME).elf qemu: $(NAME).elf
$(QEMU) $(QEMUFLAGS) -kernel $(NAME).elf $(QEMU) $(QEMUFLAGS) -kernel $(NAME).elf
uart: $(NAME).elf
$(QEMU) $(QEMUFLAGS) $(QEMUSERIALFLAGS) -kernel $(NAME).elf
debug: $(NAME).elf debug: $(NAME).elf
$(TERM) -e $(GDB) $(GDBFLAGS) & $(TERM) -e $(GDB) $(GDBFLAGS) &
$(QEMU) $(QEMUDEBUGFLAGS) -s -S -kernel $(NAME).elf $(QEMU) $(QEMUFLAGS) -s -S -kernel $(NAME).elf
debug-eclipse: clean $(NAME).elf
killall $(QEMU) &
( ( $(QEMU) $(QEMUDEBUGFLAGS) $(QEMUSERIALFLAGS) -s -S -kernel $(NAME).elf & ) & )
doc: doc:
@echo Create documentation... @echo Create documentation...

View file

@ -83,15 +83,6 @@ Overview of all branches
Add support of user-level tasks with an small interface for basic system calls 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 Usefull Links
------------- -------------
0. http://www.gnu.org/software/grub/manual/multiboot/ 0. http://www.gnu.org/software/grub/manual/multiboot/
@ -99,4 +90,3 @@ Usefull Links
2. http://www.jamesmolloy.co.uk/tutorial_html/index.html 2. http://www.jamesmolloy.co.uk/tutorial_html/index.html
3. http://techblog.lankes.org/tutorials/ 3. http://techblog.lankes.org/tutorials/
4. http://www.os.rwth-aachen.de 4. http://www.os.rwth-aachen.de
5. http://www.noteblok.net/2014/06/14/bachelor

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

View file

@ -1,6 +1,5 @@
/* /*
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
* 2014, Steffen Vogel, RWTH Aachen University
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -34,8 +33,6 @@
* This file contains the several functions to manage the page tables * This file contains the several functions to manage the page tables
*/ */
#include <eduos/tasks_types.h>
#ifndef __PAGE_H__ #ifndef __PAGE_H__
#define __PAGE_H__ #define __PAGE_H__
@ -88,10 +85,8 @@
#define PG_PAT PG_PSE #define PG_PAT PG_PSE
/// Global TLB entry (Pentium Pro and later) /// Global TLB entry (Pentium Pro and later)
#define PG_GLOBAL (1 << 8) #define PG_GLOBAL (1 << 8)
/// This table is a self-reference and should skipped by page_map_copy() /// This page or table is used during the boot process
#define PG_SELF (1 << 9) #define PG_BOOT (1 << 9)
/// This page is used for bootstrapping the paging code.
#define PG_BOOT PG_SELF
/// This page is reserved for copying /// This page is reserved for copying
#define PAGE_TMP (PAGE_FLOOR((size_t) &kernel_start) - PAGE_SIZE) #define PAGE_TMP (PAGE_FLOOR((size_t) &kernel_start) - PAGE_SIZE)
@ -138,7 +133,7 @@ int page_unmap(size_t viraddr, size_t npages);
* @retval 0 Success. Everything went fine. * @retval 0 Success. Everything went fine.
* @retval <0 Error. Something went wrong. * @retval <0 Error. Something went wrong.
*/ */
int page_map_copy(task_t *dest); int page_map_copy(size_t dest);
/** @brief Free a whole page map tree */ /** @brief Free a whole page map tree */
int page_map_drop(); int page_map_drop();

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 <eduos/stddef.h>
#include <asm/gdt.h> #include <asm/gdt.h>
#ifdef CONFIG_PCI
#include <asm/pci.h>
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #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 /** @brief Read out time stamp counter
* *
* The rdtsc asm command puts a 64 bit time stamp value * The rdtsc asm command puts a 64 bit time stamp value
@ -119,54 +57,15 @@ inline static uint64_t rdtsc(void)
return x; return x;
} }
/** @brief Read MSR /** @brief Read cr3 register
* * @return cr3's value
* 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) { static inline size_t read_cr3(void) {
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; size_t val;
asm volatile("mov %%cr0, %0" : "=r"(val)); asm volatile("mov %%cr3, %0" : "=r"(val));
return 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 /** @brief Read cr2 register
* @return cr2's value * @return cr2's value
*/ */
@ -183,15 +82,6 @@ static inline void write_cr2(size_t val) {
asm volatile("mov %0, %%cr2" : : "r"(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 /** @brief Write a value into cr3 register
* @param val The value you want to write into cr3 * @param val The value you want to write into cr3
*/ */
@ -199,22 +89,6 @@ static inline void write_cr3(size_t val) {
asm volatile("mov %0, %%cr3" : : "r"(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 /** @brief Flush cache
* *
* The wbinvd asm instruction which stands for "Write back and invalidate" * The wbinvd asm instruction which stands for "Write back and invalidate"
@ -253,30 +127,12 @@ inline static void invalid_cache(void) {
asm volatile ("invd"); asm volatile ("invd");
} }
/* Force strict CPU ordering */
typedef void (*func_memory_barrier)(void);
/// Force strict CPU ordering, serializes load and store operations. /// 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. /// 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. /// Force strict CPU ordering, serializes store operations.
extern func_memory_barrier wmb; inline static void wmb(void) { asm volatile("sfence" ::: "memory"); }
/** @brief Read out CPU ID
*
* The cpuid asm-instruction does fill some information into registers and
* this function fills those register values into the given uint32_t vars.\n
*
* @param code Input parameter for the cpuid instruction. Take a look into the intel manual.
* @param a EAX value will be stores here
* @param b EBX value will be stores here
* @param c ECX value will be stores here
* @param d EDX value will be stores here
*/
inline static void cpuid(uint32_t code, uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d) {
asm volatile ("cpuid" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "0"(code), "2"(*c));
}
/** @brief Read EFLAGS /** @brief Read EFLAGS
* *
@ -350,10 +206,6 @@ static inline size_t lsb(size_t i)
inline static int system_init(void) inline static int system_init(void)
{ {
gdt_install(); gdt_install();
cpu_detection();
#ifdef CONFIG_PCI
pci_init();
#endif
return 0; 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 vga.c gdt.c irq.c idt.c isrs.c timer.c processor.c
ASM_source := entry.asm string32.asm ASM_source := entry.asm string32.asm
MODULE := arch_x86_kernel MODULE := arch_x86_kernel

View file

@ -153,10 +153,10 @@ flush2:
; 5: Out of Bounds Exception ; 5: Out of Bounds Exception
; 6: Invalid Opcode Exception ; 6: Invalid Opcode Exception
; 7: Coprocessor Not Available Exception ; 7: Coprocessor Not Available Exception
%assign i 0 %assign i 0
%rep 8 %rep 8
isrstub_pseudo_error i isrstub_pseudo_error i
%assign i i+1 %assign i i+1
%endrep %endrep
; 8: Double Fault Exception (With Error Code!) ; 8: Double Fault Exception (With Error Code!)
@ -330,13 +330,13 @@ ALIGN 4096
global boot_map global boot_map
boot_map: boot_map:
boot_pgd: boot_pgd:
DD boot_pgt + 0x107 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_USER DD boot_pgt + 0x103 ; PG_GLOBAL | PG_RW | PG_PRESENT
times 1022 DD 0 ; PAGE_MAP_ENTRIES - 2 times 1022 DD 0 ; PAGE_MAP_ENTRIES - 2
DD boot_pgd + 0x303 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_SELF (self-reference) DD boot_pgd + 0x103 ; PG_GLOBAL | PG_RW | PG_PRESENT (self-reference)
boot_pgt: boot_pgt:
%assign i 0 %assign i 0
%rep 1024 ; PAGE_MAP_ENTRIES %rep 1024 ; PAGE_MAP_ENTRIES
DD i + 0x203 ; PG_PRESENT | PG_BOOT | PG_RW DD i | 0x203 ; PG_BOOT | PG_RW | PG_PRESENT
%assign i i + 4096 ; PAGE_SIZE %assign i i + 4096 ; PAGE_SIZE
%endrep %endrep

View file

@ -36,7 +36,7 @@
#include <asm/tss.h> #include <asm/tss.h>
#include <asm/page.h> #include <asm/page.h>
gdt_ptr_t gp; gdt_ptr_t gp;
static tss_t task_state_segment __attribute__ ((aligned (PAGE_SIZE))); static tss_t task_state_segment __attribute__ ((aligned (PAGE_SIZE)));
// currently, our kernel has full access to the ioports // currently, our kernel has full access to the ioports
static gdt_entry_t gdt[GDT_ENTRIES] = {[0 ... GDT_ENTRIES-1] = {0, 0, 0, 0, 0, 0}}; static gdt_entry_t gdt[GDT_ENTRIES] = {[0 ... GDT_ENTRIES-1] = {0, 0, 0, 0, 0, 0}};

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/processor.h>
#include <eduos/tasks.h> #include <eduos/tasks.h>
cpu_info_t cpu_info = { 0, 0 };
static uint32_t cpu_freq = 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) uint32_t detect_cpu_frequency(void)
{ {
uint64_t start, end, diff; uint64_t start, end, diff;
@ -76,61 +62,6 @@ uint32_t detect_cpu_frequency(void)
return cpu_freq; 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) uint32_t get_cpu_frequency(void)
{ {
if (cpu_freq > 0) if (cpu_freq > 0)

View file

@ -36,9 +36,6 @@ size_t* get_current_stack(void)
{ {
task_t* curr_task = current_task; task_t* curr_task = current_task;
// use new page table
write_cr3(curr_task->page_map);
return curr_task->last_stack_pointer; 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,6 +1,5 @@
/* /*
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
* 2014, Steffen Vogel, RWTH Aachen University
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -25,13 +24,10 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/** /**
* This is a 32/64 bit portable paging implementation for the x86 architecture * This is a 32/64 bit portable paging implementation for the x86 architecture
* using self-referenced page tablesi. * using self-referenced page tables.
* See http://www.noteblok.net/2014/06/14/bachelor/ for a detailed description. * 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/stdio.h>
@ -42,6 +38,7 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/io.h>
#include <asm/multiboot.h> #include <asm/multiboot.h>
/* Note that linker symbols are not variables, they have no memory /* Note that linker symbols are not variables, they have no memory
@ -67,6 +64,10 @@ static size_t * other[PAGE_LEVELS] = {
(size_t *) 0xFFFFE000 (size_t *) 0xFFFFE000
}; };
/* Addresses of child/parent tables */
#define CHILD(map, lvl, vpn) &map[lvl-1][vpn<<PAGE_MAP_BITS]
#define PARENT(map, lvl, vpn) &map[lvl+1][vpn>>PAGE_MAP_BITS]
size_t page_virt_to_phys(size_t addr) size_t page_virt_to_phys(size_t addr)
{ {
size_t vpn = addr >> PAGE_BITS; // virtual page number size_t vpn = addr >> PAGE_BITS; // virtual page number
@ -79,7 +80,7 @@ size_t page_virt_to_phys(size_t addr)
int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits) int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits)
{ {
int lvl, ret = -ENOMEM; int lvl;
long vpn = viraddr >> PAGE_BITS; long vpn = viraddr >> PAGE_BITS;
long first[PAGE_LEVELS], last[PAGE_LEVELS]; long first[PAGE_LEVELS], last[PAGE_LEVELS];
@ -89,11 +90,7 @@ int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits)
last[lvl] = (vpn+npages-1) >> (lvl * PAGE_MAP_BITS); last[lvl] = (vpn+npages-1) >> (lvl * PAGE_MAP_BITS);
} }
/** @todo: might not be sufficient! */ spinlock_lock(&kslock);
if (bits & PG_USER)
spinlock_irqsave_lock(&current_task->page_lock);
else
spinlock_lock(&kslock);
/* Start iterating through the entries /* Start iterating through the entries
* beginning at the root table (PGD or PML4) */ * beginning at the root table (PGD or PML4) */
@ -104,17 +101,16 @@ int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits)
/* There's no table available which covers the region. /* There's no table available which covers the region.
* Therefore we need to create a new empty table. */ * Therefore we need to create a new empty table. */
size_t phyaddr = get_pages(1); size_t phyaddr = get_pages(1);
if (BUILTIN_EXPECT(!phyaddr, 0)) if (BUILTIN_EXPECT(!phyaddr, 0)) {
goto out; spinlock_unlock(&kslock);
return -ENOMEM;
if (bits & PG_USER) }
atomic_int32_inc(&current_task->user_usage);
/* Reference the new table within its parent */ /* Reference the new table within its parent */
self[lvl][vpn] = phyaddr | bits | PG_PRESENT; self[lvl][vpn] = phyaddr | bits;
/* Fill new table with zeros */ /* Fill new table with zeros */
memset(&self[lvl-1][vpn<<PAGE_MAP_BITS], 0, PAGE_SIZE); memset(CHILD(self, lvl, vpn), 0, PAGE_SIZE);
} }
} }
else { /* PGT */ else { /* PGT */
@ -123,54 +119,53 @@ int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits)
* We have to flush a single TLB entry. */ * We have to flush a single TLB entry. */
tlb_flush_one_page(vpn << PAGE_BITS); tlb_flush_one_page(vpn << PAGE_BITS);
self[lvl][vpn] = phyaddr | bits | PG_PRESENT; self[lvl][vpn] = phyaddr | bits;
phyaddr += PAGE_SIZE; phyaddr += PAGE_SIZE;
} }
} }
} }
ret = 0; spinlock_unlock(&kslock);
out:
if (bits & PG_USER)
spinlock_irqsave_unlock(&current_task->page_lock);
else
spinlock_unlock(&kslock);
return ret; return 0;
} }
/** Tables are freed by page_map_drop() */ /** Tables are freed by page_map_drop() */
int page_unmap(size_t viraddr, size_t npages) int page_unmap(size_t viraddr, size_t npages)
{ {
/* We aquire both locks for kernel and task tables long vpn, start = viraddr >> PAGE_BITS;
* as we dont know to which the region belongs. */ long end = start + npages;
spinlock_irqsave_lock(&current_task->page_lock);
spinlock_lock(&kslock); spinlock_lock(&kslock);
/* Start iterating through the entries. /* Start iterating through the entries.
* Only the PGT entries are removed. Tables remain allocated. */ * Only the PGT entries are removed. Tables remain allocated. */
size_t vpn, start = viraddr>>PAGE_BITS; for (vpn=start; vpn<end; vpn++)
for (vpn=start; vpn<start+npages; vpn++)
self[0][vpn] = 0; self[0][vpn] = 0;
spinlock_irqsave_unlock(&current_task->page_lock);
spinlock_unlock(&kslock); spinlock_unlock(&kslock);
/* This can't fail because we don't make checks here */
return 0; return 0;
} }
int page_map_drop() int page_map_drop()
{ {
void traverse(int lvl, long vpn) { void traverse(int lvl, long vpn) {
kprintf("traverse(lvl=%d, vpn=%#lx)\n", lvl, vpn);
long stop; long stop;
for (stop=vpn+PAGE_MAP_ENTRIES; vpn<stop; vpn++) { for (stop=vpn+PAGE_MAP_ENTRIES; vpn<stop; vpn++) {
if ((self[lvl][vpn] & PG_PRESENT) && (self[lvl][vpn] & PG_USER)) { if (self[lvl][vpn] & PG_PRESENT) {
/* Post-order traversal */ if (self[lvl][vpn] & PG_BOOT)
if (lvl) continue;
// ost-order traversal
if (lvl > 1)
traverse(lvl-1, vpn<<PAGE_MAP_BITS); traverse(lvl-1, vpn<<PAGE_MAP_BITS);
put_pages(self[lvl][vpn] & PAGE_MASK, 1); kprintf("%#lx, ", self[lvl][vpn] & PAGE_MASK);
//put_page(self[lvl][vpn] & PAGE_MASK);
atomic_int32_dec(&current_task->user_usage); atomic_int32_dec(&current_task->user_usage);
} }
} }
@ -182,62 +177,53 @@ int page_map_drop()
spinlock_irqsave_unlock(&current_task->page_lock); spinlock_irqsave_unlock(&current_task->page_lock);
/* This can't fail because we don't make checks here */
return 0; return 0;
} }
int page_map_copy(task_t *dest) int page_map_copy(size_t dest)
{ {
int traverse(int lvl, long vpn) { int traverse(int lvl, long vpn) {
long stop; long stop;
for (stop=vpn+PAGE_MAP_ENTRIES; vpn<stop; vpn++) { for (stop=vpn+PAGE_MAP_ENTRIES; vpn<stop; vpn++) {
if (self[lvl][vpn] & PG_PRESENT) { if (self[lvl][vpn] & PG_PRESENT) {
if (self[lvl][vpn] & PG_USER) { size_t phyaddr = get_pages(1);
size_t phyaddr = get_pages(1); if (BUILTIN_EXPECT(phyaddr, 0))
if (BUILTIN_EXPECT(!phyaddr, 0)) return -ENOMEM;
return -ENOMEM;
atomic_int32_inc(&dest->user_usage);
other[lvl][vpn] = phyaddr | (self[lvl][vpn] & ~PAGE_MASK); other[lvl][vpn] = phyaddr;
if (lvl) /* PML4, PDPT, PGD */ other[lvl][vpn] |= self[lvl][vpn] & ~PAGE_MASK;
traverse(lvl-1, vpn<<PAGE_MAP_BITS); /* Pre-order traversal */
else { /* PGT */ memcpy(CHILD(other, lvl, vpn), CHILD(self, lvl, vpn), PAGE_SIZE);
page_map(PAGE_TMP, phyaddr, 1, PG_RW);
memcpy((void*) PAGE_TMP, (void*) (vpn<<PAGE_BITS), PAGE_SIZE); // pre-order traversal
} if (lvl)
} traverse(lvl-1, vpn<<PAGE_MAP_BITS);
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; return 0;
} }
spinlock_irqsave_lock(&current_task->page_lock); spinlock_lock(&kslock);
self[PAGE_LEVELS-1][PAGE_MAP_ENTRIES-2] = dest->page_map | PG_PRESENT | PG_SELF | PG_RW;
int ret = traverse(PAGE_LEVELS-1, 0); // create another temporary self-reference
self[PAGE_LEVELS-1][PAGE_MAP_ENTRIES-2] = dest | PG_PRESENT | PG_RW;
other[PAGE_LEVELS-1][PAGE_MAP_ENTRIES-1] = dest->page_map | PG_PRESENT | PG_SELF | PG_RW; traverse(PAGE_LEVELS-1, 0);
self [PAGE_LEVELS-1][PAGE_MAP_ENTRIES-2] = 0;
spinlock_irqsave_unlock(&current_task->page_lock);
/* Flush TLB entries of 'other' self-reference */ // remove temporary self-reference
flush_tlb(); self[PAGE_LEVELS-1][PAGE_MAP_ENTRIES-2] = 0;
return ret; spinlock_unlock(&kslock);
return 0;
} }
void page_fault_handler(struct state *s) void page_fault_handler(struct state *s)
{ {
size_t viraddr = read_cr2(); 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", 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->int_no, s->cs, s->eip, current_task->id, viraddr, s->error,
(s->error & 0x4) ? "user" : "supervisor", (s->error & 0x4) ? "user" : "supervisor",
(s->error & 0x10) ? "instruction" : "data", (s->error & 0x10) ? "instruction" : "data",
@ -260,40 +246,40 @@ int page_init()
/* Map kernel */ /* Map kernel */
addr = (size_t) &kernel_start; addr = (size_t) &kernel_start;
npages = PAGE_FLOOR((size_t) &kernel_end - (size_t) &kernel_start) >> PAGE_BITS; npages = PAGE_FLOOR((size_t) &kernel_end - (size_t) &kernel_start) >> PAGE_BITS;
page_map(addr, addr, npages, PG_RW | PG_GLOBAL); page_map(addr, addr, npages, PG_PRESENT | PG_RW | PG_GLOBAL);
#ifdef CONFIG_VGA #ifdef CONFIG_VGA
/* Map video memory */ /* Map video memory */
page_map(VIDEO_MEM_ADDR, VIDEO_MEM_ADDR, 1, PG_RW | PG_PCD | PG_GLOBAL); page_map(VIDEO_MEM_ADDR, VIDEO_MEM_ADDR, 1, PG_PRESENT | PG_RW | PG_PCD);
#endif #endif
/* Map multiboot information and modules */ /* Map multiboot information and modules */
if (mb_info) { if (mb_info) {
addr = (size_t) mb_info & PAGE_MASK; addr = (size_t) mb_info & PAGE_MASK;
npages = PAGE_FLOOR(sizeof(*mb_info)) >> PAGE_BITS; npages = PAGE_FLOOR(sizeof(*mb_info)) >> PAGE_BITS;
page_map(addr, addr, npages, PG_GLOBAL); page_map(addr, addr, npages, PG_PRESENT | PG_GLOBAL);
if (mb_info->flags & MULTIBOOT_INFO_MODS) { if (mb_info->flags & MULTIBOOT_INFO_MODS) {
addr = mb_info->mods_addr; addr = mb_info->mods_addr;
npages = PAGE_FLOOR(mb_info->mods_count*sizeof(multiboot_module_t)) >> PAGE_BITS; npages = PAGE_FLOOR(mb_info->mods_count*sizeof(multiboot_module_t)) >> PAGE_BITS;
page_map(addr, addr, npages, PG_GLOBAL); page_map(addr, addr, npages, PG_PRESENT | PG_GLOBAL);
multiboot_module_t* mmodule = (multiboot_module_t*) ((size_t) mb_info->mods_addr); multiboot_module_t* mmodule = (multiboot_module_t*) ((size_t) mb_info->mods_addr);
for(i=0; i<mb_info->mods_count; i++) { for(i=0; i<mb_info->mods_count; i++) {
addr = mmodule[i].mod_start; addr = mmodule[i].mod_start;
npages = PAGE_FLOOR(mmodule[i].mod_end - mmodule[i].mod_start) >> PAGE_BITS; npages = PAGE_FLOOR(mmodule[i].mod_end - mmodule[i].mod_start) >> PAGE_BITS;
page_map(addr, addr, npages, PG_USER | PG_GLOBAL); page_map(addr, addr, npages, PG_PRESENT | PG_USER | PG_GLOBAL);
} }
} }
} }
/* Unmap bootstrap identity paging (see entry.asm, PG_BOOT) */ /* Unmap bootstrap identity paging (see entry.asm, PG_BOOT) */
for (i=0; i<PAGE_MAP_ENTRIES; i++) for (i=0; i<PAGE_MAP_ENTRIES; i++) {
if (self[0][i] & PG_BOOT) if (self[0][i] & PG_BOOT) {
self[0][i] = 0; self[0][i] = 0;
tlb_flush_one_page(i << PAGE_BITS);
/* Flush TLB to adopt changes above */ }
flush_tlb(); }
return 0; return 0;
} }

View file

@ -1,5 +1,5 @@
# Constant part of the script # Constant part of the script
symbol-file eduos.elf symbol-file eduos.sym
target remote localhost:1234 target remote localhost:1234
set architecture i386 set architecture i386

View file

@ -40,15 +40,11 @@ extern "C" {
#define CACHE_LINE 64 #define CACHE_LINE 64
#define KERNEL_STACK_SIZE (8<<10) /* 8 KiB */ #define KERNEL_STACK_SIZE (8<<10) /* 8 KiB */
#define BITMAP_SIZE (128<<5) /* for 128 MiB of RAM */ #define BITMAP_SIZE (128<<5) /* for 128 MiB of RAM */
#define KMSG_SIZE (8*1024)
#define INT_SYSCALL 0x80 #define INT_SYSCALL 0x80
#define MAILBOX_SIZE 32
#define BYTE_ORDER LITTLE_ENDIAN #define BYTE_ORDER LITTLE_ENDIAN
#define CONFIG_VGA #define CONFIG_VGA
#define CONFIG_PCI
#define CONFIG_UART
#define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b)) #define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b))
//#define BUILTIN_EXPECT(exp, b) (exp) //#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__ #define __SEMAPHORE_H__
#include <eduos/string.h> #include <eduos/string.h>
#include <eduos/tasks.h>
#include <eduos/semaphore_types.h> #include <eduos/semaphore_types.h>
#include <eduos/spinlock.h> #include <eduos/spinlock.h>
#include <eduos/errno.h> #include <eduos/errno.h>

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); 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 #ifdef __cplusplus
} }
#endif #endif

View file

@ -76,7 +76,7 @@ typedef struct task {
/// Task priority /// Task priority
uint8_t prio; uint8_t prio;
/// Physical address of root page table /// Physical address of root page table
size_t page_map; size_t page_map;
/// Lock for page tables /// Lock for page tables
spinlock_irqsave_t page_lock; spinlock_irqsave_t page_lock;
/// usage in number of pages (including page map tables) /// usage in number of pages (including page map tables)

View file

@ -39,7 +39,6 @@
#include <asm/irqflags.h> #include <asm/irqflags.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/uart.h>
/* /*
* Note that linker symbols are not variables, they have no memory allocated for * Note that linker symbols are not variables, they have no memory allocated for
@ -57,16 +56,17 @@ extern atomic_int32_t total_pages;
extern atomic_int32_t total_allocated_pages; extern atomic_int32_t total_allocated_pages;
extern atomic_int32_t total_available_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_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) static int wrapper(void* arg)
{ {
@ -74,26 +74,9 @@ static int wrapper(void* arg)
memset(ustack, 0xCD, KERNEL_STACK_SIZE); memset(ustack, 0xCD, KERNEL_STACK_SIZE);
*stack-- = (size_t) arg; *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); 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) static int foo(void* arg)
@ -117,15 +100,12 @@ static int eduos_init(void)
// initialize .bss section // initialize .bss section
memset((void*)&bss_start, 0x00, ((size_t) &bss_end - (size_t) &bss_start)); memset((void*)&bss_start, 0x00, ((size_t) &bss_end - (size_t) &bss_start));
koutput_init();
system_init(); system_init();
irq_init(); irq_init();
timer_init(); timer_init();
koutput_init();
multitasking_init(); multitasking_init();
memory_init(); memory_init();
#ifdef CONFIG_UART
uart_init();
#endif
return 0; return 0;
} }

View file

@ -75,7 +75,6 @@ int multitasking_init(void)
task_table[0].prio = IDLE_PRIO; task_table[0].prio = IDLE_PRIO;
task_table[0].stack = (void*) &boot_stack; task_table[0].stack = (void*) &boot_stack;
task_table[0].page_map = read_cr3();
// register idle task // register idle task
register_task(); register_task();
@ -122,16 +121,16 @@ static void NORETURN do_exit(int arg)
kprintf("Terminate task: %u, return value %d\n", curr_task->id, arg); kprintf("Terminate task: %u, return value %d\n", curr_task->id, arg);
page_map_drop(); page_map_drop();
curr_task->status = TASK_FINISHED;
reschedule();
// decrease the number of active tasks // decrease the number of active tasks
spinlock_irqsave_lock(&readyqueues.lock); spinlock_irqsave_lock(&readyqueues.lock);
readyqueues.nr_tasks--; readyqueues.nr_tasks--;
spinlock_irqsave_unlock(&readyqueues.lock); spinlock_irqsave_unlock(&readyqueues.lock);
curr_task->status = TASK_FINISHED;
reschedule();
kprintf("Kernel panic: scheduler found no valid task\n"); kprintf("Kernel panic: scheduler found no valid task\n");
while(1) { while(1) {
HALT; HALT;
@ -204,13 +203,13 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg, uint8_t prio)
spinlock_irqsave_init(&task_table[i].page_lock); spinlock_irqsave_init(&task_table[i].page_lock);
atomic_int32_set(&task_table[i].user_usage, 0); atomic_int32_set(&task_table[i].user_usage, 0);
/* Allocated new PGD or PML4 and copy page table */ /* Allocated new PGD or PML4 and copy page table */
task_table[i].page_map = get_pages(1); size_t map = get_pages(1);
if (BUILTIN_EXPECT(!task_table[i].page_map, 0)) if (BUILTIN_EXPECT(map, 0))
goto out; goto out;
/* Copy page tables & user frames of current task to new one */ page_map_copy(map);
page_map_copy(&task_table[i]); task_table[i].page_map = map;
if (id) if (id)
*id = i; *id = i;
@ -397,7 +396,7 @@ get_task_out:
spinlock_irqsave_unlock(&readyqueues.lock); spinlock_irqsave_unlock(&readyqueues.lock);
if (current_task != orig_task) { 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); return (size_t**) &(orig_task->last_stack_pointer);
} }

View file

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

View file

@ -90,7 +90,6 @@ inline static void page_clear_mark(size_t i)
size_t get_pages(size_t npages) size_t get_pages(size_t npages)
{ {
size_t cnt, off; size_t cnt, off;
static size_t alloc_start = (size_t) -1;
if (BUILTIN_EXPECT(!npages, 0)) if (BUILTIN_EXPECT(!npages, 0))
return 0; return 0;
@ -99,18 +98,13 @@ size_t get_pages(size_t npages)
spinlock_lock(&bitmap_lock); spinlock_lock(&bitmap_lock);
if (alloc_start == (size_t)-1)
alloc_start = ((size_t) &kernel_end >> PAGE_BITS);
off = 1; off = 1;
while (off <= BITMAP_SIZE*8 - npages) { while (off <= BITMAP_SIZE*8 - npages) {
for (cnt=0; cnt<npages; cnt++) { for (cnt=0; cnt<npages; cnt++) {
if (page_marked(((off+alloc_start)%(BITMAP_SIZE*8 - npages))+cnt)) if (page_marked(off+cnt))
goto next; goto next;
} }
off = (off+alloc_start) % (BITMAP_SIZE*8 - npages);
alloc_start = off+npages;
for (cnt=0; cnt<npages; cnt++) { for (cnt=0; cnt<npages; cnt++) {
page_set_mark(off+cnt); page_set_mark(off+cnt);
} }