summaryrefslogtreecommitdiffhomepage
path: root/dev
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2025-01-10 23:40:15 +0100
committerAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2025-01-10 23:40:15 +0100
commit5fedb726774eb46d2aed9378b13bc296baf89333 (patch)
tree7d8170999fa3db72fd7794110824b6e6d0299914 /dev
parent6b63380f5f45891c5c27715cb290037d072ad212 (diff)
ADD: SMP tweaks on AMD64.
Signed-off-by: Amlal El Mahrouss <amlal.elmahrouss@icloud.com>
Diffstat (limited to 'dev')
-rw-r--r--dev/Boot/amd64-desktop.make2
-rw-r--r--dev/Kernel/ArchKit/ArchKit.h5
-rw-r--r--dev/Kernel/HALKit/AMD64/HalApplicationProcessor.cc104
-rw-r--r--dev/Kernel/HALKit/AMD64/HalCommonAPI.asm61
-rw-r--r--dev/Kernel/HALKit/AMD64/HalKernelMain.cc2
-rw-r--r--dev/Kernel/HALKit/ARM64/HalApplicationProcessor.cc14
-rw-r--r--dev/Kernel/src/HardwareThreadScheduler.cc9
-rw-r--r--dev/Kernel/src/UserProcessScheduler.cc8
8 files changed, 142 insertions, 63 deletions
diff --git a/dev/Boot/amd64-desktop.make b/dev/Boot/amd64-desktop.make
index 34cebd31..84ff8187 100644
--- a/dev/Boot/amd64-desktop.make
+++ b/dev/Boot/amd64-desktop.make
@@ -31,7 +31,7 @@ IMG_2=epm-master-2.img
EMU_FLAGS=-net none -smp 4 -m 8G -M q35 \
-bios $(BIOS) -drive \
file=fat:rw:src/Root/,index=2,format=raw \
- -d int
+ -monitor stdio
LD_FLAGS=-e Main --subsystem=10
diff --git a/dev/Kernel/ArchKit/ArchKit.h b/dev/Kernel/ArchKit/ArchKit.h
index b67cc29e..af8aef1a 100644
--- a/dev/Kernel/ArchKit/ArchKit.h
+++ b/dev/Kernel/ArchKit/ArchKit.h
@@ -43,9 +43,10 @@ namespace Kernel
/// @param base the base address.
/// @param reg the register.
/// @param value the write to write on it.
- inline Void ke_dma_write(UInt32 base, UInt32 reg, UInt32 value) noexcept
+ template <typename WordLength>
+ inline Void ke_dma_write(WordLength base, WordLength reg, WordLength value) noexcept
{
- *(volatile UInt32*)((UInt64)base + reg) = value;
+ *(volatile WordLength*)((UInt64)base + reg) = value;
}
/// @brief read from mapped memory register.
diff --git a/dev/Kernel/HALKit/AMD64/HalApplicationProcessor.cc b/dev/Kernel/HALKit/AMD64/HalApplicationProcessor.cc
index 6563f23c..19f3a486 100644
--- a/dev/Kernel/HALKit/AMD64/HalApplicationProcessor.cc
+++ b/dev/Kernel/HALKit/AMD64/HalApplicationProcessor.cc
@@ -17,8 +17,6 @@
#define kApicSignature "APIC"
-#define kApicBaseAddress (0xFEE00000)
-
#define kAPIC_ICR_Low 0x300
#define kAPIC_ICR_High 0x310
#define kAPIC_SIPI_Vector 0x00500
@@ -28,8 +26,6 @@
#define kAPIC_BASE_MSR_BSP 0x100
#define kAPIC_BASE_MSR_ENABLE 0x800
-#define kSMPMax (32U)
-
/// @note: _hal_switch_context is internal
///////////////////////////////////////////////////////////////////////////////////////
@@ -41,6 +37,12 @@
namespace Kernel::HAL
{
struct MADT_TABLE;
+ struct PROCESS_CONTROL_BLOCK;
+
+ struct PROCESS_CONTROL_BLOCK final
+ {
+ HAL::StackFramePtr mFrame;
+ };
EXTERN_C Void _hal_spin_core(Void);
@@ -48,14 +50,11 @@ namespace Kernel::HAL
STATIC Bool kSMPAware = false;
STATIC Int64 kSMPCount = 0;
- STATIC Int32 kSMPInterrupt = 0;
- STATIC UInt64 kAPICLocales[kSMPMax] = {0};
- STATIC struct
- {
- UInt64 mAddress;
- BOOL mUsed;
- } kAPICAddresses[kSMPMax];
- STATIC VoidPtr kRawMADT = nullptr;
+ STATIC UIntPtr kApicBaseAddress = 0UL;
+
+ STATIC Int32 kSMPInterrupt = 0;
+ STATIC UInt64 kAPICLocales[kSchedProcessLimitPerTeam] = {0};
+ STATIC VoidPtr kRawMADT = nullptr;
/// @brief Multiple APIC Descriptor Table.
struct MADT_TABLE final : public SDT
@@ -113,36 +112,31 @@ namespace Kernel::HAL
/***********************************************************************************/
/// @brief Send IPI command to APIC.
- /// @param apicId programmable interrupt controller id.
+ /// @param apic_id programmable interrupt controller id.
/// @param vector vector interrupt.
- /// @param targetAddress target APIC adress.
+ /// @param target target APIC adress.
/// @return
/***********************************************************************************/
- Void hal_send_start_ipi(UInt32 apicId, UInt8 vector, UInt32 targetAddress)
+ Void hal_send_start_ipi(UInt32 apic_id, UInt32 vector, UInt32 target)
{
- Kernel::ke_dma_write(targetAddress, kAPIC_ICR_High, (apicId << 24));
- Kernel::ke_dma_write(targetAddress, kAPIC_ICR_Low, kAPIC_SIPI_Vector | vector);
+ Kernel::ke_dma_write<UInt32>(target, kAPIC_ICR_High, (apic_id << 24));
+ Kernel::ke_dma_write<UInt32>(target, kAPIC_ICR_Low, kAPIC_SIPI_Vector | vector);
}
/***********************************************************************************/
/// @brief Send end IPI for CPU.
- /// @param apicId
+ /// @param apic_id
/// @param vector
- /// @param targetAddress
+ /// @param target
/// @return
/***********************************************************************************/
- Void hal_send_sipi(UInt32 apicId, UInt8 vector, UInt32 targetAddress)
+ Void hal_send_sipi(UInt32 apic_id, UInt8 vector, UInt32 target)
{
- Kernel::ke_dma_write(targetAddress, kAPIC_ICR_High, (apicId << 24));
- Kernel::ke_dma_write(targetAddress, kAPIC_ICR_Low, kAPIC_EIPI_Vector | vector);
+ Kernel::ke_dma_write<UInt32>(target, kAPIC_ICR_High, (apic_id << 24));
+ Kernel::ke_dma_write<UInt32>(target, kAPIC_ICR_Low, kAPIC_EIPI_Vector | vector);
}
- struct PROCESS_CONTROL_BLOCK final
- {
- HAL::StackFramePtr mFrame;
- };
-
STATIC PROCESS_CONTROL_BLOCK kProcessBlocks[kSchedProcessLimitPerTeam] = {0};
EXTERN_C HAL::StackFramePtr mp_get_current_context(Int64 pid)
@@ -151,14 +145,23 @@ namespace Kernel::HAL
return kProcessBlocks[process_index].mFrame;
}
- EXTERN_C BOOL mp_register_process(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr stack_frame, ProcessID pid)
+ EXTERN_C BOOL mp_register_process(HAL::StackFramePtr stack_frame, ProcessID pid)
{
- MUST_PASS(image && stack_ptr && stack_frame);
+ MUST_PASS(stack_frame);
const auto process_index = pid % kSchedProcessLimitPerTeam;
kProcessBlocks[process_index].mFrame = stack_frame;
+ auto first_id = kAPICLocales[0];
+
+ hal_send_sipi(first_id, (stack_frame->BP >> 12), kApicBaseAddress);
+
+ HardwareTimer timer(Kernel::Milliseconds(10));
+ timer.Wait();
+
+ hal_send_sipi(first_id, (stack_frame->BP >> 12), kApicBaseAddress);
+
return YES;
}
@@ -172,6 +175,11 @@ namespace Kernel::HAL
}
/***********************************************************************************/
+ /// @brief Assembly symbol to bootstrap AP.
+ /***********************************************************************************/
+ EXTERN_C Void hal_ap_start(Void);
+
+ /***********************************************************************************/
/// @brief Fetch and enable SMP scheduler.
/// @param vendor_ptr SMP containing structure.
/***********************************************************************************/
@@ -194,48 +202,50 @@ namespace Kernel::HAL
if (kMADTBlock)
{
- SizeT index_address = 0;
- SizeT index_local = 0;
- SizeT index = 0;
-
- // reset values.
+ SizeT index = 0;
kSMPInterrupt = 0;
kSMPCount = 0;
kcout << "SMP: Probing Local APICs...\r";
- UIntPtr madt_address = kMADTBlock->Address;
+ kApicBaseAddress = kMADTBlock->Address;
while (Yes)
{
if (kMADTBlock->List[index].Type > 9 ||
- kSMPCount > kSMPMax)
+ kSMPCount > kSchedProcessLimitPerTeam)
break;
switch (kMADTBlock->List[index].Type)
{
case 0x00: {
- kAPICLocales[index_local] = kMADTBlock->List[index_local].LAPIC.ProcessorID;
- kcout << "SMP: APIC ID: " << number(kAPICLocales[index_local]) << endl;
+ if (kMADTBlock->List[kSMPCount].LAPIC.ProcessorID < 1)
+ break;
+
+ kAPICLocales[kSMPCount] = kMADTBlock->List[kSMPCount].LAPIC.ProcessorID;
+ kcout << "SMP: APIC ID: " << number(kAPICLocales[kSMPCount]) << endl;
+
+ // I'll just make the AP start from scratch here.
+
+ hal_send_sipi(kAPICLocales[kSMPCount], ((UIntPtr)hal_ap_start >> 12), kApicBaseAddress);
+
+ HardwareTimer timer(Kernel::Milliseconds(10));
+ timer.Wait();
+
+ hal_send_sipi(kAPICLocales[kSMPCount], ((UIntPtr)hal_ap_start >> 12), kApicBaseAddress);
+
++kSMPCount;
break;
}
- case 0x05: {
- kAPICAddresses[index_address].mAddress = kMADTBlock->List[index_address].LAPIC_ADDRESS_OVERRIDE.Address;
- kAPICAddresses[index_address].mUsed = NO;
-
- kcout << "SMP: APIC address: " << number(madt_address) << endl;
+ default:
break;
}
- }
++index;
- ++index_address;
- ++index_local;
}
- kcout << "SMP: number of cores: " << number(kSMPCount) << endl;
+ kcout << "SMP: number of APs: " << number(kSMPCount) << endl;
// Kernel is now SMP aware.
// That means that the scheduler is now available (on MP Kernels)
diff --git a/dev/Kernel/HALKit/AMD64/HalCommonAPI.asm b/dev/Kernel/HALKit/AMD64/HalCommonAPI.asm
index dd3901e8..4a516d33 100644
--- a/dev/Kernel/HALKit/AMD64/HalCommonAPI.asm
+++ b/dev/Kernel/HALKit/AMD64/HalCommonAPI.asm
@@ -78,3 +78,64 @@ mp_system_call_handler:
pop r8
o64 sysret
+
+[bits 16]
+
+section .text
+global hal_ap_start
+
+hal_ap_start:
+ mov ax, 0x0
+ mov ss, ax
+ mov esp, 0x7000
+
+ cli
+ mov eax, cr0
+ or eax, 1
+ mov cr0, eax
+ jmp .flush
+.flush:
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ mov eax, cr4
+ or eax, 1 << 5
+ mov cr4, eax
+
+ mov eax, cr3
+ mov cr3, eax
+
+ mov ecx, 0xC0000080
+ rdmsr
+ or eax, 1
+ wrmsr
+
+ mov eax, cr0
+ or eax, (1 << 31)
+ mov cr0, eax
+
+ jmp 0x08:hal_ap_64bit_entry
+
+[bits 64]
+
+; 64-bit entry point
+section .text
+global hal_ap_64bit_entry
+hal_ap_64bit_entry:
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ mov rsp, 0x8001000 ; Stack Address for scheduler AP.
+
+ jmp hal_ap_64bit_entry_loop
+
+hal_ap_64bit_entry_loop:
+ jmp $ \ No newline at end of file
diff --git a/dev/Kernel/HALKit/AMD64/HalKernelMain.cc b/dev/Kernel/HALKit/AMD64/HalKernelMain.cc
index e27e2efb..a61fef84 100644
--- a/dev/Kernel/HALKit/AMD64/HalKernelMain.cc
+++ b/dev/Kernel/HALKit/AMD64/HalKernelMain.cc
@@ -96,9 +96,11 @@ EXTERN_C Kernel::Void hal_real_init(Kernel::Void) noexcept
Kernel::HAL::mp_get_cores(kHandoverHeader->f_HardwareTables.f_VendorPtr);
Kernel::HAL::Register64 idt_reg;
+
idt_reg.Base = (Kernel::UIntPtr)kInterruptVectorTable;
Kernel::HAL::IDTLoader idt_loader;
+
idt_loader.Load(idt_reg);
while (YES)
diff --git a/dev/Kernel/HALKit/ARM64/HalApplicationProcessor.cc b/dev/Kernel/HALKit/ARM64/HalApplicationProcessor.cc
index 4174057c..1d6dceaf 100644
--- a/dev/Kernel/HALKit/ARM64/HalApplicationProcessor.cc
+++ b/dev/Kernel/HALKit/ARM64/HalApplicationProcessor.cc
@@ -50,12 +50,14 @@ namespace Kernel
Void mp_setup_gic_el0(Void)
{
// enable distributor.
- HAL::hal_mmio_write(GICD_BASE + GICD_CTLR, 0x1);
+ HAL::hal_mmio_write(GICD_BASE + GICD_CTLR, YES);
UInt32 gicc_ctlr = HAL::hal_mmio_read<UInt32>(GICC_BASE + GICC_CTLR);
- gicc_ctlr |= 0x1; // Enable signaling of interrupts
- gicc_ctlr |= (1 << 1); // Allow Group 1 interrupts in EL0
+ const auto kEnableSignalInt = YES;
+
+ gicc_ctlr |= kEnableSignalInt; // Enable signaling of interrupts
+ gicc_ctlr |= (kEnableSignalInt << 1); // Allow Group 1 interrupts in EL0
HAL::hal_mmio_write(GICC_BASE + GICC_CTLR, gicc_ctlr);
@@ -76,7 +78,7 @@ namespace Kernel
// Enable interrupt 32 for AP.
HAL::hal_mmio_write(GICD_BASE + GICD_ISENABLER + (32 / 32) * 4, 0x01 << (32 % 32));
- kcout << "AP's GIC configured for interrupt 32." << endl;
+ kcout << "AP's GIC configured in ISR 32." << endl;
}
BOOL mp_handle_gic_interrupt_el0(Void)
@@ -108,9 +110,9 @@ namespace Kernel
return kProcessBlocks[pid % kSchedProcessLimitPerTeam].mFrame;
}
- EXTERN_C Bool mp_register_process(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr stack_frame, ProcessID pid)
+ EXTERN_C Bool mp_register_process(HAL::StackFramePtr stack_frame, ProcessID pid)
{
- MUST_PASS(image && stack_ptr && stack_frame);
+ MUST_PASS(stack_frame);
const auto process_index = pid % kSchedProcessLimitPerTeam;
diff --git a/dev/Kernel/src/HardwareThreadScheduler.cc b/dev/Kernel/src/HardwareThreadScheduler.cc
index a94ad64c..0e9a2865 100644
--- a/dev/Kernel/src/HardwareThreadScheduler.cc
+++ b/dev/Kernel/src/HardwareThreadScheduler.cc
@@ -22,7 +22,7 @@ namespace Kernel
/***********************************************************************************/
EXTERN Bool hal_check_stack(HAL::StackFramePtr frame_ptr);
- EXTERN_C Bool mp_register_process(VoidPtr image, Ptr8 stack_ptr, HAL::StackFramePtr frame, ProcessID pid);
+ EXTERN_C Bool mp_register_process(HAL::StackFramePtr frame, ProcessID pid);
STATIC HardwareThreadScheduler kHardwareThreadScheduler;
@@ -109,12 +109,15 @@ namespace Kernel
/// @retval true stack was changed, code is running.
/// @retval false stack is invalid, previous code is running.
/***********************************************************************************/
- Bool HardwareThread::Switch(VoidPtr image, Ptr8 stack_ptr, HAL::StackFramePtr frame, const ThreadID& pid)
+ Bool HardwareThread::Switch(VoidPtr image_ptr, Ptr8 stack_ptr, HAL::StackFramePtr frame, const ThreadID& pid)
{
this->fStack = frame;
this->fSourcePID = pid;
- Bool ret = mp_register_process(image, stack_ptr, fStack, this->fSourcePID);
+ fStack->BP = reinterpret_cast<UIntPtr>(image_ptr);
+ fStack->SP = reinterpret_cast<UIntPtr>(stack_ptr);
+
+ Bool ret = mp_register_process(fStack, this->fSourcePID);
if (ret)
this->Busy(YES);
diff --git a/dev/Kernel/src/UserProcessScheduler.cc b/dev/Kernel/src/UserProcessScheduler.cc
index 2d3101f2..f21e90d9 100644
--- a/dev/Kernel/src/UserProcessScheduler.cc
+++ b/dev/Kernel/src/UserProcessScheduler.cc
@@ -330,7 +330,7 @@ namespace Kernel
#endif // __ZKA_VIRTUAL_MEMORY_SUPPORT__
// React according to process kind.
- switch (process.kind)
+ switch (process.Kind)
{
case UserThread::kExectuableDylibKind:
{
@@ -439,9 +439,9 @@ namespace Kernel
for (; process_index < mTeam.AsArray().Capacity(); ++process_index)
{
- auto process = mTeam.AsArray()[process_index];
+ auto& process = mTeam.AsArray()[process_index];
- //! check if process needs to be scheduled.
+ //! check if the process needs to be run.
if (UserProcessHelper::CanBeScheduled(process))
{
// Set current process header.
@@ -455,7 +455,7 @@ namespace Kernel
if (!UserProcessHelper::Switch(process.Image.fCode, &process.StackReserve[process.StackSize - 1], process.StackFrame,
process.ProcessId))
{
- kcout << "Invalid process.\r";
+ kcout << "Invalid process (UH OH)\r";
process.Crash();
}
}