
65 changed files with 7915 additions and 6 deletions
@ -0,0 +1,11 @@
|
||||
MODULE = qemu-i386_base
|
||||
|
||||
DIRS = $(RIOTBOARD)/x86-multiboot-common
|
||||
|
||||
all: $(BINDIR)$(MODULE).a |
||||
@for i in $(DIRS) ; do "$(MAKE)" -C $$i ; done ;
|
||||
|
||||
include $(RIOTBASE)/Makefile.base |
||||
|
||||
clean:: |
||||
@for i in $(DIRS) ; do "$(MAKE)" -C $$i clean ; done ;
|
@ -0,0 +1,7 @@
|
||||
include $(RIOTBOARD)/x86-multiboot-common/Makefile.include |
||||
|
||||
CFLAGS += -march=i686 -mtune=i686
|
||||
CFLAGS += -I$(RIOTBOARD)/qemu-i386/include
|
||||
|
||||
TERMPROG = qemu-system-i386 -m 512m -serial stdio -nographic -monitor /dev/null -kernel $(BINDIR)/$(PROJECT).hex
|
||||
FLASHER = true
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* @ingroup x86 |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Board specific defines for qemu-i386. |
||||
* |
||||
* @author René Kijewski <rene.kijewski@fu-berlin.de> |
||||
*/ |
||||
|
||||
#ifndef __RIOT__BOARDS__QEMU_I386__BOARD__H |
||||
#define __RIOT__BOARDS__QEMU_I386__BOARD__H |
||||
|
||||
#define UART_PORT (COM1_PORT) /* IO port to use for UART */ |
||||
#define UART_IRQ (COM1_IRQ) /* IRQ line to use for UART */ |
||||
|
||||
#define LED_RED_ON /* not available */ |
||||
#define LED_RED_OFF /* not available */ |
||||
#define LED_RED_TOGGLE /* not available */ |
||||
|
||||
#endif |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* CPU-specific defines for qemu-i386. |
||||
* |
||||
* @ingroup x86 |
||||
* @{ |
||||
* @file |
||||
* @author René Kijewski <rene.kijewski@fu-berlin.de> |
||||
*/ |
||||
|
||||
#ifndef __RIOT__BOARDS__QEMU_I386__CPU_CONF__H |
||||
#define __RIOT__BOARDS__QEMU_I386__CPU_CONF__H |
||||
|
||||
/* FIXME: This file is just a filler. The numbers are entirely random ... */ |
||||
|
||||
#define KERNEL_CONF_STACKSIZE_DEFAULT (8192) |
||||
#define KERNEL_CONF_STACKSIZE_IDLE (8192) |
||||
#define KERNEL_CONF_STACKSIZE_PRINTF (8192) |
||||
#define KERNEL_CONF_STACKSIZE_PRINTF_FLOAT (8192) |
||||
|
||||
#define MINIMUM_STACK_SIZE (8192) |
||||
|
||||
#define UART0_BUFSIZE (16) |
||||
|
||||
#define F_CPU (1000000) /* This value is unused in x86 */ |
||||
|
||||
#endif |
||||
|
||||
/** @} */ |
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* @ingroup x86 |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Initialization code for the qemu-i386 board |
||||
* |
||||
* @author René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#include "cpu.h" |
||||
#include "x86_ports.h" |
||||
#include "x86_reboot.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
static bool qemu_shutdown(void) |
||||
{ |
||||
unsigned old_state = disableIRQ(); |
||||
|
||||
DEBUG("SHUTTING DOWN.\n"); |
||||
|
||||
/* (phony) ACPI shutdown (http://forum.osdev.org/viewtopic.php?t=16990) */ |
||||
/* Works for qemu and bochs. */ |
||||
outw(0xB004, 0x2000); |
||||
|
||||
restoreIRQ(old_state); |
||||
return false; |
||||
} |
||||
|
||||
void x86_init_board(void) |
||||
{ |
||||
x86_set_shutdown_fun(qemu_shutdown); |
||||
} |
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* @ingroup x86 |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Placeholder if someone uses x86-multiboot as a board. |
||||
* |
||||
* @author René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#include <lpm.h> |
||||
|
||||
void lpm_init(void) |
||||
{ |
||||
// void
|
||||
} |
||||
|
||||
enum lpm_mode lpm_set(enum lpm_mode target) |
||||
{ |
||||
if (target != LPM_ON) { |
||||
asm volatile ("hlt"); |
||||
} |
||||
return LPM_UNKNOWN; |
||||
} |
||||
|
||||
void lpm_awake(void) |
||||
{ |
||||
// void
|
||||
} |
||||
|
||||
void lpm_begin_awake(void) |
||||
{ |
||||
// void
|
||||
} |
||||
|
||||
void lpm_end_awake(void) |
||||
{ |
||||
// void
|
||||
} |
@ -0,0 +1,3 @@
|
||||
MODULE = x86-multiboot-common_base
|
||||
|
||||
include $(RIOTBASE)/Makefile.base |
@ -0,0 +1,56 @@
|
||||
ifeq (, $(NEWLIB_BASE)) |
||||
NEWLIB_BASE := $(RIOTBASE)/toolchain/x86/i586-none-elf
|
||||
|
||||
ifneq (0, $(shell test -e "$(NEWLIB_BASE)/lib/libc.a" && echo $$?))
|
||||
NEWLIB_PRECOMPILED_NAME := i586-newlib_2.1.0_tlsf.txz
|
||||
NEWLIB_PRECOMPILED := http://download.riot-os.org/$(NEWLIB_PRECOMPILED_NAME)
|
||||
|
||||
$(warning "Precompiled newlib is missing in $(NEWLIB_BASE)")
|
||||
$(warning "Downloading from $(NEWLIB_PRECOMPILED)")
|
||||
|
||||
$(shell cd $(RIOTBASE) && wget -qO- "$(NEWLIB_PRECOMPILED)" | tar xJ)
|
||||
endif
|
||||
endif |
||||
|
||||
ifeq (,$(BUILD_INCLUDE_BASE)) |
||||
GCC_BUILD_TRIPLET ?= $(shell gcc -dumpmachine)
|
||||
GCC_BUILD_VERSION ?= $(shell gcc -dumpversion)
|
||||
BUILD_INCLUDE_BASE = /usr/lib/gcc/$(GCC_BUILD_TRIPLET)/$(GCC_BUILD_VERSION)
|
||||
|
||||
ifeq (,$(shell echo $(GCC_BUILD_TRIPLET) | sed -e 's,-.*,,' | grep -e '\(x\|i[3-7]\)86'))
|
||||
$(warning Your build machine is a(n) $(GCC_BUILD_TRIPLET).)
|
||||
$(warning Since this is not IA32 compatible, you must set BUILD_INCLUDE_BASE explicitly!)
|
||||
endif
|
||||
endif |
||||
|
||||
export INCLUDES += -isystem $(BUILD_INCLUDE_BASE)/include \
|
||||
-isystem $(NEWLIB_BASE)/include \
|
||||
-isystem $(NEWLIB_BASE)/sys-include \
|
||||
-isystem $(BUILD_INCLUDE_BASE)/include-fixed \
|
||||
-I$(RIOTBOARD)/x86-multiboot-common/include
|
||||
export CPU = x86
|
||||
|
||||
# toolchain config
|
||||
export CC ?= $(PREFIX)gcc
|
||||
export AR ?= $(PREFIX)ar
|
||||
export AS ?= $(PREFIX)as
|
||||
export RANLIB ?= $(PREFIX)ranlib
|
||||
export LINK ?= $(RIOTBASE)/boards/x86-multiboot-common/dist/link $(PREFIX)gcc
|
||||
export SIZE ?= $(PREFIX)size
|
||||
export OBJCOPY ?= $(PREFIX)objcopy
|
||||
|
||||
export CFLAGS += -m32 -mfpmath=387 -ffreestanding -nostdlib -nostdinc -fno-builtin
|
||||
export OFLAGS = -O binary
|
||||
|
||||
LINKFLAGS += -m32 -nostdlib -nostdinc -nostartfiles -nodefaultlibs \
|
||||
--prefix=$(NEWLIB_BASE) \
|
||||
-Wl,-rpath,$(NEWLIB_BASE)/lib \
|
||||
-T $(RIOTBASE)/boards/x86-multiboot-common/linker.ld
|
||||
UNDEF += $(BINDIR)x86-multiboot-common_base/startup.o
|
||||
|
||||
#CFLAGS += -ffunction-sections -fdata-sections
|
||||
#LINKFLAGS += -Wl,--gc-sections
|
||||
#CFLAGS += -Wall -Wextra -Werror -pedantic -pedantic-errors \
|
||||
|
||||
BASELIBS += $(NEWLIB_BASE)/lib/libc.a \
|
||||
$(NEWLIB_BASE)/lib/libm.a
|
@ -0,0 +1,14 @@
|
||||
#!/bin/bash |
||||
|
||||
args=($@) |
||||
|
||||
for ((i = 0; i < ${#args[@]}; ++i)) |
||||
do |
||||
if [[ "${args[i]}" == '-lm' ]] |
||||
then |
||||
unset args[i] |
||||
break |
||||
fi |
||||
done |
||||
|
||||
exec "${args[@]}" |
@ -0,0 +1,124 @@
|
||||
/* multiboot.h - the header for Multiboot */ |
||||
/* Copyright (C) 1999, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation; either version 2 of the License, or |
||||
(at your option) any later version. |
||||
|
||||
This program is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with this program; if not, write to the Free Software |
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
||||
|
||||
/**
|
||||
* Architecture specific definitions for multiboot enabled kernels. |
||||
* |
||||
* @ingroup x86-multiboot |
||||
* @{ |
||||
* @file |
||||
*/ |
||||
|
||||
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 /**< The magic number for the Multiboot header. */ |
||||
#define MULTIBOOT_HEADER_FLAGS 0x00010003 /**< The flags for the Multiboot header. */ |
||||
#define MULTIBOOT_HEADER_CHECKSUM (-(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)) /**< The checksum for the Multiboot header. */ |
||||
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 /**< The magic number passed by a Multiboot-compliant boot loader. */ |
||||
|
||||
/**
|
||||
* @brief The Multiboot header. |
||||
* |
||||
* A multiboot enabled kernel needs to contain this header in the first 8kB of the binary file. |
||||
*/ |
||||
typedef struct multiboot_header { |
||||
unsigned long magic; /**< Set to MULTIBOOT_HEADER_MAGIC. */ |
||||
unsigned long flags; /**< Set to MULTIBOOT_HEADER_FLAGS. */ |
||||
unsigned long checksum; /**< Set to MULTIBOOT_HEADER_CHECKSUM. */ |
||||
unsigned long header_addr; /**< The address of the datum. */ |
||||
unsigned long load_addr; /**< Set to `(uintptr_t) &_kernel_memory_start`. */ |
||||
unsigned long load_end_addr; /**< Set to `(uintptr_t) &_section_data_end`. */ |
||||
unsigned long bss_end_addr; /**< Set to `(uintptr_t) &_section_bss_end` */ |
||||
unsigned long entry_addr; /**< Your entry function. */ |
||||
} multiboot_header_t; |
||||
|
||||
/**
|
||||
* @brief The symbol table for a.out. |
||||
* |
||||
* Do not use! |
||||
*/ |
||||
typedef struct aout_symbol_table { |
||||
unsigned long tabsize; |
||||
unsigned long strsize; |
||||
unsigned long addr; |
||||
unsigned long reserved; |
||||
} aout_symbol_table_t; |
||||
|
||||
/**
|
||||
* @brief The section header table for ELF. |
||||
* |
||||
* Do not use! |
||||
*/ |
||||
typedef struct elf_section_header_table { |
||||
unsigned long num; |
||||
unsigned long size; |
||||
unsigned long addr; |
||||
unsigned long shndx; |
||||
} elf_section_header_table_t; |
||||
|
||||
/**
|
||||
* @brief The multiboot information provided by the bootloader (e.g. Grub). |
||||
*/ |
||||
typedef struct multiboot_info { |
||||
unsigned long flags; |
||||
unsigned long mem_lower; |
||||
unsigned long mem_upper; |
||||
unsigned long boot_device; |
||||
unsigned long cmdline; |
||||
unsigned long mods_count; |
||||
unsigned long mods_addr; |
||||
union { |
||||
aout_symbol_table_t aout_sym; |
||||
elf_section_header_table_t elf_sec; |
||||
} u; |
||||
unsigned long mmap_length; |
||||
unsigned long mmap_addr; |
||||
} multiboot_info_t; |
||||
|
||||
/**
|
||||
* @brief The module structure. |
||||
* |
||||
* Do not use! |
||||
*/ |
||||
typedef struct module { |
||||
unsigned long mod_start; |
||||
unsigned long mod_end; |
||||
unsigned long string; |
||||
unsigned long reserved; |
||||
} module_t; |
||||
|
||||
/**
|
||||
* @brief An entry in the memory map table. |
||||
*/ |
||||
typedef struct memory_map { |
||||
unsigned long size; |
||||
unsigned long base_addr_low; |
||||
unsigned long base_addr_high; |
||||
unsigned long length_low; |
||||
unsigned long length_high; |
||||
unsigned long type; |
||||
} memory_map_t; |
||||
|
||||
enum multiboot_info_flags { |
||||
MULTIBOOT_INFO_FLAGS_MEM = 0x01, |
||||
MULTIBOOT_INFO_FLAGS_BOOT = 0x02, |
||||
MULTIBOOT_INFO_FLAGS_CMDLINE = 0x04, |
||||
MULTIBOOT_INFO_FLAGS_MODS = 0x08, |
||||
MULTIBOOT_INFO_FLAGS_SYMS1 = 0x10, |
||||
MULTIBOOT_INFO_FLAGS_SYMS2 = 0x20, |
||||
MULTIBOOT_INFO_FLAGS_MMAP = 0x40, |
||||
}; |
||||
|
||||
/** @} */ |
@ -0,0 +1,117 @@
|
||||
/* |
||||
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/* The bootloader will look at this image and start execution at the symbol |
||||
designated as the entry point. */ |
||||
ENTRY(_start) |
||||
|
||||
/* Tell where the various sections of the object files will be put in the final |
||||
kernel image. */ |
||||
SECTIONS |
||||
{ |
||||
/* Begin putting sections at 1 MiB, a conventional place for kernels to be |
||||
loaded at by the bootloader. */ |
||||
. = 1M; |
||||
_kernel_memory_start = .; |
||||
|
||||
/* First put the multiboot header, as it is required to be put very early |
||||
early in the image or the bootloader won't recognize the file format. |
||||
Next we'll put the .text section. */ |
||||
._multiboot_header : |
||||
{ |
||||
*(._multiboot_header) |
||||
} |
||||
|
||||
.note.gnu.build-id : |
||||
{ |
||||
*(.note.gnu.build-id) |
||||
} |
||||
|
||||
.text : |
||||
{ |
||||
. = ALIGN(4); |
||||
_section_text_start = .; |
||||
|
||||
*(.text) |
||||
*(.text.*) |
||||
|
||||
*(.gnu.linkonce.t) |
||||
*(.gnu.linkonce.t.*) |
||||
|
||||
_section_text_end = .; |
||||
} |
||||
. = ALIGN(0x1000); |
||||
|
||||
/* Read-only data. */ |
||||
.rodata : |
||||
{ |
||||
_section_rodata_start = .; |
||||
|
||||
*(.rodata) |
||||
*(.rodata.*) |
||||
|
||||
*(.gnu.linkonce.r) |
||||
*(.gnu.linkonce.r.*) |
||||
|
||||
_section_rodata_end = .; |
||||
} |
||||
. = ALIGN(0x1000); |
||||
|
||||
/* Read-write data (initialized) */ |
||||
.data : |
||||
{ |
||||
_section_data_start = .; |
||||
|
||||
*(.data) |
||||
*(.data.*) |
||||
|
||||
*(.gnu.linkonce.d) |
||||
*(.gnu.linkonce.d.*) |
||||
|
||||
. = ALIGN(4); |
||||
_section_data_end = .; |
||||
/* no need to align between .data and .bss */ |
||||
} |
||||
|
||||
/* Read-write data (uninitialized) and stack */ |
||||
.bss : |
||||
{ |
||||
_section_bss_start = .; |
||||
|
||||
*(COMMON) |
||||
*(COMMON.*) |
||||
|
||||
*(.bss) |
||||
*(.bss.*) |
||||
|
||||
*(.gnu.linkonce.b) |
||||
*(.gnu.linkonce.b.*) |
||||
|
||||
_section_bss_end = .; |
||||
} |
||||
|
||||
. = ALIGN(0x1000); |
||||
_kernel_memory_end = .; |
||||
|
||||
. += 0x1000; |
||||
. = ALIGN(0x10000); |
||||
_heap_start = .; |
||||
|
||||
/* The compiler may produce other sections, by default it will put them in |
||||
a segment with the same name. Simply add stuff here as needed. */ |
||||
} |
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* @ingroup x86 |
||||
* @ingroup boards |
||||
* @defgroup x86-multiboot i586 multiboot common |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Startup code to be loaded by multiboot enabled bootloaders. |
||||
* |
||||
* @author René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#include <cpu.h> |
||||
#include <multiboot.h> |
||||
#include <x86_kernel_memory.h> |
||||
#include <x86_memory.h> |
||||
#include <x86_reboot.h> |
||||
#include <x86_videoram.h> |
||||
|
||||
#include <inttypes.h> |
||||
#include <stdint.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#ifndef BREAK_STARTUP |
||||
# define BREAK_STARTUP (0) |
||||
#endif |
||||
|
||||
static void __attribute__((noreturn)) startup(uint32_t multiboot_magic, const multiboot_info_t *multiboot_info); |
||||
void __attribute__((noreturn, optimize("Os", "omit-frame-pointer"), no_instrument_function)) _start(void); |
||||
|
||||
extern const multiboot_header_t multiboot_header __attribute__((section("._multiboot_header"))); |
||||
const multiboot_header_t multiboot_header = { |
||||
.magic = MULTIBOOT_HEADER_MAGIC, |
||||
.flags = MULTIBOOT_HEADER_FLAGS, |
||||
.checksum = MULTIBOOT_HEADER_CHECKSUM, |
||||
.header_addr = (uintptr_t) &multiboot_header, |
||||
.load_addr = (uintptr_t) &_kernel_memory_start, |
||||
.load_end_addr = (uintptr_t) &_section_data_end, |
||||
.bss_end_addr = (uintptr_t) &_section_bss_end, |
||||
.entry_addr = (uintptr_t) &_start, |
||||
}; |
||||
|
||||
void __attribute__((noreturn, optimize("Os", "omit-frame-pointer"), no_instrument_function)) _start(void) |
||||
{ |
||||
asm volatile ("xor %ebp, %ebp"); |
||||
asm volatile ("push %ebp"); |
||||
asm volatile ("push %ebx"); |
||||
asm volatile ("push %eax"); |
||||
asm volatile ("push %ebp"); |
||||
asm volatile ("jmp *%0" :: "r"(&startup)); |
||||
__builtin_unreachable(); |
||||
} |
||||
|
||||
static const multiboot_info_t *multiboot_info; |
||||
|
||||
bool x86_get_memory_region(uint64_t *start, uint64_t *len, unsigned long *pos) |
||||
{ |
||||
while (1) { |
||||
if (*pos >= multiboot_info->mmap_length) { |
||||
return false; |
||||
} |
||||
|
||||
const memory_map_t *mmap = (void *)(multiboot_info->mmap_addr + *pos); |
||||
*pos += mmap->size + 4; |
||||
|
||||
*start = mmap->base_addr_low + ((uint64_t) mmap->base_addr_high << 32); |
||||
*len = mmap->length_low + ((uint64_t) mmap->length_high << 32); |
||||
|
||||
uint64_t end = *start + *len; |
||||
printf(" %08lx%08lx - %08lx%08lx ", (long) (*start >> 32), (long) *start, (long) (end >> 32), (long) end); |
||||
|
||||
if (mmap->type != 1) { |
||||
// not free (ignore reclaimable RAM)
|
||||
const char *msg; |
||||
switch (mmap->type) { |
||||
case 2: msg = "reseved"; break; |
||||
case 3: msg = "ACPI [reclaimable]"; break; |
||||
case 4: msg = "ACPI [NVS]"; break; |
||||
case 5: msg = "bad memory"; break; |
||||
default: msg = "unknown"; |
||||
} |
||||
printf("(unusable: %s)\r\n", msg); |
||||
} |
||||
else { |
||||
puts("(usable)"); |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void have_a_break(void) |
||||
{ |
||||
volatile bool cnt = false; |
||||
while (!cnt) { |
||||
asm volatile ("pause"); |
||||
} |
||||
} |
||||
|
||||
static void __attribute__((noreturn)) startup(uint32_t multiboot_magic, const multiboot_info_t *multiboot_info_) |
||||
{ |
||||
x86_init_gdt(); /* load GDT early */ |
||||
x86_load_empty_idt(); /* just a safeguard to cause a tripple fault, not really needed */ |
||||
|
||||
#if BREAK_STARTUP |
||||
have_a_break(); |
||||
#else |
||||
(void) have_a_break; |
||||
#endif |
||||
|
||||
memset(&_section_bss_start, 0, &_section_bss_end - &_section_bss_start + 1); |
||||
|
||||
videoram_puts(" Booting RIOT \r\n"); |
||||
if (multiboot_magic != MULTIBOOT_BOOTLOADER_MAGIC) { |
||||
videoram_puts(" Multiboot magic is wrong \r\n"); |
||||
x86_hlt(); |
||||
} |
||||
else if (!(multiboot_info->flags && MULTIBOOT_INFO_FLAGS_MMAP)) { |
||||
videoram_puts(" Multiboot is lacking memory map information \r\n"); |
||||
x86_hlt(); |
||||
} |
||||
|
||||
multiboot_info = multiboot_info_; |
||||
x86_startup(); |
||||
} |
@ -0,0 +1,4 @@
|
||||
export INCLUDES += -I$(RIOTCPU)/x86/include
|
||||
|
||||
export USEMODULE += quad_math
|
||||
export USEPKG += tlsf
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* Basic definitions and forwards for x86 boards. |
||||
* |
||||
* @defgroup x86 i586 |
||||
* @ingroup cpu |
||||
* @{ |
||||
* @file |
||||
* @author René Kijewski <rene.kijewski@fu-berlin.de> |
||||
*/ |
||||
|
||||
#ifndef CPU__X86__CPU__H__ |
||||
#define CPU__X86__CPU__H__ |
||||
|
||||
#include "attributes.h" |
||||
#include "irq.h" |
||||
#include "ucontext.h" |
||||
#include "cpu-conf.h" |
||||
|
||||
#include <stdbool.h> |
||||
#include <stdint.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
static inline void __attribute__((always_inline)) dINT(void) |
||||
{ |
||||
asm volatile ("cli"); |
||||
} |
||||
|
||||
static inline void __attribute__((always_inline)) eINT(void) |
||||
{ |
||||
asm volatile ("sti"); |
||||
} |
||||
|
||||
/**
|
||||
* @brief Disable interrupts and halt forever. |
||||
* |
||||
* This function is the last resort in case of an unrecoverable error. |
||||
* No message will be printed, no nothing. |
||||
*/ |
||||
static inline void __attribute__((always_inline, noreturn)) x86_hlt(void) |
||||
{ |
||||
while (1) { |
||||
asm volatile ("cli"); |
||||
asm volatile ("hlt"); |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* @brief Initialize subsystems and run kernel. |
||||
* |
||||
* Called by the board specific startup code. |
||||
* <li>The .bss has to be cleared before. |
||||
* <li>The stack has to be set up, probably somewhere in the low memory. |
||||
* <li>The A20 line has to be activated, because all the code is beyong 1MB. |
||||
* <li>Paging must be disabled. |
||||
* <li>The SS, DS, and CS must span the whole 4GB of RAM. |
||||
* <li>32 bit protected mode must be entered. |
||||
* <li>Interrupts must be disabled. |
||||
*/ |
||||
void x86_startup(void) NORETURN; |
||||
|
||||
/**
|
||||
* @brief Setup board specific hardware and such. |
||||
* |
||||
* Called by x86_startup() after all generic subsystems are activated, |
||||
* and before kernel_init() gets called. |
||||
* Interrupts are disabled before, and are expected to be disabled after calling this function. |
||||
* Interrupts may be enabled during the course of this function call. |
||||
* |
||||
* Probably most of the board specific initialization should be done in auto_init(): |
||||
* <li>You must not spawn thread_create() in this function. |
||||
* <li>The hwtimer is not set up properly at this point of executation. |
||||
*/ |
||||
void x86_init_board(void); |
||||
|
||||
/**
|
||||
* @brief Returns a range of usable physical memory. |
||||
* @param[out] start Start address of the physical memory region. |
||||
* @param[out] len Total length of the physical memory region. |
||||
* One page are 0x1000 bytes. |
||||
* @param cnt Reentrant pointer. Must be zero on first call. |
||||
* The value is entirely opaque. |
||||
* @returns true iff there was a memory region set in start and len. |
||||
* false iff there are no more memory regions. |
||||
* The function must not get called again in the latter case. |
||||
* |
||||
* Called by x86_startup() before x86_init_board() gets called. |
||||
* |
||||
* The memory management is one of the earliest subsystems to be set up. |
||||
* The uart is already configured and usable. |
||||
* The interrupt handling is already set up and you may call x86_interrupt_handler_set(). |
||||
* |
||||
* The function may return unaligned memory. |
||||
* In this case the begin of the region gets rounded up the the next page, |
||||
* and the end gets rounded down. |
||||
* The function may supply low memory regions, which will be ignored. |
||||
* The regions are expected to contain memory that lies inside the elf sections. |
||||
*/ |
||||
bool x86_get_memory_region(uint64_t *start, uint64_t *len, unsigned long *cnt); |
||||
|
||||
#endif |
||||
|
||||
/** @} */ |
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* Basic definitions for the hwtimer. |
||||
* |
||||
* @ingroup x86 |
||||
* @ingroup core_hwtimer |
||||
* @{ |
||||
* @file |
||||
* @author René Kijewski <rene.kijewski@fu-berlin.de> |
||||
*/ |
||||
|
||||
#ifndef CPU__X86__HWTIMER_CPU__H__ |
||||
#define CPU__X86__HWTIMER_CPU__H__ |
||||
|
||||
/**
|
||||
* @brief Number of configured hardware timers. |
||||
* |
||||
* This value may be set as high as you need it. |
||||
* The x86_hwtimer.c can emulate a lot of timers, since the real timers aren't used. :-) |
||||
*/ |
||||
#ifndef HWTIMER_MAXTIMERS |
||||
# define HWTIMER_MAXTIMERS 4 |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief How many "ticks" there are in one second of wallclock time. |
||||
* |
||||
* Statically configured as `1 tick = 1 µs`. |
||||
*/ |
||||
#define HWTIMER_SPEED (1000000L) |
||||
|
||||
/**
|
||||
* @brief Biggest value that can specify a valid number of hardware ticks. |
||||
* |
||||
* Since 1 tick = 1 µs, this number will flow over after 4295 seconds (1h11m34s). |
||||
*/ |
||||
#define HWTIMER_MAXTICKS (0xFFFFFFFFu) |
||||
|
||||
#endif |
||||
|
||||
/** @} */ |
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* Coroutine helper functions. The base of the multi-threading system. |
||||
* |
||||
* @ingroup x86-multithreading |
||||
* @{ |
||||
* @file |
||||
* @author René Kijewski <rene.kijewski@fu-berlin.de> |
||||
*/ |
||||
|
||||
#ifndef CPU__X86__UCONTEXT__HPP__ |
||||
#define CPU__X86__UCONTEXT__HPP__ |
||||
|
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
|
||||
/**
|
||||
* @brief Common stacksize for a signal handler. |
||||
* |
||||
* Do not use this variable. |
||||
* The standard wants us to define this variable, but you are better off the the RIOT specific macros. |
||||
*/ |
||||
#define SIGSTKSZ (2048) |
||||
|
||||
/**
|
||||
* @brief General purpose registers of an x86 CPU. |
||||
* |
||||
* Used by ucontext_t. |
||||
* Application developers should not use this type directly. |
||||
*/ |
||||
struct x86_pushad { |
||||
unsigned long ax, cx, dx, bx; /* field in ucontext_t: 3*4 -> 6*4 */ |
||||
unsigned long sp, bp, si, di; /* field in ucontext_t: 7*4 -> 10*4 */ |
||||
} __attribute__((packed)); |
||||
|
||||
/**
|
||||
* @brief Opaque memory needed to store the x87 FPU state. |
||||
* |
||||
* Used by x86_threading.c. |
||||
* Application developers should not use this type directly. |
||||
* There is only enough room for the basic x87 state, not the multimedia extensions. |
||||
*/ |
||||
struct x86_fxsave { |
||||
char opaque[512]; |
||||
} __attribute__((packed, aligned(0x10))); |
||||
|
||||
/**
|
||||
* @brief Machine specific part of the corouting state. |
||||
* |
||||
* Used by ucontext_t. |
||||
* Application developers should not use this type directly. |
||||
*/ |
||||
typedef struct mcontext { |
||||
unsigned long flags; /* field in ucontext_t: 2*4 */ |
||||
struct x86_pushad registers; /* field in ucontext_t: 3*4 -> 10*4 */ |
||||
void *ip; /* field in ucontext_t: 11*4 */ |
||||
} __attribute__((packed)) mcontext_t; |
||||
|
||||
/**
|
||||
* @brief Stack assigned to a coroutine. |
||||
* |
||||
* Used by ucontext_t. |
||||
* Application developers need to set this values to make coroutines working. |
||||
*/ |
||||
typedef struct stack { |
||||
void *ss_sp; /* field in ucontext_t: 0*4 */ |
||||
//int ss_flags;
|
||||
size_t ss_size; /* field in ucontext_t: 1*4 */ |
||||
} __attribute__((packed)) stack_t; |
||||
|
||||
/**
|
||||
* @brief Extra data to perform an `iret`. |
||||
* |
||||
* Used by x86_interrupts.c to continue a thread |
||||
* if sched_context_switch_request was set set by an ISR. |
||||
* Application developers should not use this type directly. |
||||
*/ |
||||
struct x86_interrupted_interrupt { |
||||
unsigned long ip; |
||||
unsigned long flags; |
||||
} __attribute__((packed)); |
||||
|
||||
/**
|
||||
* @brief Datatype to enable coroutines in userspace. |
||||
* |
||||
* This datatype stores the machine state of a suspended coroutine. |
||||
*/ |
||||
typedef struct ucontext { |
||||
stack_t uc_stack; /* field in ucontext_t: 0*4 - 1*4 */ |
||||
mcontext_t uc_context; /* field in ucontext_t: 2*4 -> 11*4 */ |
||||
struct ucontext *uc_link; /* field in ucontext_t: 12*4 */ |
||||
//sigset_t uc_sigmask;
|
||||
struct x86_interrupted_interrupt __intr; |
||||
struct x86_fxsave __fxsave; |
||||
} __attribute__((packed)) ucontext_t; |
||||
|
||||
/**
|
||||
* @brief Store current coroutine state. |
||||
* |
||||
* With setcontext() you can jump to this point of execution again. |
||||
* Take care about your stack, though. |
||||
* After your thread of execution left the function calling getcontext() there be dragons. |
||||
* |
||||
* The FPU registers are not stored! |
||||
*/ |
||||
int getcontext(ucontext_t *ucp); |
||||
|
||||
/**
|
||||
* @brief Restore a coroutine state. |
||||
* |
||||
* The state must be set up by calling getcontext() or makecontext() previously. |
||||
* The FPU registers won't be restored. |
||||
*/ |
||||
int setcontext(const ucontext_t *ucp) __attribute__((noreturn)); |
||||
|
||||
#pragma GCC diagnostic push |
||||
#pragma GCC diagnostic ignored "-Wstrict-prototypes" |
||||
typedef void (*makecontext_fun_t)(); |
||||
#pragma GCC diagnostic pop |
||||
|
||||
/**
|
||||
* @brief Create a coroutine / trampoline. |
||||
* @param[in] func Function to call. |
||||
* @param[in] argc Number of arguments for func. Must not exceed 5. |
||||
* |
||||
* The function arguments shall be passed after argc. |
||||
* The arguments have to be type punnable as an int, |
||||
* this includes integral types up to 4 bytes, |
||||
* but excludes int64_t, float and so on. |
||||
* |
||||
* Different from what the POSIX standard states, |
||||
* you do not have to getcontext() on ucp before calling makecontext(). |
||||
* This function creates a whole new coroutine state / trampoline. |
||||
*/ |
||||
void makecontext(ucontext_t *ucp, makecontext_fun_t func, int argc, ...); |
||||
|
||||
/**
|
||||
* @brief Swap coroutine. |
||||
* @param[out] oucp Memory to preserve current coroutine state in. |
||||
* @param[in] ucp Coroutine to execute next. |
||||
* |
||||
* This function is an atomic variant of getcontext() and setcontext(). |
||||
* Same restrictions apply. |
||||
*/ |
||||
int swapcontext(ucontext_t *oucp, const ucontext_t *ucp); |
||||
|
||||
#endif |
||||
|
||||
/** @} */ |
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* Functions to interact with the CMOS memory of the BIOS. |
||||
* |
||||
* @ingroup x86 |
||||
* @{ |
||||
* @file |
||||
* @author René Kijewski <rene.kijewski@fu-berlin.de> |
||||
*/ |
||||
|
||||
#ifndef CPU__X86__CMOS__H__ |
||||
#define CPU__X86__CMOS__H__ |
||||
|
||||
#include "x86_ports.h" |
||||
|
||||
#include <stdint.h> |
||||
|
||||
#define CMOS_ADDRESS (0x70) |
||||
#define CMOS_DATA (0x71) |
||||
|
||||
#define CMOS_SERIAL_OFFS (0x41) |
||||
#define CMOS_SERIAL_LEN (6) |
||||
|
||||
/**
|
||||
* @brief Read a CMOS register. |
||||
* @returns The value of the CMOS register. |
||||
*/ |
||||
uint8_t x86_cmos_read(int reg); |
||||
|
||||
/**
|
||||
* @brief Write a CMOS register. |
||||
*/ |
||||
void x86_cmos_write(int reg, uint8_t value); |
||||
|
||||
/**
|
||||
* @brief Read serial number of the BIOS. |
||||
* |
||||
* Most -- if not all current -- BIOSes do not seem to store any serial number here. |
||||
* This function won't cause an error, but the read serial might be some more or less random data. |
||||
* The implementor of the board specific code should know whether the BIOS contains a serial number. |
||||
*/ |
||||
void x86_cmos_serial(uint8_t (*serial)[CMOS_SERIAL_LEN]); |
||||
|
||||
#endif |
||||
|
||||
/** @} */ |
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* The interface of the architecture specific part of the hwtimer module. |
||||
* |
||||
* @ingroup x86 |
||||
* @ingroup core_hwtimer |
||||
* @{ |
||||
* @file |
||||
* @author René Kijewski <rene.kijewski@fu-berlin.de> |
||||
*/ |
||||
|
||||
#ifndef CPU__X86__HWTIMER__H__ |
||||
#define CPU__X86__HWTIMER__H__ |
||||
|
||||
/**
|
||||
* @brief Do timestamping to enable the use of the hwtimer module. |
||||
* |
||||
* This function is called during initialization by x86_startup(). |
||||
* You must not call this function on your own accord. |
||||
*/ |
||||
void x86_init_hwtimer(void); |
||||
|
||||
#endif |
||||
|
||||
/** @} */ |
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* The entry points for all interrupts on x86 boards. |
||||
* |
||||
* @ingroup x86 |
||||
* @defgroup x86-irq Interrupt handling for i586 boards |
||||
* @{ |
||||
* @file |
||||
* @author René Kijewski <rene.kijewski@fu-berlin.de> |
||||
*/ |
||||
|
||||
#ifndef CPU__X86__INTERRUPTS__H__ |
||||
#define CPU__X86__INTERRUPTS__H__ |
||||
|
||||
#include "ucontext.h" |
||||
|
||||
#include <stdint.h> |
||||
|
||||
/**
|
||||
* @brief Initialize interrupts. |
||||
* |
||||
* This function is called during initialization by x86_startup(). |
||||
* You must not call this function on your own accord. |
||||
*/ |
||||
void x86_init_interrupts(void); |
||||
|
||||
#define X86_MAX_INTERRUPTS (0x30) |
||||
|
||||
/**
|
||||
* @brief The exceptions in an x86 system. |
||||
* |
||||
* http://www.sandpile.org/x86/except.htm
|
||||
*/ |
||||
enum x86_interrupt_numbers { |
||||
X86_INT_DE = 0x00, /**< divide error */ |
||||
X86_INT_DB = 0x01, /**< debug (thrown after each instruction if X86_TF is activated) */ |
||||
X86_INT_BP = 0x03, /**< breakpoint (`int3`) */ |
||||
X86_INT_OF = 0x04, /**< overflow (`into`) */ |
||||
X86_INT_BR = 0x05, /**< boundary range exceeded (`bound`) */ |
||||
X86_INT_UD = 0x06, /**< undefined opcode */ |
||||
X86_INT_NM = 0x07, /**< device not available (raised on FPU accessing if CR0.TS is set) */ |
||||
X86_INT_DF = 0x08, /**< double fault (exceptions during exception handler invocation) */ |
||||
X86_INT_GP = 0x0d, /**< general protection */ |
||||
X86_INT_PF = 0x0e, /**< page fault */ |
||||
X86_INT_MF = 0x10, /**< math fault */ |
||||
X86_INT_AC = 0x11, /**< alignment checking */ |
||||
X86_INT_MC = 0x12, /**< machine check */ |
||||
}; |
||||
|
||||
/**
|
||||
* @brief Bits in the EFLAGS register. |
||||
* |
||||
* http://www.sandpile.org/x86/flags.htm
|
||||
*/ |
||||
enum x86_eflags { |
||||
X86_CF = 1 << 0, /**< carry */ |
||||
X86_PF = 1 << 2, /**< parity */ |
||||
X86_AF = 1 << 4, /**< adjust */ |
||||
X86_ZF = 1 << 6, /**< zero */ |
||||
X86_SF = 1 << 7, /**< signed */ |
||||
X86_TF = 1 << 8, /**< singled step (throw #DB after each instruction) */ |
||||
X86_IF = 1 << 9, /**< interrupts enabled */ |
||||
X86_DF = 1 << 10, /**< direction (0 = movs increses addresses, 1 = movs decreases addresses) */ |
||||
X86_OF = 1 << 11, /**< overflow */ |
||||
X86_IOPL_0 = 0 << 12, /**< priority level 0 (?) */ |
||||
X86_IOPL_1 = 1 << 12, /**< priority level 1 (?) */ |
||||
X86_IOPL_2 = 2 << 12, /**< priority level 2 (?) */ |
||||
X86_IOPL_3 = 3 << 12, /**< priority level 3 (?) */ |
||||
X86_NT = 1 << 14, /**< nested task */ |
||||
X86_RF = 1 << 16, /**< resume */ |
||||
X86_VM = 1 << 17, /**< virtual 8086 mode */ |
||||
X86_AC = 1 << 18, /**< alignment check */ |
||||
X86_VIF = 1 << 19, /**< virtual interrupts enabled */ |
||||
X86_VIP = 1 << 20, /**< virtual interrupts pendigng */ |
||||
X86_ID = 1 << 21, /**< able to use CPUID */ |
||||
}; |
||||
|
||||
/**
|
||||
* @brief Datum for the Interrupt Descriptor Table Register. |
||||
*/ |
||||
struct idtr_t { |
||||
uint16_t limit; /**< `sizeof (struct idt_desc) * count` */ |
||||
void *base; /**< physical address of the start of the IDT */ |
||||
} __attribute__((packed)); |
||||
|
||||
/**
|
||||
* @brief One entry in the IDT |
||||
*/ |
||||
struct idt_desc { |
||||
uint16_t offset_1; /**< offset bits 0..15 */ |
||||
uint16_t selector; /**< a code segment selector in GDT or LDT */ |
||||
uint8_t zero; /**< unused, set to 0 */ |
||||
uint8_t type_attr; /**< type and attributes, see below */ |
||||
uint16_t offset_2; /**< offset bits 16..31 */ |
||||
} __attribute__((packed)); |
||||
|
||||
/**
|
||||
* @brief Callback on interrupt. |
||||
* @param intr_num Number of interrupt -- not the number of the IRQ |
||||
* @param orig_ctx (Changable) register set of the calling thread |
||||
* @param error_code Related error code (if applies, otherwise 0) |
||||
*/ |
||||
typedef void (*x86_intr_handler_t)(uint8_t intr_num, struct x86_pushad *orig_ctx, unsigned long error_code); |
||||
|
||||
/**
|
||||
* @brief Set callback function for interrupt. |
||||
* @param num Number of interrupt. Must be less than X86_MAX_INTERRUPTS. |
||||
* @param handler Function to call, or `NULL` to use default interrupt handler. |
||||
* |
||||
* This function is meant to be called by other subsystems (x86_pic.c and x86_threading.c). |
||||
* Any upper level system should use x86_pic_set_handler() or even higher level functions. |
||||
*/ |
||||
void x86_interrupt_handler_set(unsigned num, x86_intr_handler_t handler); |
||||
|
||||
/**
|
||||
* @brief Disable interrupts and return previous EFLAGS. |
||||
*/ |
||||
static inline unsigned long __attribute__((always_inline)) x86_pushf_cli(void) |
||||
{ |
||||
unsigned long result; |
||||
asm volatile("pushf; cli; pop %0" : "=g"(result)); |
||||
return result; |
||||
} |
||||
|
||||
/**
|
||||
* @brief Set EFLAGS. |
||||
*/ |
||||
static inline void __attribute__((always_inline)) x86_restore_flags(unsigned long stored_value) |
||||
{ |
||||
asm volatile("push %0; popf" :: "g"(stored_value)); |
||||
} |
||||
|
||||
/**
|
||||
* @brief Print saved general purposed registers. |
||||
*/ |
||||
void x86_print_registers(struct x86_pushad *orig_ctx, unsigned long error_code); |
||||
|
||||
#endif |
||||
|
||||
/** @} */ |
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* Layout of the kernel memory. The symbols are set in the linker.ld. |
||||
* |
||||
* @ingroup x86 |
||||
* @{ |
||||
* @file |
||||
* @author René Kijewski <rene.kijewski@fu-berlin.de> |
||||
*/ |
||||
|
||||
#ifndef KERNEL_MEMORY_H__ |
||||
#define KERNEL_MEMORY_H__ |
||||
|
||||
/**
|
||||
* @brief First byte inside the elf segments. |
||||
* |
||||
* Expected to be the start of < |