add kernel panic utility
This also includes some minor rearrangements in terms of which header files define what.
This commit is contained in:
parent
abd9bb5d43
commit
24c6e9504d
11 changed files with 136 additions and 30 deletions
|
@ -6,19 +6,6 @@
|
|||
#include <gay/cdefs.h>
|
||||
#include <gay/types.h>
|
||||
|
||||
static __always_inline void __spin_loop(void)
|
||||
{
|
||||
/*
|
||||
* Intel says you're supposed to put this in tight spin loops as a
|
||||
* workaround for their buggy memory order violation prediction or
|
||||
* something. They also claim that it significantly reduces power
|
||||
* consumption, whatever, i don't care.
|
||||
*/
|
||||
__asm__ volatile("pause" ::: "memory");
|
||||
}
|
||||
/** @brief Use this macro to build spin-wait loops. */
|
||||
#define spin_loop for (;; __spin_loop())
|
||||
|
||||
/**
|
||||
* @brief Read an atom's current value.
|
||||
* You usually shouldn't need this function because all the other atomic
|
||||
|
|
91
arch/x86/include/arch/cpufunc.h
Normal file
91
arch/x86/include/arch/cpufunc.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/* See the end of this file for copyright and license terms. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gay/cdefs.h>
|
||||
#include <gay/types.h>
|
||||
|
||||
static __always_inline void enable_intr(void)
|
||||
{
|
||||
__asm__ volatile("sti");
|
||||
}
|
||||
|
||||
static __always_inline void disable_intr(void)
|
||||
{
|
||||
__asm__ volatile("cli" ::: "memory");
|
||||
}
|
||||
|
||||
static inline register_t read_flags(void)
|
||||
{
|
||||
register_t flags;
|
||||
|
||||
#ifdef __x86_64__
|
||||
__asm__(
|
||||
" pushfq \n"
|
||||
" popq %0 \n"
|
||||
: "=r"(flags)
|
||||
);
|
||||
#else
|
||||
__asm__(
|
||||
" pushfl \n"
|
||||
" popl %0 \n"
|
||||
: "=r"(flags)
|
||||
);
|
||||
#endif
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Temporarily disable interrupts.
|
||||
*
|
||||
* It should be noted that yes, there is also `disable_intr()`, which does the
|
||||
* exact same thing except it has no return value. This is yet another instance
|
||||
* of me finding it funny to cause unnecessary confusion, but this time it's
|
||||
* also because FreeBSD uses the same unfortunate naming scheme.
|
||||
*
|
||||
* @return The contents of the status register before disabling interrupts.
|
||||
* This should be passed to `intr_restore()` after the atomic operation
|
||||
* is complete so that the interrupt enable flag can be restored to what
|
||||
* it was before.
|
||||
*/
|
||||
static inline register_t intr_disable(void)
|
||||
{
|
||||
register_t eflags = read_flags();
|
||||
disable_intr();
|
||||
return eflags;
|
||||
}
|
||||
|
||||
static inline void intr_restore(register_t flags)
|
||||
{
|
||||
/* bit 9 is IF (Interrupt Enable Flag) */
|
||||
if (flags & (1 << 9))
|
||||
enable_intr();
|
||||
}
|
||||
|
||||
static __always_inline void halt(void)
|
||||
{
|
||||
__asm__ volatile("hlt");
|
||||
}
|
||||
|
||||
static __always_inline void x86_pause(void)
|
||||
{
|
||||
__asm__ volatile("pause");
|
||||
}
|
||||
|
||||
/** @brief Use this macro to build spin-wait loops. */
|
||||
#define spin_loop for (;; x86_pause())
|
||||
|
||||
/*
|
||||
* This file is part of GayBSD.
|
||||
* Copyright (c) 2021 fef <owo@fef.moe>.
|
||||
*
|
||||
* GayBSD is nonviolent software: you may only use, redistribute, and/or
|
||||
* modify it under the terms of the Cooperative Nonviolent Public License
|
||||
* (CNPL) as found in the LICENSE file in the source code root directory
|
||||
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
|
||||
* of the license, or (at your option) any later version.
|
||||
*
|
||||
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
|
||||
* permitted by applicable law. See the CNPL for details.
|
||||
*/
|
|
@ -6,8 +6,8 @@
|
|||
#define X86_INTR_COUNT 256
|
||||
|
||||
/*
|
||||
* These are all reserved interrupt/exception vector numbers for x86 Protected Mode.
|
||||
* Taken from the Intel Architecture Software Developer's Manual, vol. 3, table 6-1.
|
||||
* These are all reserved interrupt/exception vector numbers for x86 Protected
|
||||
* and Long Mode. Taken from the Intel SDM vol 3, sec 6.3.1, tbl 6-1.
|
||||
*/
|
||||
|
||||
/** @brief Divide Error */
|
||||
|
@ -66,16 +66,6 @@
|
|||
#include <gay/cdefs.h>
|
||||
#include <gay/types.h>
|
||||
|
||||
static __always_inline void enable_intr(void)
|
||||
{
|
||||
__asm__ volatile("sti");
|
||||
}
|
||||
|
||||
static __always_inline void disable_intr(void)
|
||||
{
|
||||
__asm__ volatile("cli" ::: "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A single entry in the Interrupt Descriptor Table as laid out in hardware.
|
||||
* Luckily, this is not quite as deranged as the GDT layout.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* See the end of this file for copyright and license terms. */
|
||||
|
||||
#include <arch/cpufunc.h>
|
||||
#include <arch/interrupt.h>
|
||||
#include <arch/port.h>
|
||||
#include <arch/segment.h>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* <https://wiki.osdev.org/PIC>
|
||||
*/
|
||||
|
||||
#include <arch/cpufunc.h>
|
||||
#include <arch/irq.h>
|
||||
#include <arch/port.h>
|
||||
#include <arch/trap.h>
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
*/
|
||||
#define __alloc_size(argn) __attribute__(( alloc_size(argn) ))
|
||||
|
||||
#define __noreturn __attribute__(( noreturn ))
|
||||
|
||||
/**
|
||||
* @brief Hint that the returned pointer will be able to hold at least as much
|
||||
* bytes as the product of the arguments `argn1` and `argn2` (counting from 1).
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <arch/sched.h>
|
||||
#include <arch/smp.h>
|
||||
|
||||
#include <gay/cdefs.h>
|
||||
#include <gay/clist.h>
|
||||
|
@ -38,15 +39,16 @@ struct task {
|
|||
* For the same reason, don't assign values to this directly, and use
|
||||
* `set_current()` instead.
|
||||
*/
|
||||
extern struct task *current;
|
||||
extern struct task *current_array[CFG_MAX_CPU];
|
||||
#define current (current_array[smp_cpuid()])
|
||||
|
||||
/**
|
||||
* @brief Update the `current` task.
|
||||
* You will almost never need this because `switch_to()` does it automatically.
|
||||
*/
|
||||
__always_inline void set_current(struct task *task)
|
||||
static inline void set_current(struct task *task)
|
||||
{
|
||||
current = task;
|
||||
current_array[smp_cpuid()] = task;
|
||||
}
|
||||
|
||||
extern struct task kernel_task;
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <gay/cdefs.h>
|
||||
#include <gay/types.h>
|
||||
|
||||
void panic(const char *fmt, ...) __noreturn;
|
||||
|
||||
/**
|
||||
* @brief Get the number of elements in a statically allocated array.
|
||||
*
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* See the end of this file for copyright and license terms. */
|
||||
|
||||
#include <arch/atom.h>
|
||||
#include <arch/cpufunc.h>
|
||||
|
||||
#include <gay/clist.h>
|
||||
#include <gay/irq.h>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* See the end of this file for copyright and license terms. */
|
||||
|
||||
#include <arch/interrupt.h>
|
||||
#include <arch/cpufunc.h>
|
||||
#include <arch/sched.h>
|
||||
|
||||
#include <gay/clist.h>
|
||||
|
@ -13,7 +13,9 @@ struct task kernel_task = {
|
|||
.state = TASK_READY,
|
||||
};
|
||||
|
||||
struct task *current = &kernel_task;
|
||||
struct task *current_array[CFG_MAX_CPU] = {
|
||||
&kernel_task,
|
||||
};
|
||||
|
||||
/*
|
||||
* Two run queues, one active and one inactive. The scheduler takes tasks out
|
||||
|
|
|
@ -1,8 +1,35 @@
|
|||
/* See the end of this file for copyright and license terms. */
|
||||
|
||||
#include <arch/cpufunc.h>
|
||||
|
||||
#include <gay/kprintf.h>
|
||||
#include <gay/types.h>
|
||||
#include <gay/util.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
void panic(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
disable_intr();
|
||||
|
||||
kprintf("Kernel panic: ");
|
||||
if (fmt == nil)
|
||||
kprintf("(nil)\n");
|
||||
else
|
||||
kvprintf(fmt, args);
|
||||
|
||||
kprintf("\nSystem halted");
|
||||
|
||||
/* no need for va_end() here i guess */
|
||||
while (1) {
|
||||
halt();
|
||||
disable_intr();
|
||||
}
|
||||
}
|
||||
|
||||
void *ptr_align(void *ptr, int log)
|
||||
{
|
||||
uintptr_t shifted = 1 << abs(log);
|
||||
|
|
Loading…
Reference in a new issue