9#include "pedigree/kernel/machine/Machine.h"
10#include "pedigree/kernel/machine/Pci.h"
11#include "pedigree/kernel/panic.h"
13#include "DeviceTree.h"
14#include "IrqManager.h"
15#include "SchedulerTimer.h"
19void psci(uint64_t function,
bool hvc) {
21 register uint32_t r0
asm(
"r0") =
static_cast<uint32_t
>(function);
23 asm volatile(
".arch_extension virt\n\thvc #0" :
"+r"(r0) : :
"memory");
25 asm volatile(
".arch_extension sec\n\tsmc #0" :
"+r"(r0) : :
"memory");
28 register uint64_t x0
asm(
"x0") = function;
30 asm volatile(
"hvc #0" :
"+r"(x0) : :
"memory");
32 asm volatile(
"smc #0" :
"+r"(x0) : :
"memory");
41 return VirtMachine::instance();
48VirtMachine::VirtMachine()
49 : m_Serial(), m_SerialKeyboard(m_Serial), m_Keyboard(&m_SerialKeyboard) {}
51VirtMachine::~VirtMachine() {
60 if (!VirtDeviceTree::valid()) {
61 panic(
"Virt: invalid device tree");
65 if (!VirtIrqManager::instance().
initialise()) {
66 panic(
"Virt: GIC initialisation failed");
68 if (!VirtTimer::instance().initialise1()) {
69 panic(
"Virt: architectural clock initialisation failed");
71 if (!VirtSchedulerTimer::instance().
initialise()) {
72 panic(
"Virt: scheduler timer initialisation failed");
74 m_bInitialised =
true;
79 panic(
"Virt: timer worker initialisation failed");
81 if (!VirtIrqManager::instance().initialiseThreaded()) {
82 panic(
"Virt: PCI interrupt worker initialisation failed");
87 if (!m_bInitialised) {
90 if (!VirtIrqManager::instance().shutdownThreaded()) {
91 panic(
"Shutdown aborted: PCI interrupt workers did not stop");
93 VirtTimer::instance().uninitialise();
94 VirtSchedulerTimer::instance().uninitialise();
98bool VirtMachine::supportsPowerOff()
const {
99 return VirtDeviceTree::psciAvailable();
103 if (!VirtDeviceTree::psciAvailable()) {
106 if (type == ShutdownType::Restart) {
107 psci(0x84000009, VirtDeviceTree::psciUsesHvc());
108 }
else if (type == ShutdownType::PowerOff) {
109 psci(0x84000008, VirtDeviceTree::psciUsesHvc());
114 return n == 0 ? &m_Serial :
nullptr;
130 return &VirtIrqManager::instance();
134 return &VirtSchedulerTimer::instance();
138 return &VirtTimer::instance();
146 m_Keyboard = keyboard ? keyboard : &m_SerialKeyboard;
virtual void deinitialise()
static uintptr_t uartBase()
void initialise() override
void deinitialise() override
void initialiseDeviceTree() override
Vga * getVga(size_t n) override
Timer * getTimer() override
size_t getNumSerial() override
size_t getNumVga() override
void initialise3() override
Called after processor startup - for thread creation etc.
Keyboard * getKeyboard() override
Serial * getSerial(size_t n) override
void setKeyboard(Keyboard *keyboard) override
void initialise() override
void finalShutdown(ShutdownType type) override
SchedulerTimer * getSchedulerTimer() override
void setBase(uintptr_t base) override
void EXPORTED_PUBLIC panic(const char *msg) NORETURN