diff --git a/cpu/x86/Makefile b/cpu/x86/Makefile deleted file mode 100644 index 08e25a221a23e6c91caff7138793ca5e05232690..0000000000000000000000000000000000000000 --- a/cpu/x86/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -MODULE = cpu - -include $(RIOTBASE)/Makefile.base diff --git a/cpu/x86/Makefile.include b/cpu/x86/Makefile.include deleted file mode 100644 index 98d8d178682aec77929fc25dbff8275490c365a1..0000000000000000000000000000000000000000 --- a/cpu/x86/Makefile.include +++ /dev/null @@ -1,3 +0,0 @@ -export USEMODULE += quad_math -export USEMODULE += periph_common -export USEPKG += tlsf diff --git a/cpu/x86/include/cpu.h b/cpu/x86/include/cpu.h deleted file mode 100644 index ef1ca69842f236d744a4cd66460d6b7468738f56..0000000000000000000000000000000000000000 --- a/cpu/x86/include/cpu.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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_H -#define CPU_H - -#include "kernel_defines.h" -#include "irq.h" -#include "ucontext.h" -#include "cpu_conf.h" - -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @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 beyond 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); - -/** - * @brief Prints the last instruction's address - */ -static inline void cpu_print_last_instruction(void) -{ - void *p; - __asm__("1: mov 1b, %0" : "=r" (p)); - printf("%p\n", p); -} - -#ifdef __cplusplus -} -#endif - -#endif /* CPU_H */ - -/** @} */ diff --git a/cpu/x86/include/periph_cpu.h b/cpu/x86/include/periph_cpu.h deleted file mode 100644 index 791cd7c906b1a3d9eebc6c163ef09584bcdeec9d..0000000000000000000000000000000000000000 --- a/cpu/x86/include/periph_cpu.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.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 - */ - -/** - * stub for x86 periph configuration - * - * @ingroup x86 - * @{ - * @file - * @author Kaspar Schleiser <kaspar@schleiser.de> - */ - -#ifndef PERIPH_CPU_H -#define PERIPH_CPU_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @name Power management configuration - * @{ - */ -#define PROVIDES_PM_OFF -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* PERIPH_CPU_H */ - -/** @} */ diff --git a/cpu/x86/include/ucontext.h b/cpu/x86/include/ucontext.h deleted file mode 100644 index c4c3d5dd3393837690fc6403915b3539149806be..0000000000000000000000000000000000000000 --- a/cpu/x86/include/ucontext.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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 UCONTEXT_H -#define UCONTEXT_H - -#include <stdlib.h> -#include <unistd.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @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_info_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_info_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); - -#ifdef __cplusplus -} -#endif - -#endif /* UCONTEXT_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_cmos.h b/cpu/x86/include/x86_cmos.h deleted file mode 100644 index d9ec146716909ecdf6f65241853bee2b2e3acc79..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_cmos.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 X86_CMOS_H -#define X86_CMOS_H - -#include "x86_ports.h" - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#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]); - -#ifdef __cplusplus -} -#endif - -#endif /* X86_CMOS_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_interrupts.h b/cpu/x86/include/x86_interrupts.h deleted file mode 100644 index 6007e6fb2368a658b873504fcd8b6f837e939541..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_interrupts.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * 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 X86_INTERRUPTS_H -#define X86_INTERRUPTS_H - -#include "ucontext.h" - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @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 #X86_INT_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); - -#ifdef __cplusplus -} -#endif - -#endif /* X86_INTERRUPTS_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_kernel_memory.h b/cpu/x86/include/x86_kernel_memory.h deleted file mode 100644 index 973ed2dfc817ad6d5e01f40a23ebf21eccee0235..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_kernel_memory.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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 X86_KERNEL_MEMORY_H -#define X86_KERNEL_MEMORY_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @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; - -#ifdef __cplusplus -} -#endif - -#endif /* X86_KERNEL_MEMORY_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_memory.h b/cpu/x86/include/x86_memory.h deleted file mode 100644 index 3a4b85082a4acd4f948cca6e1483e88228828234..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_memory.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * 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 virtual memory management of x86 boards. - * - * @ingroup x86 - * @{ - * @file - * @author René Kijewski <rene.kijewski@fu-berlin.de> - */ - -#ifndef X86_MEMORY_H -#define X86_MEMORY_H - -#include <stdbool.h> -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Maximum static size of the kernel. - * - * Each page table can hold 2MB. - * As the low memory is ignored, 1MB of virtual memory is wasted. - * Bad things will happen if this value is set too small. - * The kernel must not exceed the 10MB mark, unless you are sure that your board has no ISA hole. - * (It is unlikely that you have an ISA hole, though.) - */ -#define X86_NUM_STATIC_PT (4) -#define X86_NUM_STATIC_PD ((X86_NUM_STATIC_PT+511) / 512) /* 1GB=512 PTs each */ - -/** - * @brief Initialize virtual memory management. - * - * This function is called during initialization by x86_startup(). - * You must not call this function on your own accord. - */ -void x86_init_memory(void); - -/** - * @brief Datum for the Global Descriptor Table Register. - */ -struct gdtr_t { - uint16_t size_minus_one; - uint32_t offset; -} __attribute__((packed)); - -/** - * @brief One entry in the Global Descriptor Table. - */ -struct gdt_entry { - uint16_t limit_0_15; - uint16_t base_0_15; - uint8_t base_16_23; - uint8_t access_byte; - uint8_t limit_16_19_and_flags; - uint8_t base_24_31; -} __attribute__((packed)); - -#define GDT_AB_AC (1u << 0) /**< Access byte (set to one by CPU when accessed) */ -#define GDT_AB_RW (1u << 1) /**< If CS: read access allowed. If DS: write access allowed. */ -#define GDT_AB_DC (1u << 2) /**< Direction bit */ -#define GDT_AB_EX (1u << 3) /**< 1 = segment is CS */ -#define GDT_AB_S (1u << 4) /**< 1 = segment is CS or DS; 0 = segment is gate or TSS */ -#define GDT_AB_RING_0 (0u << 5) /**< Privilege level: ring 0 */ -#define GDT_AB_RING_1 (1u << 5) /**< Privilege level: ring 1 */ -#define GDT_AB_RING_2 (2u << 5) /**< Privilege level: ring 2 */ -#define GDT_AB_RING_3 (3u << 5) /**< Privilege level: ring 3 */ -#define GDT_AB_PR (1u << 7) /**< Segment present */ - -#define GDT_FLAG_USR4 (1u << 4) /**< bit for free use */ -#define GDT_FLAG_L (1u << 5) /**< 1 = long mode */ -#define GDT_FLAG_SZ (1u << 6) /**< 0 = 16/64 bit selector; 1 = 32 bit selector */ -#define GDT_FLAG_GR (1u << 7) /**< 0 = limit given in 1 b blocks; 1 = limit given in 4k blocks */ - -typedef uint64_t pae_page_directory_pointer_table_t[512] __attribute__((aligned(0x1000))); -typedef uint64_t pae_page_directory_t[512] __attribute__((aligned(0x1000))); -typedef uint64_t pae_page_table_t[512] __attribute__((aligned(0x1000))); - -#define PT_P (1ull << 0) /**< 1 = page present */ -#define PT_RW (1ull << 1) /**< 1 = page writable */ -#define PT_US (1ull << 2) /**< 1 = don't restrict to ring 0 */ -#define PT_PWT (1ull << 3) /**< 1 = use write-through; 0 = use write-back */ -#define PT_PCD (1ull << 4) /**< 1 = disable caching */ -#define PT_A (1ull << 5) /**< 1 = page was accessed (set by the CPU, used for swapping) */ -#define PT_D (1ull << 6) /**< 1 = dirty (set by the CPU when written to) */ -#define PT_S (1ull << 7) /**< 1 = 4MB pages */ -#define PT_PAT (1ull << 7) /**< ? */ -#define PT_G (1ull << 8) /**< 1 = global (ignored for page directory entries) */ -#define PT_USR9 (1ull << 9) /**< bit for free use */ -#define PT_USR10 (1ull << 10) /**< bit for free use */ -#define PT_USR11 (1ull << 11) /**< bit for free use */ -#define PT_XD (1ull << 63) /**< 1 = no execute */ -#define PT_ADDR_MASK (((1ull << 48) - 1) & ~((1ull << 12) - 1)) - -#ifdef DEBUG_READ_BEFORE_WRITE -# define PT_HEAP_BIT PT_USR9 -#endif - -#define PF_EC_P (1u << 0) /**< 1 = page protection violation; 0 = page not present */ -#define PF_EC_W (1u << 1) /**< 1 = accessed writingly; 0 = readingly */ -#define PF_EC_U (1u << 2) /**< 1 = ring 3 */ -#define PF_EC_R (1u << 3) /**< ? */ -#define PF_EC_I (1u << 4) /**< 1 = exception in CS; 0 = exception in DS */ - -/** - * @brief Error value for x86_get_pte(). - * - * All bits are set but PT_P. - * Most likely you are interested only if the page table is present. - * Since the PTE bits 48 to 62 are restricted, this value cannot occur in an actual PTE. - */ -#define NO_PTE (~PT_P) -/** - * @brief Read page table entry for addr. - * @param addr Does not have to be aligned. - * @returns PTE iff addr has an entry in the PDPT and PD, otherwise NO_PTE. - */ -uint64_t x86_get_pte(uint32_t addr); - -/** - * @brief Maps a range of physical pages at a new virtual address. - * @param physical_start Start address of the physical page. Must be aligned. - * @param pages Number of physical pages. - * @param bits Flags of the PTE for each page (do not forget PT_P). - * @returns Start of the virtual address range, aligned of course. - * @returns NULL if the memory was exhausted. - * - * This function is to be used by hardware drivers. - */ -void *x86_map_physical_pages(uint64_t physical_start, unsigned pages, uint64_t bits); - -/** - * @brief Allocate a range of pages. - * @param pages Number of pages to allocate. - * @param bits Flags of the PTE for each page (do not forget PT_P). - * @returns Start of the virtual address range, aligned of course. - * Use x86_get_pte() to determine the start of the physical address range. - */ -void *x86_get_virtual_pages(unsigned pages, uint64_t bits); - -/** - * @brief Deallocate a range of bytes that were allocated with x86_get_virtual_pages() - * @param virtual_start The return value of x86_get_virtual_pages(). - * @param pages Must match the original call to x86_get_virtual_pages(). - */ -void x86_release_virtual_pages(uint32_t virtual_start, unsigned pages); - -/** - * @brief Intializes the global descriptor table. - * @details This should be the very first call in the startup routine. - * Changing the segmentation confuses the JTAG. - * @details 0x0000 is an invalid descriptor. - * 0x0008 is the code segment, from 0x00000000 to 0xFFFFFFFF, executable, read-only. - * 0x0010 is the data segment, from 0x00000000 to 0xFFFFFFFF, non-executable, writable. - */ -void x86_init_gdt(void); - -#ifdef __cplusplus -} -#endif - -#endif /* X86_MEMORY_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_pci.h b/cpu/x86/include/x86_pci.h deleted file mode 100644 index cc9f8124f251749b4c2596f3e7564c9ceafad423..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_pci.h +++ /dev/null @@ -1,423 +0,0 @@ -/* - * 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 PCI subsystem of x86 boards. - * - * @ingroup x86-irq - * @{ - * @file - * @author René Kijewski <rene.kijewski@fu-berlin.de> - */ - -#ifndef X86_PCI_H -#define X86_PCI_H - -#include "x86_pci_init.h" -#include "x86_pic.h" - -#include <machine/endian.h> -#include <stdbool.h> -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialize the Peripheral Component Interconnect. - * - * This function is called during initialization by x86_startup(). - * You must not call this function on your own accord. - */ -void x86_init_pci(void); - -#define PCI_CONFIG_DATA (0x0cfc) -#define PCI_CONFIG_ADDRESS (0x0cf8) - -#define PCI_IO_ENABLE (1u << 31) -#define PCI_IO_SHIFT_BUS (16u) -#define PCI_IO_SHIFT_DEV (11u) -#define PCI_IO_SHIFT_FUN (8u) -#define PCI_IO_SHIFT_REG (0u) - -#define PCI_BUS_COUNT (1u << 8) -#define PCI_DEV_COUNT (1u << 5) -#define PCI_FUN_COUNT (1u << 3) - -#if BYTE_ORDER == LITTLE_ENDIAN -# define U8_PCItoH(x) (x) -# define U16_PCItoH(x) (x) -# define U32_PCItoH(x) (x) - -# define U8_HtoPCI(x) (x) -# define U16_HtoPCI(x) (x) -# define U32_HtoPCI(x) (x) -#else -# error "Only BYTE_ORDER == LITTLE_ENDIAN is supported right now" -#endif - -// "PCI LOCAL BUS SPECIFICATION, REV. 3.0"; Appendix 6.1. - -/** - * @brief The registers 0x00 through 0x03 of a PCI device. - */ -typedef union pci_reg_0x00 { - __extension__ struct { - /** - * @brief Vendor ID of the device - * - * The values PCI_HEADER_VENDOR_ID_INVALID, PCI_HEADER_VENDOR_ID_UNRESPONSIVE - * and PCI_HEADER_VENDOR_ID_ABSENT denote a special status. - */ - uint16_t vendor_id; - uint16_t device_id; /**< Vendor specific device ID */ - } __attribute__((packed)); - uint32_t packed; -} __attribute__((packed)) pci_reg_0x00_t; - -/** - * @brief The registers 0x04 through 0x07 of a PCI device. - */ -typedef union pci_reg_0x04 { - __extension__ struct { - uint16_t command; /**< Port to tell the PCI device to do things. */ - uint16_t status; /**< Reading the current status of a PCI device. */ - } __attribute__((packed)); - uint32_t packed; -} __attribute__((packed)) pci_reg_0x04_t; - -/** - * @brief The registers 0x08 through 0x0b of a PCI device. - */ -typedef union pci_reg_0x08 { - __extension__ struct { - uint8_t revision_id; - uint8_t programming_interface; - uint8_t subclass; - uint8_t baseclass; - } __attribute__((packed)); - uint32_t packed; -} __attribute__((packed)) pci_reg_0x08_t; - -/** - * @brief The registers 0x0c through 0x0f of a PCI device. - */ -typedef union pci_reg_0x0c { - __extension__ struct { - uint8_t cache_line_size; - uint8_t latency_timer; - uint8_t header_type; - uint8_t builtin_selftest; - } __attribute__((packed)); - uint32_t packed; -} __attribute__((packed)) pci_reg_0x0c_t; - -/** - * @brief Generic layout of the port space of a PCI device. - */ -typedef struct pci_config { - union pci_reg_0x00 reg_0x00; - union pci_reg_0x04 reg_0x04; - union pci_reg_0x08 reg_0x08; - union pci_reg_0x0c reg_0x0c; - - /* reg = 0x10 */ - uint8_t header_type_specific1[0x34 - 0x10]; - - /* reg = 0x34 */ - uint8_t capatibilities_pointer; - uint8_t header_type_specific2[0x3c - 0x35]; - - /* reg = 0x3C */ - uint8_t interrupt_line; - uint8_t interrupt_pin; - - uint8_t header_type_specific3[0x40 - 0x3e]; -} __attribute__((packed)) pci_config_t; - -/** - * @brief Layout of the port space for PCI devices with `header_type == PCI_HEADER_TYPE_GENERAL_DEVICE`. - */ -typedef struct pci_config_standard { - union pci_reg_0x00 reg_0x00; - union pci_reg_0x04 reg_0x04; - union pci_reg_0x08 reg_0x08; - union pci_reg_0x0c reg_0x0c; - - /* reg = 0x10 */ - uint32_t bar[6]; - /* reg = 0x28 */ - uint32_t cardbus_cis_pointer; - /* reg = 0x2c */ - uint16_t subsystem_vendor_id; - uint16_t subsystem_id; - // reg = 0x30 */ - uint32_t expansion_rom_address; - - /* reg = 0x34 */ - uint8_t capatibilities_pointer; - uint8_t header_type_specific2[0x3c - 0x35]; - - /* reg = 0x3C */ - uint8_t interrupt_line; - uint8_t interrupt_pin; - - uint8_t header_type_specific3[0x40 - 0x3e]; -} __attribute__((packed)) pci_config_standard_t; - -/** - * @brief Layout of the port space for PCI devices with `header_type == PCI_HEADER_TYPE_BRIDGE`. - */ -typedef struct pci_config_bridge { - union pci_reg_0x00 reg_0x00; - union pci_reg_0x04 reg_0x04; - union pci_reg_0x08 reg_0x08; - union pci_reg_0x0c reg_0x0c; - - /* reg = 0x10 */ - uint32_t bar[2]; - - /* reg = 0x18 */ - uint8_t bus_primary; - uint8_t bus_secondary; - uint8_t bus_subordinary; - uint8_t bus_secondary_latency_timer; - - /* reg = 0x1c */ - uint8_t io_lower_base; - uint8_t io_lower_limit; - uint16_t status_secondary; - - /* reg = 0x20 */ - uint16_t memory_base; - uint16_t memory_limit; - - /* reg = 0x24 */ - uint16_t prefetchable_lower_base; - uint16_t prefetchable_lower_limit; - - // reg = 0x28 - uint32_t prefetchable_upper_base; - // reg = 0x2c - uint32_t prefetchable_upper_limit; - - // reg = 0x30 - uint16_t io_upper_base; - uint16_t io_upper_limit; - - // reg = 0x34 - uint8_t capatibilities_pointer; - uint8_t header_type_specific2[0x38 - 0x35]; - - // reg = 0x38 - uint32_t extension_ron_address; - - // reg = 0x3C - uint8_t interrupt_line; - uint8_t interrupt_pin; - uint16_t bridge_control; -} __attribute__((packed)) pci_config_bridge_t; - -#define PCI_HEADER_VENDOR_ID_INVALID (0x0000u) -#define PCI_HEADER_VENDOR_ID_UNRESPONSIVE (0x0001u) -#define PCI_HEADER_VENDOR_ID_ABSENT (0xffffu) - -#define PCI_HEADER_TYPE_GENERAL_DEVICE (0x00u) -#define PCI_HEADER_TYPE_BRIDGE (0x01u) -#define PCI_HEADER_TYPE_CARD_BUS (0x02u) - -#define PCI_HEADER_TYPE_MULTI_FUNCTION (0x80u) -#define PCI_HEADER_TYPE_MASK (0x7fu) - -#define PCI_COMMAND_IO_SPACE (1u << 0) -#define PCI_COMMAND_MEMORY_SPACE (1u << 1) -#define PCI_COMMAND_BUS_MASTER (1u << 2) -#define PCI_COMMAND_SPECIAL_CYCLES (1u << 3) -#define PCI_COMMAND_MEM_WRITE_AND_INV (1u << 4) -#define PCI_COMMAND_VGA_PALETTE_SNOOP (1u << 5) -#define PCI_COMMAND_PARITY_ERR_RESPONSE (1u << 6) -#define PCI_COMMAND_SERR (1u << 8) -#define PCI_COMMAND_FAST_B2B (1u << 9) -#define PCI_COMMAND_INTERRUPT_DISABLE (1u << 10) - -#define PRI_STATUS_INTERRUPT (1u << 3) -#define PRI_STATUS_CAPATIBILITIES (1u << 4) -#define PRI_STATUS_66MHZ (1u << 5) -#define PRI_STATUS_FAST_B2B (1u << 7) -#define PRI_STATUS_MASTER_PARITY_ERROR (1u << 8) -#define PRI_STATUS_DEVSEL_FAST (0u << 9) -#define PRI_STATUS_DEVSEL_MEDIUM (1u << 9) -#define PRI_STATUS_DEVSEL_SLOW (3u << 9) -#define PRI_STATUS_DEVSEL_MASK (3u << 9) -#define PRI_STATUS_SIG_TARGET_ABORT (1u << 11) -#define PRI_STATUS_RECV_TARGET_ABORT (1u << 12) -#define PRI_STATUS_RECV_MASTER_ABORT (1u << 13) -#define PRI_STATUS_SIG_SYSTEM_ERROR (1u << 14) -#define PRI_STATUS_PARITY_ERROR (1u << 15) - -#define PCI_CAPS_PTR_MIN (0x40u) -#define PCI_CAPS_PTR_MAX (0xf0u) - -#define PCI_INTR_PIN_NONE (0x00u) -#define PCI_INTR_PIN_A (0x01u) -#define PCI_INTR_PIN_B (0x02u) -#define PCI_INTR_PIN_C (0x03u) -#define PCI_INTR_PIN_D (0x04u) - -#define PCI_BAR_IO_SPACE (1u << 0) -#define PCI_BAR_SPACE_32 (0u << 1) -#define PCI_BAR_SPACE_1M (1u << 1) -#define PCI_BAR_SPACE_64 (2u << 1) -#define PCI_BAR_SPACE_MASK (3u << 1) -#define PCI_BAR_PREFETCHABLE (1u << 3) -#define PCI_BAR_ADDR_OFFS_MEM (4u) -#define PCI_BAR_ADDR_OFFS_IO (2u) - -/** - * @brief Address type of a struct x86_pci_io. - */ -typedef enum { - PCI_IO_INVALID = 0, /**< There was an error while configuring this IO port. */ - PCI_IO_MEM, /**< physical memory */ - PCI_IO_PORT, /**< port address */ -} x86_pci_io_type_t; - -/** - * @brief One IO port of a struct x86_known_pci_device. - */ -typedef struct x86_pci_io { - x86_pci_io_type_t type; /**< Type of this IO port. */ - unsigned long length; /**< Length (in bytes or port) of this IO port. */ - union { - void *ptr; /**< Base **virtual** memory address. */ - int port; /**< Base port number. */ - } addr; /**< Base address of the IO port. */ - uint8_t bar_num; -} x86_pci_io_t; - -struct x86_known_pci_device; - -/** - * @brief A callback handler if there was an IRQ on the IRQ line of this device. - * @param[in] d Device that (might) need attention. - * - * Because PCI is multiplexer, there might not be an IRQ for this device. - * This callback is called out of the interrupt handler (irq_is_in() == true). - * Lengthy operations should be handled in a dedicated thread; use msg_send_int(). - * You must no enable interrupt inside the handler. - */ -typedef void (*x86_pci_irq_handler_t)(struct x86_known_pci_device *d); - -/** - * @brief A PCI device. - */ -typedef struct x86_known_pci_device { - uint8_t bus, dev, fun; - pci_reg_0x00_t vendor; - pci_reg_0x08_t class; - - unsigned io_count; /**< Number of entries in io. */ - struct x86_pci_io **io; /**< Pointer to io_count pointers to configured IO ports. */ - - bool managed; /**< To be set by the hardware driver if it is going to manage this device. */ - uint8_t irq; /**< IRQ line of this device. Change through x86_pci_set_irq(). */ - x86_pci_irq_handler_t irq_handler; /**< Callback function if there was an interrupt on `irq`. */ -} x86_known_pci_device_t; - -/** - * @brief Enumerate unmanaged PCI devices. - * @param index Opaque reentrant pointer for the next iteration. Must be zero at first call. - * @returns Pointer to next unmanaged PCI device, or NULL. - * - * This function shall only be called by hardware drivers. - * x86_init_pci() will call the hardware drivers once it is ready. - * To not call earlier or later on your on accord. - * - * The result is a pointer to a pointer so that you can use realloc() to extend the struct as needed. - * You must only do that if you are going to manage this device, set managed iff so. - */ -struct x86_known_pci_device **x86_enumerate_unmanaged_pci_devices(unsigned *index); - -/** - * @brief Enumerate all PCI devices. - * @param index Opaque reentrant pointer for the next iteration. Must be zero at first call. - * @returns Pointer to next PCI device, or NULL. - */ -const struct x86_known_pci_device *x86_enumerate_pci_devices(unsigned *index); - -/** - * @brief Read a long word from the PCI configuration space. - * @param reg The register must be aligned on a 4 bytes boundary. - */ -uint32_t x86_pci_read(unsigned bus, unsigned dev, unsigned fun, unsigned reg); -/** - * @brief Read a byte from the PCI configuration space. - * @param reg The register must be aligned on a 4 bytes boundary. - */ -uint8_t x86_pci_read8(unsigned bus, unsigned dev, unsigned fun, unsigned reg); -/** - * @brief Read a short word from the PCI configuration space. - * @param reg The register must be aligned on a 4 bytes boundary. - */ -uint16_t x86_pci_read16(unsigned bus, unsigned dev, unsigned fun, unsigned reg); - -/** - * @brief Write a long word to the PCI configuration space. - * @param reg The register must be aligned on a 4 bytes boundary. - */ -void x86_pci_write(unsigned bus, unsigned dev, unsigned fun, unsigned reg, uint32_t datum); -/** - * @brief Write a byte to the PCI configuration space. - * @param reg The register must be aligned on a 4 bytes boundary. - */ -void x86_pci_write8(unsigned bus, unsigned dev, unsigned fun, unsigned reg, uint8_t datum); -/** - * @brief Write a short word to the PCI configuration space. - * @param reg The register must be aligned on a 4 bytes boundary. - */ -void x86_pci_write16(unsigned bus, unsigned dev, unsigned fun, unsigned reg, uint16_t datum); - -/** - * @brief Read a long word from the PCI configuration space, and cast the datum accordingly. - * @param REG Either `0x00`, `0x04`, `0x08`, or `0x0c`. Must be a constant token. - * @returns A `union pci_reg_0x00`, `union pci_reg_0x04`, ... - */ -#define x86_pci_read_reg(REG, BUS, DEV, FUN) \ - ((union pci_reg_##REG) { .packed = x86_pci_read((BUS), (DEV), (FUN), (REG)) }) - -#define PCI_IRQ_ACPI (PIC_NUM_LPT2) /**< IRQ line that may be used by the ACPI. */ -#define PCI_IRQ_NETWORKING (PIC_NUM_9) /**< IRQ line that may be used by networking devices. */ -#define PCI_IRQ_DEFAULT (PIC_NUM_ATA_4) /**< IRQ line that may be used by other devices. */ -#define PCI_IRQ_USB (PIC_NUM_ATA_3) /**< IRQ line that may be used by USB host controllers. */ - -/** - * @brief Set the IRQ line if a PCI device. - * - * irq_num must be one of PCI_IRQ_ACPI, PCI_IRQ_NETWORKING, PCI_IRQ_DEFAULT, PCI_IRQ_USB. - * Bad things will happen if you supply any other value. - */ -void x86_pci_set_irq(struct x86_known_pci_device *d, uint8_t irq_num); - -#ifdef __cplusplus -} -#endif - -#endif /* X86_PCI_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_pci_init.h b/cpu/x86/include/x86_pci_init.h deleted file mode 100644 index 8d2840c07b581356d5b39ff4ac094fc407747030..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_pci_init.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 - */ - -#ifndef X86_PCI_INIT_H -#define X86_PCI_INIT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* no PCI devices are implemented, yet */ - -void x86_init_pci_devices(void); - -#ifdef __cplusplus -} -#endif - -#endif /* X86_PCI_INIT_H */ diff --git a/cpu/x86/include/x86_pci_strings.h b/cpu/x86/include/x86_pci_strings.h deleted file mode 100644 index 6e8386508e3ec50fbbde01c332d2fad09c958c7d..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_pci_strings.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 string representation of PCI constants. For humans. - * - * @ingroup x86-irq - * @{ - * @file - * @author René Kijewski <rene.kijewski@fu-berlin.de> - */ - -#ifndef X86_PCI_STRINGS_H -#define X86_PCI_STRINGS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Get a string representation of the device class. - * @param[out] baseclass_name Name of the base class. Supply NULL if you do not care. - * @return A string (lengthy text) that describes the device class. - * - * If the device class is unknown, then the hexadecimal value is returned. - * This function is not thread safe. - */ -const char *x86_pci_subclass_to_string(unsigned baseclass, unsigned subclass, unsigned interface, const char **baseclass_name); - -/** - * @brief Get a string representation of the device name. - * @param[out] vendor_name Name of the device vendor. Supply NULL if you do not care. - * @return A string that tells the device name. - * - * If the device ID is unknown, then the hexadecimal value is returned. - * This function is not thread safe. - */ -const char *x86_pci_device_id_to_string(unsigned vendor_id, unsigned device_id, const char **vendor_name); - -#ifdef __cplusplus -} -#endif - -#endif /* X86_PCI_STRINGS_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_pic.h b/cpu/x86/include/x86_pic.h deleted file mode 100644 index b94a56b6fddf2e748a4feeb89bd4a1bb5d50f948..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_pic.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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 IRQ handler of x86 boards. - * - * @ingroup x86-irq - * @{ - * @file - * @author René Kijewski <rene.kijewski@fu-berlin.de> - */ - -#ifndef X86_PIC_H -#define X86_PIC_H - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialize the Programmable Interrupt Controller. - * - * This function is called during initialization by x86_startup(). - * You must not call this function on your own accord. - */ -void x86_init_pic(void); - -#define X86_IRQ_COUNT (0x10) /**< Number of IRQ lines */ - -/** - * @brief Offset of the IRQ master in the interrupt numbers. - * - * x86_interrupts.c expects this value to be `0x20`. Do not change. - */ -#define PIC_MASTER_INTERRUPT_BASE (0x20) -/** - * @brief Offset of the IRQ slave in the interrupt numbers. - * - * The whole IRQ subsystem expects the IRQ slave numbers to come immediately after the master. - */ -#define PIC_SLAVE_INTERRUPT_BASE (PIC_MASTER_INTERRUPT_BASE + 8) - -#define PIC_MASTER (0x20) -#define PIC_SLAVE (0xA0) - -#define PIC_COMMAND (0x00) -#define PIC_DATA (0x01) -#define PIC_IMR (0x01) - -#define PIC_EOI 0x20 /**< End-of-interrupt command code */ - -#define PIC_READ_IRR 0x0a /**< OCW3 irq ready next CMD read */ -#define PIC_READ_ISR 0x0b /**< OCW3 irq service next CMD read */ - -#define PIC_ICW1_ICW4 (0x01) /**< ICW4 (not) needed */ -#define PIC_ICW1_SINGLE (0x02) /**< Single (cascade) mode */ -#define PIC_ICW1_INTERVAL4 (0x04) /**< Call address interval 4 (8) */ -#define PIC_ICW1_LEVEL (0x08) /**< Level triggered (edge) mode */ -#define PIC_ICW1_INIT (0x10) /**< Initialization - required! */ - -#define PIC_ICW4_8086 (0x01) /**< 8086/88 (MCS-80/85) mode */ -#define PIC_ICW4_AUTO (0x02) /**< Auto (normal) EOI */ -#define PIC_ICW4_BUF_SLAVE (0x08) /**< Buffered mode/slave */ -#define PIC_ICW4_BUF_MASTER (0x0C) /**< Buffered mode/master */ -#define PIC_ICW4_SFNM (0x10) /**< Special fully nested (not) */ - -#define PIC_NUM_PIT (0x0) /**< IRQ line of the Programmable Interrupt Controller **/ -#define PIC_NUM_KEYBOARD_CONTROLLER_1 (0x1) /**< IRQ line of the first PS/2 port **/ -#define PIC_NUM_SLAVE (0x2) /**< not a valid IRQ line! */ -#define PIC_NUM_RS232_2_4 (0x3) /**< IRQ line of COM 2+4 **/ -#define PIC_NUM_RS232_1_3 (0x4) /**< IRQ line of COM 1+2 **/ -#define PIC_NUM_LPT2 (0x5) /**< IRQ line of the secondary printer or soundcard (available for PCI) **/ -#define PIC_NUM_FLOPPY (0x6) /**< IRQ line of the floppy drive. **/ -#define PIC_NUM_LPT1 (0x7) /**< IRQ line of the parallel port (available for PCI) **/ - -#define PIC_NUM_RTC (0x8) /**< IRQ line of the Real Time Clock **/ -#define PIC_NUM_9 (0x9) /**< Free to use IRQ line (available for PCI) **/ -#define PIC_NUM_ATA_4 (0xa) /**< Free to use IRQ line (available for PCI) **/ -#define PIC_NUM_ATA_3 (0xb) /**< Free to use IRQ line (available for PCI) **/ -#define PIC_NUM_KEYBOARD_CONTROLLER_2 (0xc) /**< IRQ line of the second PS/2 port **/ -#define PIC_NUM_FPU (0xd) /**< not a valid IRQ line! */ -#define PIC_NUM_ATA_1 (0xe) /**< IRQ line of the primary IDE controller **/ -#define PIC_NUM_ATA_2 (0xf) /**< IRQ line of the secondary IDQ controller **/ - -#define PIC_MASK_PIT (1 << PIC_NUM_PIT) -#define PIC_MASK_KEYBOARD_CONTROLLER_1 (1 << PIC_NUM_KEYBOARD_CONTROLLER_1) -#define PIC_MASK_SLAVE (1 << PIC_NUM_SLAVE) -#define PIC_MASK_RS232_2_4 (1 << PIC_NUM_RS232_2_4) -#define PIC_MASK_RS232_1_3 (1 << PIC_NUM_RS232_1_3) -#define PIC_MASK_LPT2 (1 << PIC_NUM_LPT2) -#define PIC_MASK_FLOPPY (1 << PIC_NUM_FLOPPY) -#define PIC_MASK_LPT1 (1 << PIC_NUM_LPT1) - -#define PIC_MASK_RTC (1 << PIC_NUM_RTC) -#define PIC_MASK_9 (1 << PIC_NUM_9) -#define PIC_MASK_ATA_4 (1 << PIC_NUM_ATA_4) -#define PIC_MASK_ATA_3 (1 << PIC_NUM_ATA_3) -#define PIC_MASK_KEYBOARD_CONTROLLER_2 (1 << PIC_NUM_KEYBOARD_CONTROLLER_2) -#define PIC_MASK_FPU (1 << PIC_NUM_FPU) -#define PIC_MASK_ATA_1 (1 << PIC_NUM_ATA_1) -#define PIC_MASK_ATA_2 (1 << PIC_NUM_ATA_2) - -/** - * @brief Callback handler if there was an interrupt on this IRQ line. - * @param irq_num IRQ line in question. - * - * This callback is called out of the interrupt handler (irq_is_in() == true). - * Lengthy operations should be handled in a dedicated thread; use msg_send_int(). - * You must no enable interrupt inside the handler. - */ -typedef void (*x86_irq_handler_t)(uint8_t irq_num); - -/** - * @brief Set callback function for an IRQ line. - * @param handler The callback function, or NULL to do nothing. - * - * Setting a handler does not enable the interrupt. - * Use x86_pic_enable_irq() or x86_pic_disable_irq() accordingly. - * - * This function must only be called with interrupts disabled. - * - * Beware on unsetting interrupt handlers: - * The PIC default handler will still send an EOI. - * Especially the keyboard controller does not like it, - * if it is told that everything was done but it wasn't. - * A raised #X86_INT_GP might be the least of your problems. - */ -void x86_pic_set_handler(unsigned irq, x86_irq_handler_t handler); - -/** - * @brief Set the enabled IRQs - * - * Beware: this is the exact opposite of masking IRQs. - * - * This function should only be called by other subsystems like the PCI subsystem. - */ -void x86_pic_set_enabled_irqs(uint16_t mask); - -/** - * @brief Enable (unmask) an IRQ - * - * This function should only be called by other subsystems like the PCI subsystem. - */ -void x86_pic_enable_irq(unsigned num); - -/** - * @brief Disable (mask) an IRQ - * - * This function should only be called by other subsystems like the PCI subsystem. - */ -void x86_pic_disable_irq(unsigned num); - -#ifdef __cplusplus -} -#endif - -#endif /* X86_PIC_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_pit.h b/cpu/x86/include/x86_pit.h deleted file mode 100644 index d31977b7d703c6e9c0537ce358bd6fda91eb9bc0..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_pit.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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 - */ - -/** - * @brief Interfacing with the PIT. - * - * The core of the x86 port only uses the RTC for the hwtimer. - * Application developers are free to use this module. - * Be aware of portability issues. - * - * You most likely want to use the xtimer interface instead. - * - * @ingroup x86-irq - * @{ - * @file - * @author René Kijewski <rene.kijewski@fu-berlin.de> - */ - -#ifndef X86_PIT_H -#define X86_PIT_H - -#include <stdbool.h> -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define PIT_CHANNEL_0_PORT (0x40) /**< Channel 0 */ -#define PIT_CHANNEL_1_PORT (0x41) /**< Channel 1, DO NOT USE */ -#define PIT_CHANNEL_2_PORT (0x42) /**< Channel 2, do not use if you can help it */ -#define PIT_COMMAND_PORT (0x43) - -#define PIT_ACCESS_MODE_LATCH_COUNT (0 << 4) -#define PIT_ACCESS_MODE_LO_BYTE (1 << 4) -#define PIT_ACCESS_MODE_HI_BYTE (2 << 4) -#define PIT_ACCESS_MODE_LO_HI (3 << 4) - -#define PIT_INTERRUPT_ONTERMINAL_COUNT (0 << 1) /**< */ -#define PIT_ONE_SHOT (1 << 1) /**< */ -#define PIT_RATE_GENERATOR (2 << 1) /**< */ -#define PIT_SQUARE_WAVE (3 << 1) /**< */ -#define PIT_SOFWARE_TRIGGERED_STROBE (4 << 1) /**< */ -#define PIT_HARDWARE_TRIGGERED_STROBE (5 << 1) /**< */ - -#define PIT_MIN_HZ (19) -#define PIT_MAX_HZ (1193181) - -/** - * @brief Initialize the Programmable Interval Timer. - * - * This function is called during initialization by x86_startup(). - * You must not call this function on your own accord. - */ -void x86_init_pit(void); - -/** - * @brief Reads the current value of the of the channel. - * @param channel Channel (1, 2, or 3) to read from. - * @returns Current value of the channel. - * - * Channel 1 is the only channel that you should access. - * - * Channel 2 might be absent on current systems. - * It was never free to use for the OSes. - * Never access this channel! - * - * Channel 3 was originally intended to be used by the sound card. - * It's free to use, but you probably shouldn't. - */ -uint16_t x86_pit_read(unsigned channel); - -/** - * @brief Sets the speed and operation mode of a channel. - * @param channel Channel (1, 2, or 3) to set. - * @param mode Action on overflow. - * @param max After how many ticks the timer should overflow. - * - * See x86_pit_read() for considerations about the channel. - * - * The timer has a speed of 1193181hz. - * That value was convinient for hardware vendors, - * but has only the quite useless prime factors 3, 11, 19, and 173. - * That hurts the usefulness severly. - */ -void x86_pit_set2(unsigned channel, unsigned mode, uint16_t max); - -/** - * @brief Convenience wrapper for x86_pit_set2(). - * @param hz After how how long the timer should overflow. - * @returns true iff the value of hz was sane. - * - * See x86_pit_set2() for a more detailed explanation. - * max will be set to 1193181 / hz. - * That means hz has to be a value between 19 and 1193181. - * - * Beware: the 1,193,163 different values for hz will only render 2,165 different values for max. - */ -bool x86_pit_set(unsigned channel, unsigned mode, unsigned hz); - -#ifdef __cplusplus -} -#endif - -#endif /* X86_PIT_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_ports.h b/cpu/x86/include/x86_ports.h deleted file mode 100644 index 16584a19b8d5d0774b877dd6703784f8a3c70c77..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_ports.h +++ /dev/null @@ -1,194 +0,0 @@ -/* Copyright (C) 2004, 2005, 2006 Board of Trustees, Leland Stanford - * Jr. University. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -// Copy of Pintos' threads/io.h, license header extracted from Pintos' LICENSE file. - -#ifndef X86_PORTS_H -#define X86_PORTS_H - -#include <stdlib.h> -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Reads and returns a byte from PORT. - * @param[in] port Port to read from. - * @returns Read value. - */ -static inline uint8_t __attribute__((always_inline)) inb(uint16_t port) -{ - /* See [IA32-v2a] "IN". */ - uint8_t data; - __asm__ volatile("inb %w1, %b0" : "=a"(data) : "Nd"(port)); - return data; -} - -/** - * @brief Reads multiple bytes from a port. - * @param[in] port Port to read from. - * @param[out] addr Buffer to write the read values into. - * @param[in] cnt Number of bytes to read. - */ -static inline void __attribute__((always_inline)) insb(uint16_t port, void *addr, size_t cnt) -{ - /* See [IA32-v2a] "INS". */ - __asm__ volatile("rep insb" : "+D"(addr), "+c"(cnt) : "d"(port) : "memory"); -} - -/** - * @brief Reads and returns a word from PORT. - * @param[in] port Port to read from. - * @returns Read value. - */ -static inline uint16_t __attribute__((always_inline)) inw(uint16_t port) -{ - uint16_t data; - /* See [IA32-v2a] "IN". */ - __asm__ volatile("inw %w1, %w0" : "=a"(data) : "Nd"(port)); - return data; -} - -/** - * @brief Reads multiple words from a port. - * @param[in] port Port to read from. - * @param[out] addr Buffer to write the read values into. - * @param[in] cnt Number of words to read. - */ -static inline void __attribute__((always_inline)) insw(uint16_t port, void *addr, size_t cnt) -{ - /* See [IA32-v2a] "INS". */ - __asm__ volatile("rep insw" : "+D"(addr), "+c"(cnt) : "d"(port) : "memory"); -} - -/** - * @brief Reads and returns a long from PORT. - * @param[in] port Port to read from. - * @returns Read value. - */ -static inline uint32_t __attribute__((always_inline)) inl(uint16_t port) -{ - /* See [IA32-v2a] "IN". */ - uint32_t data; - __asm__ volatile("inl %w1, %0" : "=a"(data) : "Nd"(port)); - return data; -} - -/** - * @brief Reads multiple longs from a port. - * @param[in] port Port to read from. - * @param[out] addr Buffer to write the read values into. - * @param[in] cnt Number of words to read. - */ -static inline void __attribute__((always_inline)) insl(uint16_t port, void *addr, size_t cnt) -{ - /* See [IA32-v2a] "INS". */ - __asm__ volatile("rep insl" : "+D"(addr), "+c"(cnt) : "d"(port) : "memory"); -} - -/** - * @brief Writes a byte into a port. - * @param[in] port Port to write into. - * @param[in] data Byte to write. - */ -static inline void __attribute__((always_inline)) outb(uint16_t port, uint8_t data) -{ - /* See [IA32-v2b] "OUT". */ - __asm__ volatile("outb %b0, %w1" : : "a"(data), "Nd"(port)); -} - -/** - * @brief Writes multiple bytes into a port. - * @param[in] port Port to write into. - * @param[in] addr Buffer to read from. - * @param[in] cnt Number of bytes to write. - */ -static inline void __attribute__((always_inline)) outsb(uint16_t port, const void *addr, size_t cnt) -{ - /* See [IA32-v2b] "OUTS". */ - __asm__ volatile("rep outsb" : "+S"(addr), "+c"(cnt) : "d"(port)); -} - -/** - * @brief Writes a word into a port. - * @param[in] port Port to write into. - * @param[in] data Word to write. - */ -static inline void __attribute__((always_inline)) outw(uint16_t port, uint16_t data) -{ - /* See [IA32-v2b] "OUT". */ - __asm__ volatile("outw %w0, %w1" : : "a"(data), "Nd"(port)); -} - -/** - * @brief Writes multiple words into a port. - * @param[in] port Port to write into. - * @param[in] addr Buffer to read from. - * @param[in] cnt Number of words to write. - */ -static inline void __attribute__((always_inline)) outsw(uint16_t port, const void *addr, size_t cnt) -{ - /* See [IA32-v2b] "OUTS". */ - __asm__ volatile("rep outsw" : "+S"(addr), "+c"(cnt) : "d"(port)); -} - -/** - * @brief Writes a long into a port. - * @param[in] port Port to write into. - * @param[in] data Long to write. - */ -static inline void __attribute__((always_inline)) outl(uint16_t port, uint32_t data) -{ - /* See [IA32-v2b] "OUT". */ - __asm__ volatile("outl %0, %w1" : : "a"(data), "Nd"(port)); -} - -/** - * @brief Writes multiple longs into a port. - * @param[in] port Port to write into. - * @param[in] addr Buffer to read from. - * @param[in] cnt Number of longs to write. - */ -static inline void __attribute__((always_inline)) outsl(uint16_t port, const void *addr, size_t cnt) -{ - /* See [IA32-v2b] "OUTS". */ - __asm__ volatile("rep outsl" : "+S"(addr), "+c"(cnt) : "d"(port)); -} - -/** - * @brief Make sure a write to a port was already acknowledged. - */ -static inline void __attribute__((always_inline)) io_wait(void) -{ - __asm__ volatile(" jmp 1f\n" - "1: jmp 2f\n" - "2:"); -} - -#ifdef __cplusplus -} -#endif - -#endif /* X86_PORTS_H */ diff --git a/cpu/x86/include/x86_reboot.h b/cpu/x86/include/x86_reboot.h deleted file mode 100644 index 02ff7228d15e4963f22db8eb3c382cf42fa90417..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_reboot.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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 - */ - -/** - * Rebooting x86 boards. - * - * @ingroup x86 - * @{ - * @file - * @author René Kijewski <rene.kijewski@fu-berlin.de> - */ - -#ifndef X86_REBOOT_H -#define X86_REBOOT_H - -#include <stdbool.h> -#include "kernel_defines.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Prototype for a x86 reboot function. - * - * The function may return, then a naive reboot is tried. - * It is safe to call x86_kbc_reboot() inside the handler, - * then a naive reboot will be done immediately. - * - * The handler is called with interrupts disabled. - * You should keep the interrupts disabled and use busy loops. - */ -typedef void (*x86_reboot_t)(void); - -/** - * @brief Reboots the system. - * - * First the function supplied if x86_set_reboot_fun() is called (iff applies). - * Then a reboot using the keyboard controller is tried. - * And if everything fails, a tripple fault is provoked. - */ -void NORETURN x86_kbc_reboot(void); - -/** - * @brief Set specialized reboot function. - * - * This function should be utilized by the ACPI subsystem. - */ -void x86_set_reboot_fun(x86_reboot_t fun); - -/** - * @brief Loads an empty interrupt descriptor table. - * - * Any interrupt that will occur causes a tripple fault, i.e. a reboot. - * Must be called with interrupts disabled. - */ -void x86_load_empty_idt(void); - -/** - * @brief Prototype of the board specific x86 shutdown function. - * @returns `false` if the shutdown could not be scheduled. - */ -typedef bool (*x86_shutdown_t)(void); - -/** - * @brief Shutdown and power off - * @details May return. The shutdown only gets scheduled. - * @returns `false` if shutting down is not possible at this moment. - */ -bool x86_shutdown(void); - -/** - * @brief Function to call on x86_shutdown() - */ -void x86_set_shutdown_fun(x86_shutdown_t fun); - -#ifdef __cplusplus -} -#endif - -#endif /* X86_REBOOT_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_registers.h b/cpu/x86/include/x86_registers.h deleted file mode 100644 index 1489ec5a4213a1c84de2501238410eb58197021f..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_registers.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - * 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 various non-general purpose registers of x86 CPUs. - * - * @ingroup x86 - * @{ - * @file - * @author René Kijewski <rene.kijewski@fu-berlin.de> - */ - -#ifndef X86_REGISTERS_H -#define X86_REGISTERS_H - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* see "Intel® Quark SoC X1000 Core Developer’s Manual", § 4.4.1.1 (p. 47) */ -#define CR0_PE (1u << 0) /**< 1 = protected mode */ -#define CR0_MP (1u << 1) /**< 1 = monitor coprocessor (FWAIT causes an interrupt) */ -#define CR0_EM (1u << 2) /**< 1 = FPU emulation (x87 instructions cause - #X86_INT_NM, SSE causes #X86_INT_UD) */ -#define CR0_TS (1u << 3) /**< 1 = task switched flag (causes #X86_INT_NM on - x87/SSE instructions, set by CPU on hardware - task switch) */ -#define CR0_ET (1u << 4) /**< 1 = 80387; 0 = 80287 */ -#define CR0_NE (1u << 5) /**< 1 = numeric error */ -#define CR0_WP (1u << 16) /**< 1 = write proctected pages aren't writable in ring 0 either */ -#define CR0_AM (1u << 18) /**< 1 = alignment mask */ -#define CR0_NW (1u << 29) /**< 1 = not write-through */ -#define CR0_CD (1u << 30) /**< 1 = disable caching */ -#define CR0_PG (1u << 31) /**< 1 = enable paging */ - -#define CR3_PWT (1u << 3) /**< 1 = page-level writes transparent */ -#define CR3_PCD (1u << 4) /**< 1 = page-level cache disabled */ - -#define CR4_VME (1u << 0) /**< 1 = virtual 8086 mode */ -#define CR4_PVI (1u << 1) /**< 1 = protected-mode virtual interrupts */ -#define CR4_TSD (1u << 2) /**< 1 = restrict RDTSC instruction to ring 0 */ -#define CR4_DE (1u << 3) /**< 1 = debugging extension */ -#define CR4_PSE (1u << 4) /**< 1 = page size extension */ -#define CR4_PAE (1u << 5) /**< 1 = physical address extension */ -#define CR4_MCE (1u << 6) /**< 1 = machine-check enable */ -#define CR4_PGE (1u << 7) /**< 1 = enable G flag in PT */ -#define CR4_PCE (1u << 8) /**< 1 = allow RDPMC instruction in rings 1-3, too */ -#define CR4_OSFXSR (1u << 9) /**< 1 = disable #X86_INT_NM if CR0.TS=1 */ -#define CR4_OSXMMEXCPT (1u << 10) /**< 1 = enable unmasked SSE exceptions */ -#define CR4_SMEP (1u << 10) /**< 1 = enables supervisor-mode execution prevention */ - -#define X86_CR_ATTR __attribute__ ((always_inline, no_instrument_function)) - -/** - * @brief Read the Control Register 0, various control flags for the CPU. - */ -static inline uint32_t X86_CR_ATTR cr0_read(void) -{ - uint32_t result; - __asm__ volatile ("mov %%cr0, %%eax" : "=a"(result)); - return result; -} - -/** - * @brief Set the Control Register 0, various control flags for the CPU. - * - * You must not blank out unknown bits. - * First use cr0_read(), then set and reset the bit you want to manipulate, - * then call this function. - */ -static inline void X86_CR_ATTR cr0_write(uint32_t value) -{ - __asm__ volatile ("mov %%eax, %%cr0" :: "a"(value)); -} - -/** - * @brief Read the Page Fault Linear Address. - * - * The PFLA is the address which was accessed when the page fauled occured, - * i.e. this is not the PC of the \#PF! - */ -static inline uint32_t X86_CR_ATTR cr2_read(void) -{ - uint32_t result; - __asm__ volatile ("mov %%cr2, %%eax" : "=a"(result)); - return result; -} - -/** - * @brief Read the (physical) address of the page table. - * - * You are doing it wrong if you ever find you need to call this function ... - */ -static inline uint32_t X86_CR_ATTR cr3_read(void) -{ - uint32_t result; - __asm__ volatile ("mov %%cr3, %%eax" : "=a"(result)); - return result; -} - -/** - * @brief Set the (pyhsical) address of the page table. - * - * This flushes the TLB for all pages that do not have the PT_G flag. - */ -static inline void X86_CR_ATTR cr3_write(uint32_t value) -{ - __asm__ volatile ("mov %%eax, %%cr3" :: "a"(value)); -} - -/** - * @brief Set the Control Register 4, various control flags for the CPU. - */ -static inline uint32_t X86_CR_ATTR cr4_read(void) -{ - uint32_t result; - __asm__ volatile ("mov %%cr4, %%eax" : "=a"(result)); - return result; -} - -/** - * @brief Set the Control Register 4, various control flags for the CPU. - * - * You must not blank out unknown bits. - * First use cr0_read(), then set and reset the bit you want to manipulate, - * then call this function. - */ -static inline void X86_CR_ATTR cr4_write(uint32_t value) -{ - __asm__ volatile ("mov %%eax, %%cr4" :: "a"(value)); -} - -#define EFER_SCE (1u << 0) -#define EFER_LME (1u << 8) -#define EFER_LMA (1u << 10) -#define EFER_NXE (1u << 11) -#define EFER_SVME (1u << 12) -#define EFER_LMSLE (1u << 12) -#define EFER_FFXSR (1u << 14) - -#define MSR_EFER (0xC0000080) - -/** - * @brief Read a Machine Specific Register. - */ -static inline uint64_t X86_CR_ATTR msr_read(uint32_t msr) -{ - uint32_t eax, edx; - __asm__ volatile ( - "rdmsr" - : "=a"(eax), "=d"(edx) - : "c"(msr) - ); - return (((uint64_t) edx) << 32) | eax; -} - -/** - * @brief Set a Machine Specific Register. - * - * You must not blank out unknown bits. - * First use msr_read(), then set and reset the bit you want to manipulate, - * then call this function. - */ -static inline void X86_CR_ATTR msr_set(uint32_t msr, uint64_t value) -{ - __asm__ volatile ( - "wrmsr" - :: "a"((uint32_t) value), "d"((uint32_t) (value >> 32)), "c"(msr) - ); -} - -#define CPUID_FPU (1ull << 0) -#define CPUID_VME (1ull << 1) -#define CPUID_DE (1ull << 2) -#define CPUID_PSE (1ull << 3) -#define CPUID_TSC (1ull << 4) -#define CPUID_MSR (1ull << 5) -#define CPUID_PAE (1ull << 6) -#define CPUID_MCE (1ull << 7) -#define CPUID_CX8 (1ull << 8) -#define CPUID_APIC (1ull << 9) -#define CPUID_SEP (1ull << 11) -#define CPUID_MTRR (1ull << 12) -#define CPUID_PGE (1ull << 13) -#define CPUID_MCA (1ull << 14) -#define CPUID_CMOV (1ull << 15) -#define CPUID_PAT (1ull << 16) -#define CPUID_PSE36 (1ull << 17) -#define CPUID_PSN (1ull << 18) -#define CPUID_CLF (1ull << 19) -#define CPUID_DTES (1ull << 21) -#define CPUID_ACPI (1ull << 22) -#define CPUID_MMX (1ull << 23) -#define CPUID_FXSR (1ull << 24) -#define CPUID_SSE (1ull << 25) -#define CPUID_SSE2 (1ull << 26) -#define CPUID_SS (1ull << 27) -#define CPUID_HTT (1ull << 28) -#define CPUID_TM1 (1ull << 29) -#define CPUID_IA64 (1ull << 30) -#define CPUID_PBE (1ull << 31) -#define CPUID_SSE3 (1ull << (32 + 0)) -#define CPUID_PCLMUL (1ull << (32 + 1)) -#define CPUID_DTES64 (1ull << (32 + 2)) -#define CPUID_MONITOR (1ull << (32 + 3)) -#define CPUID_DS_CPL (1ull << (32 + 4)) -#define CPUID_VMX (1ull << (32 + 5)) -#define CPUID_SMX (1ull << (32 + 6)) -#define CPUID_EST (1ull << (32 + 7)) -#define CPUID_TM2 (1ull << (32 + 8)) -#define CPUID_SSSE3 (1ull << (32 + 9)) -#define CPUID_CID (1ull << (32 + 10)) -#define CPUID_FMA (1ull << (32 + 12)) -#define CPUID_CX16 (1ull << (32 + 13)) -#define CPUID_ETPRD (1ull << (32 + 14)) -#define CPUID_PDCM (1ull << (32 + 15)) -#define CPUID_DCA (1ull << (32 + 18)) -#define CPUID_SSE4_1 (1ull << (32 + 19)) -#define CPUID_SSE4_2 (1ull << (32 + 20)) -#define CPUID_x2APIC (1ull << (32 + 21)) -#define CPUID_MOVBE (1ull << (32 + 22)) -#define CPUID_POPCNT (1ull << (32 + 23)) -#define CPUID_AES (1ull << (32 + 25)) -#define CPUID_XSAVE (1ull << (32 + 26)) -#define CPUID_OSXSAVE (1ull << (32 + 27)) -#define CPUID_AVX (1ull << (32 + 28)) - -/** - * @brief Read the basic features of the CPU. - * - * http://www.sandpile.org/x86/cpuid.htm - */ -static inline uint64_t X86_CR_ATTR cpuid_caps(void) -{ - uint32_t edx, ecx; - __asm__ volatile ("cpuid" : "=d"(edx), "=c"(ecx) : "a"(1) : "ebx"); - return ((uint64_t) ecx << 32) | edx; -} - -#ifdef __cplusplus -} -#endif - -#endif /* X86_REGISTERS_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_rtc.h b/cpu/x86/include/x86_rtc.h deleted file mode 100644 index 3928843c6fd80ad3d64e93aba5471341482d120d..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_rtc.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - * 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 - */ - -/** - * @brief Interfacing the realtime clock on x86 boards. - * - * Only use this module to read the current time. - * Using the other functions in applications would break the hwtimer. - * - * @ingroup x86-irq - * @{ - * @file - * @author René Kijewski <rene.kijewski@fu-berlin.de> - */ - -#ifndef X86_RTC_H -#define X86_RTC_H - -#include "msg.h" -#include "x86_cmos.h" - -#include <stdbool.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief A timestamp. - * - * The value of the century is unreliable. - */ -typedef union x86_rtc_data { - __extension__ struct { - uint8_t second, minute, hour; - uint8_t day, month, year, century; - }; - uint64_t timestamp; /**< The full timestamp as a 64bit integer - representation */ -} x86_rtc_data_t; - -#define RTC_REG_SECOND (0x00) -#define RTC_REG_ALARM_SECOND (0x01) -#define RTC_REG_MINUTE (0x02) -#define RTC_REG_ALARM_MINUTE (0x03) -#define RTC_REG_HOUR (0x04) -#define RTC_REG_ALARM_HOUR (0x05) -#define RTC_REG_DOW (0x06) -#define RTC_REG_DAY (0x07) -#define RTC_REG_MONTH (0x08) -#define RTC_REG_YEAR (0x09) -#define RTC_REG_A (0x0a) -#define RTC_REG_B (0x0b) -#define RTC_REG_C (0x0c) -#define RTC_REG_D (0x0d) -#define RTC_REG_POST (0x0e) -#define RTC_REG_CENTURY (0x32) - -#define RTC_REG_A_HZ_OFF ( 0 << 0) -#define RTC_REG_A_HZ_8192 ( 3 << 0) -#define RTC_REG_A_HZ_4096 ( 4 << 0) -#define RTC_REG_A_HZ_2048 ( 5 << 0) -#define RTC_REG_A_HZ_1024 ( 6 << 0) -#define RTC_REG_A_HZ_512 ( 7 << 0) -#define RTC_REG_A_HZ_256 ( 8 << 0) -#define RTC_REG_A_HZ_128 ( 9 << 0) -#define RTC_REG_A_HZ_64 (10 << 0) -#define RTC_REG_A_HZ_32 (11 << 0) -#define RTC_REG_A_HZ_16 (12 << 0) -#define RTC_REG_A_HZ_8 (13 << 0) -#define RTC_REG_A_HZ_4 (14 << 0) -#define RTC_REG_A_HZ_2 (15 << 0) -#define RTC_REG_A_HZ_MASK (15 << 0) -#define RTC_REG_A_DIVIDER_MASK ( 3 << 4) -#define RTC_REG_A_UPDATING ( 1 << 7) - -#define RTC_REG_B_DST (1 << 0) -#define RTC_REG_B_24H (1 << 1) -#define RTC_REG_B_BIN (1 << 2) -#define RTC_REG_B_WAVE (1 << 3) -#define RTC_REG_B_INT_UPDATE (1 << 4) -#define RTC_REG_B_INT_ALARM (1 << 5) -#define RTC_REG_B_INT_PERIODIC (1 << 6) -#define RTC_REG_B_INT_MASK (7 << 4) -#define RTC_REG_B_UPDATE (1 << 7) - -#define RTC_REG_C_IRQ_UPDATE (1 << 4) -#define RTC_REG_C_IRQ_ALARM (1 << 5) -#define RTC_REG_C_IRQ_PERIODIC (1 << 6) -#define RTC_REG_C_IRQ (1 << 7) - -#define RTC_REG_D_VALID (1 << 7) - -#define RTC_REG_POST_TIME_INVALID (1 << 2) -#define RTC_REG_POST_POWER_LOSS (1 << 7) - -/** - * @brief Initialize the Real Time Clock. - * - * This function is called during initialization by x86_startup(). - * You must not call this function on your own accord. - * - * The RTC subsystem will refuse to work if the CMOS says that - * @li there was a power loss, - * @li the stored time is invalid (i.e. February 30), or - * @li the CMOS had a checksum failure. - */ -void x86_init_rtc(void); - -/** - * @brief Read the current time. - * @returns false iff the RTC is unreliable, the value of dest is random is this case. - * - * This reads the CMOS value - * The standard does not tell the timezone of this value. - */ -bool x86_rtc_read(x86_rtc_data_t *dest); - -/** - * @brief A custom callback handler for RTC interrupts. - * @param reg_c The value of CMOS register C. - */ -typedef void (*x86_rtc_callback_t)(uint8_t reg_c); - -/** - * @brief Set an RTC alarm. - * @param[in] when Time when the RTC you raise an interrupt. The date part is ignored. - * @param msg_content The value for msg_t::content.value. - * @param target_pid The process which shall receive the message, `KERNEL_PID_UNDEF` to disable. - * @param allow_replace Whether it is allowed to overwrite an existing alarm. - * - * The value of msg_t::type will be `reg_c | (RTC_REG_B_INT_UPDATE << 8)`, - * where `reg_c` is the value of CMOS register C. - * - * You should not call this function directly. - * You should use xtimer instead. - */ -bool x86_rtc_set_alarm(const x86_rtc_data_t *when, uint32_t msg_content, kernel_pid_t target_pid, bool allow_replace); - -/** - * @brief Set up periodic interrupts - * @param hz How often a second the interrupt should fire, e.g. RTC_REG_A_HZ_8192. - * @param msg_content The value for msg_t::content.value. - * @param target_pid The process which shall receive the message, `KERNEL_PID_UNDEF` to disable. - * @param allow_replace Whether it is allowed to overwrite an existing alarm. - * - * The value of msg_t::type will be `reg_c | (RTC_REG_B_INT_PERIODIC << 8)`, - * where `reg_c` is the value of CMOS register C. - * - * You should not call this function directly. - * You should use xtimer instead. - */ -bool x86_rtc_set_periodic(uint8_t hz, uint32_t msg_content, kernel_pid_t target_pid, bool allow_replace); - -/** - * @brief Set up secondly interrupts. - * @param msg_content The value for msg_t::content.value. - * @param target_pid The process which shall receive the message, `KERNEL_PID_UNDEF` to disable. - * @param allow_replace Whether it is allowed to overwrite an existing alarm. - * - * The value of msg_t::type will be `reg_c | (RTC_REG_B_INT_UPDATE << 8)`, - * where `reg_c` is the value of CMOS register C. - * - * You should not call this function directly. - * You should use xtimer instead. - */ -bool x86_rtc_set_update(uint32_t msg_content, kernel_pid_t target_pid, bool allow_replace); - -/** - * @brief Set custom alarm interrupt handler. - * @param cb Your custom handler, or NULL to use default. - * - * You must never use this function. - * It is only there for x86_hwtimer.c, - * because the hwtimer subsystem gets set up before the message system works. - */ -void x86_rtc_set_alarm_callback(x86_rtc_callback_t cb); - -/** - * @brief Set custom periodic interrupt handler. - * @param cb Your custom handler, or NULL to use default. - * - * You must never use this function. - * It is only there for x86_hwtimer.c, - * because the hwtimer subsystem gets set up before the message system works. - */ -void x86_rtc_set_periodic_callback(x86_rtc_callback_t cb); - -/** - * @brief Set custom update interrupt handler. - * @param cb Your custom handler, or NULL to use default. - * - * You must never use this function. - * It is only there for x86_hwtimer.c, - * because the hwtimer subsystem gets set up before the message system works. - */ -void x86_rtc_set_update_callback(x86_rtc_callback_t cb); - -#ifdef __cplusplus -} -#endif - -#endif /* X86_RTC_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_threading.h b/cpu/x86/include/x86_threading.h deleted file mode 100644 index 257f47bd28d90b96b9523e383faa9d491baf0468..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_threading.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 - */ - -/** - * Using multiple threads on x86 boards. - * - * @ingroup x86 - * @defgroup x86-multithreading i586 multithreading support - * @{ - * @file - * @author René Kijewski <rene.kijewski@fu-berlin.de> - */ - -#ifndef X86_THREADING_H -#define X86_THREADING_H - -#include <stdbool.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialize threading. - * - * This function is called during initialization by x86_startup(). - * You must not call this function on your own accord. - */ -void x86_init_threading(void); - -/** - * @brief The getter/setter for irq_is_in() for the x86 port. - */ -extern bool x86_in_isr; - -#ifdef __cplusplus -} -#endif - -#endif /* X86_THREADING_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_uart.h b/cpu/x86/include/x86_uart.h deleted file mode 100644 index bf983f9a2442737e0bffd194914bcb8dae50201c..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_uart.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * 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 - */ - -/** - * Using Communations Port 0 (COM0) to interface with a human being on x86 boards. - * - * @ingroup x86-irq - * @{ - * @file - * @author René Kijewski <rene.kijewski@fu-berlin.de> - */ - -#ifndef X86_UART_H -#define X86_UART_H - -#include "x86_pic.h" - -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <unistd.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Early initialization of the UART system, before there are interrupts. - * - * This function is called during initialization by x86_startup(). - * You must not call this function on your own accord. - */ -void x86_early_init_uart(void); - -/** - * @brief Full initialization of the Universal Asynchronous Receiver Transmitter. - * - * This function is called during initialization by x86_startup(). - * You must not call this function on your own accord. - */ -void x86_init_uart(void); - -/** - * @brief Write out characters to the UART. - * @param[in] buf Buffer to write. - * @param len Length of the buffer. - * @returns Actual amount of bytes written, always the same as len. - * - * This function blocks with interrupts disabled once the output buffer is full. - */ -ssize_t x86_uart_write(const char *buf, size_t len); - -/** - * @brief Read in characters to the UART. - * @param[out] buf Buffer to set. - * @param len Length of the buffer. - * @returns Actual amount of bytes read, always the same as len. - * - * This function blocks with interrupts disabled once the input buffer is full. - */ -ssize_t x86_uart_read(char *buf, size_t len); - -#define COM1_PORT (0x03F8) -#define COM2_PORT (0x02F8) -#define COM3_PORT (0x03E8) -#define COM4_PORT (0x02E8) - -#define COM1_IRQ (PIC_NUM_RS232_1_3) -#define COM2_IRQ (PIC_NUM_RS232_2_4) -#define COM3_IRQ (PIC_NUM_RS232_1_3) -#define COM4_IRQ (PIC_NUM_RS232_2_4) - -/* 115200 baud */ -#define BAUD_LL (0x01) -#define BAUD_HL (0x00) - -enum uart_port_offs_t { - /* DLAB RW */ - THR = 0, /* 0 W Transmitter Holding Buffer */ - RBR = 0, /* 0 R Receiver Buffer */ - DLL = 0, /* 1 RW Divisor Latch Low Byte */ - IER = 1, /* 0 RW Interrupt Enable Register */ - DLH = 1, /* 1 RW Divisor Latch High Byte */ - IIR = 2, /* - R Interrupt Identification Register */ - FCR = 2, /* - RW FIFO Control Register */ - LCR = 3, /* - RW Line Control Register */ - MCR = 4, /* - RW Modem Control Register */ - LSR = 5, /* - R Line Status Register */ - MSR = 6, /* - R Modem Status Register */ - SR = 7, /* - RW Scratch Register */ -}; - -enum ier_t { - IER_RECV = 1 << 0, /* Enable Received Data Available Interrupt */ - IER_SEND = 1 << 1, /* Enable Transmitter Holding Register Empty Interrupt */ - IER_LS = 1 << 2, /* Enable Receiver Line Status Interrupt */ - IER_MS = 1 << 3, /* Enable Modem Status Interrupt */ - IER_SLEEP = 1 << 4, /* Enables Sleep Mode (16750) */ - IER_LPM = 1 << 5, /* Enables Low Power Mode (16750) */ -}; - -enum fcr_t { - FCR_ENABLE = 1 << 0, /* Enable FIFOs */ - FCR_CLR_RECV = 1 << 1, /* Clear Receive FIFO */ - FCR_CLR_SEND = 1 << 2, /* Clear Transmit FIFO */ - FCR_MDA = 1 << 3, /* DMA Mode Select */ - FCR_64BYTE = 1 << 5, /* Enable 64 Byte FIFO (16750) */ - - FCR_TRIGGER_1 = 0 << 6, /* 1 byte */ - FCR_TRIGGER_16 = 1 << 6, /* 16 bytes */ - FCR_TRIGGER_32 = 2 << 6, /* 32 bytes */ - FCR_TRIGGER_56 = 3 << 6, /* 56 bytes */ -}; - -enum lcr_t { - LCR_WORD_BITS_5 = (0) << 0, /* Word length: 5 bits */ - LCR_WORD_BITS_6 = (1) << 0, /* Word length: 6 bits */ - LCR_WORD_BITS_7 = (2) << 0, /* Word length: 7 bits */ - LCR_WORD_BITS_8 = (3) << 0, /* Word length: 8 bits */ - - LCR_STOP_BITS_1 = (0) << 2, /* Stop bits: 1 */ - LCR_STOP_BITS_2 = (1) << 2, /* Stop bits: 1.5 or 2 */ - - LCR_PAR_NONE = (0) << 3, /* no parity */ - LCR_PAR_ODD = (1) << 3, /* odd parity */ - LCR_PAR_EVEN = (3) << 3, /* even parity */ - LCR_PAR_MARK = (5) << 3, /* mark (?) */ - LCR_PAR_SPACE = (7) << 3, /* space (?) */ - - LCR_SET_BREAK = (1) << 6, /* set break enabled */ - - LCR_DLAB = (1) << 7, /* divisor latch access bit */ -}; - -enum mcr_t { - MCR_DSR = 1 << 0, /* Data Terminal Ready */ - MCR_RTS = 1 << 1, /* Request To Send */ - MCR_AUX1 = 1 << 2, /* Auxiliary Output 1 */ - MCR_AUX2 = 1 << 3, /* Auxiliary Output 2 */ - MCR_LOOPBACK = 1 << 4, /* Loopback Mode */ - MCR_AUTOFLOW = 1 << 5, /* Autoflow Control Enabled (16750) */ -}; - -enum iir_t { - IIR_IPF = 1 << 0, /* interrupt pending flag */ - - IIR_INT_MASK = 3 << 1, - IIR_INT_MS = 0 << 1, /* modem status interrupt (reset: read MSR) */ - IIR_INT_TH = 1 << 1, /* THR empty interrupt (reset: read IIR or write to THR) */ - IIR_INT_BR = 2 << 1, /* recv data available interrupt (reset: read RBR) */ - IIR_INT_LS = 3 << 1, /* line status changed (reset: read LSR) */ - IIR_INT_TO = 6 << 1, /* timeout interrupt pending (reset: read RBR) */ - - IIR_FIFO64 = 1 << 5, /* 64 byte FIFO enabled */ - - IIR_FIFO_MASK = 3 << 6, - IIR_FIFO_NONE = 0 << 6, /* no FIFO available */ - IIR_FIFO_RES = 1 << 6, /* reserved condition */ - IIR_FIFO_MAL = 2 << 6, /* FIFO enabled, not working */ - IIR_FIFO_ENABLED = 3 << 6, /* FIFO enabled */ -}; - -#ifdef __cplusplus -} -#endif - -#endif /* X86_UART_H */ - -/** @} */ diff --git a/cpu/x86/include/x86_videoram.h b/cpu/x86/include/x86_videoram.h deleted file mode 100644 index 7cefb7ab8571c8bed52abf0808da689db0b05824..0000000000000000000000000000000000000000 --- a/cpu/x86/include/x86_videoram.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 - */ - -/** - * Writing to the videoram. - * - * @ingroup x86 - * @{ - * @file - * @author René Kijewski <rene.kijewski@fu-berlin.de> - */ - -#ifndef X86_VIDEORAM_H -#define X86_VIDEORAM_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Print out a single character on the graphical device. - * - * This method can be used before the UART system was initialized. - * - * Special characters that are understood: '\\n' and '\\r'. - * Use DOS newlines. - */ -void videoram_putc(char c); - -/** - * @brief Print out multiple characters on the graphical device. - * - * This is the same as calling videoram_putc() repeatedly. - */ -void videoram_put(const char *s); - -/** - * @brief Print out multiple characters on the graphical device, then go to the next line. - * - * This is the same as calling `videoram_put(s); videoram_put("\r\n");`. - */ -void videoram_puts(const char *s); - -/** - * @brief Print out a hexadecimal number on the graphical device, including "0x" at the start. - */ -void videoram_put_hex(unsigned long v); - -#ifdef __cplusplus -} -#endif - -#endif /* X86_VIDEORAM_H */ - -/** @} */ diff --git a/cpu/x86/nop_nop_nop.inc b/cpu/x86/nop_nop_nop.inc deleted file mode 100644 index 49b9ec1f2e65b84f8f55639a824ea8357ca947f6..0000000000000000000000000000000000000000 --- a/cpu/x86/nop_nop_nop.inc +++ /dev/null @@ -1,128 +0,0 @@ -#if 0 - -from itertools import cycle - -regs = [ ('eax', [1,0,0,0,0,0,0]), - ('ecx', [0,1,0,0,0,0,0]), - ('edx', [0,0,1,0,0,0,0]), - #('ebx', [0,0,0,1,0,0,0]), - #('ebp', [0,0,0,0,1,0,0]), - ('esi', [0,0,0,0,0,1,0]), - ('edi', [0,0,0,0,0,0,1]), ] -REGS0 = list(regs) - -for cur in cycle(range(len(regs))): - nex = (cur + 1) % len(regs) - print 'asm volatile ("xor %%%s, %%%s");' % (regs[cur][0], regs[nex][0]) - val = [a^b for a, b in zip(regs[cur][1], regs[nex][1])] - regs[nex] = (regs[nex][0], val) - if regs == REGS0: - break - -#endif - -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); -asm volatile ("xor %eax, %ecx"); -asm volatile ("xor %ecx, %edx"); -asm volatile ("xor %edx, %esi"); -asm volatile ("xor %esi, %edi"); -asm volatile ("xor %edi, %eax"); diff --git a/cpu/x86/x86_cmos.c b/cpu/x86/x86_cmos.c deleted file mode 100644 index e35b769a2658bfba515f6c603a32281088c2e67f..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_cmos.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 Accessing the CMOS space of the BIOS. - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include "x86_cmos.h" - -uint8_t x86_cmos_read(int reg) -{ - outb(CMOS_ADDRESS, reg); - io_wait(); - return inb(CMOS_DATA); -} - -void x86_cmos_write(int reg, uint8_t value) -{ - outb(CMOS_ADDRESS, reg); - io_wait(); - outb(CMOS_DATA, value); -} - -void x86_cmos_serial(uint8_t (*serial)[CMOS_SERIAL_LEN]) -{ - for (unsigned i = 0; i < CMOS_SERIAL_LEN; ++i) { - (*serial)[i] = x86_cmos_read(CMOS_SERIAL_OFFS + i); - } -} diff --git a/cpu/x86/x86_glue.c b/cpu/x86/x86_glue.c deleted file mode 100644 index b7cc3dc421253f1282d74dd606fac414b40f1448..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_glue.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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 The interface between newlib and kernel functions. - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include "kernel_defines.h" -#include "cpu.h" -#include "sched.h" -#include "x86_uart.h" - -#include <signal.h> -#include <sys/stat.h> -#include <unistd.h> - -void _exit(int status) -{ - (void) status; - sched_task_exit(); - UNREACHABLE(); -} - -#ifndef MODULE_POSIX -/* Already defined in /sys/posix/unistd.c */ - -int close(int fildes) -{ - /* TODO */ - (void) fildes; - return -1; -} -#endif - -pid_t getpid(void) -{ - return (pid_t) sched_active_pid; -} - -int fstat(int fildes, struct stat *buf) -{ - /* TODO */ - (void) fildes; - (void) buf; - return -1; -} - -int isatty(int fildes) -{ - /* TODO */ - (void) fildes; - return 0; /* sic */ -} - -int kill(pid_t pid, int sig) -{ - /* TODO */ - (void) pid; - (void) sig; - return -1; -} - -off_t lseek(int fildes, off_t offset, int whence) -{ - /* TODO */ - (void) fildes; - (void) offset; - (void) whence; - return (off_t) -1; -} - -ssize_t read(int fildes, void *buf, size_t nbyte) -{ - if (nbyte == 0) { - /* allow reading nothing from every FD ... */ - return 0; - } - else if (fildes == STDOUT_FILENO || fildes == STDERR_FILENO) { - /* cannot read from STDOUT or STDERR */ - return -1; - } - else if (fildes == STDIN_FILENO) { - return x86_uart_read(buf, nbyte); - } - - /* TODO: find appropriate FILE */ - (void) fildes; - (void) buf; - (void) nbyte; - return -1; -} - -ssize_t write(int fildes, const void *buf, size_t nbyte) -{ - if (nbyte == 0) { - /* allow writing nothing to every FD ... */ - return 0; - } - else if (fildes == STDIN_FILENO) { - /* cannot write to STDIN */ - return -1; - } - else if (fildes == STDOUT_FILENO || fildes == STDERR_FILENO) { - return x86_uart_write(buf, nbyte); - } - - /* TODO: find appropriate FILE */ - (void) fildes; - (void) buf; - (void) nbyte; - return -1; -} diff --git a/cpu/x86/x86_interrupts.c b/cpu/x86/x86_interrupts.c deleted file mode 100644 index 86991e8a2cc865dac3f00b1fb3aa8512ab3830e3..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_interrupts.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - * 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-irq - * @{ - * - * @file - * @brief Interrupt entry points for x86. - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include <stdint.h> -#include <stdio.h> - -#include "kernel_defines.h" -#include "cpu.h" -#include "sched.h" -#include "thread.h" -#include "ucontext.h" - -#include "x86_interrupts.h" -#include "x86_memory.h" -#include "x86_ports.h" -#include "x86_registers.h" -#include "x86_threading.h" - - -#define ASM_FUN_ATTRIBUTES \ - __attribute__((noinline)) \ - __attribute__((no_instrument_function)) \ - __attribute__((optimize("Os", "omit-frame-pointer"))) - -static const char *const exception_name[X86_MAX_INTERRUPTS] = { - [0x00] = "Divide by zero", - [0x01] = "Debug", - [0x02] = "Non-maskable Interrupt", - [0x03] = "Breakpoint", - [0x04] = "Overflow", - [0x05] = "Bound range", - [0x06] = "Invalid Opcode", - [0x07] = "Device not available", - [0x08] = "Double Fault", - [0x09] = NULL, - [0x0a] = NULL, - [0x0b] = NULL, - [0x0c] = NULL, - [0x0d] = "General Protection Fault", - [0x0e] = "Page Fault", - [0x0f] = NULL, - [0x10] = "x87 Floating-Point Exception", - [0x11] = "Alignment Check", - [0x12] = "Machine Check", - [0x13] = NULL, - [0x14] = NULL, - [0x15] = NULL, - [0x16] = NULL, - [0x17] = NULL, - [0x18] = NULL, - [0x19] = NULL, - [0x1a] = NULL, - [0x1b] = NULL, - [0x1c] = NULL, - [0x1d] = NULL, - [0x1e] = NULL, - [0x1f] = NULL, - [0x20] = "PIC PIT", - [0x21] = "PIC KBC1", - [0x22] = NULL, - [0x23] = "PIC RS232 2/4", - [0x24] = "PIC RS232 1/3", - [0x25] = "PIC LPT2", - [0x26] = "PIC floppy", - [0x27] = "PIC LPT1", - [0x28] = "PIC RTC", - [0x29] = "PIC #9", - [0x2a] = "PIC ATA4", - [0x2b] = "PIC ATA3", - [0x2c] = "PIC KBC2", - [0x2d] = NULL, - [0x2e] = "PIC ATA1", - [0x2f] = "PIC ATA2", -}; - -uint8_t x86_current_interrupt; -unsigned long x86_current_interrupt_error_code; -struct x86_pushad x86_interrupted_ctx; -char x86_interrupt_handler_stack[2048]; - -static x86_intr_handler_t x86_registered_interrupts[X86_MAX_INTERRUPTS]; - -static void print_stacktrace(unsigned long bp, unsigned long ip) -{ - puts("<stack trace>"); - printf(" %08lx\n", ip); - for (unsigned max_depth = 0; max_depth < 30; ++max_depth) { - uint64_t pte = x86_get_pte(bp) & x86_get_pte(bp + 4); - if (!(pte & PT_P) || !(pte & PT_PWT)) { - puts(" ???"); - break; - } - - unsigned long *bp_ = (void *) bp; - ip = bp_[1]; - if (ip == 0) { - break; - } - printf(" %08lx\n", ip); - bp = bp_[0]; - if (bp == 0) { - break; - } - } - puts("</stack trace>"); -} - -void x86_print_registers(struct x86_pushad *orig_ctx, unsigned long error_code) -{ - unsigned long *sp = (void *) orig_ctx->sp; /* ip, cs, flags */ - printf("EAX=%08lx ECX=%08lx EDX=%08lx EBX=%08lx\n", orig_ctx->ax, orig_ctx->cx, orig_ctx->dx, orig_ctx->bx); - printf("ESP=%08lx EBP=%08lx ESI=%08lx EDI=%08lx\n", orig_ctx->sp, orig_ctx->bp, orig_ctx->si, orig_ctx->di); - printf("Error code=%08lx\n", error_code); - printf("CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n", cr0_read(), cr2_read(), cr3_read(), cr4_read()); - printf("EIP=%04lx:%08lx EFLAGS=%08lx\n", sp[1], sp[0], sp[2]); - - print_stacktrace(orig_ctx->bp, sp[0]); -} - -static void intr_handler_default(uint8_t intr_num, struct x86_pushad *orig_ctx, unsigned long error_code) -{ - printf("Unhandled interrupt 0x%02x (%s)\n", intr_num, exception_name[intr_num]); - x86_print_registers(orig_ctx, error_code); - puts("Halting."); - x86_hlt(); -} - -void x86_int_exit(void) NORETURN; - -static void continue_after_intr(void) -{ - ucontext_t *ctx = (ucontext_t *) sched_active_thread->sp; - x86_interrupted_ctx = ctx->uc_context.registers; - __asm__ volatile ( - "push %0\n" /* flags */ - "push $0x0008\n" /* cs */ - "push %1\n" /* ip */ - "jmp x86_int_exit" - :: "g"(ctx->__intr.flags), "g"(ctx->__intr.ip) - ); - __builtin_unreachable(); -} - -static unsigned in_intr_handler = 0, old_intr; -__attribute__((used)) void x86_int_handler(void) -{ - switch (in_intr_handler++) { - case 0: - break; - case 1: - printf("Interrupt 0x%02x (%s) while handling 0x%02x (%s)\n", - x86_current_interrupt, exception_name[x86_current_interrupt], - old_intr, exception_name[old_intr]); - x86_print_registers(&x86_interrupted_ctx, x86_current_interrupt_error_code); - puts("Halting."); - x86_hlt(); - default: - x86_hlt(); - } - old_intr = x86_current_interrupt; - - bool old_in_isr = x86_in_isr; - x86_in_isr = true; - - x86_intr_handler_t intr_handler = x86_registered_interrupts[x86_current_interrupt]; - (intr_handler ? intr_handler : intr_handler_default)(x86_current_interrupt, &x86_interrupted_ctx, x86_current_interrupt_error_code); - - --in_intr_handler; - - unsigned long *sp = (void *) x86_interrupted_ctx.sp; /* ip, cs, flags */ - if (!sched_context_switch_request || !(sp[2] & X86_IF)) { - x86_in_isr = old_in_isr; - return; - } - - ucontext_t *ctx = (ucontext_t *) sched_active_thread->sp; - ctx->uc_context.registers = x86_interrupted_ctx; - ctx->uc_stack.ss_sp = x86_interrupt_handler_stack; - ctx->uc_stack.ss_size = sizeof x86_interrupt_handler_stack; - __asm__ volatile ("pushf; pop %0" : "=g"(ctx->uc_context.flags)); - ctx->uc_context.ip = (void *) (uintptr_t) &continue_after_intr; - ctx->__intr.ip = sp[0]; - ctx->__intr.flags = sp[2]; - - thread_yield_higher(); - __builtin_unreachable(); -} - -__attribute__((used)) void ASM_FUN_ATTRIBUTES NORETURN x86_int_entry(void) -{ - __asm__ volatile ("mov %eax, (4*0 + x86_interrupted_ctx)"); - __asm__ volatile ("mov %ecx, (4*1 + x86_interrupted_ctx)"); - __asm__ volatile ("mov %edx, (4*2 + x86_interrupted_ctx)"); - __asm__ volatile ("mov %ebx, (4*3 + x86_interrupted_ctx)"); - __asm__ volatile ("mov %ebp, (4*5 + x86_interrupted_ctx)"); - __asm__ volatile ("mov %esi, (4*6 + x86_interrupted_ctx)"); - __asm__ volatile ("mov %edi, (4*7 + x86_interrupted_ctx)"); - - __asm__ volatile ("jnc 1f"); - __asm__ volatile (" mov (%esp), %eax"); - __asm__ volatile (" add $4, %esp"); - __asm__ volatile (" jmp 2f"); - __asm__ volatile ("1:"); - __asm__ volatile (" xor %eax, %eax"); - __asm__ volatile ("2:"); - __asm__ volatile (" mov %eax, x86_current_interrupt_error_code"); - - __asm__ volatile ("mov %esp, (4*4 + x86_interrupted_ctx)"); - __asm__ volatile ("mov %0, %%esp" :: "g"(&x86_interrupt_handler_stack[sizeof x86_interrupt_handler_stack])); - __asm__ volatile ("call x86_int_handler"); - __asm__ volatile ("jmp x86_int_exit"); - __builtin_unreachable(); -} - -__attribute__((used)) void ASM_FUN_ATTRIBUTES NORETURN x86_int_exit(void) -{ - __asm__ volatile ("mov (4*0 + x86_interrupted_ctx), %eax"); - __asm__ volatile ("mov (4*1 + x86_interrupted_ctx), %ecx"); - __asm__ volatile ("mov (4*2 + x86_interrupted_ctx), %edx"); - __asm__ volatile ("mov (4*3 + x86_interrupted_ctx), %ebx"); - __asm__ volatile ("mov (4*5 + x86_interrupted_ctx), %ebp"); - __asm__ volatile ("mov (4*6 + x86_interrupted_ctx), %esi"); - __asm__ volatile ("mov (4*7 + x86_interrupted_ctx), %edi"); - __asm__ volatile ("mov (4*4 + x86_interrupted_ctx), %esp"); - - __asm__ volatile ("iret"); - __builtin_unreachable(); -} - -#define DECLARE_INT(NUM, HAS_ERROR_CODE, MNEMONIC) \ - static void ASM_FUN_ATTRIBUTES NORETURN x86_int_entry_##NUM##h(void) \ - { \ - __asm__ volatile ("movb %0, x86_current_interrupt" :: "n"(0x##NUM)); \ - if ((HAS_ERROR_CODE)) { \ - __asm__ volatile ("stc"); \ - } \ - else { \ - __asm__ volatile ("clc"); \ - }\ - __asm__ volatile ("jmp x86_int_entry"); \ - __builtin_unreachable(); \ - } -DECLARE_INT(00, 0, "#DE") -DECLARE_INT(01, 0, "#DB") -DECLARE_INT(02, 0, "NMI") -DECLARE_INT(03, 0, "#BP") -DECLARE_INT(04, 0, "#OF") -DECLARE_INT(05, 0, "#BR") -DECLARE_INT(06, 0, "#UD") -DECLARE_INT(07, 0, "#NM") -DECLARE_INT(08, 1, "#DF") -DECLARE_INT(0d, 1, "#GP") -DECLARE_INT(0e, 1, "#PF") -DECLARE_INT(10, 0, "#MF") -DECLARE_INT(11, 1, "#AC") -DECLARE_INT(12, 0, "#MC") -DECLARE_INT(20, 0, "PIC PIT") -DECLARE_INT(21, 1, "PIC KBC1") -DECLARE_INT(23, 0, "PIC RS232 2/4") -DECLARE_INT(24, 0, "PIC RS232 1/3") -DECLARE_INT(25, 0, "PIC LPT2") -DECLARE_INT(26, 0, "PIC floppy") -DECLARE_INT(27, 0, "PIC LPT1") -DECLARE_INT(28, 0, "PIC RPC") -DECLARE_INT(29, 0, "PIC #9") -DECLARE_INT(2a, 0, "PIC ATA4") -DECLARE_INT(2b, 0, "PIC ATA3") -DECLARE_INT(2c, 0, "PIC KBC2") -DECLARE_INT(2e, 0, "PIC ATA1") -DECLARE_INT(2f, 0, "PIC ATA2") - -static struct idt_desc X86_IDT_ENTRIES[X86_MAX_INTERRUPTS]; -static struct idtr_t idtr = { - .limit = sizeof X86_IDT_ENTRIES, - .base = &X86_IDT_ENTRIES[0], -}; - -#define INTR_TEST_REG_AX (0xAA00AA00ul) -#define INTR_TEST_REG_DX (0x00DD00DDul) -#define INTR_TEST_REG_CX (0xC0C0C0C0ul) -#define INTR_TEST_REG_BX (0x0B0B0B0Bul) -#define INTR_TEST_REG_SI (0x00666600ul) -#define INTR_TEST_REG_DI (0x33000033ul) - -static void intr_handler_test_int_bp(uint8_t intr_num, struct x86_pushad *orig_ctx, unsigned long error_code) -{ - (void) error_code; - if (intr_num != X86_INT_BP || - orig_ctx->ax != INTR_TEST_REG_AX || - orig_ctx->dx != INTR_TEST_REG_DX || - orig_ctx->cx != INTR_TEST_REG_CX || - orig_ctx->bx != INTR_TEST_REG_BX || - orig_ctx->si != INTR_TEST_REG_SI || - orig_ctx->di != INTR_TEST_REG_DI - ) { - puts("Interrupt handler test failed (int 3, capture registers)."); - x86_hlt(); - } - orig_ctx->ax ^= -1; - orig_ctx->dx ^= -2; - orig_ctx->cx ^= -3; - orig_ctx->bx ^= -4; - orig_ctx->si ^= -5; - orig_ctx->di ^= -6; -} - -static void test_int_bp(void) -{ - x86_registered_interrupts[X86_INT_BP] = intr_handler_test_int_bp; - - unsigned long ax = INTR_TEST_REG_AX; - unsigned long dx = INTR_TEST_REG_DX; - unsigned long cx = INTR_TEST_REG_CX; - unsigned long bx = INTR_TEST_REG_BX; - unsigned long si; - unsigned long di; - unsigned long eflags_before, eflags_after; - __asm__ volatile ( - "mov %8, %%esi\n" - "mov %9, %%edi\n" - "pushf; pop %6\n" - "int3\n" - "pushf; pop %7\n" - "mov %%esi, %4\n" - "mov %%edi, %5\n" - : "+a"(ax), "+d"(dx), "+c"(cx), "+b"(bx), "=g"(si), "=g"(di), "=g"(eflags_before), "=g"(eflags_after) - : "n"(INTR_TEST_REG_SI), "n"(INTR_TEST_REG_DI) - : "esi", "edi" - ); - if (ax != (INTR_TEST_REG_AX ^ -1) || - dx != (INTR_TEST_REG_DX ^ -2) || - cx != (INTR_TEST_REG_CX ^ -3) || - bx != (INTR_TEST_REG_BX ^ -4) || - si != (INTR_TEST_REG_SI ^ -5) || - di != (INTR_TEST_REG_DI ^ -6) || - /* ignore EFLAGS.TF, hurts debugging */ - ((eflags_before != eflags_after) && ((eflags_before ^ eflags_after) != X86_TF)) - ) { - puts("Interrupt handler test failed (int 3, return code)."); - x86_hlt(); - } - - x86_registered_interrupts[X86_INT_BP] = NULL; -} - -static inline void __attribute__((always_inline)) set_idt_desc(void (*fun_)(void), unsigned num, unsigned pl) -{ - uintptr_t fun = (uintptr_t) fun_; - X86_IDT_ENTRIES[num] = (struct idt_desc) { - .offset_1 = fun & 0xffff, - .selector = 8, - .zero = 0, - .type_attr = 14 | (0 << 4) | (pl << 5) | (1 << 7), - .offset_2 = fun >> 16, - }; -} - -#define SET_IDT_DESC(NUM, HAS_ERROR_CODE, MNEMONIC, PL) \ - (set_idt_desc(x86_int_entry_##NUM##h, 0x##NUM, PL)); - -static void load_interrupt_descriptor_table(void) -{ - SET_IDT_DESC(00, 0, "#DE", 0) - SET_IDT_DESC(01, 0, "#DB", 0) - SET_IDT_DESC(02, 0, "NMI", 0) - SET_IDT_DESC(03, 0, "#BP", 3) - SET_IDT_DESC(04, 0, "#OF", 0) - SET_IDT_DESC(05, 0, "#BR", 0) - SET_IDT_DESC(06, 0, "#UD", 0) - SET_IDT_DESC(07, 0, "#NM", 0) - SET_IDT_DESC(08, 1, "#DF", 0) - SET_IDT_DESC(0d, 1, "#GP", 0) - SET_IDT_DESC(0e, 1, "#PF", 0) - SET_IDT_DESC(10, 0, "#MF", 0) - SET_IDT_DESC(11, 1, "#AC", 0) - SET_IDT_DESC(12, 0, "#MC", 0) - SET_IDT_DESC(20, 0, "PIC PIT", 0) - SET_IDT_DESC(21, 1, "PIC KBC1", 0) - SET_IDT_DESC(23, 0, "PIC RS232 2/4", 0) - SET_IDT_DESC(24, 0, "PIC RS232 1/3", 0) - SET_IDT_DESC(25, 0, "PIC LPT2", 0) - SET_IDT_DESC(26, 0, "PIC floppy", 0) - SET_IDT_DESC(27, 0, "PIC LPT1", 0) - SET_IDT_DESC(28, 0, "PIC RPC", 0) - SET_IDT_DESC(29, 0, "PIC #9", 0) - SET_IDT_DESC(2a, 0, "PIC ATA4", 0) - SET_IDT_DESC(2b, 0, "PIC ATA3", 0) - SET_IDT_DESC(2c, 0, "PIC KBC2", 0) - SET_IDT_DESC(2e, 0, "PIC ATA1", 0) - SET_IDT_DESC(2f, 0, "PIC ATA2", 0) - - __asm__ volatile ("lidt %0" :: "m"(idtr)); -} - -void x86_init_interrupts(void) -{ - load_interrupt_descriptor_table(); - test_int_bp(); - puts("Interrupt handling initialized"); -} - -void x86_interrupt_handler_set(unsigned num, x86_intr_handler_t handler) -{ - x86_registered_interrupts[num] = handler; -} diff --git a/cpu/x86/x86_memory.c b/cpu/x86/x86_memory.c deleted file mode 100644 index a1a2b6b190efa8e389ef1a5a3a1f225052a01ae1..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_memory.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - * 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 Virtual memory management. - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include "x86_kernel_memory.h" -#include "x86_interrupts.h" -#include "x86_memory.h" -#include "x86_registers.h" -#include "cpu.h" -#include "irq.h" -#include "tlsf-malloc.h" - -#include <malloc.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -/* Compare Figure 44 (p. 99) of "Intel® Quark SoC X1000 Core Developer’s Manual" */ -#define PT_CR3_BITS (0) -#define PT_PDPT_BITS (PT_P) -#define PT_PD_BITS (PT_P | PT_RW | PT_US) - -#ifndef DEBUG_READ_BEFORE_WRITE -# define PT_HEAP_BITS (PT_P | PT_RW | PT_US | pt_xd) -#else -# define PT_HEAP_BITS (PT_HEAP_BIT | PT_RW | PT_US | pt_xd) -#endif - -static uint64_t pt_xd = PT_XD; - -typedef union page { - char content[4096]; - uint64_t next_page; - uint64_t indices[512]; -} __attribute__((aligned(0x1000))) page_t; - -static volatile page_t TEMP_PAGE; -#define TEMP_PAGE_PT (((uintptr_t) &TEMP_PAGE / 0x1000) / 512) -#define TEMP_PAGE_PTE (((uintptr_t) &TEMP_PAGE / 0x1000) % 512) - -void x86_init_gdt(void) -{ - static const struct gdt_entry gdt_entries[3] = { - [0x0000 / 8] = { - .limit_0_15 = 0, - .base_0_15 = 0, - .base_16_23 = 0, - .access_byte = 0, - .limit_16_19_and_flags = 0, - .base_24_31 = 0, - }, - /* cppcheck-suppress duplicateExpression - * it's for consistent look & feel */ - [0x0008 / 8] = { - .limit_0_15 = 0xFFFF, - .base_0_15 = 0, - .base_16_23 = 0, - .access_byte = GDT_AB_EX | GDT_AB_S | GDT_AB_RING_0 | GDT_AB_PR, - .limit_16_19_and_flags = 0xF | GDT_FLAG_SZ | GDT_FLAG_GR, - .base_24_31 = 0, - }, - [0x0010 / 8] = { - .limit_0_15 = 0xFFFF, - .base_0_15 = 0, - .base_16_23 = 0, - .access_byte = GDT_AB_RW | GDT_AB_S | GDT_AB_RING_0 | GDT_AB_PR, - .limit_16_19_and_flags = 0xF | GDT_FLAG_SZ | GDT_FLAG_GR, - .base_24_31 = 0, - }, - }; - static const struct gdtr_t gdt = { - .size_minus_one = sizeof gdt_entries - 1, - .offset = (unsigned long) &gdt_entries[0], - }; - - __asm__ volatile ("" :: "a"(0x0010)); - - __asm__ volatile ("lgdt %0" :: "m"(gdt)); - __asm__ volatile ("ljmp $0x0008, $1f\n" - "1:"); - - __asm__ volatile ("mov %ax, %ds"); - __asm__ volatile ("mov %ax, %es"); - __asm__ volatile ("mov %ax, %fs"); - __asm__ volatile ("mov %ax, %gs"); - __asm__ volatile ("mov %ax, %ss"); -} - -/* Addresses in PDPT, PD, and PT are linear addresses. */ -/* TEMP_PAGE is used to to access these pages. */ -static pae_page_table_t static_pts[X86_NUM_STATIC_PT]; -static pae_page_directory_t static_pds[X86_NUM_STATIC_PD]; -static pae_page_directory_pointer_table_t pdpt; - -static void init_elf_static_section(uint64_t bits, void *start_, void *end_) -{ - unsigned long start = ((unsigned long) start_) / 0x1000; - unsigned long end = (((unsigned long) end_) + 0x1000 - 1) / 0x1000; - for (unsigned i = start; i < end; ++i) { - unsigned pt_num = i / 512; - unsigned pte_num = i % 512; - static_pts[pt_num][pte_num] = (i * 0x1000) | PT_P | PT_G | bits; - } -} - -static void check_requirements(void) -{ - uint64_t cpuid = cpuid_caps(); - if ((cpuid & CPUID_PAE) == 0) { - puts("Your CPU does not support PAE! Halting."); - x86_hlt(); - } - if ((cpuid & CPUID_PGE) == 0) { - puts("Your CPU does not support PGE! Halting."); - x86_hlt(); - } - if ((cpuid & CPUID_MSR) == 0) { - puts("Warning: Your CPU does not support MSR!\n" - " Setting PT_XD = 0."); - pt_xd = 0; - } - else { - /* enable NX bit (if possible) */ - uint64_t efer = msr_read(MSR_EFER); - efer |= EFER_NXE; - msr_set(MSR_EFER, efer); - if (!(msr_read(MSR_EFER) & EFER_NXE)) { - puts("Warning: Your hardware does not support the NX bit!\n" - " Setting PT_XD = 0."); - pt_xd = 0; - } - } -} - -static void init_pagetable(void) -{ - /* identity map tables */ - for (unsigned i = 0; i < X86_NUM_STATIC_PD; ++i) { - pdpt[i] = ((uintptr_t) &static_pds[i]) | PT_PDPT_BITS; - } - for (unsigned i = 0; i < X86_NUM_STATIC_PT; ++i) { - unsigned pd_num = i / 512; - unsigned pt_num = i % 512; - static_pds[pd_num][pt_num] = ((uintptr_t) &static_pts[i]) | PT_PD_BITS; - } - init_elf_static_section(PT_RW | pt_xd, (void *) 0, (void *) 0x100000); - init_elf_static_section(PT_US, &_section_text_start, &_section_text_end); - init_elf_static_section(PT_US | pt_xd, &_section_rodata_start, &_section_rodata_end); - init_elf_static_section(PT_US | PT_RW | pt_xd, &_section_data_start, &_section_bss_end); - - /* activate PAE */ - /* FIXME: add x86_init_cr4() */ - uint32_t cr4 = cr4_read(); - cr4 |= CR4_PAE | CR4_MCE | CR4_PGE | CR4_PCE | CR4_OSXMMEXCPT; - cr4 &= ~(CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_OSFXSR | CR4_SMEP); - cr4_write(cr4); - - /* load page table */ - cr3_write((uint32_t) &pdpt | PT_CR3_BITS); - - /* activate paging */ - uint32_t cr0 = cr0_read(); - cr0 |= CR0_PE | CR0_NE | CR0_WP | CR0_PG; - cr0 &= ~(CR0_MP | CR0_EM | CR0_TS | CR0_AM | CR0_NW | CR0_CD); - cr0_write(cr0); -} - -static void set_temp_page(uint64_t addr) -{ - static_pts[TEMP_PAGE_PT][TEMP_PAGE_PTE] = addr != -1ull ? addr | PT_P | PT_RW | pt_xd : 0; - __asm__ volatile ("invlpg (%0)" :: "r"(&TEMP_PAGE)); -} - -static inline uint64_t min64(uint64_t a, uint64_t b) -{ - return a <= b ? a : b; -} - -static inline uint64_t max64(uint64_t a, uint64_t b) -{ - return a >= b ? a : b; -} - -static uint32_t init_free_pages_heap_position = (uintptr_t) &_heap_start; - -static uint64_t init_free_pages_sub(uint64_t table, uint64_t bits, unsigned index, uint64_t *start, uint64_t *pos) -{ - set_temp_page(table); - if (TEMP_PAGE.indices[index] & PT_P) { - return TEMP_PAGE.indices[index] & PT_ADDR_MASK; - } - - TEMP_PAGE.indices[index] = *start | bits; - - uint64_t result = *start; - *start += 0x1000; - *pos = max64(*start, *pos); - init_free_pages_heap_position += 0x1000; - return result; -} - -static bool add_pages_to_pool(uint64_t start, uint64_t end) -{ - start += 0xFFF; - start &= ~0xFFF; - end &= ~0xFFF; - - start = max64(start, (uintptr_t) &_kernel_memory_end); - uint64_t pos = start; - - uint32_t addr = init_free_pages_heap_position >> 12; - unsigned pte_i = addr % 512; - addr >>= 9; - unsigned pt_i = addr % 512; - addr >>= 9; - unsigned pd_i = addr; - - if (pd_i >= 4) { - return false; - } - - while (pos < end) { - uint64_t table = (uintptr_t) &pdpt; - - table = init_free_pages_sub(table, PT_PDPT_BITS, pd_i, &start, &pos); - if (pos >= end) { - break; - } - - table = init_free_pages_sub(table, PT_PD_BITS, pt_i, &start, &pos); - if (pos >= end) { - break; - } - - set_temp_page(table); - TEMP_PAGE.indices[pte_i] = pos | PT_HEAP_BITS; - pos += 0x1000; - - if (++pte_i >= 512) { - pte_i = 0; - if (++pt_i >= 512) { - pt_i = 0; - if (++pd_i >= 4) { - break; - } - } - } - } - - if (start < end) { - cr3_write((uint32_t) &pdpt | PT_CR3_BITS); /* flush tlb */ - tlsf_add_pool((void *) init_free_pages_heap_position, end - start); - init_free_pages_heap_position += end - start; - } - - return true; -} - -static void init_free_pages(void) -{ - printf("Kernel memory: %p - %p\r\n", - (void *)&_kernel_memory_start, (void *)&_kernel_memory_end); - printf(" .text: %p - %p\r\n", (void *)&_section_text_start, (void *)&_section_text_end); - printf(" .rodata: %p - %p\r\n", (void *)&_section_rodata_start, (void *)&_section_rodata_end); - printf(" .data: %p - %p\r\n", (void *)&_section_data_start, (void *)&_section_data_end); - printf(" .bss: %p - %p\r\n", (void *)&_section_bss_start, (void *)&_section_bss_end); - printf("Unmapped memory: %p - %p\r\n", (void *)&_kernel_memory_end, (void *)&_heap_start); - printf("Heap start: %p\r\n", (void *)&_heap_start); - - unsigned long cnt = 0; - uint64_t start, len; - while (x86_get_memory_region(&start, &len, &cnt)) { - uint64_t end = start + len; - if (!add_pages_to_pool(start, end)) { - break; - } - } - - unsigned long free_pages_count = (init_free_pages_heap_position - (uintptr_t) &_heap_start) / 4096; - float mem_amount = free_pages_count * (4096 / 1024); - const char *mem_unit = "kB"; - if (mem_amount >= 2 * 1024) { - mem_amount /= 1024; - mem_unit = "MB"; - } - if (mem_amount >= 2 * 1024) { - mem_amount /= 1024; - mem_unit = "GB"; - } - printf("There are %lu free pages (%.3f %s) available for the heap.\n", free_pages_count, mem_amount, mem_unit); -} - -static unsigned handling_pf; -static void pagefault_handler(uint8_t intr_num, struct x86_pushad *orig_ctx, unsigned long error_code) -{ - (void) intr_num; /* intr_num == X86_INT_PF */ - - ++handling_pf; - - switch (handling_pf) { - case 1: - break; /* first #PF */ - - case 2: /* pagefault while handing a page fault. */ - puts("A page fault occured while handling a page fault!"); - x86_print_registers(orig_ctx, error_code); - puts("Halting."); - /* fall through */ - - default: /* pagefault while printing #PF message, everything is lost */ - x86_hlt(); - } - -#ifdef DEBUG_READ_BEFORE_WRITE - uint32_t virtual_addr = cr2_read(); - uint64_t pte = x86_get_pte(virtual_addr); -#endif - - if (error_code & PF_EC_I) { - puts("Page fault while fetching instruction."); - x86_print_registers(orig_ctx, error_code); - puts("Halting."); - x86_hlt(); - } -#ifdef DEBUG_READ_BEFORE_WRITE - else if ((pte != NO_PTE) && !(pte & PT_P) && (pte & PT_HEAP_BIT)) { - /* mark as present */ - TEMP_PAGE.indices[(virtual_addr >> 12) % 512] |= PT_P; - __asm__ volatile ("invlpg (%0)" :: "r"(virtual_addr)); - - /* initialize for easier debugging */ - uint32_t *p = (uint32_t *) (virtual_addr & ~0xfff); - for (unsigned i = 0; i < 0x1000 / 4; ++i) { - const union { - char str_value[4]; - uint32_t int_value; - } debug_init = { .str_value = "RIOT" }; - *p++ = debug_init.int_value; - } - - /* print a warning if the page was read before written */ - if (!(error_code & PF_EC_W)) { - unsigned long *sp = (void *) orig_ctx->sp; /* ip, cs, flags */ - printf("DEBUG: Read before write on heap address 0x%08x (physical: 0x%016llx) at 0x%08lx.\n", - virtual_addr, pte & PT_ADDR_MASK, sp[0]); - } - } -#endif - else if (error_code & PF_EC_P) { - printf("Page fault: access violation while %s present page.\n", (error_code & PF_EC_W) ? "writing to" : "reading from"); - x86_print_registers(orig_ctx, error_code); - puts("Halting."); - x86_hlt(); - } - else { - printf("Page fault: access violation while %s non-present page.\n", (error_code & PF_EC_W) ? "writing to" : "reading from"); - x86_print_registers(orig_ctx, error_code); - puts("Halting."); - x86_hlt(); - } - - --handling_pf; -} - -static void init_pagefault_handler(void) -{ - x86_interrupt_handler_set(X86_INT_PF, &pagefault_handler); -} - -void x86_init_memory(void) -{ - check_requirements(); - - init_pagetable(); - init_pagefault_handler(); - init_free_pages(); - - puts("Virtual memory initialized"); -} - -uint64_t x86_get_pte(uint32_t addr) -{ - addr >>= 12; - unsigned pte_i = addr % 512; - addr >>= 9; - unsigned pt_i = addr % 512; - addr >>= 9; - unsigned pd_i = addr; - - if (pdpt[pd_i] & PT_P) { - set_temp_page(pdpt[pd_i] & PT_ADDR_MASK); - if (TEMP_PAGE.indices[pt_i] & PT_P) { - set_temp_page(TEMP_PAGE.indices[pt_i] & PT_ADDR_MASK); - return TEMP_PAGE.indices[pte_i]; - } - } - return NO_PTE; -} - -static void virtual_pages_set_bits(uint32_t virtual_addr, unsigned pages, uint64_t bits) -{ - while (pages-- > 0) { - unsigned pte_i = (virtual_addr >> 12) % 512; - - uint64_t old_physical_addr = x86_get_pte(virtual_addr) & PT_ADDR_MASK; - TEMP_PAGE.indices[pte_i] = old_physical_addr | bits; - __asm__ volatile ("invlpg (%0)" :: "r"(virtual_addr)); - - virtual_addr += 0x1000; - } -} - -void *x86_map_physical_pages(uint64_t physical_start, unsigned pages, uint64_t bits) -{ - if (bits & PT_XD) { - bits &= ~PT_XD; - bits |= pt_xd; - } - - /* We use an already set up space, so we are sure that the upper level page tables are allocated. */ - /* We cut out a slice and re-add the physical pages. */ - char *result = memalign(0x1000, pages * 0x1000); - if (!result) { - return NULL; - } - - for (unsigned page = 0; page < pages; ++page) { - uint64_t physical_addr = physical_start + page * 0x1000; - uint32_t virtual_addr = (uintptr_t) result + page * 0x1000; - unsigned pte_i = (virtual_addr >> 12) % 512; - - uint64_t old_pte = x86_get_pte(virtual_addr); - TEMP_PAGE.indices[pte_i] = physical_addr | bits; - - if (page == 0) { - uint64_t old_physical_addr = old_pte & PT_ADDR_MASK; - - /* FIXME: does this work? Won't work if TLSF joins different buffers. */ - add_pages_to_pool(old_physical_addr, old_physical_addr + 0x1000 * pages); - } - } - - cr3_write((uint32_t) &pdpt | PT_CR3_BITS); /* flush tlb */ - return result; -} - -void *x86_get_virtual_pages(unsigned pages, uint64_t bits) -{ - if (bits & PT_XD) { - bits &= ~PT_XD; - bits |= pt_xd; - } - - char *result = memalign(0x1000, pages * 0x1000); - if (!result) { - return (void *) -1ul; - } - - virtual_pages_set_bits((uintptr_t) result, pages, bits); - return result; -} - -void x86_release_virtual_pages(uint32_t virtual_start, unsigned pages) -{ - virtual_pages_set_bits(virtual_start, pages, PT_HEAP_BITS); - free((void *) virtual_start); -} diff --git a/cpu/x86/x86_pci.c b/cpu/x86/x86_pci.c deleted file mode 100644 index ac9949d877daf1e5ca255132b518cbd335ffe266..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_pci.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * 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-irq - * @{ - * - * @file - * @brief PCI configuration and accessing. - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include "x86_memory.h" -#include "x86_pci.h" -#include "x86_pci_init.h" -#include "x86_pci_strings.h" -#include "x86_ports.h" - -#include <malloc.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -static struct x86_known_pci_device **known_pci_devices = NULL; -static unsigned num_known_pci_devices; - -static void set_addr(unsigned bus, unsigned dev, unsigned fun, unsigned reg) -{ - unsigned addr = PCI_IO_ENABLE - | (bus << PCI_IO_SHIFT_BUS) - | (dev << PCI_IO_SHIFT_DEV) - | (fun << PCI_IO_SHIFT_FUN) - | (reg << PCI_IO_SHIFT_REG); - outl(PCI_CONFIG_ADDRESS, addr); -} - -uint32_t x86_pci_read(unsigned bus, unsigned dev, unsigned fun, unsigned reg) -{ - set_addr(bus, dev, fun, reg); - return U32_PCItoH(inl(PCI_CONFIG_DATA)); -} - -uint8_t x86_pci_read8(unsigned bus, unsigned dev, unsigned fun, unsigned reg) -{ - set_addr(bus, dev, fun, reg); - return U8_PCItoH(inb(PCI_CONFIG_DATA)); -} - -uint16_t x86_pci_read16(unsigned bus, unsigned dev, unsigned fun, unsigned reg) -{ - set_addr(bus, dev, fun, reg); - return U16_PCItoH(inw(PCI_CONFIG_DATA)); -} - -static bool pci_vendor_id_valid(uint16_t vendor_id) -{ - return vendor_id != PCI_HEADER_VENDOR_ID_INVALID && - vendor_id != PCI_HEADER_VENDOR_ID_UNRESPONSIVE && - vendor_id != PCI_HEADER_VENDOR_ID_ABSENT; -} - -void x86_pci_write(unsigned bus, unsigned dev, unsigned fun, unsigned reg, uint32_t datum) -{ - set_addr(bus, dev, fun, reg); - outl(PCI_CONFIG_DATA, U32_HtoPCI(datum)); -} - -void x86_pci_write8(unsigned bus, unsigned dev, unsigned fun, unsigned reg, uint8_t datum) -{ - set_addr(bus, dev, fun, reg); - outb(PCI_CONFIG_DATA, U8_HtoPCI(datum)); -} - -void x86_pci_write16(unsigned bus, unsigned dev, unsigned fun, unsigned reg, uint16_t datum) -{ - set_addr(bus, dev, fun, reg); - outw(PCI_CONFIG_DATA, U16_HtoPCI(datum)); -} - -static unsigned pci_init_secondary_bus(unsigned bus, unsigned dev, unsigned fun) -{ - known_pci_devices[num_known_pci_devices - 1]->managed = true; - - /* TODO */ - printf(" TODO: pci_init_secondary_bus(0x%x, 0x%x, 0x%x)\n", bus, dev, fun); - (void) bus; - (void) dev; - (void) fun; - return 0; -} - -static void pci_setup_ios(struct x86_known_pci_device *dev) -{ - /* § 6.2.5. (pp. 224) */ - - unsigned bar_count = 0; - unsigned bar_base; - - unsigned header_type = x86_pci_read_reg(0x0c, dev->bus, dev->dev, dev->fun).header_type & PCI_HEADER_TYPE_MASK; - switch (header_type) { - case PCI_HEADER_TYPE_GENERAL_DEVICE: - bar_count = 6; - bar_base = 0x10; - break; - case PCI_HEADER_TYPE_BRIDGE: - bar_count = 2; - bar_base = 0x10; - break; - default: - printf(" Cannot configure header_type == 0x%02x, yet.\n", header_type); - return; - } - - for (unsigned bar_num = 0; bar_num < bar_count; ++bar_num) { - uint32_t old_bar = x86_pci_read(dev->bus, dev->dev, dev->fun, bar_base + 4 * bar_num); - if (old_bar == 0) { - continue; - } - - x86_pci_write(dev->bus, dev->dev, dev->fun, bar_base + 4 * bar_num, -1ul); - uint32_t tmp_bar = x86_pci_read(dev->bus, dev->dev, dev->fun, bar_base + 4 * bar_num); - x86_pci_write(dev->bus, dev->dev, dev->fun, bar_base + 4 * bar_num, old_bar); - if ((old_bar & PCI_BAR_IO_SPACE) != (tmp_bar & PCI_BAR_IO_SPACE)) { - /* cannot happen (?) */ - continue; - } - - dev->io = realloc(dev->io, sizeof (*dev->io) * (dev->io_count + 1)); - struct x86_pci_io *io = calloc(1, sizeof *io); - dev->io[dev->io_count] = io; - io->bar_num = bar_num; - ++dev->io_count; - - unsigned addr_offs = (tmp_bar & PCI_BAR_IO_SPACE) ? PCI_BAR_ADDR_OFFS_IO : PCI_BAR_ADDR_OFFS_MEM; - uint32_t length_tmp = tmp_bar >> addr_offs; - uint32_t length = 1 << addr_offs; - while ((length_tmp & 1) == 0) { - length <<= 1; - length_tmp >>= 1; - } - io->length = length; - - if (tmp_bar & PCI_BAR_IO_SPACE) { - io->type = PCI_IO_PORT; - io->addr.port = old_bar & ~((1 << PCI_BAR_ADDR_OFFS_IO) - 1); - printf(" BAR %u: I/O space, ports 0x%04x-0x%04x\n", - bar_num, io->addr.port, io->addr.port + length - 1); - } - else if ((old_bar & PCI_BAR_IO_SPACE) != PCI_BAR_SPACE_32 && (old_bar & PCI_BAR_IO_SPACE) != PCI_BAR_SPACE_64) { - printf(" BAR %u: memory with unknown location 0x%x, ERROR!\n", bar_num, (old_bar >> 1) & 3); - } - else { - uint32_t physical_start = old_bar & ~0xfff; - void *ptr = x86_map_physical_pages(physical_start, (length + 0xfff) / 0x1000, PT_P | PT_G | PT_RW | PT_PWT | PT_PCD | PT_XD); - if (!ptr) { - io->type = PCI_IO_INVALID; - printf(" BAR %u: memory, physical = 0x%08x-0x%08x, ERROR!\n", - bar_num, (unsigned) physical_start, physical_start + length - 1); - } - else { - io->type = PCI_IO_MEM; - io->addr.ptr = (char *) ptr + (old_bar & ~0xfff & ~((1 << PCI_BAR_ADDR_OFFS_MEM) - 1)); - printf(" BAR %u: memory, physical = 0x%08x-0x%08x, virtual = 0x%08x-0x%08x\n", - bar_num, - physical_start, physical_start + length - 1, - (unsigned) ptr, (unsigned) ((uintptr_t) ptr + length - 1)); - } - } - } -} - -static void pci_find_on_bus(unsigned bus); - -void x86_pci_set_irq(struct x86_known_pci_device *d, uint8_t irq_num) -{ - if (d->irq == irq_num) { - return; - } - - d->irq = irq_num; - uint32_t old_3c = x86_pci_read(d->bus, d->dev, d->fun, 0x3c); - x86_pci_write(d->bus, d->dev, d->fun, 0x3c, (old_3c & ~0xff) | d->irq); - - printf(" IRQ: new = %u, old = %u\n", d->irq, old_3c & 0xff); -} - -static void pci_find_function(unsigned bus, unsigned dev, unsigned fun) -{ - union pci_reg_0x00 vendor = x86_pci_read_reg(0x00, bus, dev, fun); - if (!pci_vendor_id_valid(vendor.vendor_id)) { - return; - } - - union pci_reg_0x08 class = x86_pci_read_reg(0x08, bus, dev, fun); - const char *baseclass_name, *subclass_name = x86_pci_subclass_to_string(class.baseclass, - class.subclass, - class.programming_interface, - &baseclass_name); - const char *vendor_name, *device_name = x86_pci_device_id_to_string(vendor.vendor_id, vendor.device_id, &vendor_name); - printf(" %02x:%02x.%x \"%s\": \"%s\" (%s: %s, rev: %02hhx)\n", - bus, dev, fun, vendor_name, device_name, baseclass_name, subclass_name, class.revision_id); - - /* cppcheck-suppress memleakOnRealloc - * (reason: TODO this is a bug) */ - known_pci_devices = realloc(known_pci_devices, sizeof (*known_pci_devices) * (num_known_pci_devices + 1)); - struct x86_known_pci_device *d = calloc(1, sizeof *d); - known_pci_devices[num_known_pci_devices] = d; - ++num_known_pci_devices; - - d->bus = bus; - d->dev = dev; - d->fun = fun; - d->vendor = vendor; - d->class = class; - d->managed = false; - - uint32_t old_3c = x86_pci_read(bus, dev, fun, 0x3c); - if (old_3c & 0xff) { - d->irq = PCI_IRQ_DEFAULT; - x86_pci_write(bus, dev, fun, 0x3c, (old_3c & ~0xff) | d->irq); - printf(" IRQ: new = %u, old = %u\n", d->irq, old_3c & 0xff); - } - - pci_setup_ios(d); - - if (class.baseclass == 0x06 && class.subclass == 0x04) { - unsigned secondary_bus = pci_init_secondary_bus(bus, dev, fun); - if (secondary_bus != 0) { - pci_find_on_bus(secondary_bus); - } - } -} - -static void pci_find_on_bus(unsigned bus) -{ - for (unsigned dev = 0; dev < PCI_DEV_COUNT; ++dev) { - if (!pci_vendor_id_valid(x86_pci_read_reg(0x00, bus, dev, 0).vendor_id)) { - continue; - } - - if (x86_pci_read_reg(0x0c, bus, dev, 0).header_type & PCI_HEADER_TYPE_MULTI_FUNCTION) { - for (unsigned fun = 0; fun < PCI_FUN_COUNT; ++fun) { - pci_find_function(bus, dev, fun); - } - } - else { - pci_find_function(bus, dev, 0); - } - } -} - -static void pci_find(void) -{ - if (x86_pci_read_reg(0x0c, 0, 0, 0).header_type & PCI_HEADER_TYPE_MULTI_FUNCTION) { - for (unsigned fun = 0; fun < PCI_FUN_COUNT; ++fun) { - if (pci_vendor_id_valid(x86_pci_read_reg(0x00, 0, 0, fun).vendor_id)) { - pci_find_on_bus(fun); - } - } - } - else { - pci_find_on_bus(0); - } -} - -static void irq_handler(uint8_t irq_num) -{ - for (unsigned i = 0; i < num_known_pci_devices; ++i) { - struct x86_known_pci_device *d = known_pci_devices[i]; - if (d->managed && d->irq_handler && d->irq == irq_num) { - d->irq_handler(d); - } - } -} - -void x86_init_pci(void) -{ - x86_pic_set_handler(PCI_IRQ_ACPI, irq_handler); - x86_pic_enable_irq(PCI_IRQ_ACPI); - x86_pic_set_handler(PCI_IRQ_NETWORKING, irq_handler); - x86_pic_enable_irq(PCI_IRQ_NETWORKING); - x86_pic_set_handler(PCI_IRQ_DEFAULT, irq_handler); - x86_pic_enable_irq(PCI_IRQ_DEFAULT); - x86_pic_set_handler(PCI_IRQ_USB, irq_handler); - x86_pic_enable_irq(PCI_IRQ_USB); - - puts("Looking up PCI devices"); - pci_find(); - - x86_init_pci_devices(); -} - -struct x86_known_pci_device **x86_enumerate_unmanaged_pci_devices(unsigned *index) -{ - while (*index < num_known_pci_devices) { - struct x86_known_pci_device **result = &known_pci_devices[*index]; - ++*index; - if (*result && !(**result).managed) { - return result; - } - } - return NULL; -} - -const struct x86_known_pci_device *x86_enumerate_pci_devices(unsigned *index) -{ - while (*index < num_known_pci_devices) { - struct x86_known_pci_device *result = known_pci_devices[*index]; - ++*index; - if (result) { - return result; - } - } - return NULL; -} diff --git a/cpu/x86/x86_pci_init.c b/cpu/x86/x86_pci_init.c deleted file mode 100644 index 8d828fa4b7af489231a949c889af991d371675c3..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_pci_init.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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-irq - * @{ - * - * @file - * @brief PCI device setup - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include "x86_pci.h" -#include "x86_pci_init.h" - -void x86_init_pci_devices(void) -{ - /* no PCI devices are implemented, yet */ -} diff --git a/cpu/x86/x86_pci_strings.c b/cpu/x86/x86_pci_strings.c deleted file mode 100644 index 436c4b319efcdac08a74b43639cf0f2ae4207745..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_pci_strings.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - * 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-irq - * @{ - * - * @file - * @brief String names of PCI classes, vendors, and devices. - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include "x86_pci_strings.h" - -#include <stdio.h> - -/* TODO: don't always include all strings */ - -const char *x86_pci_subclass_to_string(unsigned baseclass, unsigned subclass, unsigned interface, const char **baseclass_name) -{ - static char temp_baseclass_number[7], temp_subclass_number[7]; - - const char *baseclass_name_null; - if (!baseclass_name) { - baseclass_name = &baseclass_name_null; - } - - // "PCI LOCAL BUS SPECIFICATION, REV. 3.0"; Appendix D. - switch (baseclass) { - case 0x00: - *baseclass_name = "Device was built before Class Code definitions were finalized"; - switch (subclass) { - case 0x00: return "Non-VGA"; - case 0x01: return "VGA"; - } - break; - - case 0x01: - *baseclass_name = "Mass storage controller"; - switch (subclass) { - case 0x00: return "SCSI bus controller"; - case 0x01: return "IDE controller"; - case 0x02: return "Floppy disk controller"; - case 0x03: return "IPI bus controller"; - case 0x04: return "RAID controller"; - case 0x05: return "ATA controller"; - case 0x06: return "Serial ATA Direct Port Access"; - case 0x80: return "Other mass storage controller"; - } - break; - - case 0x02: - *baseclass_name = "Network controller"; - switch (subclass) { - case 0x00: return "Ethernet controller"; - case 0x01: return "Token Ring controller"; - case 0x02: return "FDDI controller"; - case 0x03: return "ATM controller"; - case 0x04: return "ISDN controller"; - case 0x05: return "WorldFip controller"; - case 0x06: return "PICMG 2.14 Multi Computing"; - case 0x80: return "Other network controller"; - } - break; - - case 0x03: - *baseclass_name = "Display controller"; - switch (subclass) { - case 0x00: switch (interface) { - case 0x00: return "VGA-compatible controller"; - case 0x01: return "8514-compatible controller"; - default: return "[UNDEFINED IN ACPI 3.0]"; - } - case 0x01: return "XGA coltroller"; - case 0x02: return "3D controller"; - case 0x80: return "Other display controller"; - } - break; - - case 0x04: - *baseclass_name = "Multimedia device"; - switch (subclass) { - case 0x00: return "Video device"; - case 0x01: return "Audio device"; - case 0x02: return "Computer telephony device"; - case 0x80: return "Other multimedia device"; - } - break; - - case 0x05: - *baseclass_name = "Memory controller"; - switch (subclass) { - case 0x00: return "RAM"; - case 0x01: return "Flash"; - case 0x80: return "Other memory controller"; - } - break; - - case 0x06: - *baseclass_name = "Bridge device"; - switch (subclass) { - case 0x00: return "Host bridge"; - case 0x01: return "ISA bridge"; - case 0x02: return "EISA bridge"; - case 0x03: return "MCA bridge"; - case 0x04: return "PCI-to-PCI bridge"; - case 0x05: return "PCMCIA bridge"; - case 0x06: return "NuBus bridge"; - case 0x07: return "CardBus bridge"; - case 0x08: return "RACEway bridge"; - case 0x09: return "Semi-transparent PCI-to-PCI bridge"; - case 0x0a: return "InfiniBand-to-PCI host bridge"; - case 0x80: return "Other bridge device"; - } - break; - - case 0x07: - *baseclass_name = "Simple communication controller"; - switch (subclass) { - case 0x00: - switch (interface) { - case 0x00: return "Generic XT-compatible serial controller"; - case 0x01: return "16450-compatible serial controller"; - case 0x02: return "16550-compatible serial controller"; - case 0x03: return "16650-compatible serial controller"; - case 0x04: return "16750-compatible serial controller"; - case 0x05: return "16850-compatible serial controller"; - case 0x06: return "16950-compatible serial controller"; - } - break; - case 0x01: - switch (interface) { - case 0x00: return "Parallel port"; - case 0x01: return "Bi-directional parallel port"; - case 0x02: return "ECP 1.X compliant parallel port"; - case 0x03: return "IEEE1284 controller"; - case 0xef: return "IEEE1284 target device"; - } - break; - case 0x02: return "Multiport serial controller"; - case 0x03: - switch (interface) { - case 0x00: return "Generic modem"; - case 0x01: return "Hayes compatible modem, 16450-compatible interface"; - case 0x02: return "Hayes compatible modem, 16550-compatible interface"; - case 0x03: return "Hayes compatible modem, 16650-compatible interface"; - case 0x04: return "Hayes compatible modem, 16750-compatible interface"; - } - break; - case 0x04: return "GPIB (IEEE 488.1/2) controller"; - case 0x05: return "Smart Card"; - case 0x80: return "Other communications device"; - } - break; - - case 0x08: - *baseclass_name = "Base system peripheral"; - switch (subclass) { - case 0x00: - switch (interface) { - case 0x00: return "Generic 8259 PIC"; - case 0x01: return "ISA PIC"; - case 0x02: return "EISA PIC"; - case 0x10: return "I/O APIC interrupt controller (see below)"; - case 0x20: return "I/O(x) APIC interrupt controller"; - } - break; - - case 0x01: - switch (interface) { - case 0x00: return "Generic 8237 DMA controller"; - case 0x01: return "ISA DMA controller"; - case 0x02: return "EISA DMA controller"; - } - break; - - case 0x02: - switch (interface) { - case 0x00: return "Generic 8254 system timer"; - case 0x01: return "ISA system timer"; - case 0x02: return "EISA system timers (two timers)"; - } - break; - - case 0x03: - switch (interface) { - case 0x00: return "Generic RTC controller"; - case 0x01: return "ISA RTC controller"; - } - break; - - case 0x04: return "Generic PCI Hot-Plug controller"; - case 0x80: return "Other system peripheral"; - } - break; - - case 0x09: - *baseclass_name = "Input device"; - switch (subclass) { - case 0x00: return "Keyboard controller"; - case 0x01: return "Digitizer (pen)"; - case 0x02: return "Mouse controller"; - case 0x03: return "Scanner controller"; - case 0x04: return "Gameport controller"; - case 0x80: return "Other input controller"; - } - break; - - case 0x0a: - *baseclass_name = "Docking station"; - switch (subclass) { - case 0x00: return "Generic docking station"; - case 0x80: return "Other type of docking station"; - } - break; - - case 0x0b: - *baseclass_name = "Processor"; - switch (subclass) { - case 0x00: return "386"; - case 0x01: return "486"; - case 0x02: return "Pentium"; - case 0x10: return "Alpha"; - case 0x20: return "PowerPC"; - case 0x30: return "MIPS"; - case 0x40: return "Co-processor"; - } - break; - - case 0x0c: - *baseclass_name = "Serial bus controller"; - switch (subclass) { - case 0x00: - switch (interface) { - case 0x00: return "IEEE 1394 (FireWire)"; - case 0x01: return "IEEE 1394 following the 1394 OpenHCI specification"; - } - break; - - case 0x01: return "ACCESS.bus"; - case 0x02: return "SSA"; - - case 0x03: - switch (interface) { - case 0x00: return "Universal Serial Bus (USB) following the Universal Host Controller Specification"; - case 0x10: return "Universal Serial Bus (USB) following the Open Host Controller Specification"; - case 0x20: return "USB2 host controller following the Intel Enhanced Host Controller Interface"; - case 0x80: return "Universal Serial Bus with no specific programming interface"; - case 0xfe: return "USB device"; - } - break; - - case 0x04: return "Fibre Channel"; - case 0x05: return "SMBus"; - case 0x06: return "InfiniBand"; - - case 0x07: - switch (interface) { - case 0x00: return "IPMI SMIC Interface"; - case 0x01: return "IPMI Kybd Controller Style Interface"; - case 0x02: return "IPMI Block Transfer Interface"; - } - break; - - case 0x08: return "SERCOS Interface Standard (IEC 61491)"; - case 0x09: return "CANbus"; - } - break; - - case 0x0d: - *baseclass_name = "Wireless controller"; - switch (subclass) { - case 0x00: return "iRDA compatible controller"; - case 0x01: return "Consumer IR controller"; - case 0x10: return "RF controller"; - case 0x11: return "Bluetooth"; - case 0x12: return "Broadband"; - case 0x20: return "Ethernet (802.11a)"; - case 0x21: return "Ethernet (802.11b)"; - case 0x80: return "Other type of wireless controller"; - } - break; - - case 0x0e: - *baseclass_name = "Intelligent I/O controller"; - switch (subclass) { - case 0x00: - switch (interface) { - case 0x00: return "Message FIFO at offset 040h"; - default: return "Intelligent I/O (I2O) Architecture Specification 1.0"; - } - break; - } - break; - - case 0x0f: - *baseclass_name = "Satellite communication controller"; - switch (subclass) { - case 0x01: return "TV"; - case 0x02: return "Audio"; - case 0x03: return "Voice"; - case 0x04: return "Data"; - } - break; - - case 0x10: - *baseclass_name = "Encryption/Decryption controller"; - switch (subclass) { - case 0x00: return "Network and computing en/decryption"; - case 0x10: return "Entertainment en/decryption"; - case 0x80: return "Other en/decryption"; - } - break; - - case 0x11: - *baseclass_name = "Data acquisition and signal processing controller"; - switch (subclass) { - case 0x00: return "DPIO modules"; - case 0x01: return "Performance counters"; - case 0x10: return "Communications synchronization plus time and frequency test/measurement"; - case 0x20: return "Management card"; - case 0x80: return "Other data acquisition/signal processing controllers"; - } - break; - - case 0xff: - *baseclass_name = "Other device"; - break; - - default: - snprintf(temp_baseclass_number, sizeof temp_baseclass_number, "0x%04x", baseclass); - *baseclass_name = temp_baseclass_number; - } - snprintf(temp_subclass_number, sizeof temp_subclass_number, "0x%04x", subclass); - return temp_subclass_number; -} - -const char *x86_pci_device_id_to_string(unsigned vendor_id, unsigned device_id, const char **vendor_name) -{ - static char temp_vendor_name[7], temp_device_name[7]; - - const char *vendor_name_null; - if (!vendor_name) { - vendor_name = &vendor_name_null; - } - - // http://pci-ids.ucw.cz/read/PC/ - // http://www.pcidatabase.com/ - switch (vendor_id) { - case 0x1013: - *vendor_name = "Cirrus Logic"; - switch (device_id) { - case 0x00b8: return "GD 5446"; - } - break; - - case 0x8086: - *vendor_name = "Intel Corporation"; - switch (device_id) { - case 0x100e: return "82540EM Gigabit Ethernet Controller"; - case 0x1237: return "440FX - 82441FX PMC [Natoma]"; - case 0x2415: return "82801AA AC'97 Audio Controller"; - case 0x2668: return "82801FB/FBM/FR/FW/FRW (ICH6 Family) HDA Controller"; - case 0x7000: return "82371SB PIIX3 ISA [Natoma/Triton II]"; - case 0x7010: return "82371SB PIIX3 IDE [Natoma/Triton II]"; - case 0x7020: return "82371SB PIIX3 USB [Natoma/Triton II]"; - case 0x7113: return "82371AB/EB/MB PIIX4 ACPI"; - - /* intel galileo */ - /* FIXME: find out the actual names ... */ - case 0x0958: return "Host Bridge"; - case 0x095E: return "Legacy Bridge"; - case 0x11C3: return "PCIe* Root Port 0"; - case 0x11C4: return "PCIe* Root Port 1"; - case 0x08A7: return "SDIO / eMMC Controller"; - case 0x0936: return "HS-UART"; - case 0x0939: return "USB 2.0 Device"; - case 0x093A: return "USB OHCI Host Controller"; - case 0x0937: return "10/100 Ethernet"; - case 0x0935: return "SPI Controller"; - case 0x0934: return "I2C* Controller and GPIO Controller"; - } - break; - - default: - snprintf(temp_vendor_name, sizeof temp_vendor_name, "0x%04x", vendor_id); - *vendor_name = temp_vendor_name; - } - snprintf(temp_device_name, sizeof temp_device_name, "0x%04x", device_id); - return temp_device_name; -} diff --git a/cpu/x86/x86_pic.c b/cpu/x86/x86_pic.c deleted file mode 100644 index 3dd5c18ffd56e3f9a5fe254e8b39d0940200a63c..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_pic.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * 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-irq - * @{ - * - * @file - * @brief Configuration and interrupt handling for the Programmable Interrupt Controller (PIC). - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include "x86_interrupts.h" -#include "x86_pic.h" -#include "x86_ports.h" -#include "cpu.h" -#include "irq.h" - -#include <stdio.h> - -static x86_irq_handler_t x86_registered_irqs[X86_IRQ_COUNT]; - -static const char *const IRQ_NAMES[X86_IRQ_COUNT] __attribute__((unused)) = { - "PIT", - "KBC 1", - NULL, - "COM 2/4", - "COM 1/3", - "LPT 2", - "FLOPPY", - "LPT 1", - "RTC", - "#9", - "ATA 4", - "ATA 3", - "KBC 2", - NULL, - "ATA 1", - "ATA 2", -}; - -static bool spurious_irq(uint8_t irq_num) -{ - if (irq_num < 8) { - outb(PIC_MASTER + PIC_COMMAND, PIC_READ_ISR); - return (inb(PIC_MASTER + PIC_COMMAND) & (1 << irq_num)) == 0; - } - - return false; -#if 0 /* TODO: does not work */ - irq_num -= 8; - outb(PIC_SLAVE + PIC_COMMAND, PIC_READ_ISR); - if (inb(PIC_SLAVE + PIC_COMMAND) & (1 << irq_num)) { - outb(PIC_MASTER + PIC_COMMAND, PIC_EOI); - return true; - } - return false; -#endif -} - -static void pic_interrupt_entry(uint8_t intr_num, struct x86_pushad *orig_ctx, unsigned long error_code) -{ - (void) error_code; - (void) orig_ctx; - - uint8_t irq_num = intr_num - PIC_MASTER_INTERRUPT_BASE; - if (spurious_irq(irq_num)) { - return; - } - - x86_irq_handler_t handler = x86_registered_irqs[irq_num]; - if (handler) { - handler(irq_num); - } - - outb(PIC_MASTER + PIC_COMMAND, PIC_EOI); - if (irq_num > 7) { - outb(PIC_SLAVE + PIC_COMMAND, PIC_EOI); - } -} - -static void pic_remap(void) -{ - /* tell both PICs we want to initialize them */ - outb(PIC_MASTER + PIC_COMMAND, PIC_ICW1_INIT + PIC_ICW1_ICW4); - io_wait(); - outb(PIC_SLAVE + PIC_COMMAND, PIC_ICW1_INIT + PIC_ICW1_ICW4); - io_wait(); - - /* which ISR should be called if an IRQ occurs */ - outb(PIC_MASTER + PIC_DATA, PIC_MASTER_INTERRUPT_BASE); - io_wait(); - outb(PIC_SLAVE + PIC_DATA, PIC_SLAVE_INTERRUPT_BASE); - io_wait(); - - /* IRQ of the master the slave talks to */ - outb(PIC_MASTER + PIC_DATA, 1 << PIC_NUM_SLAVE); - io_wait(); - outb(PIC_SLAVE + PIC_DATA, PIC_NUM_SLAVE); - io_wait(); - - /* use PC mode */ - outb(PIC_MASTER + PIC_DATA, PIC_ICW4_8086); - io_wait(); - outb(PIC_SLAVE + PIC_DATA, PIC_ICW4_8086); -} - -static void pic_register_handler(void) -{ - for (unsigned i = 0; i < X86_IRQ_COUNT; ++i) { - x86_interrupt_handler_set(PIC_MASTER_INTERRUPT_BASE + i, &pic_interrupt_entry); - } -} - -void x86_pic_set_enabled_irqs(uint16_t mask) -{ - unsigned old_status = irq_disable(); - - mask |= PIC_MASK_SLAVE; - mask &= ~PIC_MASK_FPU; - outb(PIC_MASTER + PIC_IMR, ~(uint8_t) mask); - io_wait(); - outb(PIC_SLAVE + PIC_IMR, ~(uint8_t) (mask >> 8)); - - irq_restore(old_status); -} - -void x86_pic_enable_irq(unsigned num) -{ - unsigned old_status = irq_disable(); - - uint16_t port; - if (num < 8) { - port = PIC_MASTER; - } - else { - num -= 8; - port = PIC_SLAVE; - } - uint8_t cur = inb(port + PIC_IMR); - outb(port + PIC_IMR, cur & ~(1 << num)); - - irq_restore(old_status); -} - -void x86_pic_disable_irq(unsigned num) -{ - unsigned old_status = irq_disable(); - - uint16_t port; - if (num < 8) { - port = PIC_MASTER; - } - else { - num -= 8; - port = PIC_SLAVE; - } - uint8_t cur = inb(port + PIC_IMR); - outb(port + PIC_IMR, cur | (1 << num)); - - irq_restore(old_status); -} - -void x86_init_pic(void) -{ - pic_register_handler(); - pic_remap(); - x86_pic_set_enabled_irqs(0); - - puts("PIC initialized"); -} - -void x86_pic_set_handler(unsigned irq, x86_irq_handler_t handler) -{ - x86_registered_irqs[irq] = handler; -} diff --git a/cpu/x86/x86_pit.c b/cpu/x86/x86_pit.c deleted file mode 100644 index 32984dd47aaec4bceadf9ad09507d9d49c99b2c9..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_pit.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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-irq - * @{ - * - * @file - * @brief Configuration and interrupt handling for the Programmable Interval Timer (PIT). - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include "x86_interrupts.h" -#include "x86_pit.h" -#include "x86_ports.h" -#include "cpu.h" -#include "irq.h" - -#include <stdio.h> - -void x86_init_pit(void) -{ - puts("PIT initialized"); -} - -uint16_t x86_pit_read(unsigned channel) -{ - unsigned old_flags = irq_disable(); - outb(PIT_COMMAND_PORT, (channel - 1) << 6 | PIT_ACCESS_MODE_LATCH_COUNT); - uint16_t lohi = inb(PIT_CHANNEL_0_PORT + channel - 1); - lohi += inb(PIT_CHANNEL_0_PORT + channel - 1) << 8; - irq_restore(old_flags); - return lohi; -} - -void x86_pit_set2(unsigned channel, unsigned mode, uint16_t max) -{ - unsigned old_flags = irq_disable(); - outb(PIT_COMMAND_PORT, ((channel - 1) << 6) | mode | PIT_ACCESS_MODE_LO_HI); - outb(PIT_CHANNEL_0_PORT + channel - 1, max & 0xff); - outb(PIT_CHANNEL_0_PORT + channel - 1, max >> 8); - irq_restore(old_flags); -} - -bool x86_pit_set(unsigned channel, unsigned mode, unsigned hz) -{ - if (PIT_MIN_HZ > hz || hz > PIT_MAX_HZ) { - return false; - } - - uint16_t max = PIT_MAX_HZ / hz; - x86_pit_set2(channel, mode, max); - return true; -} diff --git a/cpu/x86/x86_reboot.c b/cpu/x86/x86_reboot.c deleted file mode 100644 index 244f2057ee87e02e6a1d3c07c812384990148fb8..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_reboot.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de> - * 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 Configurable reboot handler for x86. - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * @author Kaspar Schleiser <kaspar@schleiser.de> - * - * @} - */ - -#include "x86_interrupts.h" -#include "x86_ports.h" -#include "x86_reboot.h" -#include "periph/pm.h" - -#define KBC_DATA (0x60) -#define KBC_STATUS (0x64) -#define KBC_COMMAND (0x64) - -#define KBC_OUTPUT_FULL (1u << 0) -#define KBC_INPUT_FULL (1u << 1) - -#define KBC_RESET ((uint8_t) ~(1u << 0)) - -static const struct idtr_t EMPTY_IDT = { - .limit = 0, - .base = NULL, -}; - -void x86_load_empty_idt(void) -{ - __asm__ volatile ("lidt %0" :: "m"(EMPTY_IDT)); -} - -static bool fail_violently; - -void NORETURN x86_kbc_reboot(void) -{ - /* First load an empty IDT. Any interrupt will cause a tripple fault. */ - x86_load_empty_idt(); - - while (1) { - if (fail_violently) { - __asm__ volatile ("int3"); /* Cause a tripple fault. Won't return. */ - } - fail_violently = true; - - for (unsigned i = 0; i < 0x100; ++i) { - for (unsigned j = 0; j < 0x10000; ++j) { - uint8_t c = inb(KBC_STATUS); - if (c & KBC_OUTPUT_FULL) { - (void) inb(KBC_DATA); - } - else if (!(c & KBC_OUTPUT_FULL)) { - outb(KBC_COMMAND, KBC_RESET); - break; - } - } - } - - __asm__ volatile ("int3"); /* Cause a tripple fault. Won't return. */ - } -} - -static x86_reboot_t reboot_fun; -static bool reboot_twice; - -void pm_reboot(void) -{ - __asm__ volatile ("cli"); - if (!reboot_twice) { - reboot_twice = true; - if (reboot_fun) { - reboot_fun(); - } - } - x86_kbc_reboot(); -} - -void pm_off(void) -{ - x86_shutdown(); -} - -void x86_set_reboot_fun(x86_reboot_t fun) -{ - reboot_fun = fun; -} - -static x86_shutdown_t shutdown_fun; - -bool x86_shutdown(void) -{ - if (!shutdown_fun) { - return false; - } - return shutdown_fun(); -} - -void x86_set_shutdown_fun(x86_shutdown_t fun) -{ - shutdown_fun = fun; -} diff --git a/cpu/x86/x86_rtc.c b/cpu/x86/x86_rtc.c deleted file mode 100644 index e03aa34d368da6d2ea825584d5a3d44bd5dff913..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_rtc.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * 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-irq - * @{ - * - * @file - * @brief Reading and interrupt handling for the Real Time Clock (RTC). - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include "x86_pic.h" -#include "x86_rtc.h" -#include "irq.h" - -#include <stdio.h> - - -#define ENABLE_DEBUG (0) -#include "debug.h" - -static bool valid; - -static int32_t alarm_msg_content, periodic_msg_content, update_msg_content; -static kernel_pid_t alarm_pid = KERNEL_PID_UNDEF, periodic_pid = KERNEL_PID_UNDEF, update_pid = KERNEL_PID_UNDEF; - -static void alarm_callback_default(uint8_t reg_c) -{ - if (alarm_pid != KERNEL_PID_UNDEF) { - msg_t m; - m.type = reg_c | (RTC_REG_B_INT_ALARM << 8); - m.content.value = alarm_msg_content; - msg_send_int(&m, alarm_pid); - } -} - -static void periodic_callback_default(uint8_t reg_c) -{ - if (periodic_pid != KERNEL_PID_UNDEF) { - msg_t m; - m.type = reg_c | (RTC_REG_B_INT_PERIODIC << 8); - m.content.value = periodic_msg_content; - msg_send_int(&m, periodic_pid); - } -} - -static void update_callback_default(uint8_t reg_c) -{ - if (update_pid != KERNEL_PID_UNDEF) { - msg_t m; - m.type = reg_c | (RTC_REG_B_INT_UPDATE << 8); - m.content.value = update_msg_content; - msg_send_int(&m, update_pid); - } -} - -static x86_rtc_callback_t alarm_callback = alarm_callback_default; -static x86_rtc_callback_t periodic_callback = periodic_callback_default; -static x86_rtc_callback_t update_callback = update_callback_default; - -void x86_rtc_set_alarm_callback(x86_rtc_callback_t cb) -{ - alarm_callback = cb ? cb : alarm_callback_default; -} - -void x86_rtc_set_periodic_callback(x86_rtc_callback_t cb) -{ - periodic_callback = cb ? cb : periodic_callback_default; -} - -void x86_rtc_set_update_callback(x86_rtc_callback_t cb) -{ - update_callback = cb ? cb : update_callback_default; -} - -static void rtc_irq_handler(uint8_t irq_num) -{ - (void) irq_num; /* == PIC_NUM_RTC */ - - uint8_t c = x86_cmos_read(RTC_REG_C); - DEBUG("RTC: c = 0x%02x, IRQ=%u, A=%u, P=%u, U=%u\n", c, (c & RTC_REG_C_IRQ) ? 1 : 0, - (c & RTC_REG_C_IRQ_ALARM) ? 1 : 0, - (c & RTC_REG_C_IRQ_PERIODIC) ? 1 : 0, - (c & RTC_REG_C_IRQ_UPDATE) ? 1 : 0); - if (!(c & RTC_REG_C_IRQ)) { - return; - } - if (c & RTC_REG_C_IRQ_ALARM) { - alarm_callback(c); - } - if (c & RTC_REG_C_IRQ_PERIODIC) { - periodic_callback(c); - } - if (c & RTC_REG_C_IRQ_UPDATE) { - update_callback(c); - } -} - -void x86_init_rtc(void) -{ - uint8_t d = x86_cmos_read(RTC_REG_D); - valid = (d & RTC_REG_D_VALID) != 0; - if (!valid) { - puts("Warning: RTC does not work."); - return; - } - - x86_cmos_write(RTC_REG_B, x86_cmos_read(RTC_REG_B) & ~RTC_REG_B_INT_MASK); - rtc_irq_handler(0); - x86_pic_set_handler(PIC_NUM_RTC, &rtc_irq_handler); - x86_pic_enable_irq(PIC_NUM_RTC); - - x86_rtc_data_t now; - x86_rtc_read(&now); - printf("RTC initialized [%02hhu:%02hhu:%02hhu, %04u-%02hhu-%02hhu]\n", - now.hour, now.minute, now.second, - now.century * 100 + now.year, now.month, now.day); - - if (x86_cmos_read(RTC_REG_POST) & (RTC_REG_POST_POWER_LOSS | RTC_REG_POST_TIME_INVALID)) { - puts("Warning: RTC time is invalid (power loss?)"); - } -} - -static inline bool is_update_in_progress(void) -{ - return (x86_cmos_read(RTC_REG_A) & RTC_REG_A_UPDATING) != 0; -} - -static uint8_t bcd2binary(uint8_t datum) -{ - return (datum / 16) * 10 + (datum % 16); -} - -static uint8_t binary2bcd(uint8_t datum) -{ - return (datum / 10) * 16 + (datum % 10); -} - -bool x86_rtc_read(x86_rtc_data_t *dest) -{ - if (!valid) { - return false; - } - - unsigned old_status = irq_disable(); - - while (is_update_in_progress()) { - __asm__ volatile ("pause"); - } - - uint8_t b = x86_cmos_read(RTC_REG_B); - do { - dest->second = x86_cmos_read(RTC_REG_SECOND); - dest->minute = x86_cmos_read(RTC_REG_MINUTE); - dest->hour = x86_cmos_read(RTC_REG_HOUR); - dest->day = x86_cmos_read(RTC_REG_DAY); - dest->month = x86_cmos_read(RTC_REG_MONTH); - dest->year = x86_cmos_read(RTC_REG_YEAR); - dest->century = bcd2binary(x86_cmos_read(RTC_REG_CENTURY)); - } while (dest->second != x86_cmos_read(RTC_REG_SECOND)); - if (dest->century == 0) { - dest->century = 20; // safe guess - } - - if (!(b & RTC_REG_B_BIN)) { - dest->second = bcd2binary(dest->second); - dest->minute = bcd2binary(dest->minute); - dest->hour = ((dest->hour & 0x0F) + (((dest->hour & 0x70) / 16) * 10)) | (dest->hour & 0x80); - dest->day = bcd2binary(dest->day); - dest->month = bcd2binary(dest->month); - dest->year = bcd2binary(dest->year); - } - if (!(b & RTC_REG_B_24H) && (dest->hour & 0x80)) { - dest->hour = ((dest->hour & 0x7F) + 12) % 24; - } - - irq_restore(old_status); - return true; -} - -bool x86_rtc_set_alarm(const x86_rtc_data_t *when, uint32_t msg_content, kernel_pid_t target_pid, bool allow_replace) -{ - if (!valid) { - return false; - } - - unsigned old_status = irq_disable(); - bool result; - if (target_pid == KERNEL_PID_UNDEF) { - result = true; - alarm_pid = KERNEL_PID_UNDEF; - - uint8_t b = x86_cmos_read(RTC_REG_B); - x86_cmos_write(RTC_REG_B, b & ~RTC_REG_B_INT_ALARM); - } - else { - result = allow_replace || alarm_pid == KERNEL_PID_UNDEF; - if (result) { - alarm_msg_content = msg_content; - alarm_pid = target_pid; - - uint8_t b = x86_cmos_read(RTC_REG_B); - if (b & RTC_REG_B_BIN) { - x86_cmos_write(RTC_REG_ALARM_SECOND, when->second); - x86_cmos_write(RTC_REG_ALARM_MINUTE, when->minute); - x86_cmos_write(RTC_REG_ALARM_HOUR, when->hour); - } - else { - x86_cmos_write(RTC_REG_ALARM_SECOND, binary2bcd(when->second)); - x86_cmos_write(RTC_REG_ALARM_MINUTE, binary2bcd(when->minute)); - x86_cmos_write(RTC_REG_ALARM_HOUR, binary2bcd(when->hour)); - } - x86_cmos_write(RTC_REG_B, b | RTC_REG_B_INT_ALARM); - } - } - rtc_irq_handler(0); - irq_restore(old_status); - return result; -} - -bool x86_rtc_set_periodic(uint8_t hz, uint32_t msg_content, kernel_pid_t target_pid, bool allow_replace) -{ - if (!valid) { - return false; - } - - unsigned old_status = irq_disable(); - bool result; - if (target_pid == KERNEL_PID_UNDEF || hz == RTC_REG_A_HZ_OFF) { - result = true; - periodic_pid = KERNEL_PID_UNDEF; - - uint8_t old_divider = x86_cmos_read(RTC_REG_A) & ~RTC_REG_A_HZ_MASK; - x86_cmos_write(RTC_REG_A, old_divider | RTC_REG_A_HZ_OFF); - x86_cmos_write(RTC_REG_B, x86_cmos_read(RTC_REG_B) & ~RTC_REG_B_INT_PERIODIC); - } - else { - result = allow_replace || periodic_pid == KERNEL_PID_UNDEF; - if (result) { - periodic_msg_content = msg_content; - periodic_pid = target_pid; - - uint8_t old_divider = x86_cmos_read(RTC_REG_A) & ~RTC_REG_A_HZ_MASK; - x86_cmos_write(RTC_REG_A, old_divider | hz); - x86_cmos_write(RTC_REG_B, x86_cmos_read(RTC_REG_B) | RTC_REG_B_INT_PERIODIC); - } - } - rtc_irq_handler(0); - irq_restore(old_status); - return result; -} - -bool x86_rtc_set_update(uint32_t msg_content, kernel_pid_t target_pid, bool allow_replace) -{ - if (!valid) { - return false; - } - - unsigned old_status = irq_disable(); - bool result; - if (target_pid == KERNEL_PID_UNDEF) { - result = true; - update_pid = KERNEL_PID_UNDEF; - - x86_cmos_write(RTC_REG_B, x86_cmos_read(RTC_REG_B) & ~RTC_REG_B_INT_UPDATE); - } - else { - result = allow_replace || update_pid == KERNEL_PID_UNDEF; - if (result) { - update_msg_content = msg_content; - update_pid = target_pid; - - x86_cmos_write(RTC_REG_B, x86_cmos_read(RTC_REG_B) | RTC_REG_B_INT_UPDATE); - } - } - rtc_irq_handler(0); - irq_restore(old_status); - return result; -} diff --git a/cpu/x86/x86_startup.c b/cpu/x86/x86_startup.c deleted file mode 100644 index 53663ec5d417ba60b826ec4746d5ddc371edcacc..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_startup.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 The common startup code for the x86 port. - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include "x86_interrupts.h" -#include "x86_memory.h" -#include "x86_pci.h" -#include "x86_pic.h" -#include "x86_pit.h" -#include "x86_rtc.h" -#include "x86_threading.h" -#include "x86_uart.h" - -#include <cpu.h> -#include <tlsf-malloc.h> - -#include <stdio.h> - -#include "kernel_init.h" - -/* Must be <= 0x1000 because otherwise x86_map_physical_pages() might get a page out of this pool. - * Because static memory has the PT_G flag, flushing the TLB would cause a stale PT - * after calling add_pages_to_pool() in x86_map_physical_pages(). - */ -static char early_malloc_pool[0x1000] __attribute__((aligned(4))); - -void x86_startup(void) -{ - tlsf_create_with_pool(early_malloc_pool, sizeof early_malloc_pool); - - x86_early_init_uart(); - x86_init_threading(); - x86_init_interrupts(); - x86_init_pic(); - x86_init_uart(); - x86_init_memory(); - x86_init_rtc(); - x86_init_pit(); - x86_init_pci(); - puts("RIOT x86 hardware initialization complete."); - - x86_init_board(); - puts("RIOT board initialization complete."); - - kernel_init(); /* should not return */ - puts("kernel_init returned"); - x86_hlt(); -} diff --git a/cpu/x86/x86_threading.c b/cpu/x86/x86_threading.c deleted file mode 100644 index 97c435bea29eddff84c0bdb5b432a26e54566ed8..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_threading.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * 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-multithreading - * @{ - * - * @file - * @brief Multi-thread management for x86. - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include "x86_interrupts.h" -#include "x86_reboot.h" -#include "x86_registers.h" -#include "x86_threading.h" -#include "cpu.h" -#include "irq.h" -#include "ucontext.h" -#include "sched.h" -#include "stdbool.h" -#include "thread.h" - -#define ENABLE_DEBUG (0) -#include "debug.h" - -static char isr_stack[SIGSTKSZ]; -static ucontext_t isr_context; - -static char end_stack[SIGSTKSZ]; -static ucontext_t end_context; - -bool x86_in_isr = true; - -static kernel_pid_t fpu_owner = KERNEL_PID_UNDEF; - -//static ucontext_t *cur_ctx, *isr_ctx; - -static struct x86_fxsave initial_fpu_state; - -int irq_is_in(void) -{ - return x86_in_isr; -} - -unsigned irq_disable(void) -{ - unsigned long eflags = x86_pushf_cli(); - return (eflags & X86_IF) != 0; -} - -unsigned irq_enable(void) -{ - unsigned long eflags; - __asm__ volatile ("pushf; pop %0; sti" : "=g"(eflags)); - return (eflags & X86_IF) != 0; -} - -void irq_restore(unsigned state) -{ - if (state) { - __asm__ volatile ("sti"); - } - else { - __asm__ volatile ("cli"); - } -} - -int irq_is_in(void); - -static void __attribute__((noreturn)) isr_thread_yield(void) -{ - sched_run(); - ucontext_t *ctx = (ucontext_t *) sched_active_thread->sp; - DEBUG("isr_thread_yield(): switching to (%s, %p)\n\n", sched_active_thread->name, ctx->uc_context.ip); - - uint32_t cr0 = cr0_read(); - cr0 |= CR0_TS; - cr0_write(cr0); - - x86_in_isr = false; - setcontext(ctx); -} - -void thread_yield_higher(void) -{ - if (x86_in_isr) { - isr_thread_yield(); - } - - unsigned old_intr = irq_disable(); - - x86_in_isr = true; - isr_context.uc_stack.ss_sp = isr_stack; - isr_context.uc_stack.ss_size = sizeof isr_stack; - makecontext(&isr_context, isr_thread_yield, 0); - swapcontext((ucontext_t *) sched_active_thread->sp, &isr_context); - - irq_restore(old_intr); -} - -void *thread_arch_isr_stack_pointer(void) -{ - return isr_context.uc_stack.ss_sp; -} - -void *thread_arch_isr_stack_start(void) -{ - return isr_stack; -} - -void isr_cpu_switch_context_exit(void) -{ - DEBUG("XXX: cpu_switch_context_exit(), num_tasks = %d\n", sched_num_threads); - - if (sched_num_threads <= 2) { - /* there is always "idle" and "x86-hwtimer" */ - DEBUG("cpu_switch_context_exit(): last task has ended. Shutting down.\n"); - x86_shutdown(); - } - - if ((sched_context_switch_request == 1) || (sched_active_thread == NULL)) { - sched_run(); - } - - ucontext_t *ctx = (ucontext_t *)(sched_active_thread->sp); - DEBUG("XXX: cpu_switch_context_exit(): calling setcontext(%s, %p)\n\n", sched_active_thread->name, ctx->uc_context.ip); - - x86_in_isr = false; - - setcontext(ctx); -} - -void cpu_switch_context_exit(void) -{ - irq_disable(); - - if (!x86_in_isr) { - x86_in_isr = true; - isr_context.uc_stack.ss_sp = isr_stack; - isr_context.uc_stack.ss_size = sizeof isr_stack; - makecontext(&isr_context, isr_cpu_switch_context_exit, 0); - setcontext(&isr_context); - } - else { - isr_cpu_switch_context_exit(); - } - __builtin_unreachable(); -} - -char *thread_stack_init(thread_task_func_t task_func, void *arg, void *stack_start, int stacksize) -{ - DEBUG("thread_stack_init()\n"); - - unsigned int *stk = stack_start; - - ucontext_t *p = (ucontext_t *)(stk + ((stacksize - sizeof(ucontext_t)) / sizeof(void *))); - stacksize -= sizeof(ucontext_t); - - getcontext(p); - p->uc_stack.ss_sp = stk; - p->uc_stack.ss_size = stacksize; - p->uc_link = &end_context; - p->uc_context.flags |= X86_IF; - p->__fxsave = initial_fpu_state; - makecontext(p, (makecontext_fun_t) task_func, 1, arg); - - return (char *) p; -} - -static void fpu_used_interrupt(uint8_t intr_num, struct x86_pushad *orig_ctx, unsigned long error_code) -{ - static volatile struct x86_fxsave fpu_data; - - (void) intr_num; - (void) orig_ctx; - (void) error_code; - - __asm__ volatile ("clts"); /* clear task switch flag */ - - if (fpu_owner == sched_active_pid) { - return; - } - - if (fpu_owner != KERNEL_PID_UNDEF) { - ucontext_t *ctx_owner = (ucontext_t *) sched_threads[fpu_owner]->sp; - __asm__ volatile ("fxsave (%0)" :: "r"(&fpu_data)); - ctx_owner->__fxsave = fpu_data; - } - - ucontext_t *ctx_active = (ucontext_t *) sched_active_thread->sp; - fpu_data = ctx_active->__fxsave; - __asm__ volatile ("fxrstor (%0)" :: "r"(&fpu_data)); - - fpu_owner = sched_active_pid; -} - -static void x86_thread_exit(void) -{ - irq_disable(); - if (fpu_owner == sched_active_pid) { - fpu_owner = KERNEL_PID_UNDEF; - } - sched_task_exit(); -} - -void x86_init_threading(void) -{ - getcontext(&end_context); - end_context.uc_stack.ss_sp = end_stack; - end_context.uc_stack.ss_size = sizeof end_stack; - makecontext(&end_context, x86_thread_exit, 0); - - x86_interrupt_handler_set(X86_INT_NM, fpu_used_interrupt); - __asm__ volatile ("fxsave (%0)" :: "r"(&initial_fpu_state)); - - DEBUG("Threading initialized\n"); -} diff --git a/cpu/x86/x86_uart.c b/cpu/x86/x86_uart.c deleted file mode 100644 index 4df080e1ee984dc3e992905276893271cd590c16..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_uart.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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-irq - * @{ - * - * @file - * @brief UART reading and writing. - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include "board.h" -#include "x86_ports.h" -#include "x86_uart.h" - -#include <cpu.h> - -#include <inttypes.h> -#include <stdint.h> -#include <stdio.h> - -void x86_early_init_uart(void) -{ - outb(UART_PORT + IER, 0x00); /* Disable all interrupts */ - - outb(UART_PORT + LCR, LCR_DLAB); - outb(UART_PORT + DLL, BAUD_LL); /* Set divisor (lo byte) */ - outb(UART_PORT + DLH, BAUD_HL); /* (hi byte) */ - outb(UART_PORT + LCR, LCR_WORD_BITS_8 | LCR_PAR_NONE | LCR_STOP_BITS_1); - outb(UART_PORT + FCR, FCR_ENABLE | FCR_CLR_RECV | FCR_CLR_SEND | FCR_TRIGGER_16); - outb(UART_PORT + MCR, MCR_DSR | MCR_RTS | MCR_AUX2); -} - -static bool is_output_empty(void) -{ - uint8_t data = inb(UART_PORT + LSR); - return (data & 0x20) != 0; -} - -static bool is_input_empty(void) -{ - uint8_t data = inb(UART_PORT + LSR); - return (data & 0x01) == 0; -} - -ssize_t x86_uart_write(const char *buf, size_t len) -{ - if (!UART_PORT) { - return -1; - } - (void) buf; - - size_t written = 0; - while (written < len) { - while (!is_output_empty()) { - __asm__ volatile ("pause"); - } - outb(UART_PORT + THR, buf[written]); - ++written; - } - return written; -} - -ssize_t x86_uart_read(char *buf, size_t len) -{ - if (!UART_PORT) { - return -1; - } - - size_t read = 0; - while (read < len) { - while (!is_input_empty()) { - __asm__ volatile ("pause"); - } - buf[read] = inb(UART_PORT + RBR); - ++read; - } - return read; -} - -void x86_init_uart(void) -{ -} diff --git a/cpu/x86/x86_ucontext.c b/cpu/x86/x86_ucontext.c deleted file mode 100644 index b6ca00247d0b6ffc5d72e75106b3315894a8d292..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_ucontext.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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-multithreading - * @{ - * - * @file - * @brief Coroutine helper functions. - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include <ucontext.h> - -#include <stdarg.h> - -int __attribute__((optimize("omit-frame-pointer"), no_instrument_function)) getcontext(ucontext_t *ucp) -{ - __asm__ volatile ("pushf\n" :: "a"(ucp)); - __asm__ volatile ("pop 4*2(%eax)\n"); - - __asm__ volatile ("mov %eax, 4*3(%eax)\n"); - __asm__ volatile ("mov %ecx, 4*4(%eax)\n"); - __asm__ volatile ("mov %edx, 4*5(%eax)\n"); - __asm__ volatile ("mov %ebx, 4*6(%eax)\n"); - /* __asm__ volatile ("mov %esp, 4*7(%eax)\n"); omitted */ - __asm__ volatile ("mov %ebp, 4*8(%eax)\n"); - __asm__ volatile ("mov %esi, 4*9(%eax)\n"); - __asm__ volatile ("mov %edi, 4*10(%eax)\n"); - - __asm__ volatile ("lea 4(%esp), %edx\n"); - __asm__ volatile ("mov %edx, 4*0(%eax)\n"); - __asm__ volatile ("xor %edx, %edx\n"); - __asm__ volatile ("mov %edx, 4*1(%eax)\n"); - - __asm__ volatile ("mov (%esp), %edx\n"); - __asm__ volatile ("mov %edx, 4*11(%eax)\n"); - - return 0; -} - -int __attribute__((optimize("omit-frame-pointer"), no_instrument_function)) setcontext(const ucontext_t *ucp) -{ - __asm__ volatile ("1:\n" :: "a"(ucp)); - - /* __asm__ volatile ("mov 4*3(%eax), %eax\n");, omitted */ - __asm__ volatile ("mov 4*4(%eax), %ecx\n"); - /* __asm__ volatile ("mov 4*5(%eax), %edx\n");, omitted */ - __asm__ volatile ("mov 4*6(%eax), %ebx\n"); - /* __asm__ volatile ("mov 4*7(%eax), %esp\n");, omitted */ - __asm__ volatile ("mov 4*8(%eax), %ebp\n"); - __asm__ volatile ("mov 4*9(%eax), %esi\n"); - __asm__ volatile ("mov 4*10(%eax), %edi\n"); - - __asm__ volatile ("mov 4*0(%eax), %esp\n"); - __asm__ volatile ("add 4*1(%eax), %esp\n"); - - __asm__ volatile ("mov 4*11(%eax), %edx\n"); - __asm__ volatile ("mov %eax, %ebx\n"); - - __asm__ volatile ("push 4*2(%eax)\n"); - __asm__ volatile ("popf\n"); - - __asm__ volatile ("call *%edx\n"); - - __asm__ volatile ("mov 4*12(%ebx), %eax\n"); - __asm__ volatile ("jmp 1b\n"); - __builtin_unreachable(); -} - -static void __attribute__((optimize("omit-frame-pointer"), noreturn, no_instrument_function)) makecontext_entrypoint(void) -{ - /* ebx = ucp, ecx = argc, ebp = arg[0], esi = arg[1], edi = arg[2] */ - __asm__ volatile ("mov 4*3(%ebx), %eax\n"); /* eax = func */ - - __asm__ volatile ("jecxz 0f\n"); - __asm__ volatile ("cmpb $1, %cl; je 1f\n"); - __asm__ volatile ("cmpb $2, %cl; je 2f\n"); - __asm__ volatile ("cmpb $3, %cl; je 3f\n"); - __asm__ volatile ("cmpb $4, %cl; je 4f\n"); - - __asm__ volatile (" mov 4*7(%ebx), %edx; push %edx\n"); - __asm__ volatile ("4: mov 4*5(%ebx), %edx; push %edx\n"); - __asm__ volatile ("3: push %edi\n"); - __asm__ volatile ("2: push %esi\n"); - __asm__ volatile ("1: push %ebp\n"); - __asm__ volatile ("0: call *%eax\n"); /* call func(...), preserves ebx */ - - __asm__ volatile ("mov 4*12(%ebx), %eax\n"); - __asm__ volatile ("push %eax\n"); - __asm__ volatile ("call setcontext\n"); - __builtin_unreachable(); -} - -void makecontext(ucontext_t *ucp, makecontext_fun_t func, int argc, ...) -{ - ucp->uc_context.ip = (void *) (unsigned long) &makecontext_entrypoint; - ucp->uc_context.registers.bx = (unsigned long) ucp; - - ucp->uc_context.registers.ax = (unsigned long) func; - ucp->uc_context.registers.cx = argc > 0 ? argc : 0; - - if (argc <= 0) { - return; - } - - unsigned long *arg_registers[5] = { - &ucp->uc_context.registers.bp, - &ucp->uc_context.registers.si, - &ucp->uc_context.registers.di, - &ucp->uc_context.registers.dx, - &ucp->uc_context.registers.sp, - }; - va_list ap; - va_start(ap, argc); - for (int i = 0; i < argc; ++i) { - *arg_registers[i] = va_arg(ap, unsigned long); - } - va_end(ap); -} - -int swapcontext(ucontext_t *oucp, const ucontext_t *ucp) -{ - /* Valid sentinel: an address in .text section is not valid for a stack pointer. */ - oucp->uc_context.registers.sp = (unsigned long) &swapcontext; - getcontext(oucp); - if (oucp->uc_context.registers.sp == (unsigned long) &swapcontext) { - oucp->uc_context.registers.sp = 0; - setcontext(ucp); - } - return 0; -} diff --git a/cpu/x86/x86_videoram.c b/cpu/x86/x86_videoram.c deleted file mode 100644 index fac5354afe2b2d50be3402677a37c7b18fbe8016..0000000000000000000000000000000000000000 --- a/cpu/x86/x86_videoram.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 Trivial functions to write to the videoram. - * - * @author René Kijewski <rene.kijewski@fu-berlin.de> - * - * @} - */ - -#include "x86_videoram.h" - -#define VIDEORAM ((char *) 0xB8000) - -void videoram_putc(char c) -{ - static unsigned pos = 0; - if (c == '\n') { - pos += 80; - } - else if (c == '\r') { - pos = (pos / 80) * 80; - } - else { - VIDEORAM[2 * pos + 0] = c; - VIDEORAM[2 * pos + 1] = (char) 0x9E; /* light blue bg, light yellow fg */ - ++pos; - } - if (pos >= 25 * 80) { - pos = 0; - } -} - -void videoram_put(const char *s) -{ - for (; *s; ++s) { - videoram_putc(*s); - } -} - -void videoram_puts(const char *s) -{ - videoram_put(s); - videoram_put("\r\n"); -} - -void videoram_put_hex(unsigned long v) -{ - char s[2 + 2 * sizeof v + 1]; - char *p = &s[sizeof s]; - - *--p = 0; - do { - char c = v % 16; - v /= 16; - *--p = c + (c < 10 ? '0' : 'A' - 10); - } while (v > 0); - *--p = 'x'; - *--p = '0'; - - videoram_put(p); -}