ARM: Unified PD,EC,SC,PT,SM,HIP,MBUF class.
This commit is contained in:
parent
33f6645939
commit
e5533fac12
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Execution Context (EC)
|
||||
*
|
||||
* Copyright (C) 2019-2023 Udo Steinberg, BedRock Systems, Inc.
|
||||
*
|
||||
* This file is part of the NOVA microhypervisor.
|
||||
*
|
||||
* NOVA is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* NOVA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License version 2 for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "assert.hpp"
|
||||
#include "ec.hpp"
|
||||
#include "extern.hpp"
|
||||
#include "mtd.hpp"
|
||||
#include "utcb.hpp"
|
||||
|
||||
class Ec_arch final : private Ec
|
||||
{
|
||||
friend class Ec;
|
||||
|
||||
private:
|
||||
static constexpr auto needs_pio { false };
|
||||
|
||||
// Constructor: Kernel Thread
|
||||
Ec_arch (cpu_t, cont_t);
|
||||
|
||||
// Constructor: HST EC
|
||||
Ec_arch (bool, Fpu *, Space_obj *, Space_hst *, Space_pio *, cpu_t, unsigned long, uintptr_t, uintptr_t, void *);
|
||||
|
||||
// Constructor: GST EC
|
||||
Ec_arch (bool, Fpu *, Space_obj *, Space_hst *, Vmcb *, cpu_t, unsigned long, uintptr_t);
|
||||
|
||||
static void handle_irq_kern() asm ("handle_irq_kern");
|
||||
|
||||
[[noreturn]]
|
||||
static void handle_irq_user() asm ("handle_irq_user");
|
||||
|
||||
[[noreturn]]
|
||||
static void handle_exc_kern (Exc_regs *) asm ("handle_exc_kern");
|
||||
|
||||
[[noreturn]]
|
||||
static void handle_exc_user (Exc_regs *) asm ("handle_exc_user");
|
||||
|
||||
[[noreturn]]
|
||||
static void ret_user_hypercall (Ec *);
|
||||
|
||||
[[noreturn]]
|
||||
static void ret_user_exception (Ec *);
|
||||
|
||||
[[noreturn]]
|
||||
static void ret_user_vmexit (Ec *);
|
||||
|
||||
[[noreturn]]
|
||||
static void set_vmm_regs (Ec *);
|
||||
|
||||
ALWAYS_INLINE
|
||||
inline void state_load (Ec *const self, Mtd_arch mtd)
|
||||
{
|
||||
assert (cont == ret_user_vmexit || cont == ret_user_exception);
|
||||
|
||||
self->get_utcb()->arch()->load (mtd, cpu_regs());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE
|
||||
inline bool state_save (Ec *const self, Mtd_arch mtd)
|
||||
{
|
||||
assert (cont == ret_user_vmexit || cont == ret_user_exception);
|
||||
|
||||
return self->get_utcb()->arch()->save (mtd, cpu_regs(), self->get_obj());
|
||||
}
|
||||
|
||||
[[noreturn]] ALWAYS_INLINE
|
||||
inline void make_current()
|
||||
{
|
||||
uintptr_t dummy;
|
||||
|
||||
// Reset stack
|
||||
asm volatile ("adrp %0, %1; mov sp, %0" : "=&r" (dummy) : "S" (&DSTK_TOP) : "memory");
|
||||
|
||||
// Become current EC and invoke continuation
|
||||
(*cont)(current = this);
|
||||
|
||||
UNREACHED;
|
||||
}
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Space
|
||||
* System-Call Interface
|
||||
*
|
||||
* Copyright (C) 2019-2023 Udo Steinberg, BedRock Systems, Inc.
|
||||
*
|
||||
|
@ -17,21 +17,5 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "atomic.hpp"
|
||||
#include "kobject.hpp"
|
||||
#include "status.hpp"
|
||||
|
||||
class Pd;
|
||||
class Space_hst;
|
||||
|
||||
class Space : public Kobject
|
||||
{
|
||||
private:
|
||||
Pd *const pd;
|
||||
|
||||
protected:
|
||||
inline Space (Kobject::Subtype s, Pd *p) : Kobject (Kobject::Type::PD, s), pd (p) {}
|
||||
|
||||
public:
|
||||
inline auto get_pd() const { return pd; }
|
||||
};
|
||||
template void Ec::send_msg<Ec_arch::ret_user_exception> (Ec *);
|
||||
template void Ec::send_msg<Ec_arch::ret_user_vmexit> (Ec *);
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Execution Context (EC)
|
||||
*
|
||||
* Copyright (C) 2019-2023 Udo Steinberg, BedRock Systems, Inc.
|
||||
*
|
||||
* This file is part of the NOVA microhypervisor.
|
||||
*
|
||||
* NOVA is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* NOVA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License version 2 for more details.
|
||||
*/
|
||||
|
||||
#include "assert.hpp"
|
||||
#include "cpu.hpp"
|
||||
#include "ec_arch.hpp"
|
||||
#include "entry.hpp"
|
||||
#include "event.hpp"
|
||||
#include "extern.hpp"
|
||||
#include "fpu.hpp"
|
||||
#include "pd.hpp"
|
||||
#include "sc.hpp"
|
||||
#include "space_gst.hpp"
|
||||
#include "space_hst.hpp"
|
||||
#include "stdio.hpp"
|
||||
#include "vmcb.hpp"
|
||||
|
||||
// Constructor: Kernel Thread
|
||||
Ec_arch::Ec_arch (cpu_t c, cont_t x) : Ec (&Space_hst::nova, c, x) {}
|
||||
|
||||
// Constructor: HST EC
|
||||
Ec_arch::Ec_arch (bool t, Fpu *f, Space_obj *obj, Space_hst *hst, Space_pio *pio, cpu_t c, unsigned long e, uintptr_t sp, uintptr_t hva, void *k) : Ec (t, f, obj, hst, pio, k, c, e, t ? send_msg<ret_user_exception> : nullptr)
|
||||
{
|
||||
assert (obj && hst && !pio && k);
|
||||
|
||||
trace (TRACE_CREATE, "EC:%p created (OBJ:%p HST:%p CPU:%u UTCB:%p %c)", static_cast<void *>(this), static_cast<void *>(obj), static_cast<void *>(hst), c, k, subtype == Kobject::Subtype::EC_LOCAL ? 'L' : 'G');
|
||||
|
||||
exc_regs().sp() = sp;
|
||||
exc_regs().set_ep (Event::hst_arch + Event::Selector::STARTUP);
|
||||
|
||||
// Map UTCB
|
||||
hst->update (hva, Kmem::ptr_to_phys (kpage), 0, Paging::Permissions (Paging::K | Paging::U | Paging::W | Paging::R), Memattr::ram());
|
||||
}
|
||||
|
||||
// Constructor: GST EC
|
||||
Ec_arch::Ec_arch (bool t, Fpu *f, Space_obj *obj, Space_hst *hst, Vmcb *v, cpu_t c, unsigned long e, uintptr_t sp) : Ec (t, f, obj, hst, v, nullptr, c, e, set_vmm_regs)
|
||||
{
|
||||
assert (obj && hst && v);
|
||||
|
||||
trace (TRACE_CREATE, "EC:%p created (OBJ:%p HST:%p CPU:%u VMCB:%p %c)", static_cast<void *>(this), static_cast<void *>(obj), static_cast<void *>(hst), c, static_cast<void *>(v), subtype == Kobject::Subtype::EC_VCPU_REAL ? 'R' : 'O');
|
||||
|
||||
exc_regs().sp() = sp;
|
||||
exc_regs().set_ep (Event::gst_arch + Event::Selector::STARTUP);
|
||||
}
|
||||
|
||||
// Factory: GST EC
|
||||
Ec *Ec::create_gst (Status &s, Pd *pd, bool t, bool fpu, cpu_t cpu, unsigned long evt, uintptr_t sp, uintptr_t /*hva*/)
|
||||
{
|
||||
auto const obj { pd->get_obj() };
|
||||
auto const hst { pd->get_hst() };
|
||||
|
||||
if (EXPECT_FALSE (!obj || !hst)) {
|
||||
s = Status::ABORTED;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// FIXME: Refcount updates
|
||||
|
||||
auto const f { fpu ? new (pd->fpu_cache) Fpu : nullptr };
|
||||
auto const v { new Vmcb };
|
||||
Ec *ec;
|
||||
|
||||
if (EXPECT_TRUE ((!fpu || f) && v && (ec = new (cache) Ec_arch (t, f, obj, hst, v, cpu, evt, sp))))
|
||||
return ec;
|
||||
|
||||
delete v;
|
||||
Fpu::operator delete (f, pd->fpu_cache);
|
||||
|
||||
s = Status::MEM_OBJ;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Ec::adjust_offset_ticks (uint64_t t)
|
||||
{
|
||||
if (subtype == Kobject::Subtype::EC_VCPU_OFFS)
|
||||
regs.vmcb->tmr.cntvoff += t;
|
||||
}
|
||||
|
||||
void Ec::handle_hazard (unsigned h, cont_t func)
|
||||
{
|
||||
if (EXPECT_FALSE (h & (Hazard::ILLEGAL | Hazard::RECALL | Hazard::SLEEP | Hazard::SCHED))) {
|
||||
|
||||
Cpu::preemption_point();
|
||||
|
||||
if (Cpu::hazard & Hazard::SLEEP) { // Reload
|
||||
cont = func;
|
||||
Cpu::fini();
|
||||
}
|
||||
|
||||
if (Cpu::hazard & Hazard::SCHED) { // Reload
|
||||
cont = func;
|
||||
Scheduler::schedule();
|
||||
}
|
||||
|
||||
if (h & Hazard::ILLEGAL)
|
||||
kill ("Illegal execution state");
|
||||
|
||||
if (regs.hazard & Hazard::RECALL) { // Reload
|
||||
|
||||
regs.hazard.clr (Hazard::RECALL);
|
||||
|
||||
if (func == Ec_arch::ret_user_vmexit) {
|
||||
exc_regs().set_ep (Event::gst_arch + Event::Selector::RECALL);
|
||||
send_msg<Ec_arch::ret_user_vmexit> (this);
|
||||
} else {
|
||||
exc_regs().set_ep (Event::hst_arch + Event::Selector::RECALL);
|
||||
send_msg<Ec_arch::ret_user_exception> (this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Point of no return after checking all diversions: this EC will run
|
||||
|
||||
if (EXPECT_FALSE (h & Hazard::FPU))
|
||||
Cpu::hazard & Hazard::FPU ? Fpu::disable() : Fpu::enable();
|
||||
}
|
||||
|
||||
void Ec_arch::ret_user_hypercall (Ec *const self)
|
||||
{
|
||||
auto const h { (Cpu::hazard ^ self->regs.hazard) & (Hazard::ILLEGAL | Hazard::RECALL | Hazard::FPU | Hazard::RCU | Hazard::SLEEP | Hazard::SCHED) };
|
||||
if (EXPECT_FALSE (h))
|
||||
self->handle_hazard (h, ret_user_hypercall);
|
||||
|
||||
trace (TRACE_CONT, "EC:%p %s to M:%#x IP:%#lx SP:%#lx", static_cast<void *>(self), __func__, self->exc_regs().mode(), self->exc_regs().ip(), self->exc_regs().sp());
|
||||
|
||||
if (Vmcb::current)
|
||||
Vmcb::load_hst();
|
||||
|
||||
self->get_hst()->make_current();
|
||||
|
||||
asm volatile ("mov sp, %0;" EXPAND (LOAD_STATE ERET) : : "r" (&self->exc_regs()), "m" (self->exc_regs()));
|
||||
|
||||
UNREACHED;
|
||||
}
|
||||
|
||||
void Ec_arch::ret_user_exception (Ec *const self)
|
||||
{
|
||||
auto const h { (Cpu::hazard ^ self->regs.hazard) & (Hazard::ILLEGAL | Hazard::RECALL | Hazard::FPU | Hazard::RCU | Hazard::SLEEP | Hazard::SCHED) };
|
||||
if (EXPECT_FALSE (h))
|
||||
self->handle_hazard (h, ret_user_exception);
|
||||
|
||||
trace (TRACE_CONT, "EC:%p %s to M:%#x IP:%#lx SP:%#lx", static_cast<void *>(self), __func__, self->exc_regs().mode(), self->exc_regs().ip(), self->exc_regs().sp());
|
||||
|
||||
if (Vmcb::current)
|
||||
Vmcb::load_hst();
|
||||
|
||||
self->get_hst()->make_current();
|
||||
|
||||
asm volatile ("mov sp, %0;" EXPAND (LOAD_STATE ERET) : : "r" (&self->exc_regs()), "m" (self->exc_regs()));
|
||||
|
||||
UNREACHED;
|
||||
}
|
||||
|
||||
void Ec_arch::ret_user_vmexit (Ec *const self)
|
||||
{
|
||||
auto const h { (Cpu::hazard ^ self->regs.hazard) & (Hazard::ILLEGAL | Hazard::RECALL | Hazard::FPU | Hazard::RCU | Hazard::SLEEP | Hazard::SCHED) };
|
||||
if (EXPECT_FALSE (h))
|
||||
self->handle_hazard (h, ret_user_vmexit);
|
||||
|
||||
trace (TRACE_CONT, "EC:%p %s to M:%#x IP:%#lx", static_cast<void *>(self), __func__, self->exc_regs().mode(), self->exc_regs().ip());
|
||||
|
||||
auto const v { self->regs.vmcb };
|
||||
|
||||
if (Vmcb::current != v)
|
||||
v->load_gst(); // Restore full register state
|
||||
else
|
||||
v->load_tmr(); // Restore only vTMR PPI state
|
||||
|
||||
self->get_gst()->make_current();
|
||||
|
||||
asm volatile ("mov sp, %0;" EXPAND (LOAD_STATE ERET) : : "r" (&self->exc_regs()), "m" (self->exc_regs()));
|
||||
|
||||
UNREACHED;
|
||||
}
|
||||
|
||||
void Ec_arch::set_vmm_regs (Ec *const self)
|
||||
{
|
||||
assert (self->is_vcpu());
|
||||
assert (self->cpu == Cpu::id);
|
||||
|
||||
auto const v { self->regs.vmcb };
|
||||
|
||||
Cpu::set_vmm_regs (self->sys_regs().gpr, v->el2.hcr, v->el2.vpidr, v->el2.vmpidr, v->gic.elrsr);
|
||||
|
||||
send_msg<ret_user_vmexit> (self);
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Execution Context (EC)
|
||||
*
|
||||
* Copyright (C) 2019-2023 Udo Steinberg, BedRock Systems, Inc.
|
||||
*
|
||||
* This file is part of the NOVA microhypervisor.
|
||||
*
|
||||
* NOVA is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* NOVA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License version 2 for more details.
|
||||
*/
|
||||
|
||||
#include "assert.hpp"
|
||||
#include "ec_arch.hpp"
|
||||
#include "event.hpp"
|
||||
#include "fpu.hpp"
|
||||
#include "interrupt.hpp"
|
||||
#include "pd.hpp"
|
||||
#include "smc.hpp"
|
||||
#include "stdio.hpp"
|
||||
#include "vmcb.hpp"
|
||||
|
||||
void Ec::fpu_load()
|
||||
{
|
||||
assert (fpu);
|
||||
fpu->load();
|
||||
regs.hazard.set (Hazard::FPU);
|
||||
}
|
||||
|
||||
void Ec::fpu_save()
|
||||
{
|
||||
assert (fpu);
|
||||
fpu->save();
|
||||
regs.hazard.clr (Hazard::FPU);
|
||||
}
|
||||
|
||||
void Ec_arch::handle_exc_kern (Exc_regs *r)
|
||||
{
|
||||
auto const iss { r->el2.esr & BIT_RANGE (24, 0) };
|
||||
|
||||
switch (r->ep()) {
|
||||
|
||||
case 0x21: // Inst Abort
|
||||
case 0x25: // Data Abort
|
||||
trace (TRACE_KILL, "KERN %s abort (ISS:%#lx) at IP:%#lx FAR:%#lx", r->ep() == 0x21 ? "INST" : "DATA", iss, r->el2.elr, r->el2.far);
|
||||
break;
|
||||
|
||||
default:
|
||||
trace (TRACE_KILL, "KERN exception %#lx (ISS:%#lx) at IP:%#lx", r->ep(), iss, r->el2.elr);
|
||||
break;
|
||||
}
|
||||
|
||||
current->kill ("exception");
|
||||
}
|
||||
|
||||
void Ec_arch::handle_exc_user (Exc_regs *r)
|
||||
{
|
||||
auto const esr { static_cast<uint32_t>(r->el2.esr) };
|
||||
|
||||
Ec *const self { current };
|
||||
|
||||
bool resolved { false };
|
||||
|
||||
// SVC #0 from AArch64 state
|
||||
if (EXPECT_TRUE (esr == (VAL_SHIFT (0x15, 26) | BIT (25) | 0)))
|
||||
(*syscall[r->sys.gpr[0] & BIT_RANGE (3, 0)])(self);
|
||||
|
||||
// SVC #1 from AArch64 state
|
||||
else if (esr == (VAL_SHIFT (0x15, 26) | BIT (25) | 1))
|
||||
resolved = self->get_obj() == Pd::root->get_obj() && Cpu::feature (Cpu::Cpu_feature::EL3) && Smc::proxy (r->sys.gpr);
|
||||
|
||||
// FPU Access
|
||||
else if (r->ep() == 0x7)
|
||||
resolved = switch_fpu (self);
|
||||
|
||||
trace (TRACE_EXCEPTION, "EC:%p %s %#lx at M:%#x IP:%#lx", static_cast<void *>(self), self->is_vcpu() ? "VMX" : "EXC", r->ep(), r->mode(), r->el2.elr);
|
||||
|
||||
if (self->is_vcpu()) {
|
||||
self->regs.vmcb->save_gst();
|
||||
resolved ? ret_user_vmexit (self) : send_msg<ret_user_vmexit> (self);
|
||||
} else
|
||||
resolved ? ret_user_exception (self) : send_msg<ret_user_exception> (self);
|
||||
}
|
||||
|
||||
void Ec_arch::handle_irq_kern()
|
||||
{
|
||||
Interrupt::handler (false);
|
||||
}
|
||||
|
||||
void Ec_arch::handle_irq_user()
|
||||
{
|
||||
Ec *const self { current };
|
||||
|
||||
Event::Selector evt = Interrupt::handler (self->is_vcpu());
|
||||
|
||||
if (!self->is_vcpu())
|
||||
ret_user_exception (self);
|
||||
|
||||
self->regs.vmcb->save_gst();
|
||||
|
||||
if (evt == Event::Selector::NONE)
|
||||
ret_user_vmexit (self);
|
||||
|
||||
assert (self->regs.vmcb->tmr.cntv_act);
|
||||
|
||||
self->exc_regs().set_ep (Event::gst_arch + evt);
|
||||
|
||||
send_msg<ret_user_vmexit> (self);
|
||||
}
|
|
@ -45,12 +45,15 @@ vector_table:
|
|||
.org vector_table + 0x200 // Synchronous
|
||||
DECR_STACK
|
||||
SAVE_STATE_EXC
|
||||
b 1f
|
||||
mov x0, sp
|
||||
adr lr, 1f
|
||||
b handle_exc_kern
|
||||
|
||||
.org vector_table + 0x280 // IRQ
|
||||
DECR_STACK
|
||||
SAVE_STATE
|
||||
b 1f
|
||||
adr lr, 1f
|
||||
b handle_irq_kern
|
||||
|
||||
.org vector_table + 0x300 // FIQ
|
||||
b .
|
||||
|
@ -58,43 +61,61 @@ vector_table:
|
|||
.org vector_table + 0x380 // SError
|
||||
DECR_STACK
|
||||
SAVE_STATE_EXC
|
||||
b .
|
||||
mov x0, sp
|
||||
adr lr, 1f
|
||||
b handle_exc_kern
|
||||
|
||||
/*
|
||||
* Entry from EL0/EL1 with EL1 using AArch64
|
||||
*/
|
||||
.org vector_table + 0x400 // Synchronous
|
||||
SAVE_STATE_EXC
|
||||
b .
|
||||
mov x0, sp
|
||||
adrp x1, DSTK_TOP
|
||||
mov sp, x1
|
||||
b handle_exc_user
|
||||
|
||||
.org vector_table + 0x480 // IRQ
|
||||
SAVE_STATE
|
||||
b .
|
||||
adrp x1, DSTK_TOP
|
||||
mov sp, x1
|
||||
b handle_irq_user
|
||||
|
||||
.org vector_table + 0x500 // FIQ
|
||||
b .
|
||||
|
||||
.org vector_table + 0x580 // SError
|
||||
SAVE_STATE_EXC
|
||||
b .
|
||||
mov x0, sp
|
||||
adrp x1, DSTK_TOP
|
||||
mov sp, x1
|
||||
b handle_exc_user
|
||||
|
||||
/*
|
||||
* Entry from EL0/EL1 with EL1 using AArch32
|
||||
*/
|
||||
.org vector_table + 0x600 // Synchronous
|
||||
SAVE_STATE_EXC
|
||||
b .
|
||||
mov x0, sp
|
||||
adrp x1, DSTK_TOP
|
||||
mov sp, x1
|
||||
b handle_exc_user
|
||||
|
||||
.org vector_table + 0x680 // IRQ
|
||||
SAVE_STATE
|
||||
b .
|
||||
adrp x1, DSTK_TOP
|
||||
mov sp, x1
|
||||
b handle_irq_user
|
||||
|
||||
.org vector_table + 0x700 // FIQ
|
||||
b .
|
||||
|
||||
.org vector_table + 0x780 // SError
|
||||
SAVE_STATE_EXC
|
||||
b .
|
||||
mov x0, sp
|
||||
adrp x1, DSTK_TOP
|
||||
mov sp, x1
|
||||
b handle_exc_user
|
||||
|
||||
/*
|
||||
* Exit to EL2
|
||||
|
|
|
@ -15,8 +15,10 @@
|
|||
* GNU General Public License version 2 for more details.
|
||||
*/
|
||||
|
||||
#include "ec.hpp"
|
||||
#include "fpu.hpp"
|
||||
|
||||
void Fpu::fini()
|
||||
{
|
||||
Ec::switch_fpu (nullptr);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "acpi.hpp"
|
||||
#include "assert.hpp"
|
||||
#include "gicc.hpp"
|
||||
#include "ptab_hpt.hpp"
|
||||
#include "space_hst.hpp"
|
||||
#include "stdio.hpp"
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "gicd.hpp"
|
||||
#include "lock_guard.hpp"
|
||||
#include "lowlevel.hpp"
|
||||
#include "ptab_hpt.hpp"
|
||||
#include "space_hst.hpp"
|
||||
#include "stdio.hpp"
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include "acpi.hpp"
|
||||
#include "gich.hpp"
|
||||
#include "ptab_hpt.hpp"
|
||||
#include "space_hst.hpp"
|
||||
#include "stdio.hpp"
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "gicd.hpp"
|
||||
#include "gicr.hpp"
|
||||
#include "lowlevel.hpp"
|
||||
#include "ptab_hpt.hpp"
|
||||
#include "space_hst.hpp"
|
||||
#include "stdio.hpp"
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "hip.hpp"
|
||||
#include "interrupt.hpp"
|
||||
#include "multiboot.hpp"
|
||||
#include "ptab_hpt.hpp"
|
||||
#include "sm.hpp"
|
||||
#include "space_hst.hpp"
|
||||
#include "space_obj.hpp"
|
Loading…
Reference in New Issue