add kernel panic utility

This also includes some minor rearrangements in
terms of which header files define what.
main
anna 3 years ago
parent abd9bb5d43
commit 24c6e9504d
Signed by: fef
GPG Key ID: EC22E476DC2D3D84

@ -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

@ -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…
Cancel
Save