mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-05-31 16:57:58 +00:00
Fix 32-bit compilation
This commit is contained in:
parent
8898791257
commit
bef0897442
@ -1,7 +1,7 @@
|
||||
/* Based on this tutorial:
|
||||
https://github.com/s-matyukevich/raspberry-pi-os */
|
||||
|
||||
.section ".text.boot"
|
||||
.section ".text.boot", "a"
|
||||
|
||||
.extern _bss_start
|
||||
.extern _bss_end
|
||||
|
@ -18,7 +18,7 @@
|
||||
.intel_syntax noprefix
|
||||
|
||||
.code32
|
||||
.section .multiboot
|
||||
.section .multiboot, "a"
|
||||
.align 4
|
||||
|
||||
MULTIBOOT_HEADER:
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
.code32
|
||||
.section .bootstrap.text
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.global Multiboot1_start
|
||||
Multiboot1_start:
|
||||
|
@ -18,7 +18,7 @@
|
||||
.intel_syntax noprefix
|
||||
|
||||
.code32
|
||||
.section .bootstrap.text
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.global DetectCPUID
|
||||
DetectCPUID:
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
.code32
|
||||
.section .bootstrap.text
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.align 32
|
||||
.global gdtr
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
.code64
|
||||
.section .bootstrap.data
|
||||
.section .bootstrap.data, "a"
|
||||
|
||||
/* Access bits */
|
||||
A = 0x1
|
||||
|
@ -19,7 +19,7 @@
|
||||
.extern Multiboot2_start
|
||||
|
||||
/* https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html */
|
||||
.section .multiboot2
|
||||
.section .multiboot2, "a"
|
||||
.align 0x1000
|
||||
MULTIBOOT2_HEADER_START:
|
||||
.long 0xE85250D6
|
||||
|
@ -18,13 +18,13 @@
|
||||
PAGE_TABLE_SIZE = 0x4
|
||||
|
||||
.code32
|
||||
.section .bootstrap.data
|
||||
.section .bootstrap.data, "a"
|
||||
.align 0x1000
|
||||
.global BootPageTable
|
||||
BootPageTable:
|
||||
.space 0x10000 /* 0x4000 bytes will be used in UpdatePageTable */
|
||||
|
||||
.section .bootstrap.text
|
||||
.section .bootstrap.text, "a"
|
||||
.global UpdatePageTable
|
||||
UpdatePageTable:
|
||||
mov $(BootPageTable + 0x0000), %edi /* First PML4E */
|
||||
|
@ -30,14 +30,14 @@ KERNEL_STACK_SIZE = 0x4000 /* 16KB */
|
||||
.extern GDT64.Code
|
||||
.extern GDT64.Data
|
||||
|
||||
.section .bootstrap.data
|
||||
.section .bootstrap.data, "a"
|
||||
MB_HeaderMagic:
|
||||
.quad 0
|
||||
|
||||
MB_HeaderInfo:
|
||||
.quad 0
|
||||
|
||||
.section .bootstrap.text
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.global Multiboot2_start
|
||||
Multiboot2_start:
|
||||
@ -113,7 +113,7 @@ HigherHalfStart:
|
||||
hlt
|
||||
jmp .Hang
|
||||
|
||||
.section .bootstrap.bss
|
||||
.section .bootstrap.bss, "a"
|
||||
.align 16
|
||||
KernelStack:
|
||||
.space KERNEL_STACK_SIZE
|
||||
|
@ -21,7 +21,7 @@
|
||||
.extern Multiboot2_start
|
||||
|
||||
.code32
|
||||
.section .bootstrap.text
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
|
@ -24,7 +24,7 @@ TRAMPOLINE_IDT = 0x590
|
||||
TRAMPOLINE_CORE = 0x600
|
||||
TRAMPOLINE_START = 0x2000
|
||||
|
||||
.section .text
|
||||
.section .text, "a"
|
||||
|
||||
/* ========== 16-bit ========== */
|
||||
|
||||
|
158
Architecture/i386/AdvancedConfigurationAndPowerInterface.cpp
Normal file
158
Architecture/i386/AdvancedConfigurationAndPowerInterface.cpp
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel 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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "acpi.hpp"
|
||||
|
||||
#include <debug.h>
|
||||
#include <io.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
namespace ACPI
|
||||
{
|
||||
__no_sanitize("alignment") void *ACPI::FindTable(ACPI::ACPIHeader *ACPIHeader, char *Signature)
|
||||
{
|
||||
for (uint64_t t = 0; t < ((ACPIHeader->Length - sizeof(ACPI::ACPIHeader)) / (XSDTSupported ? 8 : 4)); t++)
|
||||
{
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
|
||||
|
||||
// TODO: Should I be concerned about unaligned memory access?
|
||||
ACPI::ACPIHeader *SDTHdr = nullptr;
|
||||
if (XSDTSupported)
|
||||
SDTHdr = (ACPI::ACPIHeader *)(*(uint64_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 8)));
|
||||
else
|
||||
SDTHdr = (ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 4)));
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (SDTHdr->Signature[i] != Signature[i])
|
||||
break;
|
||||
if (i == 3)
|
||||
{
|
||||
trace("%s found at address %p", Signature, (uintptr_t)SDTHdr);
|
||||
return SDTHdr;
|
||||
}
|
||||
}
|
||||
}
|
||||
// warn("%s not found!", Signature);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ACPI::SearchTables(ACPIHeader *Header)
|
||||
{
|
||||
if (!Header)
|
||||
return;
|
||||
|
||||
HPET = (HPETHeader *)FindTable(Header, (char *)"HPET");
|
||||
FADT = (FADTHeader *)FindTable(Header, (char *)"FACP");
|
||||
MCFG = (MCFGHeader *)FindTable(Header, (char *)"MCFG");
|
||||
BGRT = (BGRTHeader *)FindTable(Header, (char *)"BGRT");
|
||||
SRAT = (SRATHeader *)FindTable(Header, (char *)"SRAT");
|
||||
TPM2 = (TPM2Header *)FindTable(Header, (char *)"TPM2");
|
||||
TCPA = (TCPAHeader *)FindTable(Header, (char *)"TCPA");
|
||||
WAET = (WAETHeader *)FindTable(Header, (char *)"WAET");
|
||||
MADT = (MADTHeader *)FindTable(Header, (char *)"APIC");
|
||||
HEST = (HESTHeader *)FindTable(Header, (char *)"HEST");
|
||||
FindTable(Header, (char *)"BERT");
|
||||
FindTable(Header, (char *)"CPEP");
|
||||
FindTable(Header, (char *)"DSDT");
|
||||
FindTable(Header, (char *)"ECDT");
|
||||
FindTable(Header, (char *)"EINJ");
|
||||
FindTable(Header, (char *)"ERST");
|
||||
FindTable(Header, (char *)"FACS");
|
||||
FindTable(Header, (char *)"MSCT");
|
||||
FindTable(Header, (char *)"MPST");
|
||||
FindTable(Header, (char *)"OEMx");
|
||||
FindTable(Header, (char *)"PMTT");
|
||||
FindTable(Header, (char *)"PSDT");
|
||||
FindTable(Header, (char *)"RASF");
|
||||
FindTable(Header, (char *)"RSDT");
|
||||
FindTable(Header, (char *)"SBST");
|
||||
FindTable(Header, (char *)"SLIT");
|
||||
FindTable(Header, (char *)"SSDT");
|
||||
FindTable(Header, (char *)"XSDT");
|
||||
FindTable(Header, (char *)"DRTM");
|
||||
FindTable(Header, (char *)"FPDT");
|
||||
FindTable(Header, (char *)"GTDT");
|
||||
FindTable(Header, (char *)"PCCT");
|
||||
FindTable(Header, (char *)"S3PT");
|
||||
FindTable(Header, (char *)"MATR");
|
||||
FindTable(Header, (char *)"MSDM");
|
||||
FindTable(Header, (char *)"WPBT");
|
||||
FindTable(Header, (char *)"OSDT");
|
||||
FindTable(Header, (char *)"RSDP");
|
||||
FindTable(Header, (char *)"NFIT");
|
||||
FindTable(Header, (char *)"ASF!");
|
||||
FindTable(Header, (char *)"BOOT");
|
||||
FindTable(Header, (char *)"CSRT");
|
||||
FindTable(Header, (char *)"DBG2");
|
||||
FindTable(Header, (char *)"DBGP");
|
||||
FindTable(Header, (char *)"DMAR");
|
||||
FindTable(Header, (char *)"IBFT");
|
||||
FindTable(Header, (char *)"IORT");
|
||||
FindTable(Header, (char *)"IVRS");
|
||||
FindTable(Header, (char *)"LPIT");
|
||||
FindTable(Header, (char *)"MCHI");
|
||||
FindTable(Header, (char *)"MTMR");
|
||||
FindTable(Header, (char *)"SLIC");
|
||||
FindTable(Header, (char *)"SPCR");
|
||||
FindTable(Header, (char *)"SPMI");
|
||||
FindTable(Header, (char *)"UEFI");
|
||||
FindTable(Header, (char *)"VRTC");
|
||||
FindTable(Header, (char *)"WDAT");
|
||||
FindTable(Header, (char *)"WDDT");
|
||||
FindTable(Header, (char *)"WDRT");
|
||||
FindTable(Header, (char *)"ATKG");
|
||||
FindTable(Header, (char *)"GSCI");
|
||||
FindTable(Header, (char *)"IEIT");
|
||||
FindTable(Header, (char *)"HMAT");
|
||||
FindTable(Header, (char *)"CEDT");
|
||||
FindTable(Header, (char *)"AEST");
|
||||
}
|
||||
|
||||
ACPI::ACPI()
|
||||
{
|
||||
trace("Initializing ACPI");
|
||||
if (bInfo.RSDP->Revision >= 2 && bInfo.RSDP->XSDTAddress)
|
||||
{
|
||||
debug("XSDT supported");
|
||||
XSDTSupported = true;
|
||||
XSDT = (ACPIHeader *)(bInfo.RSDP->XSDTAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("RSDT supported");
|
||||
XSDT = (ACPIHeader *)(uintptr_t)bInfo.RSDP->RSDTAddress;
|
||||
}
|
||||
|
||||
this->SearchTables(XSDT);
|
||||
|
||||
if (FADT)
|
||||
{
|
||||
outb(s_cst(uint16_t, FADT->SMI_CommandPort), FADT->AcpiEnable);
|
||||
while (!(inw(s_cst(uint16_t, FADT->PM1aControlBlock)) & 1))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
ACPI::~ACPI()
|
||||
{
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@
|
||||
.intel_syntax noprefix
|
||||
|
||||
.code32
|
||||
.section .multiboot
|
||||
.section .multiboot, "a"
|
||||
.align 4
|
||||
|
||||
MULTIBOOT_HEADER:
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
.code32
|
||||
.section .bootstrap.text
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.global Multiboot1_start
|
||||
Multiboot1_start:
|
||||
|
@ -18,7 +18,7 @@
|
||||
.intel_syntax noprefix
|
||||
|
||||
.code32
|
||||
.section .bootstrap.text
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.global DetectCPUID
|
||||
DetectCPUID:
|
||||
|
@ -18,7 +18,7 @@
|
||||
.intel_syntax noprefix
|
||||
|
||||
.code32
|
||||
.section .bootstrap.text
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.align 32
|
||||
.global gdtr
|
||||
|
@ -21,7 +21,7 @@
|
||||
.extern Multiboot2_start
|
||||
|
||||
/* https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html */
|
||||
.section .multiboot2
|
||||
.section .multiboot2, "a"
|
||||
.align 0x1000
|
||||
MULTIBOOT2_HEADER_START:
|
||||
.long 0xE85250D6
|
||||
|
@ -19,7 +19,7 @@
|
||||
KERNEL_VIRTUAL_BASE = 0xC0000000 /* 3GB */
|
||||
KERNEL_PAGE_NUMBER = 768 /* KERNEL_VIRTUAL_BASE >> 22 */
|
||||
|
||||
.section .bootstrap.data
|
||||
.section .bootstrap.data, "a"
|
||||
.align 0x1000
|
||||
.global BootPageTable
|
||||
BootPageTable:
|
||||
|
@ -24,14 +24,14 @@ KERNEL_STACK_SIZE = 0x4000 /* 16KB */
|
||||
.extern LoadGDT32
|
||||
.extern BootPageTable
|
||||
|
||||
.section .bootstrap.data
|
||||
.section .bootstrap.data, "a"
|
||||
MB_HeaderMagic:
|
||||
.quad 0
|
||||
|
||||
MB_HeaderInfo:
|
||||
.quad 0
|
||||
|
||||
.section .bootstrap.text
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.global Multiboot2_start
|
||||
Multiboot2_start:
|
||||
@ -73,7 +73,7 @@ Multiboot2_start:
|
||||
hlt
|
||||
jmp .Hang
|
||||
|
||||
.section .bootstrap.bss
|
||||
.section .bootstrap.bss, "a"
|
||||
.align 16
|
||||
KernelStack:
|
||||
.space KERNEL_STACK_SIZE
|
||||
|
@ -21,7 +21,7 @@
|
||||
.extern Multiboot2_start
|
||||
|
||||
.code32
|
||||
.section .bootstrap.text
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
|
255
Architecture/i386/DifferentiatedSystemDescriptionTable.cpp
Normal file
255
Architecture/i386/DifferentiatedSystemDescriptionTable.cpp
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel 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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "acpi.hpp"
|
||||
|
||||
#include <time.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#include "cpu/apic.hpp"
|
||||
#include "../../kernel.h"
|
||||
|
||||
#define ACPI_TIMER 0x0001
|
||||
#define ACPI_BUSMASTER 0x0010
|
||||
#define ACPI_GLOBAL 0x0020
|
||||
#define ACPI_POWER_BUTTON 0x0100
|
||||
#define ACPI_SLEEP_BUTTON 0x0200
|
||||
#define ACPI_RTC_ALARM 0x0400
|
||||
#define ACPI_PCIE_WAKE 0x4000
|
||||
#define ACPI_WAKE 0x8000
|
||||
|
||||
namespace ACPI
|
||||
{
|
||||
__always_inline inline bool IsCanonical(uint64_t Address)
|
||||
{
|
||||
return ((Address <= 0x00007FFFFFFFFFFF) || ((Address >= 0xFFFF800000000000) && (Address <= 0xFFFFFFFFFFFFFFFF)));
|
||||
}
|
||||
|
||||
#define ACPI_ENABLED 0x0001
|
||||
#define ACPI_SLEEP 0x2000
|
||||
|
||||
#define ACPI_GAS_MMIO 0
|
||||
#define ACPI_GAS_IO 1
|
||||
#define ACPI_GAS_PCI 2
|
||||
|
||||
void DSDT::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
|
||||
{
|
||||
debug("SCI Handle Triggered");
|
||||
uint16_t Event = 0;
|
||||
{
|
||||
uint16_t a = 0, b = 0;
|
||||
if (acpi->FADT->PM1aEventBlock)
|
||||
{
|
||||
a = inw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock));
|
||||
outw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock), a);
|
||||
}
|
||||
if (acpi->FADT->PM1bEventBlock)
|
||||
{
|
||||
b = inw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock));
|
||||
outw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock), b);
|
||||
}
|
||||
Event = a | b;
|
||||
}
|
||||
|
||||
debug("SCI Event: %#lx", Event);
|
||||
if (Event & ACPI_BUSMASTER)
|
||||
{
|
||||
fixme("ACPI Busmaster");
|
||||
}
|
||||
else if (Event & ACPI_GLOBAL)
|
||||
{
|
||||
fixme("ACPI Global");
|
||||
}
|
||||
else if (Event & ACPI_POWER_BUTTON)
|
||||
{
|
||||
if (TaskManager && !TaskManager->IsPanic())
|
||||
{
|
||||
TaskManager->CreateThread(TaskManager->CreateProcess(nullptr,
|
||||
"Shutdown",
|
||||
Tasking::TaskExecutionMode::Kernel),
|
||||
Tasking::IP(KST_Shutdown));
|
||||
}
|
||||
else
|
||||
KernelShutdownThread(false);
|
||||
}
|
||||
else if (Event & ACPI_SLEEP_BUTTON)
|
||||
{
|
||||
fixme("ACPI Sleep Button");
|
||||
}
|
||||
else if (Event & ACPI_RTC_ALARM)
|
||||
{
|
||||
fixme("ACPI RTC Alarm");
|
||||
}
|
||||
else if (Event & ACPI_PCIE_WAKE)
|
||||
{
|
||||
fixme("ACPI PCIe Wake");
|
||||
}
|
||||
else if (Event & ACPI_WAKE)
|
||||
{
|
||||
fixme("ACPI Wake");
|
||||
}
|
||||
else if (Event & ACPI_TIMER)
|
||||
{
|
||||
fixme("ACPI Timer");
|
||||
}
|
||||
else
|
||||
{
|
||||
error("ACPI unknown event %#lx on CPU %d", Event, GetCurrentCPU()->ID);
|
||||
CPU::Stop();
|
||||
}
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
void DSDT::Shutdown()
|
||||
{
|
||||
trace("Shutting down...");
|
||||
if (SCI_EN == 1)
|
||||
{
|
||||
outw(s_cst(uint16_t, acpi->FADT->PM1aControlBlock),
|
||||
s_cst(uint16_t,
|
||||
(inw(s_cst(uint16_t,
|
||||
acpi->FADT->PM1aControlBlock)) &
|
||||
0xE3FF) |
|
||||
((SLP_TYPa << 10) | ACPI_SLEEP)));
|
||||
|
||||
if (acpi->FADT->PM1bControlBlock)
|
||||
outw(s_cst(uint16_t, acpi->FADT->PM1bControlBlock),
|
||||
s_cst(uint16_t,
|
||||
(inw(
|
||||
s_cst(uint16_t, acpi->FADT->PM1bControlBlock)) &
|
||||
0xE3FF) |
|
||||
((SLP_TYPb << 10) | ACPI_SLEEP)));
|
||||
|
||||
outw(s_cst(uint16_t, PM1a_CNT), SLP_TYPa | SLP_EN);
|
||||
if (PM1b_CNT)
|
||||
outw(s_cst(uint16_t, PM1b_CNT), SLP_TYPb | SLP_EN);
|
||||
}
|
||||
}
|
||||
|
||||
void DSDT::Reboot()
|
||||
{
|
||||
trace("Rebooting...");
|
||||
switch (acpi->FADT->ResetReg.AddressSpace)
|
||||
{
|
||||
case ACPI_GAS_MMIO:
|
||||
{
|
||||
*(uint8_t *)(acpi->FADT->ResetReg.Address) = acpi->FADT->ResetValue;
|
||||
break;
|
||||
}
|
||||
case ACPI_GAS_IO:
|
||||
{
|
||||
outb(s_cst(uint16_t, acpi->FADT->ResetReg.Address), acpi->FADT->ResetValue);
|
||||
break;
|
||||
}
|
||||
case ACPI_GAS_PCI:
|
||||
{
|
||||
fixme("ACPI_GAS_PCI not supported.");
|
||||
/*
|
||||
seg - 0
|
||||
bus - 0
|
||||
dev - (FADT->ResetReg.Address >> 32) & 0xFFFF
|
||||
function - (FADT->ResetReg.Address >> 16) & 0xFFFF
|
||||
offset - FADT->ResetReg.Address & 0xFFFF
|
||||
value - FADT->ResetValue
|
||||
*/
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
error("Unknown reset register address space: %d", acpi->FADT->ResetReg.AddressSpace);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt)
|
||||
{
|
||||
this->acpi = acpi;
|
||||
uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt);
|
||||
uint8_t *S5Address = (uint8_t *)(Address) + 36;
|
||||
ACPI::ACPI::ACPIHeader *Header = (ACPI::ACPI::ACPIHeader *)Address;
|
||||
size_t Length = Header->Length;
|
||||
while (Length-- > 0)
|
||||
{
|
||||
if (!memcmp(S5Address, "_S5_", 4))
|
||||
break;
|
||||
S5Address++;
|
||||
}
|
||||
if (Length <= 0)
|
||||
{
|
||||
warn("_S5 not present in ACPI");
|
||||
return;
|
||||
}
|
||||
if ((*(S5Address - 1) == 0x08 || (*(S5Address - 2) == 0x08 && *(S5Address - 1) == '\\')) && *(S5Address + 4) == 0x12)
|
||||
{
|
||||
S5Address += 5;
|
||||
S5Address += ((*S5Address & 0xC0) >> 6) + 2;
|
||||
if (*S5Address == 0x0A)
|
||||
S5Address++;
|
||||
SLP_TYPa = s_cst(uint16_t, *(S5Address) << 10);
|
||||
S5Address++;
|
||||
if (*S5Address == 0x0A)
|
||||
S5Address++;
|
||||
SLP_TYPb = s_cst(uint16_t, *(S5Address) << 10);
|
||||
SMI_CMD = acpi->FADT->SMI_CommandPort;
|
||||
ACPI_ENABLE = acpi->FADT->AcpiEnable;
|
||||
ACPI_DISABLE = acpi->FADT->AcpiDisable;
|
||||
PM1a_CNT = acpi->FADT->PM1aControlBlock;
|
||||
PM1b_CNT = acpi->FADT->PM1bControlBlock;
|
||||
PM1_CNT_LEN = acpi->FADT->PM1ControlLength;
|
||||
SLP_EN = 1 << 13;
|
||||
SCI_EN = 1;
|
||||
trace("ACPI Shutdown is supported");
|
||||
ACPIShutdownSupported = true;
|
||||
|
||||
uint16_t value = ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_WAKE;
|
||||
{
|
||||
uint16_t a = s_cst(uint16_t, acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2));
|
||||
uint16_t b = s_cst(uint16_t, acpi->FADT->PM1bEventBlock + (acpi->FADT->PM1EventLength / 2));
|
||||
debug("SCI Event: %#lx [a:%#x b:%#x]", value, a, b);
|
||||
if (acpi->FADT->PM1aEventBlock)
|
||||
outw(a, value);
|
||||
if (acpi->FADT->PM1bEventBlock)
|
||||
outw(b, value);
|
||||
}
|
||||
|
||||
{
|
||||
uint16_t a = 0, b = 0;
|
||||
if (acpi->FADT->PM1aEventBlock)
|
||||
{
|
||||
a = inw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock));
|
||||
outw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock), a);
|
||||
}
|
||||
if (acpi->FADT->PM1bEventBlock)
|
||||
{
|
||||
b = inw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock));
|
||||
outw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock), b);
|
||||
}
|
||||
}
|
||||
((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, acpi->FADT->SCI_Interrupt, 1);
|
||||
return;
|
||||
}
|
||||
warn("Failed to parse _S5 in ACPI");
|
||||
SCI_EN = 0;
|
||||
}
|
||||
|
||||
DSDT::~DSDT()
|
||||
{
|
||||
}
|
||||
}
|
@ -76,7 +76,7 @@ namespace Memory
|
||||
{
|
||||
// 0x1000 aligned
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFFFFFFFFFF000;
|
||||
Address &= 0xFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
|
||||
@ -101,7 +101,7 @@ namespace Memory
|
||||
PageDirectoryEntry *Virtual::GetPDE(void *VirtualAddress, MapType Type)
|
||||
{
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFFFFFFFFFF000;
|
||||
Address &= 0xFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
@ -113,7 +113,7 @@ namespace Memory
|
||||
PageTableEntry *Virtual::GetPTE(void *VirtualAddress, MapType Type)
|
||||
{
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFFFFFFFFFF000;
|
||||
Address &= 0xFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
|
91
Architecture/i386/MultipleAPICDescriptionTable.cpp
Normal file
91
Architecture/i386/MultipleAPICDescriptionTable.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel 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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "acpi.hpp"
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
namespace ACPI
|
||||
{
|
||||
MADT::MADT(ACPI::MADTHeader *madt)
|
||||
{
|
||||
trace("Initializing MADT");
|
||||
CPUCores = 0;
|
||||
LAPICAddress = (LAPIC *)(uintptr_t)madt->LocalControllerAddress;
|
||||
for (uint8_t *ptr = (uint8_t *)(madt->Entries);
|
||||
(uintptr_t)(ptr) < (uintptr_t)(madt) + madt->Header.Length;
|
||||
ptr += *(ptr + 1))
|
||||
{
|
||||
switch (*(ptr))
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (ptr[4] & 1)
|
||||
{
|
||||
lapic.push_back((LocalAPIC *)ptr);
|
||||
KPrint("Local APIC \e8888FF%d\eCCCCCC (APIC \e8888FF%d\eCCCCCC) found.", lapic.back()->ACPIProcessorId, lapic.back()->APICId);
|
||||
CPUCores++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
ioapic.push_back((MADTIOApic *)ptr);
|
||||
KPrint("I/O APIC \e8888FF%d\eCCCCCC (Address \e8888FF%#lx\eCCCCCC) found.", ioapic.back()->APICID, ioapic.back()->Address);
|
||||
Memory::Virtual(KernelPageTable).Map((void *)(uintptr_t)ioapic.back()->Address, (void *)(uintptr_t)ioapic.back()->Address, Memory::PTFlag::RW | Memory::PTFlag::PCD); // Make sure that the address is mapped.
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
iso.push_back((MADTIso *)ptr);
|
||||
KPrint("ISO (IRQ:\e8888FF%#lx\eCCCCCC, BUS:\e8888FF%#lx\eCCCCCC, GSI:\e8888FF%#lx\eCCCCCC, %s\eCCCCCC/%s\eCCCCCC) found.",
|
||||
iso.back()->IRQSource, iso.back()->BuSSource, iso.back()->GSI,
|
||||
iso.back()->Flags & 0x00000004 ? "\e1770FFActive High" : "\e475EFFActive Low",
|
||||
iso.back()->Flags & 0x00000100 ? "\e00962DEdge Triggered" : "\e008F58Level Triggered");
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
nmi.push_back((MADTNmi *)ptr);
|
||||
KPrint("NMI \e8888FF%#lx\eCCCCCC (lint:\e8888FF%#lx\eCCCCCC) found.", nmi.back()->processor, nmi.back()->lint);
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
LAPICAddress = (LAPIC *)ptr;
|
||||
KPrint("APIC found at \e8888FF%#lx\eCCCCCC", LAPICAddress);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
KPrint("Unknown MADT entry \e8888FF%#lx\eCCCCCC", *(ptr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
Memory::Virtual(KernelPageTable).Map((void *)LAPICAddress, (void *)LAPICAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD); // I should map more than one page?
|
||||
}
|
||||
CPUCores--; // We start at 0 (BSP) and end at 11 (APs), so we have 12 cores.
|
||||
KPrint("Total CPU cores: %d", CPUCores + 1);
|
||||
}
|
||||
|
||||
MADT::~MADT()
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,411 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel 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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "apic.hpp"
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <uart.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <cpu.hpp>
|
||||
#include <smp.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../acpi.hpp"
|
||||
|
||||
NewLock(APICLock);
|
||||
|
||||
using namespace CPU::x32;
|
||||
using namespace CPU::x86;
|
||||
|
||||
/*
|
||||
In constructor ‘APIC::APIC::APIC(int)’:
|
||||
warning: left shift count >= width of type
|
||||
| APICBaseAddress = BaseStruct.ApicBaseLo << 12u | BaseStruct.ApicBaseHi << 32u;
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~^~~~~~
|
||||
*/
|
||||
#pragma GCC diagnostic ignored "-Wshift-count-overflow"
|
||||
|
||||
namespace APIC
|
||||
{
|
||||
// headache
|
||||
// https://www.amd.com/system/files/TechDocs/24593.pdf
|
||||
// https://www.naic.edu/~phil/software/intel/318148.pdf
|
||||
|
||||
uint32_t APIC::Read(uint32_t Register)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (Register != APIC_ICRLO &&
|
||||
Register != APIC_ICRHI &&
|
||||
Register != APIC_ID)
|
||||
debug("APIC::Read(%#lx) [x2=%d]", Register, x2APICSupported ? 1 : 0);
|
||||
#endif
|
||||
if (x2APICSupported)
|
||||
{
|
||||
if (Register != APIC_ICRHI)
|
||||
return s_cst(uint32_t, rdmsr((Register >> 4) + 0x800));
|
||||
else
|
||||
return s_cst(uint32_t, rdmsr(0x30 + 0x800));
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU::MemBar::Barrier();
|
||||
uint32_t ret = *((volatile uint32_t *)((uintptr_t)APICBaseAddress + Register));
|
||||
CPU::MemBar::Barrier();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
void APIC::Write(uint32_t Register, uint32_t Value)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (Register != APIC_EOI &&
|
||||
Register != APIC_TDCR &&
|
||||
Register != APIC_TIMER &&
|
||||
Register != APIC_TICR &&
|
||||
Register != APIC_ICRLO &&
|
||||
Register != APIC_ICRHI)
|
||||
debug("APIC::Write(%#lx, %#lx) [x2=%d]", Register, Value, x2APICSupported ? 1 : 0);
|
||||
#endif
|
||||
if (x2APICSupported)
|
||||
{
|
||||
if (Register != APIC_ICRHI)
|
||||
wrmsr((Register >> 4) + 0x800, Value);
|
||||
else
|
||||
wrmsr(MSR_X2APIC_ICR, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU::MemBar::Barrier();
|
||||
*((volatile uint32_t *)(((uintptr_t)APICBaseAddress) + Register)) = Value;
|
||||
CPU::MemBar::Barrier();
|
||||
}
|
||||
}
|
||||
|
||||
void APIC::IOWrite(uint64_t Base, uint32_t Register, uint32_t Value)
|
||||
{
|
||||
debug("APIC::IOWrite(%#lx, %#lx, %#lx)", Base, Register, Value);
|
||||
CPU::MemBar::Barrier();
|
||||
*((volatile uint32_t *)(((uintptr_t)Base))) = Register;
|
||||
CPU::MemBar::Barrier();
|
||||
*((volatile uint32_t *)(((uintptr_t)Base + 16))) = Value;
|
||||
CPU::MemBar::Barrier();
|
||||
}
|
||||
|
||||
uint32_t APIC::IORead(uint64_t Base, uint32_t Register)
|
||||
{
|
||||
debug("APIC::IORead(%#lx, %#lx)", Base, Register);
|
||||
CPU::MemBar::Barrier();
|
||||
*((volatile uint32_t *)(((uintptr_t)Base))) = Register;
|
||||
CPU::MemBar::Barrier();
|
||||
uint32_t ret = *((volatile uint32_t *)(((uintptr_t)Base + 16)));
|
||||
CPU::MemBar::Barrier();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void APIC::EOI() { this->Write(APIC_EOI, 0); }
|
||||
|
||||
void APIC::WaitForIPI()
|
||||
{
|
||||
InterruptCommandRegisterLow icr = {.raw = 0};
|
||||
do
|
||||
{
|
||||
icr.raw = this->Read(APIC_ICRLO);
|
||||
CPU::Pause();
|
||||
} while (icr.DeliveryStatus != Idle);
|
||||
}
|
||||
|
||||
void APIC::IPI(uint8_t CPU, InterruptCommandRegisterLow icr)
|
||||
{
|
||||
SmartCriticalSection(APICLock);
|
||||
if (x2APICSupported)
|
||||
{
|
||||
wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
|
||||
this->WaitForIPI();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->Write(APIC_ICRHI, (CPU << 24));
|
||||
this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
|
||||
this->WaitForIPI();
|
||||
}
|
||||
}
|
||||
|
||||
void APIC::SendInitIPI(uint8_t CPU)
|
||||
{
|
||||
SmartCriticalSection(APICLock);
|
||||
if (x2APICSupported)
|
||||
{
|
||||
InterruptCommandRegisterLow icr = {.raw = 0};
|
||||
icr.DeliveryMode = INIT;
|
||||
icr.Level = Assert;
|
||||
wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
|
||||
this->WaitForIPI();
|
||||
}
|
||||
else
|
||||
{
|
||||
InterruptCommandRegisterLow icr = {.raw = 0};
|
||||
icr.DeliveryMode = INIT;
|
||||
icr.Level = Assert;
|
||||
this->Write(APIC_ICRHI, (CPU << 24));
|
||||
this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
|
||||
this->WaitForIPI();
|
||||
}
|
||||
}
|
||||
|
||||
void APIC::SendStartupIPI(uint8_t CPU, uint64_t StartupAddress)
|
||||
{
|
||||
SmartCriticalSection(APICLock);
|
||||
if (x2APICSupported)
|
||||
{
|
||||
InterruptCommandRegisterLow icr = {.raw = 0};
|
||||
icr.Vector = s_cst(uint8_t, StartupAddress >> 12);
|
||||
icr.DeliveryMode = Startup;
|
||||
icr.Level = Assert;
|
||||
wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
|
||||
this->WaitForIPI();
|
||||
}
|
||||
else
|
||||
{
|
||||
InterruptCommandRegisterLow icr = {.raw = 0};
|
||||
icr.Vector = s_cst(uint8_t, StartupAddress >> 12);
|
||||
icr.DeliveryMode = Startup;
|
||||
icr.Level = Assert;
|
||||
this->Write(APIC_ICRHI, (CPU << 24));
|
||||
this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
|
||||
this->WaitForIPI();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t APIC::IOGetMaxRedirect(uint32_t APICID)
|
||||
{
|
||||
uint32_t TableAddress = (this->IORead((((ACPI::MADT *)PowerManager->GetMADT())->ioapic[APICID]->Address), GetIOAPICVersion));
|
||||
return ((IOAPICVersion *)&TableAddress)->MaximumRedirectionEntry;
|
||||
}
|
||||
|
||||
void APIC::RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status)
|
||||
{
|
||||
uint64_t Value = Vector;
|
||||
|
||||
int64_t IOAPICTarget = -1;
|
||||
for (uint64_t i = 0; ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[std::size_t(i)] != 0; i++)
|
||||
if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[std::size_t(i)]->GSIBase <= GSI)
|
||||
if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[std::size_t(i)]->GSIBase + IOGetMaxRedirect(s_cst(uint32_t, i)) > GSI)
|
||||
{
|
||||
IOAPICTarget = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IOAPICTarget == -1)
|
||||
{
|
||||
error("No ISO table found for I/O APIC");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: IOAPICRedirectEntry Entry = {.raw = 0};
|
||||
|
||||
if (Flags & ActiveHighLow)
|
||||
Value |= (1 << 13);
|
||||
|
||||
if (Flags & EdgeLevel)
|
||||
Value |= (1 << 15);
|
||||
|
||||
if (!Status)
|
||||
Value |= (1 << 16);
|
||||
|
||||
Value |= (((uintptr_t)CPU) << 56);
|
||||
uint32_t IORegister = (GSI - ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[std::size_t(IOAPICTarget)]->GSIBase) * 2 + 16;
|
||||
|
||||
this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[std::size_t(IOAPICTarget)]->Address,
|
||||
IORegister, (uint32_t)Value);
|
||||
this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[std::size_t(IOAPICTarget)]->Address,
|
||||
IORegister + 1, (uint32_t)(Value >> 32));
|
||||
}
|
||||
|
||||
void APIC::RedirectIRQ(int CPU, uint16_t IRQ, int Status)
|
||||
{
|
||||
for (uint64_t i = 0; i < ((ACPI::MADT *)PowerManager->GetMADT())->iso.size(); i++)
|
||||
if (((ACPI::MADT *)PowerManager->GetMADT())->iso[std::size_t(i)]->IRQSource == IRQ)
|
||||
{
|
||||
debug("[ISO %d] Mapping to source IRQ%#d GSI:%#lx on CPU %d",
|
||||
i, ((ACPI::MADT *)PowerManager->GetMADT())->iso[std::size_t(i)]->IRQSource,
|
||||
((ACPI::MADT *)PowerManager->GetMADT())->iso[std::size_t(i)]->GSI,
|
||||
CPU);
|
||||
|
||||
this->RawRedirectIRQ(((ACPI::MADT *)PowerManager->GetMADT())->iso[std::size_t(i)]->IRQSource + 0x20,
|
||||
((ACPI::MADT *)PowerManager->GetMADT())->iso[std::size_t(i)]->GSI,
|
||||
((ACPI::MADT *)PowerManager->GetMADT())->iso[std::size_t(i)]->Flags,
|
||||
CPU, Status);
|
||||
return;
|
||||
}
|
||||
debug("Mapping IRQ%d on CPU %d", IRQ, CPU);
|
||||
this->RawRedirectIRQ(IRQ + 0x20, IRQ, 0, CPU, Status);
|
||||
}
|
||||
|
||||
void APIC::RedirectIRQs(int CPU)
|
||||
{
|
||||
SmartCriticalSection(APICLock);
|
||||
debug("Redirecting IRQs...");
|
||||
for (uint8_t i = 0; i < 16; i++)
|
||||
this->RedirectIRQ(CPU, i, 1);
|
||||
debug("Redirecting IRQs completed.");
|
||||
}
|
||||
|
||||
APIC::APIC(int Core)
|
||||
{
|
||||
SmartCriticalSection(APICLock);
|
||||
APIC_BASE BaseStruct = {.raw = rdmsr(MSR_APIC_BASE)};
|
||||
uint64_t BaseLow = BaseStruct.ApicBaseLo;
|
||||
uint64_t BaseHigh = BaseStruct.ApicBaseHi;
|
||||
this->APICBaseAddress = BaseLow << 12u | BaseHigh << 32u;
|
||||
trace("APIC Address: %#lx", this->APICBaseAddress);
|
||||
Memory::Virtual().Map((void *)this->APICBaseAddress, (void *)this->APICBaseAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD);
|
||||
|
||||
bool x2APICSupported = false;
|
||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
||||
{
|
||||
CPU::x86::AMD::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
if (cpuid.ECX.x2APIC)
|
||||
{
|
||||
// x2APICSupported = cpuid.ECX.x2APIC;
|
||||
fixme("x2APIC is supported");
|
||||
}
|
||||
}
|
||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
||||
{
|
||||
CPU::x86::Intel::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
if (cpuid.ECX.x2APIC)
|
||||
{
|
||||
// x2APICSupported = cpuid.ECX.x2APIC;
|
||||
fixme("x2APIC is supported");
|
||||
}
|
||||
}
|
||||
|
||||
if (x2APICSupported)
|
||||
{
|
||||
this->x2APICSupported = true;
|
||||
wrmsr(MSR_APIC_BASE, (rdmsr(MSR_APIC_BASE) | (1 << 11)) & ~(1 << 10));
|
||||
BaseStruct.EN = 1;
|
||||
wrmsr(MSR_APIC_BASE, BaseStruct.raw);
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseStruct.EN = 1;
|
||||
wrmsr(MSR_APIC_BASE, BaseStruct.raw);
|
||||
}
|
||||
|
||||
this->Write(APIC_TPR, 0x0);
|
||||
// this->Write(APIC_SVR, this->Read(APIC_SVR) | 0x100); // 0x1FF or 0x100 ? on https://wiki.osdev.org/APIC is 0x100
|
||||
|
||||
if (!this->x2APICSupported)
|
||||
{
|
||||
this->Write(APIC_DFR, 0xF0000000);
|
||||
this->Write(APIC_LDR, this->Read(APIC_ID));
|
||||
}
|
||||
|
||||
ACPI::MADT *madt = (ACPI::MADT *)PowerManager->GetMADT();
|
||||
|
||||
for (size_t i = 0; i < madt->nmi.size(); i++)
|
||||
{
|
||||
if (madt->nmi[std::size_t(i)]->processor != 0xFF && Core != madt->nmi[std::size_t(i)]->processor)
|
||||
return;
|
||||
|
||||
uint32_t nmi = 0x402;
|
||||
if (madt->nmi[std::size_t(i)]->flags & 2)
|
||||
nmi |= 1 << 13;
|
||||
if (madt->nmi[std::size_t(i)]->flags & 8)
|
||||
nmi |= 1 << 15;
|
||||
if (madt->nmi[std::size_t(i)]->lint == 0)
|
||||
this->Write(APIC_LINT0, nmi);
|
||||
else if (madt->nmi[std::size_t(i)]->lint == 1)
|
||||
this->Write(APIC_LINT1, nmi);
|
||||
}
|
||||
|
||||
// Setup the spurrious interrupt vector
|
||||
Spurious Spurious = {.raw = this->Read(APIC_SVR)};
|
||||
Spurious.Vector = IRQ223; // TODO: Should I map the IRQ to something?
|
||||
Spurious.Software = 1;
|
||||
this->Write(APIC_SVR, s_cst(uint32_t, Spurious.raw));
|
||||
|
||||
static int once = 0;
|
||||
if (!once++)
|
||||
{
|
||||
// Disable PIT
|
||||
outb(0x43, 0x28);
|
||||
outb(0x40, 0x0);
|
||||
|
||||
// Disable PIC
|
||||
outb(0x21, 0xFF);
|
||||
outb(0xA1, 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
APIC::~APIC() {}
|
||||
|
||||
void Timer::OnInterruptReceived(TrapFrame *Frame) { UNUSED(Frame); }
|
||||
|
||||
void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds)
|
||||
{
|
||||
SmartCriticalSection(APICLock);
|
||||
LVTTimer timer = {.raw = 0};
|
||||
timer.Vector = s_cst(uint8_t, Vector);
|
||||
timer.TimerMode = 0;
|
||||
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
|
||||
this->lapic->Write(APIC_TDCR, DivideBy128);
|
||||
else
|
||||
this->lapic->Write(APIC_TDCR, DivideBy16);
|
||||
this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks * Miliseconds));
|
||||
this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw));
|
||||
}
|
||||
|
||||
Timer::Timer(APIC *apic) : Interrupts::Handler(0) /* IRQ0 */
|
||||
{
|
||||
SmartCriticalSection(APICLock);
|
||||
this->lapic = apic;
|
||||
LVTTimerDivide Divider = DivideBy16;
|
||||
|
||||
trace("Initializing APIC timer on CPU %d", GetCurrentCPU()->ID);
|
||||
|
||||
this->lapic->Write(APIC_TDCR, Divider);
|
||||
this->lapic->Write(APIC_TICR, 0xFFFFFFFF);
|
||||
|
||||
TimeManager->Sleep(1, Time::Units::Milliseconds);
|
||||
|
||||
// Mask the timer
|
||||
this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */);
|
||||
Ticks = 0xFFFFFFFF - this->lapic->Read(APIC_TCCR);
|
||||
|
||||
// Config for IRQ0 timer
|
||||
LVTTimer timer = {.raw = 0};
|
||||
timer.Vector = IRQ0;
|
||||
timer.Mask = Unmasked;
|
||||
timer.TimerMode = LVTTimerMode::OneShot;
|
||||
|
||||
// Initialize APIC timer
|
||||
this->lapic->Write(APIC_TDCR, Divider);
|
||||
this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks));
|
||||
this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw));
|
||||
trace("%d APIC Timer %d ticks in.", GetCurrentCPU()->ID, Ticks);
|
||||
KPrint("APIC Timer: \e8888FF%ld\eCCCCCC ticks.", Ticks);
|
||||
}
|
||||
|
||||
Timer::~Timer()
|
||||
{
|
||||
}
|
||||
}
|
@ -228,7 +228,14 @@ namespace GlobalDescriptorTable
|
||||
gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF;
|
||||
gdt[Core].Entries->TaskStateSegment.BaseMiddle = uint8_t((Base >> 16) & 0xFF);
|
||||
gdt[Core].Entries->TaskStateSegment.BaseHigh = uint8_t((Base >> 24) & 0xFF);
|
||||
|
||||
#pragma diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wshift-count-overflow"
|
||||
|
||||
gdt[Core].Entries->TaskStateSegment.BaseUpper = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF);
|
||||
|
||||
#pragma diagnostic pop
|
||||
|
||||
gdt[Core].Entries->TaskStateSegment.Access = {.A = 1, .RW = 0, .DC = 0, .E = 1, .S = 0, .DPL = 0, .P = 1};
|
||||
gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF);
|
||||
|
||||
|
@ -23,7 +23,17 @@
|
||||
#include <cpu.hpp>
|
||||
#include <atomic>
|
||||
|
||||
#include <smp.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <assert.h>
|
||||
#include <cpu.hpp>
|
||||
#include <atomic>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../acpi.hpp"
|
||||
#include "apic.hpp"
|
||||
|
||||
enum SMPTrampolineAddress
|
||||
{
|
||||
@ -59,8 +69,19 @@ namespace SMP
|
||||
{
|
||||
int CPUCores = 0;
|
||||
|
||||
void Initialize(void *madt)
|
||||
void Initialize(void *_madt)
|
||||
{
|
||||
ACPI::MADT *madt = (ACPI::MADT *)_madt;
|
||||
|
||||
int Cores = madt->CPUCores + 1;
|
||||
|
||||
if (Config.Cores > madt->CPUCores + 1)
|
||||
KPrint("More cores requested than available. Using %d cores", madt->CPUCores + 1);
|
||||
else if (Config.Cores != 0)
|
||||
Cores = Config.Cores;
|
||||
|
||||
CPUCores = Cores;
|
||||
|
||||
fixme("SMP::Initialize() is not implemented!");
|
||||
}
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ namespace APIC
|
||||
void SendInitIPI(uint8_t CPU);
|
||||
void SendStartupIPI(uint8_t CPU, uint64_t StartupAddress);
|
||||
uint32_t IOGetMaxRedirect(uint32_t APICID);
|
||||
void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
|
||||
void RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
|
||||
void RedirectIRQ(int CPU, uint16_t IRQ, int Status);
|
||||
APIC(int Core);
|
||||
~APIC();
|
||||
|
@ -35,74 +35,92 @@
|
||||
|
||||
NewLock(DriverDisplayPrintLock);
|
||||
|
||||
void DriverDebugPrint(char *String, unsigned long DriverUID) { trace("[%ld] %s", DriverUID, String); }
|
||||
void DriverDebugPrint(char *String, __UINT64_TYPE__ DriverUID)
|
||||
{
|
||||
trace("[%ld] %s", DriverUID, String);
|
||||
}
|
||||
|
||||
void DriverDisplayPrint(char *String)
|
||||
{
|
||||
SmartLock(DriverDisplayPrintLock);
|
||||
for (unsigned long i = 0; i < strlen(String); i++)
|
||||
for (__UINT64_TYPE__ i = 0; i < strlen(String); i++)
|
||||
Display->Print(String[i], 0, true);
|
||||
}
|
||||
|
||||
void *RequestPage(unsigned long Size)
|
||||
void *RequestPage(__UINT64_TYPE__ Size)
|
||||
{
|
||||
void *ret = KernelAllocator.RequestPages(Size + 1);
|
||||
drvdbg("Allocated %ld pages (%#lx-%#lx)", Size, (unsigned long)ret, (unsigned long)ret + FROM_PAGES(Size));
|
||||
void *ret = KernelAllocator.RequestPages(size_t(Size + 1));
|
||||
drvdbg("Allocated %ld pages (%#lx-%#lx)",
|
||||
Size, (__UINT64_TYPE__)ret,
|
||||
(__UINT64_TYPE__)ret + FROM_PAGES(Size));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FreePage(void *Page, unsigned long Size)
|
||||
void FreePage(void *Page, __UINT64_TYPE__ Size)
|
||||
{
|
||||
drvdbg("Freeing %ld pages (%#lx-%#lx)", Size, (unsigned long)Page, (unsigned long)Page + FROM_PAGES(Size));
|
||||
KernelAllocator.FreePages(Page, Size + 1);
|
||||
drvdbg("Freeing %ld pages (%#lx-%#lx)",
|
||||
Size, (__UINT64_TYPE__)Page,
|
||||
(__UINT64_TYPE__)Page + FROM_PAGES(Size));
|
||||
KernelAllocator.FreePages(Page, size_t(Size + 1));
|
||||
}
|
||||
|
||||
void MapMemory(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags)
|
||||
void MapMemory(void *VirtualAddress, void *PhysicalAddress, __UINT64_TYPE__ Flags)
|
||||
{
|
||||
SmartLock(DriverDisplayPrintLock);
|
||||
drvdbg("Mapping %#lx to %#lx with flags %#lx...", (unsigned long)VirtualAddress, (unsigned long)PhysicalAddress, Flags);
|
||||
drvdbg("Mapping %#lx to %#lx with flags %#lx...",
|
||||
(__UINT64_TYPE__)VirtualAddress,
|
||||
(__UINT64_TYPE__)PhysicalAddress, Flags);
|
||||
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
|
||||
}
|
||||
|
||||
void UnmapMemory(void *VirtualAddress)
|
||||
{
|
||||
SmartLock(DriverDisplayPrintLock);
|
||||
drvdbg("Unmapping %#lx...", (unsigned long)VirtualAddress);
|
||||
drvdbg("Unmapping %#lx...",
|
||||
(__UINT64_TYPE__)VirtualAddress);
|
||||
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
|
||||
}
|
||||
|
||||
void *Drivermemcpy(void *Destination, void *Source, unsigned long Size)
|
||||
void *Drivermemcpy(void *Destination, void *Source, __UINT64_TYPE__ Size)
|
||||
{
|
||||
SmartLock(DriverDisplayPrintLock);
|
||||
drvdbg("Copying %ld bytes from %#lx-%#lx to %#lx-%#lx...", Size,
|
||||
(unsigned long)Source, (unsigned long)Source + Size,
|
||||
(unsigned long)Destination, (unsigned long)Destination + Size);
|
||||
return memcpy(Destination, Source, Size);
|
||||
(__UINT64_TYPE__)Source, (__UINT64_TYPE__)Source + Size,
|
||||
(__UINT64_TYPE__)Destination, (__UINT64_TYPE__)Destination + Size);
|
||||
return memcpy(Destination, Source, size_t(Size));
|
||||
}
|
||||
|
||||
void *Drivermemset(void *Destination, int Value, unsigned long Size)
|
||||
void *Drivermemset(void *Destination, int Value, __UINT64_TYPE__ Size)
|
||||
{
|
||||
SmartLock(DriverDisplayPrintLock);
|
||||
drvdbg("Setting value %#x at %#lx-%#lx (%ld bytes)...", Value,
|
||||
(unsigned long)Destination, (unsigned long)Destination + Size,
|
||||
Size);
|
||||
return memset(Destination, Value, Size);
|
||||
(__UINT64_TYPE__)Destination,
|
||||
(__UINT64_TYPE__)Destination + Size, Size);
|
||||
return memset(Destination, Value, size_t(Size));
|
||||
}
|
||||
|
||||
void DriverNetSend(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
||||
void DriverNetSend(__UINT32_TYPE__ DriverID,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT16_TYPE__ Size)
|
||||
{
|
||||
// This is useless I guess...
|
||||
if (NIManager)
|
||||
NIManager->DrvSend(DriverID, Data, Size);
|
||||
}
|
||||
|
||||
void DriverNetReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
||||
void DriverNetReceive(__UINT32_TYPE__ DriverID,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT16_TYPE__ Size)
|
||||
{
|
||||
if (NIManager)
|
||||
NIManager->DrvReceive(DriverID, Data, Size);
|
||||
}
|
||||
|
||||
void DriverAHCIDiskRead(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
|
||||
void DriverAHCIDiskRead(__UINT32_TYPE__ DriverID,
|
||||
__UINT64_TYPE__ Sector,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT32_TYPE__ SectorCount,
|
||||
__UINT8_TYPE__ Port)
|
||||
{
|
||||
DumpData("DriverDiskRead", Data, SectorCount * 512);
|
||||
UNUSED(DriverID);
|
||||
@ -110,41 +128,50 @@ void DriverAHCIDiskRead(unsigned int DriverID, unsigned long Sector, unsigned ch
|
||||
UNUSED(Port);
|
||||
}
|
||||
|
||||
void DriverAHCIDiskWrite(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
|
||||
void DriverAHCIDiskWrite(__UINT32_TYPE__ DriverID,
|
||||
__UINT64_TYPE__ Sector,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT32_TYPE__ SectorCount,
|
||||
__UINT8_TYPE__ Port)
|
||||
{
|
||||
DumpData("DriverDiskWrite", Data, SectorCount * 512);
|
||||
DumpData("DriverDiskWrite",
|
||||
Data, SectorCount * 512);
|
||||
UNUSED(DriverID);
|
||||
UNUSED(Sector);
|
||||
UNUSED(Port);
|
||||
}
|
||||
|
||||
char *DriverPCIGetDeviceName(unsigned int VendorID, unsigned int DeviceID)
|
||||
char *DriverPCIGetDeviceName(__UINT32_TYPE__ VendorID,
|
||||
__UINT32_TYPE__ DeviceID)
|
||||
{
|
||||
UNUSED(VendorID);
|
||||
UNUSED(DeviceID);
|
||||
return (char *)"Unknown";
|
||||
}
|
||||
|
||||
unsigned int DriverGetWidth()
|
||||
__UINT32_TYPE__ DriverGetWidth()
|
||||
{
|
||||
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
|
||||
/* TODO: We won't rely only on display buffers,
|
||||
what about graphics drivers and changing resolutions? */
|
||||
return Display->GetBuffer(0)->Width;
|
||||
}
|
||||
|
||||
unsigned int DriverGetHeight()
|
||||
__UINT32_TYPE__ DriverGetHeight()
|
||||
{
|
||||
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
|
||||
/* TODO: We won't rely only on display buffers,
|
||||
what about graphics drivers and changing resolutions? */
|
||||
return Display->GetBuffer(0)->Height;
|
||||
}
|
||||
|
||||
void DriverSleep(unsigned long Milliseconds)
|
||||
void DriverSleep(__UINT64_TYPE__ Milliseconds)
|
||||
{
|
||||
SmartLock(DriverDisplayPrintLock);
|
||||
drvdbg("Sleeping for %ld milliseconds...", Milliseconds);
|
||||
if (TaskManager)
|
||||
TaskManager->Sleep(Milliseconds);
|
||||
else
|
||||
TimeManager->Sleep(Milliseconds, Time::Units::Milliseconds);
|
||||
TimeManager->Sleep(size_t(Milliseconds),
|
||||
Time::Units::Milliseconds);
|
||||
}
|
||||
|
||||
int Driversprintf(char *Buffer, const char *Format, ...)
|
||||
|
@ -30,6 +30,8 @@
|
||||
#elif defined(a32)
|
||||
#include "../Architecture/i386/cpu/gdt.hpp"
|
||||
#include "../Architecture/i386/cpu/idt.hpp"
|
||||
#include "../Architecture/i386/acpi.hpp"
|
||||
#include "../Architecture/i386/cpu/apic.hpp"
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
@ -47,11 +49,9 @@ namespace Interrupts
|
||||
};
|
||||
std::vector<Event> RegisteredEvents;
|
||||
|
||||
#if defined(a64)
|
||||
#if defined(a86)
|
||||
/* APIC::APIC */ void *apic[MAX_CPU];
|
||||
/* APIC::Timer */ void *apicTimer[MAX_CPU];
|
||||
#elif defined(a32)
|
||||
/* APIC::APIC */ void *apic[MAX_CPU];
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
void *InterruptFrames[INT_FRAMES_MAX];
|
||||
@ -89,10 +89,12 @@ namespace Interrupts
|
||||
CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE;
|
||||
if (CoreData->Checksum != CPU_DATA_CHECKSUM)
|
||||
{
|
||||
KPrint("CPU %d checksum mismatch! %x != %x", Core, CoreData->Checksum, CPU_DATA_CHECKSUM);
|
||||
KPrint("CPU %d checksum mismatch! %x != %x",
|
||||
Core, CoreData->Checksum, CPU_DATA_CHECKSUM);
|
||||
CPU::Stop();
|
||||
}
|
||||
debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
|
||||
debug("Stack for core %d is %#lx (Address: %#lx)",
|
||||
Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
|
||||
#elif defined(aa64)
|
||||
warn("aarch64 is not supported yet");
|
||||
#endif
|
||||
@ -100,7 +102,7 @@ namespace Interrupts
|
||||
|
||||
void Enable(int Core)
|
||||
{
|
||||
#if defined(a64)
|
||||
#if defined(a86)
|
||||
if (((ACPI::MADT *)PowerManager->GetMADT())->LAPICAddress != nullptr)
|
||||
{
|
||||
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
|
||||
@ -113,8 +115,6 @@ namespace Interrupts
|
||||
error("LAPIC not found");
|
||||
// TODO: PIC
|
||||
}
|
||||
#elif defined(a32)
|
||||
warn("i386 is not supported yet");
|
||||
#elif defined(aa64)
|
||||
warn("aarch64 is not supported yet");
|
||||
#endif
|
||||
@ -123,15 +123,13 @@ namespace Interrupts
|
||||
void InitializeTimer(int Core)
|
||||
{
|
||||
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
|
||||
#if defined(a64)
|
||||
#if defined(a86)
|
||||
if (apic[Core] != nullptr)
|
||||
apicTimer[Core] = new APIC::Timer((APIC::APIC *)apic[Core]);
|
||||
else
|
||||
{
|
||||
fixme("apic not found");
|
||||
}
|
||||
#elif defined(a32)
|
||||
warn("i386 is not supported yet");
|
||||
#elif defined(aa64)
|
||||
warn("aarch64 is not supported yet");
|
||||
#endif
|
||||
|
@ -21,6 +21,7 @@
|
||||
#if defined(a64)
|
||||
#include "../Architecture/amd64/acpi.hpp"
|
||||
#elif defined(a32)
|
||||
#include "../Architecture/i386/acpi.hpp"
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
@ -883,10 +884,10 @@ namespace PCI
|
||||
}
|
||||
}
|
||||
|
||||
void PCI::EnumerateFunction(uintptr_t DeviceAddress, uintptr_t Function)
|
||||
void PCI::EnumerateFunction(uint64_t DeviceAddress, uintptr_t Function)
|
||||
{
|
||||
uintptr_t Offset = Function << 12;
|
||||
uintptr_t FunctionAddress = DeviceAddress + Offset;
|
||||
uint64_t FunctionAddress = DeviceAddress + Offset;
|
||||
Memory::Virtual(KernelPageTable).Map((void *)FunctionAddress, (void *)FunctionAddress, Memory::PTFlag::RW);
|
||||
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)FunctionAddress;
|
||||
if (PCIDeviceHdr->DeviceID == 0)
|
||||
@ -899,10 +900,10 @@ namespace PCI
|
||||
#endif
|
||||
}
|
||||
|
||||
void PCI::EnumerateDevice(uintptr_t BusAddress, uintptr_t Device)
|
||||
void PCI::EnumerateDevice(uint64_t BusAddress, uintptr_t Device)
|
||||
{
|
||||
uintptr_t Offset = Device << 15;
|
||||
uintptr_t DeviceAddress = BusAddress + Offset;
|
||||
uint64_t DeviceAddress = BusAddress + Offset;
|
||||
Memory::Virtual(KernelPageTable).Map((void *)DeviceAddress, (void *)DeviceAddress, Memory::PTFlag::RW);
|
||||
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)DeviceAddress;
|
||||
if (PCIDeviceHdr->DeviceID == 0)
|
||||
@ -913,10 +914,10 @@ namespace PCI
|
||||
EnumerateFunction(DeviceAddress, Function);
|
||||
}
|
||||
|
||||
void PCI::EnumerateBus(uintptr_t BaseAddress, uintptr_t Bus)
|
||||
void PCI::EnumerateBus(uint64_t BaseAddress, uintptr_t Bus)
|
||||
{
|
||||
uintptr_t Offset = Bus << 20;
|
||||
uintptr_t BusAddress = BaseAddress + Offset;
|
||||
uint64_t BusAddress = BaseAddress + Offset;
|
||||
Memory::Virtual(KernelPageTable).Map((void *)BusAddress, (void *)BusAddress, Memory::PTFlag::RW);
|
||||
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)BusAddress;
|
||||
if (Bus != 0) // TODO: VirtualBox workaround (UNTESTED ON REAL HARDWARE!)
|
||||
@ -955,20 +956,18 @@ namespace PCI
|
||||
|
||||
PCI::PCI()
|
||||
{
|
||||
#if defined(a64)
|
||||
#if defined(a86)
|
||||
int Entries = s_cst(int, ((((ACPI::ACPI *)PowerManager->GetACPI())->MCFG->Header.Length) - sizeof(ACPI::ACPI::MCFGHeader)) / sizeof(DeviceConfig));
|
||||
Memory::Virtual vmm = Memory::Virtual(KernelPageTable);
|
||||
for (int t = 0; t < Entries; t++)
|
||||
{
|
||||
DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uintptr_t)((ACPI::ACPI *)PowerManager->GetACPI())->MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t));
|
||||
vmm.Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW);
|
||||
debug("PCI Entry %d Address:%#llx BUS:%#llx-%#llx", t, NewDeviceConfig->BaseAddress,
|
||||
debug("PCI Entry %d Address:%p BUS:%#x-%#x", t, NewDeviceConfig->BaseAddress,
|
||||
NewDeviceConfig->StartBus, NewDeviceConfig->EndBus);
|
||||
for (uintptr_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++)
|
||||
EnumerateBus(NewDeviceConfig->BaseAddress, Bus);
|
||||
}
|
||||
#elif defined(a32)
|
||||
error("PCI not implemented on i386");
|
||||
#elif defined(aa64)
|
||||
error("PCI not implemented on aarch64");
|
||||
#endif
|
||||
|
@ -19,13 +19,16 @@
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
#include <io.h>
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
#if defined(a64)
|
||||
#include <io.h>
|
||||
|
||||
#include "../Architecture/amd64/acpi.hpp"
|
||||
#elif defined(a32)
|
||||
#include "../Architecture/i386/acpi.hpp"
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
namespace Power
|
||||
{
|
||||
@ -86,45 +89,3 @@ namespace Power
|
||||
trace("Power manager initialized");
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(a32)
|
||||
|
||||
namespace Power
|
||||
{
|
||||
void Power::Reboot()
|
||||
{
|
||||
warn("Reboot not implemented for i386");
|
||||
}
|
||||
|
||||
void Power::Shutdown()
|
||||
{
|
||||
warn("Shutdown not implemented for i386");
|
||||
}
|
||||
|
||||
Power::Power()
|
||||
{
|
||||
error("Power not implemented for i386");
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(aa64)
|
||||
|
||||
namespace Power
|
||||
{
|
||||
void Power::Reboot()
|
||||
{
|
||||
warn("Reboot not implemented for aarch64");
|
||||
}
|
||||
|
||||
void Power::Shutdown()
|
||||
{
|
||||
warn("Shutdown not implemented for aarch64");
|
||||
}
|
||||
|
||||
Power::Power()
|
||||
{
|
||||
error("Power not implemented for aarch64");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -53,10 +53,6 @@ namespace SymbolResolver
|
||||
__unused uint64_t Shndx,
|
||||
uintptr_t Sections)
|
||||
{
|
||||
#ifdef a32
|
||||
fixme("Function not working on 32-bit");
|
||||
return;
|
||||
#endif
|
||||
char *sections = reinterpret_cast<char *>(Sections);
|
||||
|
||||
Elf_Sym *Symbols = nullptr;
|
||||
|
158
DAPI.hpp
158
DAPI.hpp
@ -84,32 +84,32 @@ struct KernelAPI
|
||||
|
||||
struct KAPIInfo
|
||||
{
|
||||
unsigned long Offset;
|
||||
unsigned int DriverUID;
|
||||
__UINT64_TYPE__ Offset;
|
||||
__UINT32_TYPE__ DriverUID;
|
||||
char KernelDebug;
|
||||
} Info;
|
||||
|
||||
struct KAPIMemory
|
||||
{
|
||||
unsigned long PageSize;
|
||||
void *(*RequestPage)(unsigned long Size);
|
||||
void (*FreePage)(void *Page, unsigned long Size);
|
||||
void (*Map)(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags);
|
||||
__UINT64_TYPE__ PageSize;
|
||||
void *(*RequestPage)(__UINT64_TYPE__ Size);
|
||||
void (*FreePage)(void *Page, __UINT64_TYPE__ Size);
|
||||
void (*Map)(void *VirtualAddress, void *PhysicalAddress, __UINT64_TYPE__ Flags);
|
||||
void (*Unmap)(void *VirtualAddress);
|
||||
} Memory;
|
||||
|
||||
struct KAPIPCI
|
||||
{
|
||||
char *(*GetDeviceName)(unsigned int VendorID, unsigned int DeviceID);
|
||||
char *(*GetDeviceName)(__UINT32_TYPE__ VendorID, __UINT32_TYPE__ DeviceID);
|
||||
} PCI;
|
||||
|
||||
struct KAPIUtilities
|
||||
{
|
||||
void (*DebugPrint)(char *String, unsigned long DriverUID);
|
||||
void (*DebugPrint)(char *String, __UINT64_TYPE__ DriverUID);
|
||||
void (*DisplayPrint)(char *Value);
|
||||
void *(*memcpy)(void *Destination, void *Source, unsigned long Size);
|
||||
void *(*memset)(void *Destination, int Value, unsigned long Size);
|
||||
void (*Sleep)(unsigned long Milliseconds);
|
||||
void *(*memcpy)(void *Destination, void *Source, __UINT64_TYPE__ Size);
|
||||
void *(*memset)(void *Destination, int Value, __UINT64_TYPE__ Size);
|
||||
void (*Sleep)(__UINT64_TYPE__ Milliseconds);
|
||||
int (*sprintf)(char *Buffer, const char *Format, ...);
|
||||
} Util;
|
||||
|
||||
@ -118,8 +118,8 @@ struct KernelAPI
|
||||
/** Connects to the network manager */
|
||||
struct
|
||||
{
|
||||
void (*SendPacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size);
|
||||
void (*ReceivePacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size);
|
||||
void (*SendPacket)(__UINT32_TYPE__ DriverID, __UINT8_TYPE__ *Data, __UINT16_TYPE__ Size);
|
||||
void (*ReceivePacket)(__UINT32_TYPE__ DriverID, __UINT8_TYPE__ *Data, __UINT16_TYPE__ Size);
|
||||
} Network;
|
||||
|
||||
/** Connects to the disk manager */
|
||||
@ -127,16 +127,16 @@ struct KernelAPI
|
||||
{
|
||||
struct
|
||||
{
|
||||
void (*ReadSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port);
|
||||
void (*WriteSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port);
|
||||
void (*ReadSector)(__UINT32_TYPE__ DriverID, __UINT64_TYPE__ Sector, __UINT8_TYPE__ *Data, __UINT32_TYPE__ SectorCount, __UINT8_TYPE__ Port);
|
||||
void (*WriteSector)(__UINT32_TYPE__ DriverID, __UINT64_TYPE__ Sector, __UINT8_TYPE__ *Data, __UINT32_TYPE__ SectorCount, __UINT8_TYPE__ Port);
|
||||
} AHCI;
|
||||
} Disk;
|
||||
} Command;
|
||||
|
||||
struct KAPIDisplay
|
||||
{
|
||||
unsigned int (*GetWidth)(void);
|
||||
unsigned int (*GetHeight)(void);
|
||||
__UINT32_TYPE__ (*GetWidth)(void);
|
||||
__UINT32_TYPE__ (*GetHeight)(void);
|
||||
/* TODO: Add more */
|
||||
} Display;
|
||||
} __attribute__((packed));
|
||||
@ -230,21 +230,21 @@ union KernelCallback
|
||||
{
|
||||
CallbackReason Reason;
|
||||
void *RawPtr;
|
||||
unsigned long RawData;
|
||||
__UINT64_TYPE__ RawData;
|
||||
|
||||
/** When the kernel wants to send a packet. */
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned char *Data;
|
||||
unsigned long Length;
|
||||
__UINT8_TYPE__ *Data;
|
||||
__UINT64_TYPE__ Length;
|
||||
} Send;
|
||||
|
||||
struct
|
||||
{
|
||||
char Name[128];
|
||||
unsigned long MAC;
|
||||
__UINT64_TYPE__ MAC;
|
||||
} Fetch;
|
||||
} NetworkCallback;
|
||||
|
||||
@ -253,16 +253,16 @@ union KernelCallback
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned long Sector;
|
||||
unsigned long SectorCount;
|
||||
unsigned char Port;
|
||||
unsigned char *Buffer;
|
||||
__UINT64_TYPE__ Sector;
|
||||
__UINT64_TYPE__ SectorCount;
|
||||
__UINT8_TYPE__ Port;
|
||||
__UINT8_TYPE__ *Buffer;
|
||||
bool Write;
|
||||
} RW;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned char Ports;
|
||||
__UINT8_TYPE__ Ports;
|
||||
int BytesPerSector;
|
||||
} Fetch;
|
||||
} DiskCallback;
|
||||
@ -272,9 +272,9 @@ union KernelCallback
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned long X;
|
||||
unsigned long Y;
|
||||
unsigned long Z;
|
||||
__UINT64_TYPE__ X;
|
||||
__UINT64_TYPE__ Y;
|
||||
__UINT64_TYPE__ Z;
|
||||
struct
|
||||
{
|
||||
bool Left;
|
||||
@ -290,7 +290,7 @@ union KernelCallback
|
||||
*
|
||||
* @note This is a scancode, not a character.
|
||||
*/
|
||||
unsigned char Key;
|
||||
__UINT8_TYPE__ Key;
|
||||
} Keyboard;
|
||||
} InputCallback;
|
||||
|
||||
@ -308,7 +308,7 @@ union KernelCallback
|
||||
*
|
||||
* 0 - 100
|
||||
*/
|
||||
unsigned char Volume;
|
||||
__UINT8_TYPE__ Volume;
|
||||
|
||||
/**
|
||||
* Adjust the encoding.
|
||||
@ -349,7 +349,7 @@ union KernelCallback
|
||||
*
|
||||
* ... - More
|
||||
*/
|
||||
unsigned short Encoding;
|
||||
__UINT16_TYPE__ Encoding;
|
||||
|
||||
/**
|
||||
* Adjust the sample rate.
|
||||
@ -364,7 +364,7 @@ union KernelCallback
|
||||
* 7 - 88200 Hz
|
||||
* 8 - 96000 Hz
|
||||
*/
|
||||
unsigned char SampleRate;
|
||||
__UINT8_TYPE__ SampleRate;
|
||||
|
||||
/**
|
||||
* Adjust the channels.
|
||||
@ -372,30 +372,30 @@ union KernelCallback
|
||||
* 0 - Mono
|
||||
* 1 - Stereo
|
||||
*/
|
||||
unsigned char Channels;
|
||||
__UINT8_TYPE__ Channels;
|
||||
} Adjust;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned char *Data;
|
||||
unsigned long Length;
|
||||
__UINT8_TYPE__ *Data;
|
||||
__UINT64_TYPE__ Length;
|
||||
} Send;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned char Volume;
|
||||
unsigned short Encoding;
|
||||
unsigned char SampleRate;
|
||||
unsigned char Channels;
|
||||
__UINT8_TYPE__ Volume;
|
||||
__UINT16_TYPE__ Encoding;
|
||||
__UINT8_TYPE__ SampleRate;
|
||||
__UINT8_TYPE__ Channels;
|
||||
} Fetch;
|
||||
} AudioCallback;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned char Vector;
|
||||
__UINT8_TYPE__ Vector;
|
||||
} InterruptInfo;
|
||||
};
|
||||
unsigned long raw;
|
||||
__UINT64_TYPE__ raw;
|
||||
} __attribute__((packed));
|
||||
|
||||
union CPURegisters
|
||||
@ -403,51 +403,51 @@ union CPURegisters
|
||||
struct
|
||||
{
|
||||
#if defined(__x86_64__) || defined(__amd64__)
|
||||
unsigned long r15;
|
||||
unsigned long r14;
|
||||
unsigned long r13;
|
||||
unsigned long r12;
|
||||
unsigned long r11;
|
||||
unsigned long r10;
|
||||
unsigned long r9;
|
||||
unsigned long r8;
|
||||
__UINT64_TYPE__ r15;
|
||||
__UINT64_TYPE__ r14;
|
||||
__UINT64_TYPE__ r13;
|
||||
__UINT64_TYPE__ r12;
|
||||
__UINT64_TYPE__ r11;
|
||||
__UINT64_TYPE__ r10;
|
||||
__UINT64_TYPE__ r9;
|
||||
__UINT64_TYPE__ r8;
|
||||
|
||||
unsigned long rbp;
|
||||
unsigned long rdi;
|
||||
unsigned long rsi;
|
||||
unsigned long rdx;
|
||||
unsigned long rcx;
|
||||
unsigned long rbx;
|
||||
unsigned long rax;
|
||||
__UINT64_TYPE__ rbp;
|
||||
__UINT64_TYPE__ rdi;
|
||||
__UINT64_TYPE__ rsi;
|
||||
__UINT64_TYPE__ rdx;
|
||||
__UINT64_TYPE__ rcx;
|
||||
__UINT64_TYPE__ rbx;
|
||||
__UINT64_TYPE__ rax;
|
||||
|
||||
unsigned long InterruptNumber;
|
||||
unsigned long ErrorCode;
|
||||
unsigned long rip;
|
||||
unsigned long cs;
|
||||
unsigned long rflags;
|
||||
unsigned long rsp;
|
||||
unsigned long ss;
|
||||
__UINT64_TYPE__ InterruptNumber;
|
||||
__UINT64_TYPE__ ErrorCode;
|
||||
__UINT64_TYPE__ rip;
|
||||
__UINT64_TYPE__ cs;
|
||||
__UINT64_TYPE__ rflags;
|
||||
__UINT64_TYPE__ rsp;
|
||||
__UINT64_TYPE__ ss;
|
||||
#elif defined(__i386__)
|
||||
unsigned int ebp;
|
||||
unsigned int edi;
|
||||
unsigned int esi;
|
||||
unsigned int edx;
|
||||
unsigned int ecx;
|
||||
unsigned int ebx;
|
||||
unsigned int eax;
|
||||
__UINT32_TYPE__ ebp;
|
||||
__UINT32_TYPE__ edi;
|
||||
__UINT32_TYPE__ esi;
|
||||
__UINT32_TYPE__ edx;
|
||||
__UINT32_TYPE__ ecx;
|
||||
__UINT32_TYPE__ ebx;
|
||||
__UINT32_TYPE__ eax;
|
||||
|
||||
unsigned int InterruptNumber;
|
||||
unsigned int ErrorCode;
|
||||
unsigned int eip;
|
||||
unsigned int cs;
|
||||
unsigned int eflags;
|
||||
unsigned int esp;
|
||||
unsigned int ss;
|
||||
__UINT32_TYPE__ InterruptNumber;
|
||||
__UINT32_TYPE__ ErrorCode;
|
||||
__UINT32_TYPE__ eip;
|
||||
__UINT32_TYPE__ cs;
|
||||
__UINT32_TYPE__ eflags;
|
||||
__UINT32_TYPE__ esp;
|
||||
__UINT32_TYPE__ ss;
|
||||
#else
|
||||
#warning "Unsupported architecture"
|
||||
#endif
|
||||
};
|
||||
unsigned long raw;
|
||||
__UINT64_TYPE__ raw;
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif // !__FENNIX_DRIVER_API_H__
|
||||
|
@ -47,6 +47,7 @@ namespace Execute
|
||||
uint64_t EntryPoint,
|
||||
uint64_t BaseAddress)
|
||||
{
|
||||
#if defined(a64)
|
||||
char *aux_platform = (char *)mm->RequestPages(1, true); /* TODO: 4KiB is too much for this */
|
||||
strcpy(aux_platform, "x86_64");
|
||||
|
||||
@ -82,6 +83,7 @@ namespace Execute
|
||||
// AT_HWCAP 16
|
||||
// AT_MINSIGSTKSZ 51
|
||||
// AT_SYSINFO_EHDR 33
|
||||
#endif
|
||||
}
|
||||
|
||||
void ELFObject::LoadExec_x86_32(int fd, PCB *TargetProcess)
|
||||
@ -93,6 +95,7 @@ namespace Execute
|
||||
|
||||
void ELFObject::LoadExec_x86_64(int fd, PCB *TargetProcess)
|
||||
{
|
||||
#if defined(a64)
|
||||
std::string InterpreterPath;
|
||||
std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP);
|
||||
foreach (auto Interp in PhdrINTERP)
|
||||
@ -121,19 +124,7 @@ namespace Execute
|
||||
|
||||
if (LoadInterpreter(ifd, TargetProcess))
|
||||
{
|
||||
/* ba deci de aici trb sa fac
|
||||
sa se incarce interperter-ul
|
||||
argv[1] ar trb sa fie locatia pt intrep */
|
||||
|
||||
// modific argv-ul
|
||||
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
/* FIXME: specify argv[1] as the location for the interpreter */
|
||||
|
||||
debug("Interpreter loaded successfully");
|
||||
fclose(ifd);
|
||||
@ -231,6 +222,7 @@ namespace Execute
|
||||
|
||||
this->ip = EntryPoint;
|
||||
this->IsElfValid = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ELFObject::LoadDyn_x86_32(int fd, PCB *TargetProcess)
|
||||
@ -242,6 +234,7 @@ namespace Execute
|
||||
|
||||
void ELFObject::LoadDyn_x86_64(int fd, PCB *TargetProcess)
|
||||
{
|
||||
#if defined(a64)
|
||||
std::string InterpreterPath;
|
||||
std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP);
|
||||
foreach (auto Interp in PhdrINTERP)
|
||||
@ -270,18 +263,7 @@ namespace Execute
|
||||
|
||||
if (LoadInterpreter(ifd, TargetProcess))
|
||||
{
|
||||
/* ba deci de aici trb sa fac
|
||||
sa se incarce interperter-ul
|
||||
argv[1] ar trb sa fie locatia pt intrep */
|
||||
|
||||
// modific argv-ul
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
|
||||
/* FIXME: specify argv[1] as the location for the interpreter */
|
||||
|
||||
debug("Interpreter loaded successfully");
|
||||
fclose(ifd);
|
||||
@ -619,6 +601,7 @@ namespace Execute
|
||||
|
||||
this->ip = EntryPoint;
|
||||
this->IsElfValid = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ELFObject::LoadInterpreter(int fd, PCB *TargetProcess)
|
||||
|
@ -95,6 +95,7 @@ namespace Execute
|
||||
|
||||
Elf64_Sym ELFLookupSymbol(int fd, const char *Name)
|
||||
{
|
||||
#if defined(a64)
|
||||
off_t OldOffset = lseek(fd, 0, SEEK_CUR);
|
||||
|
||||
Elf64_Ehdr Header;
|
||||
@ -152,6 +153,7 @@ namespace Execute
|
||||
}
|
||||
error("Symbol not found.");
|
||||
lseek(fd, OldOffset, SEEK_SET);
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -198,6 +200,8 @@ namespace Execute
|
||||
Elf64_Shdr *Target = GetELFSection(Header, Symbol->st_shndx);
|
||||
return (uintptr_t)Header + Symbol->st_value + Target->sh_offset;
|
||||
}
|
||||
#elif defined(a32)
|
||||
return 0xdead;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
15
Kernel.cpp
15
Kernel.cpp
@ -252,9 +252,16 @@ EXTERNC void KPrint(const char *Format, ...)
|
||||
uint64_t Nanoseconds = TimeManager->GetNanosecondsSinceClassCreation();
|
||||
if (Nanoseconds != 0)
|
||||
{
|
||||
#if defined(a64)
|
||||
printf("\eCCCCCC[\e00AEFF%lu.%07lu\eCCCCCC] ",
|
||||
Nanoseconds / 10000000,
|
||||
Nanoseconds % 10000000);
|
||||
Nanoseconds / 10000000, Nanoseconds % 10000000);
|
||||
#elif defined(a32)
|
||||
printf("\eCCCCCC[\e00AEFF%llu.%07llu\eCCCCCC] ",
|
||||
Nanoseconds / 10000000, Nanoseconds % 10000000);
|
||||
#elif defined(aa64)
|
||||
printf("\eCCCCCC[\e00AEFF%lu.%07lu\eCCCCCC] ",
|
||||
Nanoseconds / 10000000, Nanoseconds % 10000000);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,10 +331,8 @@ EXTERNC NIF void Main()
|
||||
KPrint("Enabling Interrupts on Bootstrap Processor");
|
||||
Interrupts::Enable(0);
|
||||
|
||||
#if defined(a64)
|
||||
#if defined(a86)
|
||||
PowerManager->InitDSDT();
|
||||
#elif defined(a32)
|
||||
// FIXME: Add ACPI support for i386
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
|
@ -30,17 +30,31 @@ void cmd_top(const char *)
|
||||
printf("\e9400A1PID \e9CA100Name \e00A15BState \eCCCCCCPriority Memory Usage CPU Usage\n");
|
||||
foreach (auto Proc in TaskManager->GetProcessList())
|
||||
{
|
||||
#if defined(a64)
|
||||
printf("\e9400A1%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %ld %ld\n",
|
||||
Proc->ID, Proc->Name, Proc->Status == Running ? "Running" : "Stopped",
|
||||
Proc->Info.Priority, Proc->Memory->GetAllocatedMemorySize(),
|
||||
Proc->Info.UserTime + Proc->Info.KernelTime);
|
||||
#elif defined(a32)
|
||||
printf("\e9400A1%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %lld %lld\n",
|
||||
Proc->ID, Proc->Name, Proc->Status == Running ? "Running" : "Stopped",
|
||||
Proc->Info.Priority, Proc->Memory->GetAllocatedMemorySize(),
|
||||
Proc->Info.UserTime + Proc->Info.KernelTime);
|
||||
#endif
|
||||
|
||||
foreach (auto Thrd in Proc->Threads)
|
||||
{
|
||||
#if defined(a64)
|
||||
printf(" \eA80011%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %ld %ld\n",
|
||||
Thrd->ID, Thrd->Name, Thrd->Status == Running ? "Running" : "Stopped",
|
||||
Thrd->Info.Priority, Thrd->Memory->GetAllocatedMemorySize(),
|
||||
Thrd->Info.UserTime + Thrd->Info.KernelTime);
|
||||
#elif defined(a32)
|
||||
printf(" \eA80011%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %lld %lld\n",
|
||||
Thrd->ID, Thrd->Name, Thrd->Status == Running ? "Running" : "Stopped",
|
||||
Thrd->Info.Priority, Thrd->Memory->GetAllocatedMemorySize(),
|
||||
Thrd->Info.UserTime + Thrd->Info.KernelTime);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,12 +27,12 @@ void cmd_uptime(const char *)
|
||||
{
|
||||
if (TimeManager)
|
||||
{
|
||||
size_t Nanoseconds =
|
||||
uint64_t Nanoseconds =
|
||||
TimeManager->GetNanosecondsSinceClassCreation();
|
||||
size_t Seconds = Nanoseconds / 10000000;
|
||||
size_t Minutes = Seconds / 60;
|
||||
size_t Hours = Minutes / 60;
|
||||
size_t Days = Hours / 24;
|
||||
uint64_t Seconds = Nanoseconds / 10000000;
|
||||
uint64_t Minutes = Seconds / 60;
|
||||
uint64_t Hours = Minutes / 60;
|
||||
uint64_t Days = Hours / 24;
|
||||
|
||||
debug("Nanoseconds: %ld", Nanoseconds);
|
||||
|
||||
@ -40,9 +40,15 @@ void cmd_uptime(const char *)
|
||||
Minutes %= 60;
|
||||
Hours %= 24;
|
||||
|
||||
#if defined(a64)
|
||||
printf("%ld days, %ld hours, %ld minutes, %ld %s\n",
|
||||
Days, Hours, Minutes, Seconds,
|
||||
Seconds == 1 ? "second" : "seconds");
|
||||
#elif defined(a32)
|
||||
printf("%lld days, %lld hours, %lld minutes, %lld %s\n",
|
||||
Days, Hours, Minutes, Seconds,
|
||||
Seconds == 1 ? "second" : "seconds");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -170,8 +170,14 @@ void TaskMgr()
|
||||
continue;
|
||||
int Status = Proc->Status.load();
|
||||
uint64_t ProcessCpuUsage = GetUsage(OldSystemTime, &Proc->Info);
|
||||
#if defined(a64)
|
||||
printf("\e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld)\n",
|
||||
Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime);
|
||||
#elif defined(a32)
|
||||
printf("\e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld)\n",
|
||||
Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
foreach (auto Thd in Proc->Threads)
|
||||
{
|
||||
@ -185,7 +191,7 @@ void TaskMgr()
|
||||
Thd->Info.UserTime, Thd->Registers.rip,
|
||||
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.rip) : "unknown");
|
||||
#elif defined(a32)
|
||||
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld, IP: \e24FF2B%#lx \eEDFF24%s\e00AAAA)\n\eAABBCC",
|
||||
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld, IP: \e24FF2B%#x \eEDFF24%s\e00AAAA)\n\eAABBCC",
|
||||
Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime,
|
||||
Thd->Info.UserTime, Thd->Registers.eip,
|
||||
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.eip) : "unknown");
|
||||
@ -196,12 +202,14 @@ void TaskMgr()
|
||||
OldSystemTime = TimeManager->GetCounter();
|
||||
#if defined(a64)
|
||||
register uintptr_t CurrentStackAddress asm("rsp");
|
||||
printf("Sanity: %d, Stack: %#lx", sanity++, CurrentStackAddress);
|
||||
#elif defined(a32)
|
||||
register uintptr_t CurrentStackAddress asm("esp");
|
||||
printf("Sanity: %d, Stack: %#x", sanity++, CurrentStackAddress);
|
||||
#elif defined(aa64)
|
||||
register uintptr_t CurrentStackAddress asm("sp");
|
||||
#endif
|
||||
printf("Sanity: %d, Stack: %#lx", sanity++, CurrentStackAddress);
|
||||
#endif
|
||||
if (sanity > 1000)
|
||||
sanity = 0;
|
||||
Display->SetBufferCursor(0, tmpX, tmpY);
|
||||
|
@ -72,7 +72,7 @@ namespace AdvancedHostControllerInterface
|
||||
this->AHCIPortType = Type;
|
||||
this->HBAPortPtr = PortPtr;
|
||||
this->Buffer = static_cast<uint8_t *>(KAPI.Memory.RequestPage(1));
|
||||
memset(this->Buffer, 0, KAPI.Memory.PageSize);
|
||||
memset(this->Buffer, 0, size_t(KAPI.Memory.PageSize));
|
||||
this->PortNumber = PortNumber;
|
||||
}
|
||||
|
||||
|
@ -283,7 +283,8 @@ namespace AudioCodec97
|
||||
|
||||
do
|
||||
{
|
||||
size_t Wrote = (KAPI.Memory.PageSize > Length) ? Length : KAPI.Memory.PageSize;
|
||||
size_t Wrote = (KAPI.Memory.PageSize > Length) ? size_t(Length)
|
||||
: size_t(KAPI.Memory.PageSize);
|
||||
|
||||
if (Wrote == 0)
|
||||
break;
|
||||
|
@ -113,9 +113,14 @@ namespace Gigabit
|
||||
RX[i]->Status = 0;
|
||||
}
|
||||
|
||||
#pragma diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wshift-count-overflow"
|
||||
|
||||
WriteCMD(REG::TXDESCLO, (uint32_t)(Ptr >> 32));
|
||||
WriteCMD(REG::TXDESCHI, (uint32_t)(Ptr & 0xFFFFFFFF));
|
||||
|
||||
#pragma diagnostic pop
|
||||
|
||||
WriteCMD(REG::RXDESCLO, (uint32_t)Ptr);
|
||||
WriteCMD(REG::RXDESCHI, 0);
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "../Architecture/amd64/cpu/gdt.hpp"
|
||||
#elif defined(a32)
|
||||
#include "../Architecture/i386/cpu/apic.hpp"
|
||||
#include "../Architecture/i386/cpu/gdt.hpp"
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
@ -218,9 +219,9 @@ namespace Tasking
|
||||
foreach (AuxiliaryVector var in auxv_array)
|
||||
{
|
||||
// Subtract the size of the auxillary vector
|
||||
Stack64 -= sizeof(Elf64_auxv_t) / sizeof(uintptr_t);
|
||||
Stack64 -= sizeof(Elf_auxv_t) / sizeof(uintptr_t);
|
||||
// Store the auxillary vector
|
||||
POKE(Elf64_auxv_t, Stack64) = var.archaux;
|
||||
POKE(Elf_auxv_t, Stack64) = var.archaux;
|
||||
// TODO: Store strings to the stack
|
||||
}
|
||||
|
||||
@ -263,7 +264,14 @@ namespace Tasking
|
||||
debug("SubtractStack: %#lx", SubtractStack);
|
||||
|
||||
// Set the stack pointer to the new stack
|
||||
this->Registers.rsp = ((uintptr_t)this->Stack->GetStackTop() - SubtractStack);
|
||||
uintptr_t StackPointerReg = ((uintptr_t)this->Stack->GetStackTop() - SubtractStack);
|
||||
#if defined(a64)
|
||||
this->Registers.rsp = StackPointerReg;
|
||||
#elif defined(a32)
|
||||
this->Registers.esp = StackPointerReg;
|
||||
#elif defined(aa64)
|
||||
this->Registers.sp = StackPointerReg;
|
||||
#endif
|
||||
|
||||
if (ArgvSize > 0)
|
||||
delete[] ArgvStrings;
|
||||
@ -274,10 +282,22 @@ namespace Tasking
|
||||
DumpData("Stack Data", (void *)((uintptr_t)this->Stack->GetStackPhysicalTop() - (uintptr_t)SubtractStack), SubtractStack);
|
||||
#endif
|
||||
|
||||
#if defined(a64)
|
||||
this->Registers.rdi = (uintptr_t)ArgvSize; // argc
|
||||
this->Registers.rsi = (uintptr_t)(this->Registers.rsp + 8); // argv
|
||||
this->Registers.rcx = (uintptr_t)EnvpSize; // envc
|
||||
this->Registers.rdx = (uintptr_t)(this->Registers.rsp + 8 + (8 * ArgvSize) + 8); // envp
|
||||
#elif defined(a32)
|
||||
this->Registers.eax = (uintptr_t)ArgvSize; // argc
|
||||
this->Registers.ebx = (uintptr_t)(this->Registers.esp + 4); // argv
|
||||
this->Registers.ecx = (uintptr_t)EnvpSize; // envc
|
||||
this->Registers.edx = (uintptr_t)(this->Registers.esp + 4 + (4 * ArgvSize) + 4); // envp
|
||||
#elif defined(aa64)
|
||||
this->Registers.x0 = (uintptr_t)ArgvSize; // argc
|
||||
this->Registers.x1 = (uintptr_t)(this->Registers.sp + 8); // argv
|
||||
this->Registers.x2 = (uintptr_t)EnvpSize; // envc
|
||||
this->Registers.x3 = (uintptr_t)(this->Registers.sp + 8 + (8 * ArgvSize) + 8); // envp
|
||||
#endif
|
||||
}
|
||||
|
||||
void TCB::SetupUserStack_x86_32(const char **argv,
|
||||
|
@ -77,15 +77,17 @@ typedef struct
|
||||
} a_un;
|
||||
} Elf64_auxv_t;
|
||||
|
||||
#if defined(a64)
|
||||
typedef Elf64_auxv_t Elf_auxv_t;
|
||||
#elif defined(a32)
|
||||
typedef Elf64_auxv_t Elf_auxv_t;
|
||||
#elif defined(aa64)
|
||||
typedef Elf64_auxv_t Elf_auxv_t;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#if defined(a64)
|
||||
Elf64_auxv_t archaux;
|
||||
#elif defined(a32)
|
||||
Elf32_auxv_t archaux;
|
||||
#elif defined(aa64)
|
||||
Elf64_auxv_t archaux;
|
||||
#endif
|
||||
Elf_auxv_t archaux;
|
||||
} AuxiliaryVector;
|
||||
|
||||
#endif // !__FENNIX_KERNEL_ABI_H__
|
||||
|
@ -210,6 +210,35 @@ namespace CPU
|
||||
|
||||
namespace x32
|
||||
{
|
||||
/**
|
||||
* @brief MSR_APIC_BASE structure
|
||||
* @see MSR_APIC_BASE
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/** @brief Reserved */
|
||||
uint32_t Reserved0 : 8;
|
||||
/**
|
||||
* @brief BSP Flag
|
||||
* @details If the BSP flag is set to 1, the processor is the bootstrap processor.
|
||||
*/
|
||||
uint32_t BSP : 1;
|
||||
/** @brief Reserved */
|
||||
uint32_t Reserved1 : 1;
|
||||
/** @brief Enable x2APIC mode */
|
||||
uint32_t EXTD : 1;
|
||||
/** @brief APIC Global Enable */
|
||||
uint32_t EN : 1;
|
||||
/** @brief APIC Base Low Address */
|
||||
uint32_t ApicBaseLo : 20;
|
||||
/** @brief APIC Base High Address */
|
||||
uint32_t ApicBaseHi : 32;
|
||||
};
|
||||
uint64_t raw;
|
||||
} __packed APIC_BASE;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
|
@ -213,7 +213,7 @@ namespace PCI
|
||||
|
||||
struct DeviceConfig
|
||||
{
|
||||
uintptr_t BaseAddress;
|
||||
uint64_t BaseAddress;
|
||||
uint16_t PCISegGroup;
|
||||
uint8_t StartBus;
|
||||
uint8_t EndBus;
|
||||
@ -228,9 +228,9 @@ namespace PCI
|
||||
public:
|
||||
std::vector<PCIDeviceHeader *> &GetDevices() { return Devices; }
|
||||
void MapPCIAddresses(PCIDeviceHeader *PCIDevice, Memory::PageTable *Table = nullptr);
|
||||
void EnumerateFunction(uintptr_t DeviceAddress, uintptr_t Function);
|
||||
void EnumerateDevice(uintptr_t BusAddress, uintptr_t Device);
|
||||
void EnumerateBus(uintptr_t BaseAddress, uintptr_t Bus);
|
||||
void EnumerateFunction(uint64_t DeviceAddress, uintptr_t Function);
|
||||
void EnumerateDevice(uint64_t BusAddress, uintptr_t Device);
|
||||
void EnumerateBus(uint64_t BaseAddress, uintptr_t Bus);
|
||||
std::vector<PCIDeviceHeader *> FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF);
|
||||
std::vector<PCIDeviceHeader *> FindPCIDevice(int VendorID, int DeviceID);
|
||||
|
||||
|
@ -52,15 +52,15 @@ namespace Time
|
||||
private:
|
||||
struct HPET
|
||||
{
|
||||
uintptr_t GeneralCapabilities;
|
||||
uintptr_t Reserved0;
|
||||
uintptr_t GeneralConfiguration;
|
||||
uintptr_t Reserved1;
|
||||
uintptr_t GeneralIntStatus;
|
||||
uintptr_t Reserved2;
|
||||
uintptr_t Reserved3[24];
|
||||
uintptr_t MainCounterValue;
|
||||
uintptr_t Reserved4;
|
||||
uint64_t GeneralCapabilities;
|
||||
uint64_t Reserved0;
|
||||
uint64_t GeneralConfiguration;
|
||||
uint64_t Reserved1;
|
||||
uint64_t GeneralIntStatus;
|
||||
uint64_t Reserved2;
|
||||
uint64_t Reserved3[24];
|
||||
uint64_t MainCounterValue;
|
||||
uint64_t Reserved4;
|
||||
};
|
||||
|
||||
uint32_t clk = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user