Initial import of the x86 port
Currently this works only in qemu.
This commit is contained in:
parent
2b95e7b144
commit
4e4f908379
|
@ -11,3 +11,4 @@ cachegrind.out*
|
|||
.project
|
||||
.cproject
|
||||
.settings
|
||||
/toolchain
|
||||
|
|
|
@ -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,3 @@
|
|||
MODULE = cpu
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
|
@ -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 the high memory, i.e. 1MB.
|
||||
*/
|
||||
extern char _kernel_memory_start;
|
||||
|
||||
/**
|
||||
* @brief Start of first byte of code inside the .text segment.
|
||||
*
|
||||
* This symbol does not have to be aligned.
|
||||
*/
|
||||
extern char _section_text_start;
|
||||
|
||||
/**
|
||||
* @brief First byte after the code.
|
||||
*
|
||||
* This symbol does not have to be aligned.
|
||||
*/
|
||||
extern char _section_text_end;
|
||||
|
||||
/**
|
||||
* @brief First byte inside the .rodata segment.
|
||||
*
|
||||
* This symbol is expected to be aligned.
|
||||
*/
|
||||
extern char _section_rodata_start;
|
||||
|
||||
/**
|
||||
* @brief First byte after the .rodata segment.
|
||||
*
|
||||
* This symbol does not have to be aligned.
|
||||
*/
|
||||
extern char _section_rodata_end;
|
||||
|
||||
/**
|
||||
* @brief First byte inside the .data segment.
|
||||
*
|
||||
* This symbol is expected to be aligned.
|
||||
*/
|
||||
extern char _section_data_start;
|
||||
|
||||
/**
|
||||
* @brief First byte after the .data segment.
|
||||
*
|
||||
* This symbol does not have to be aligned, since it shares the same previleges as the .bss segment.
|
||||
*/
|
||||
extern char _section_data_end;
|
||||
|
||||
/**
|
||||
* @brief Start of the .bss segment.
|
||||
*
|
||||
* Probably unaligned.
|
||||
* The .bss segment must follow the .data segment with no other segment inbetween.
|
||||
* It's likely that `&_section_data_end == &_section_bss_start`.
|
||||
*/
|
||||
extern char _section_bss_start;
|
||||
|
||||
/**
|
||||
* @brief First byte after the .bss segment.
|
||||
*
|
||||
* This symbol should not to be aligned, because RAM cycles would be wasted to clear unused bytes otherwise.
|
||||
*/
|
||||
extern char _section_bss_end;
|
||||
|
||||
/**
|
||||
* @brief First byte after the last of the common elf segments.
|
||||
*
|
||||
* This symbol is expected to be aligned.
|
||||
* The "common elf segments" are .text, .rodata, .data and .bss.
|
||||
* All the (physical) memory beyond this point will be overwritten at the pleasure of the kernel.
|
||||
*/
|
||||
extern char _kernel_memory_end;
|
||||
|
||||
/**
|
||||
* @brief First byte that may be mapped as the heap
|
||||
*
|
||||
* This symbol is expected to be aligned.
|
||||
* Must be bigger than _kernel_memory_end.
|
||||
* There should be a space between _kernel_memory_end and _heap_start, but it does not have to.
|
||||
*/
|
||||
extern char _heap_start;
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||