Files
jsix_import/src/kernel/panic.serial/main.cpp
Justin C. Miller f5208d1641 [all] Remove dependencies on non-freestanding libc
This is the first of two rather big changes to clean up includes
throughout the project. In this commit, the implicit semi-dependency on
libc that bonnibel adds to every module is removed. Previously, I was
sloppy with includes of libc headers and include directory order. Now,
the freestanding headers from libc are split out into libc_free, and an
implicit real dependency is added onto this module, unless `no_libc` is
set to `True`. The full libc needs to be explicitly specified as a
dependency to be used.

Several things needed to change in order to do this:

- Many places use `memset` or `memcpy` that cannot depend on libc. The
  kernel has basic implementations of them itself for this reason. Now
  those functions are moved into the lower-level `j6/memutils.h`, and
  libc merely references them. Other modules are now free to reference
  those functions from libj6 instead.
- The kernel's `assert.h` was renamed kassert.h (matching its `kassert`
  function) so that the new `util/assert.h` can use `__has_include` to
  detect it and make sure the `assert` macro is usable in libutil code.
- Several implementation header files under `__libj6/` also moved under
  the new libc_free.
- A new `include_phase` property has been added to modules for Bonnibel,
  which can be "normal" (default) or "late" which uses `-idirafter`
  instead of `-I` for includes.
- Since `<utility>` and `<new>` are not freestanding, implementations of
  `remove_reference`, `forward`, `move`, and `swap` were added to the
  `util` namespace to replace those from `std`, and `util/new.h` was
  added to declare `operator new` and `operator delete`.
2023-07-12 19:38:31 -07:00

75 lines
1.9 KiB
C++

#include <util/new.h>
#include <util/no_construct.h>
#include "cpu.h"
#include "display.h"
#include "io.h"
#include "serial.h"
#include "symbol_table.h"
struct cpu_state;
bool main_cpu_done = false;
bool asserting_locked = false;
unsigned remaining = 0;
util::no_construct<panicking::serial_port> __com1_storage;
panicking::serial_port &com1 = __com1_storage.value;
util::no_construct<panicking::symbol_table> __syms_storage;
panicking::symbol_table &syms = __syms_storage.value;
static constexpr int order = __ATOMIC_ACQ_REL;
extern "C"
void panic_handler(const cpu_state *regs)
{
cpu_data &cpu = current_cpu();
panic_data *panic = cpu.panic;
// If we're not running on the CPU that panicked, wait
// for it to finish
if (!panic) {
while (!main_cpu_done);
} else {
new (&com1) panicking::serial_port {panicking::COM1};
new (&syms) panicking::symbol_table {panic->symbol_data};
remaining = panic->cpus;
}
while (__atomic_test_and_set(&asserting_locked, order))
asm ("pause");
panicking::frame const *fp = nullptr;
asm ( "movq (%%rbp), %0" : "=r" (fp) );
if (panic)
print_header(com1, panic->message, panic->function,
panic->file, panic->line);
print_cpu(com1, cpu);
print_callstack(com1, syms, fp);
print_cpu_state(com1, *regs);
if (panic && panic->user_state)
print_user_state(com1, *panic->user_state);
__atomic_clear(&asserting_locked, order);
// If we're running on the CPU that panicked, tell the
// others we have finished
main_cpu_done = true;
if (__atomic_sub_fetch(&remaining, 1, order) == 0) {
// No remaining CPUs, if we're running on QEMU,
// tell it to exit
constexpr uint32_t exit_code = 255;
asm ( "outl %%eax, %%dx" :: "a"(exit_code), "d"(0xf4) );
}
while (1) asm ("hlt");
}
#define NDEBUG
#include "../cpprt.cpp"