From 3899c2a42e28589765565baf1959a379e5f9b612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 08:44:55 +0200 Subject: [PATCH 01/18] Update github workflows --- .github/workflows/kernel-build.yml | 1 + .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/kernel-build.yml b/.github/workflows/kernel-build.yml index e29d091..bb1a811 100644 --- a/.github/workflows/kernel-build.yml +++ b/.github/workflows/kernel-build.yml @@ -15,6 +15,7 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v4 + with: { fetch-depth: 0 } - name: Install LLVM and Clang uses: KyleMayes/install-llvm-action@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b99f1f7..b768835 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -101,4 +101,4 @@ jobs: Changes since `${{ steps.version.outputs.last }}`: ${{ steps.notes.outputs.notes }} - files: ${{ steps.collect.outputs.list }} + files: ${{ steps.renamed.outputs.list }} From 871e113221a1c2727f330a9f62fd4d7072fa5358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 08:46:41 +0200 Subject: [PATCH 02/18] Add debug test loop --- src/Kernel/KernelMain.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index 452f3fb..8875db1 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -88,7 +88,8 @@ void KernelMain() while (true) { - CpuGenerateInvalidInstruction(); + KernelConsolePrint(String("Loop WFI\n")); + //CpuGenerateInvalidInstruction(); CpuWaitForInterrupt(); } } From ca4da93a7b5ee0fff2214e949972f400c7bd2876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 08:57:05 +0200 Subject: [PATCH 03/18] Add debug log --- src/Kernel/KernelMain.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index 8875db1..5c99c64 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -82,10 +82,16 @@ void KernelMain() KernelConsolePrint(String("(%s %d-bit)\n\n"), platformInformation.Name.Pointer, platformInformation.ArchitectureBits); KernelConsoleResetStyle(); + KernelConsolePrint(String("Set Trap handler\n")); CpuSetTrapHandler(KernelTrapHandler); + KernelConsolePrint(String("Set Timer\n")); BiosSetTimer(CpuReadTime() + 10000000); + + KernelConsolePrint(String("Enable Interrupts\n")); CpuEnableInterrupts(CpuInterruptType_Timer); + KernelConsolePrint(String("Entering loop\n")); + while (true) { KernelConsolePrint(String("Loop WFI\n")); From b570885c2a0c76bf35b80ccd12fb78363fa68ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 09:04:02 +0200 Subject: [PATCH 04/18] Add more logs --- src/Kernel/KernelMain.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index 5c99c64..f863a56 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -80,7 +80,9 @@ void KernelMain() KernelConsoleSetForegroundColor(KernelConsoleColorHighlight); KernelConsolePrint(String("Kanso OS %s "), KANSO_VERSION_FULL); KernelConsolePrint(String("(%s %d-bit)\n\n"), platformInformation.Name.Pointer, platformInformation.ArchitectureBits); + KernelConsolePrint(String("After Header display\n")); KernelConsoleResetStyle(); + KernelConsolePrint(String("After reset\n")); KernelConsolePrint(String("Set Trap handler\n")); CpuSetTrapHandler(KernelTrapHandler); From f554e1ee8d2de8f5b3984fb707e08b93d7eab826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 09:18:56 +0200 Subject: [PATCH 05/18] Change RISC-V interrupt flag handling --- src/Kernel/KernelMain.c | 2 -- src/Kernel/Platforms/RiscV/Cpu.c | 8 +++++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index f863a56..5c99c64 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -80,9 +80,7 @@ void KernelMain() KernelConsoleSetForegroundColor(KernelConsoleColorHighlight); KernelConsolePrint(String("Kanso OS %s "), KANSO_VERSION_FULL); KernelConsolePrint(String("(%s %d-bit)\n\n"), platformInformation.Name.Pointer, platformInformation.ArchitectureBits); - KernelConsolePrint(String("After Header display\n")); KernelConsoleResetStyle(); - KernelConsolePrint(String("After reset\n")); KernelConsolePrint(String("Set Trap handler\n")); CpuSetTrapHandler(KernelTrapHandler); diff --git a/src/Kernel/Platforms/RiscV/Cpu.c b/src/Kernel/Platforms/RiscV/Cpu.c index c72409a..b19e229 100644 --- a/src/Kernel/Platforms/RiscV/Cpu.c +++ b/src/Kernel/Platforms/RiscV/Cpu.c @@ -197,8 +197,9 @@ inline void CpuSetTrapHandler(CpuTrapHandler trapHandler) if (trapHandler) { __asm__ volatile( - "csrw stvec, %0\n" - "csrsi sstatus, 2" + "csrw sie, zero\n" + "csrci sstatus, 2\n" + "csrw stvec, %0" : : "r" (kernel_trap_entry)); } @@ -213,7 +214,8 @@ inline void CpuEnableInterrupts(CpuInterruptType types) auto mask = ComputeCpuInterruptMask(types); __asm__ volatile ( - "csrs sie, %0" + "csrs sie, %0\n" + "csrsi sstatus, 2" : : "r"(mask) : "memory" From af6e7dfe711a3603ddbcfcfc7f48ffed16d983b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 09:28:30 +0200 Subject: [PATCH 06/18] Test handler --- src/Kernel/KernelMain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index 5c99c64..54a073c 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -85,7 +85,7 @@ void KernelMain() KernelConsolePrint(String("Set Trap handler\n")); CpuSetTrapHandler(KernelTrapHandler); KernelConsolePrint(String("Set Timer\n")); - BiosSetTimer(CpuReadTime() + 10000000); + //BiosSetTimer(CpuReadTime() + 10000000); KernelConsolePrint(String("Enable Interrupts\n")); CpuEnableInterrupts(CpuInterruptType_Timer); @@ -95,7 +95,7 @@ void KernelMain() while (true) { KernelConsolePrint(String("Loop WFI\n")); - //CpuGenerateInvalidInstruction(); + CpuGenerateInvalidInstruction(); CpuWaitForInterrupt(); } } From 2e71e8b05e92a9b6a580db1f5487d85ea78616ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 09:46:46 +0200 Subject: [PATCH 07/18] Change invalid instruction --- src/Kernel/Platforms/RiscV/Cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Kernel/Platforms/RiscV/Cpu.c b/src/Kernel/Platforms/RiscV/Cpu.c index b19e229..ec45359 100644 --- a/src/Kernel/Platforms/RiscV/Cpu.c +++ b/src/Kernel/Platforms/RiscV/Cpu.c @@ -149,8 +149,8 @@ inline uint64_t CpuReadCycle() #endif inline void CpuGenerateInvalidInstruction() -{ - __asm__ volatile ("unimp"); +{ + __asm__ volatile (".word 0xFFFFFFFF"); } /* Masks and “all-ones” patterns for the three fields we test. */ From 0dbb4bcdc0b92ee0c8195c15ce8de988dc705a24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 09:57:20 +0200 Subject: [PATCH 08/18] Test debug breakpoint --- src/Kernel/KernelMain.c | 4 ++++ src/Kernel/Platforms/RiscV/Cpu.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index 54a073c..fecc852 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -48,6 +48,10 @@ void KernelTrapHandler(CpuTrapFrame* trapFrame) errorName = String("Address error"); break; + case CpuTrapSynchronousType_Debug: + errorName = String("Debug not implemented"); + break; + case CpuTrapSynchronousType_PageError: errorName = String("Page error"); break; diff --git a/src/Kernel/Platforms/RiscV/Cpu.c b/src/Kernel/Platforms/RiscV/Cpu.c index ec45359..6b681b1 100644 --- a/src/Kernel/Platforms/RiscV/Cpu.c +++ b/src/Kernel/Platforms/RiscV/Cpu.c @@ -150,7 +150,8 @@ inline uint64_t CpuReadCycle() inline void CpuGenerateInvalidInstruction() { - __asm__ volatile (".word 0xFFFFFFFF"); + //__asm__ volatile (".word 0xFFFFFFFF"); + __asm__ volatile ("ebreak"); } /* Masks and “all-ones” patterns for the three fields we test. */ From e9e2b291a6538a0e069da00fc4e05eeceb2d77b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 10:03:09 +0200 Subject: [PATCH 09/18] Test another sync trap handling --- src/Kernel/Platforms/RiscV/Cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kernel/Platforms/RiscV/Cpu.c b/src/Kernel/Platforms/RiscV/Cpu.c index 6b681b1..6002c97 100644 --- a/src/Kernel/Platforms/RiscV/Cpu.c +++ b/src/Kernel/Platforms/RiscV/Cpu.c @@ -151,7 +151,7 @@ inline uint64_t CpuReadCycle() inline void CpuGenerateInvalidInstruction() { //__asm__ volatile (".word 0xFFFFFFFF"); - __asm__ volatile ("ebreak"); + __asm__ volatile ("auipc t0, 0 \njalr x0, t0, 2"); } /* Masks and “all-ones” patterns for the three fields we test. */ From 11209a66a695a217ea6d866ee3d77a240593a234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 10:15:44 +0200 Subject: [PATCH 10/18] Test software interrupt --- src/Kernel/KernelMain.c | 6 +++--- src/Kernel/Platforms/RiscV/Cpu.c | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index fecc852..ab8ae08 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -89,17 +89,17 @@ void KernelMain() KernelConsolePrint(String("Set Trap handler\n")); CpuSetTrapHandler(KernelTrapHandler); KernelConsolePrint(String("Set Timer\n")); - //BiosSetTimer(CpuReadTime() + 10000000); + BiosSetTimer(CpuReadTime() + 10000000); KernelConsolePrint(String("Enable Interrupts\n")); - CpuEnableInterrupts(CpuInterruptType_Timer); + CpuEnableInterrupts(CpuInterruptType_Timer | CpuInterruptType_Software); KernelConsolePrint(String("Entering loop\n")); while (true) { KernelConsolePrint(String("Loop WFI\n")); - CpuGenerateInvalidInstruction(); + //CpuGenerateInvalidInstruction(); CpuWaitForInterrupt(); } } diff --git a/src/Kernel/Platforms/RiscV/Cpu.c b/src/Kernel/Platforms/RiscV/Cpu.c index 6002c97..1438964 100644 --- a/src/Kernel/Platforms/RiscV/Cpu.c +++ b/src/Kernel/Platforms/RiscV/Cpu.c @@ -150,8 +150,7 @@ inline uint64_t CpuReadCycle() inline void CpuGenerateInvalidInstruction() { - //__asm__ volatile (".word 0xFFFFFFFF"); - __asm__ volatile ("auipc t0, 0 \njalr x0, t0, 2"); + __asm__ volatile ("unimp"); } /* Masks and “all-ones” patterns for the three fields we test. */ From 2c0db83ef0f669d7cc1c742f4b06f247ff5ca1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 10:29:09 +0200 Subject: [PATCH 11/18] Test with all interrupts enabled --- src/Kernel/KernelMain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index ab8ae08..2c8188a 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -92,7 +92,7 @@ void KernelMain() BiosSetTimer(CpuReadTime() + 10000000); KernelConsolePrint(String("Enable Interrupts\n")); - CpuEnableInterrupts(CpuInterruptType_Timer | CpuInterruptType_Software); + CpuEnableInterrupts(CpuInterruptType_All); KernelConsolePrint(String("Entering loop\n")); From 80a5a265be89cac8bd80b5fbea728ee265003c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 10:50:36 +0200 Subject: [PATCH 12/18] Add debug info --- src/Kernel/KernelMain.c | 1 + src/Kernel/Platforms/RiscV/Cpu.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index 2c8188a..27cdf93 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -14,6 +14,7 @@ const char KernelLogo[] = void KernelTrapHandler(CpuTrapFrame* trapFrame) { + KernelConsolePrint(String("Trap Handler\n")); auto trapCause = CpuTrapFrameGetCause(trapFrame); auto errorName = String("Unknown kernel trap cause"); diff --git a/src/Kernel/Platforms/RiscV/Cpu.c b/src/Kernel/Platforms/RiscV/Cpu.c index 1438964..6cc1fa8 100644 --- a/src/Kernel/Platforms/RiscV/Cpu.c +++ b/src/Kernel/Platforms/RiscV/Cpu.c @@ -207,6 +207,12 @@ inline void CpuSetTrapHandler(CpuTrapHandler trapHandler) { __asm__ volatile("csrsi sstatus, 0"); } + + uintptr_t v; +__asm__ volatile ("csrr %0, stvec" : "=r"(v)); +KernelConsolePrint(String("stvec = %x (mode=%s)\n"), + v, + (v & 1) ? "vectored" : "direct"); } inline void CpuEnableInterrupts(CpuInterruptType types) From 6f1d0e5e99bc8671501075ceeef36eda75573ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 10:57:39 +0200 Subject: [PATCH 13/18] Add debug log --- src/Kernel/KernelMain.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index 27cdf93..04cea35 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -73,7 +73,15 @@ void KernelTrapHandler(CpuTrapFrame* trapFrame) CpuLogTrapFrame(trapFrame); KernelFailure(String("%s. (Code=%x, Extra=%x)"), errorName, trapCause.Code, trapCause.ExtraInformation); } - +static void DumpCSRs(const char *tag) +{ + uintptr_t sstatus, sie, sip; + __asm__ volatile ("csrr %0, sstatus" : "=r"(sstatus)); + __asm__ volatile ("csrr %0, sie" : "=r"(sie)); + __asm__ volatile ("csrr %0, sip" : "=r"(sip)); + KernelConsolePrint(String("[%s] sstatus=%x sie=%x sip=%x\n"), + tag, sstatus, sie, sip); +} void KernelMain() { auto platformInformation = PlatformGetInformation(); @@ -90,10 +98,13 @@ void KernelMain() KernelConsolePrint(String("Set Trap handler\n")); CpuSetTrapHandler(KernelTrapHandler); KernelConsolePrint(String("Set Timer\n")); - BiosSetTimer(CpuReadTime() + 10000000); KernelConsolePrint(String("Enable Interrupts\n")); CpuEnableInterrupts(CpuInterruptType_All); + DumpCSRs("after enable"); + + BiosSetTimer(CpuReadTime() + 10000000); + DumpCSRs("after set-timer"); KernelConsolePrint(String("Entering loop\n")); From 58745811a79426b83ca1dec607c5cb762659a40a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 11:04:35 +0200 Subject: [PATCH 14/18] Add debugging --- src/Kernel/KernelMain.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index 04cea35..a5c5ed1 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -103,7 +103,7 @@ void KernelMain() CpuEnableInterrupts(CpuInterruptType_All); DumpCSRs("after enable"); - BiosSetTimer(CpuReadTime() + 10000000); + //BiosSetTimer(CpuReadTime() + 10'000'000); DumpCSRs("after set-timer"); KernelConsolePrint(String("Entering loop\n")); @@ -111,6 +111,9 @@ void KernelMain() while (true) { KernelConsolePrint(String("Loop WFI\n")); + + + __asm__ volatile ("csrs sip, %0" :: "r"(1UL << 1)); //CpuGenerateInvalidInstruction(); CpuWaitForInterrupt(); } From 589b4b007613a84479ac65dbf4f737b5955a276a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 11:27:46 +0200 Subject: [PATCH 15/18] Add more logs --- src/Kernel/KernelMain.c | 5 ++--- src/Kernel/Platforms/RiscV/Sbi.c | 9 +++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index a5c5ed1..ce0fcfb 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -103,7 +103,8 @@ void KernelMain() CpuEnableInterrupts(CpuInterruptType_All); DumpCSRs("after enable"); - //BiosSetTimer(CpuReadTime() + 10'000'000); + + BiosSetTimer(CpuReadTime() + 10'000'000); DumpCSRs("after set-timer"); KernelConsolePrint(String("Entering loop\n")); @@ -112,8 +113,6 @@ void KernelMain() { KernelConsolePrint(String("Loop WFI\n")); - - __asm__ volatile ("csrs sip, %0" :: "r"(1UL << 1)); //CpuGenerateInvalidInstruction(); CpuWaitForInterrupt(); } diff --git a/src/Kernel/Platforms/RiscV/Sbi.c b/src/Kernel/Platforms/RiscV/Sbi.c index 53ee71c..1a9e7f2 100644 --- a/src/Kernel/Platforms/RiscV/Sbi.c +++ b/src/Kernel/Platforms/RiscV/Sbi.c @@ -73,6 +73,15 @@ void BiosSetTimer(uint64_t timeValue) #else SbiCallFunction(SbiExtension_Time, 0x00, timeValue, 0, 0, 0, 0, 0); #endif + + uint64_t now = CpuReadTime(); +uint64_t deadline = now + 10'000'000ULL; /* 2.5 s @ 4 MHz */ + +SbiReturn rc = SbiCallFunction(SbiExtension_Time, 0, /* EID=TIME, FID=0 */ + deadline, 0, 0, 0, 0, 0); + +KernelConsolePrint(String("set_timer: err=%d val=%lx now=%lx dl=%lx\n"), + rc.ReturnCode, rc.Value, now, deadline); } void BiosReset(BiosResetType resetType, BiosResetReason reason) From d14cc907aea028de14feedc42c769dfa2860e22d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Sun, 15 Jun 2025 12:50:53 +0200 Subject: [PATCH 16/18] Add debug info --- src/Kernel/KernelMain.c | 10 ++-------- src/Kernel/Platforms/RiscV/Sbi.c | 9 +++------ 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index ce0fcfb..fec3fe3 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -95,20 +95,14 @@ void KernelMain() KernelConsolePrint(String("(%s %d-bit)\n\n"), platformInformation.Name.Pointer, platformInformation.ArchitectureBits); KernelConsoleResetStyle(); - KernelConsolePrint(String("Set Trap handler\n")); CpuSetTrapHandler(KernelTrapHandler); - KernelConsolePrint(String("Set Timer\n")); + BiosSetTimer(CpuReadTime()); + DumpCSRs("after set-timer"); KernelConsolePrint(String("Enable Interrupts\n")); CpuEnableInterrupts(CpuInterruptType_All); DumpCSRs("after enable"); - - BiosSetTimer(CpuReadTime() + 10'000'000); - DumpCSRs("after set-timer"); - - KernelConsolePrint(String("Entering loop\n")); - while (true) { KernelConsolePrint(String("Loop WFI\n")); diff --git a/src/Kernel/Platforms/RiscV/Sbi.c b/src/Kernel/Platforms/RiscV/Sbi.c index 1a9e7f2..d14ddbe 100644 --- a/src/Kernel/Platforms/RiscV/Sbi.c +++ b/src/Kernel/Platforms/RiscV/Sbi.c @@ -69,16 +69,13 @@ void BiosDebugConsoleWrite(ReadOnlySpanChar message) void BiosSetTimer(uint64_t timeValue) { #if PLATFORM_ARCHITECTURE_BITS == 32 - SbiCallFunction(SbiExtension_Time, 0x00, (uintptr_t)timeValue, (uintptr_t)(timeValue >> 32), 0, 0, 0, 0); + auto rc = SbiCallFunction(SbiExtension_Time, 0x00, (uintptr_t)timeValue, (uintptr_t)(timeValue >> 32), 0, 0, 0, 0); #else - SbiCallFunction(SbiExtension_Time, 0x00, timeValue, 0, 0, 0, 0, 0); + auto rc = SbiCallFunction(SbiExtension_Time, 0x00, timeValue, 0, 0, 0, 0, 0); #endif uint64_t now = CpuReadTime(); -uint64_t deadline = now + 10'000'000ULL; /* 2.5 s @ 4 MHz */ - -SbiReturn rc = SbiCallFunction(SbiExtension_Time, 0, /* EID=TIME, FID=0 */ - deadline, 0, 0, 0, 0, 0); +uint64_t deadline = timeValue; /* 2.5 s @ 4 MHz */ KernelConsolePrint(String("set_timer: err=%d val=%lx now=%lx dl=%lx\n"), rc.ReturnCode, rc.Value, now, deadline); From 9b3450d135d98801c0ead6eab69332d1d1f678da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Mon, 16 Jun 2025 15:39:29 +0200 Subject: [PATCH 17/18] WIP DTB parsing --- src/Common/Memory.h | 6 +- src/Common/String.c | 2 +- src/Common/Types.h | 8 + src/Kernel/KernelMain.c | 26 ++- src/Kernel/Platform.h | 16 +- src/Kernel/Platforms/RiscV/Boot.S | 8 +- src/Kernel/Platforms/RiscV/Cpu.c | 17 +- src/Kernel/Platforms/RiscV/KernelTrapEntry.S | 2 +- src/Kernel/Platforms/RiscV/Platform.c | 172 ++++++++++++++++++- src/Kernel/Platforms/RiscV/Sbi.c | 10 +- 10 files changed, 219 insertions(+), 48 deletions(-) diff --git a/src/Common/Memory.h b/src/Common/Memory.h index db19655..6205cef 100644 --- a/src/Common/Memory.h +++ b/src/Common/Memory.h @@ -11,12 +11,12 @@ typedef struct Span##name { type* Pointer; size_t Length; } Span##name; \ typedef struct ReadOnlySpan##name { const type* Pointer; size_t Length; } ReadOnlySpan##name; \ \ - static inline Span##name MakeSpan##name(type* pointer, size_t length) \ + static inline Span##name CreateSpan##name(type* pointer, size_t length) \ { \ return (Span##name) { .Pointer = pointer, .Length = length }; \ } \ \ - static inline ReadOnlySpan##name MakeReadOnlySpan##name(const type* pointer, size_t length) \ + static inline ReadOnlySpan##name CreateReadOnlySpan##name(const type* pointer, size_t length) \ { \ return (ReadOnlySpan##name) { .Pointer = pointer, .Length = length }; \ } \ @@ -30,7 +30,7 @@ (__extension__ ({ \ static_assert((length) >= 0, "StackAlloc: length must be an integer-constant expression"); \ type array[(length)]; \ - MakeSpan##name(array, (size_t)(length)); \ + CreateSpan##name(array, (size_t)(length)); \ })) DefineSpan(Char, char) diff --git a/src/Common/String.c b/src/Common/String.c index 1f09819..0fb4f1b 100644 --- a/src/Common/String.c +++ b/src/Common/String.c @@ -2,7 +2,7 @@ ReadOnlySpanChar String(const char* string) { - return MakeReadOnlySpanChar(string, __builtin_strlen(string)); + return CreateReadOnlySpanChar(string, __builtin_strlen(string)); } bool StringEquals(ReadOnlySpanChar string1, ReadOnlySpanChar string2) diff --git a/src/Common/Types.h b/src/Common/Types.h index b939e47..b0f9edd 100644 --- a/src/Common/Types.h +++ b/src/Common/Types.h @@ -23,6 +23,14 @@ static_assert(sizeof(uintptr_t) == sizeof(void *), "uintptr_t is not pointer-siz #define PLATFORM_ARCHITECTURE_BITS (__SIZEOF_POINTER__ * 8) +typedef enum +{ + ByteOrder_LittleEndian = __ORDER_LITTLE_ENDIAN__, + ByteOrder_BigEndian = __ORDER_BIG_ENDIAN__ +} ByteOrder; + +#define PLATFORM_BYTE_ORDER __BYTE_ORDER__ + #define va_list __builtin_va_list #define va_start __builtin_va_start #define va_end __builtin_va_end diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index fec3fe3..31bce80 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -14,7 +14,6 @@ const char KernelLogo[] = void KernelTrapHandler(CpuTrapFrame* trapFrame) { - KernelConsolePrint(String("Trap Handler\n")); auto trapCause = CpuTrapFrameGetCause(trapFrame); auto errorName = String("Unknown kernel trap cause"); @@ -26,7 +25,7 @@ void KernelTrapHandler(CpuTrapFrame* trapFrame) CpuClearPendingInterrupts(CpuInterruptType_Timer); //CpuDisableInterrupts(CpuInterruptType_Timer); //SbiSetTimer((uint64_t)-1); - BiosSetTimer(CpuReadTime() + 10000000); + BiosSetTimer(CpuReadTime() + 10'000'000); auto programCounter = CpuTrapFrameGetProgramCounter(trapFrame); KernelConsolePrint(String("Kernel trap handler: %l (PC=%x).\n"), CpuReadTime(), programCounter); @@ -73,15 +72,7 @@ void KernelTrapHandler(CpuTrapFrame* trapFrame) CpuLogTrapFrame(trapFrame); KernelFailure(String("%s. (Code=%x, Extra=%x)"), errorName, trapCause.Code, trapCause.ExtraInformation); } -static void DumpCSRs(const char *tag) -{ - uintptr_t sstatus, sie, sip; - __asm__ volatile ("csrr %0, sstatus" : "=r"(sstatus)); - __asm__ volatile ("csrr %0, sie" : "=r"(sie)); - __asm__ volatile ("csrr %0, sip" : "=r"(sip)); - KernelConsolePrint(String("[%s] sstatus=%x sie=%x sip=%x\n"), - tag, sstatus, sie, sip); -} + void KernelMain() { auto platformInformation = PlatformGetInformation(); @@ -95,17 +86,20 @@ void KernelMain() KernelConsolePrint(String("(%s %d-bit)\n\n"), platformInformation.Name.Pointer, platformInformation.ArchitectureBits); KernelConsoleResetStyle(); + KernelConsolePrint(String("Boot Cpu ID: %d\n"), platformInformation.BootCpuId); + + auto platformDevices = PlatformGetDevices(); + + + BiosSetTimer(CpuReadTime() + 10'000'000); CpuSetTrapHandler(KernelTrapHandler); - BiosSetTimer(CpuReadTime()); - DumpCSRs("after set-timer"); - KernelConsolePrint(String("Enable Interrupts\n")); + // TODO: Test Timer only when the hardware is running fine CpuEnableInterrupts(CpuInterruptType_All); - DumpCSRs("after enable"); while (true) { - KernelConsolePrint(String("Loop WFI\n")); + KernelConsolePrint(String("WFI\n")); //CpuGenerateInvalidInstruction(); CpuWaitForInterrupt(); diff --git a/src/Kernel/Platform.h b/src/Kernel/Platform.h index c445db4..d340f34 100644 --- a/src/Kernel/Platform.h +++ b/src/Kernel/Platform.h @@ -11,10 +11,16 @@ typedef struct { ReadOnlySpanChar Name; uint32_t ArchitectureBits; + uint8_t BootCpuId; } PlatformInformation; -PlatformInformation PlatformGetInformation(); +// TODO: We should maybe put that in common and call it SystemDevice or SystemStaticDevice +typedef struct +{ +} PlatformDevices; +PlatformInformation PlatformGetInformation(); +PlatformDevices PlatformGetDevices(); // -------------------------------------------------------------------------------------- // Cpu @@ -22,10 +28,10 @@ PlatformInformation PlatformGetInformation(); typedef enum { - CpuInterruptType_None = 0, - CpuInterruptType_Software = 1, - CpuInterruptType_Timer = 2, - CpuInterruptType_External = 4, + CpuInterruptType_None = 0x00, + CpuInterruptType_Software = 0x01, + CpuInterruptType_Timer = 0x02, + CpuInterruptType_External = 0x04, CpuInterruptType_All = 0xFF, } CpuInterruptType; diff --git a/src/Kernel/Platforms/RiscV/Boot.S b/src/Kernel/Platforms/RiscV/Boot.S index 27a2d2c..a714660 100644 --- a/src/Kernel/Platforms/RiscV/Boot.S +++ b/src/Kernel/Platforms/RiscV/Boot.S @@ -18,7 +18,13 @@ boot: addi t0, t0, 1 blt t0, t1, .Lclear_bss_loop -.Lrun_init_array: + # Save boot parameters + la t0, globalBootHartId + save_pointer a0, (t0) + + la t0, globalDeviceTreeData + save_pointer a1, (t0) + # Run init array la t2, __INIT_ARRAY_START la t3, __INIT_ARRAY_END diff --git a/src/Kernel/Platforms/RiscV/Cpu.c b/src/Kernel/Platforms/RiscV/Cpu.c index 6cc1fa8..e2e558d 100644 --- a/src/Kernel/Platforms/RiscV/Cpu.c +++ b/src/Kernel/Platforms/RiscV/Cpu.c @@ -197,9 +197,9 @@ inline void CpuSetTrapHandler(CpuTrapHandler trapHandler) if (trapHandler) { __asm__ volatile( - "csrw sie, zero\n" - "csrci sstatus, 2\n" - "csrw stvec, %0" + "csrw sie, zero\n" + "csrci sstatus, 2\n" + "csrw stvec, %0" : : "r" (kernel_trap_entry)); } @@ -207,12 +207,6 @@ inline void CpuSetTrapHandler(CpuTrapHandler trapHandler) { __asm__ volatile("csrsi sstatus, 0"); } - - uintptr_t v; -__asm__ volatile ("csrr %0, stvec" : "=r"(v)); -KernelConsolePrint(String("stvec = %x (mode=%s)\n"), - v, - (v & 1) ? "vectored" : "direct"); } inline void CpuEnableInterrupts(CpuInterruptType types) @@ -220,8 +214,8 @@ inline void CpuEnableInterrupts(CpuInterruptType types) auto mask = ComputeCpuInterruptMask(types); __asm__ volatile ( - "csrs sie, %0\n" - "csrsi sstatus, 2" + "csrs sie, %0\n" + "csrsi sstatus, 2" : : "r"(mask) : "memory" @@ -259,7 +253,6 @@ inline void CpuWaitForInterrupt() void LogRegister(ReadOnlySpanChar name, uintptr_t value, uint8_t padding, bool insertTab) { - // TODO: Color the register name with the keyword blue of VScode? KernelConsoleSetForegroundColor(KernelConsoleColorKeyword); KernelConsolePrint(String("%s"), name); KernelConsoleResetStyle(); diff --git a/src/Kernel/Platforms/RiscV/KernelTrapEntry.S b/src/Kernel/Platforms/RiscV/KernelTrapEntry.S index b718b9f..5a6c3b4 100644 --- a/src/Kernel/Platforms/RiscV/KernelTrapEntry.S +++ b/src/Kernel/Platforms/RiscV/KernelTrapEntry.S @@ -1,6 +1,6 @@ #include "AsmCommon.h" -.global kernel_trap_entry # TODO: Rename +.global kernel_trap_entry .section .text.interrupt diff --git a/src/Kernel/Platforms/RiscV/Platform.c b/src/Kernel/Platforms/RiscV/Platform.c index aeb390a..f4bb542 100644 --- a/src/Kernel/Platforms/RiscV/Platform.c +++ b/src/Kernel/Platforms/RiscV/Platform.c @@ -1,12 +1,182 @@ #include "../../Platform.h" +#include "Memory.h" #include "String.h" +#include "Types.h" + +// TODO: Add tests + +uintptr_t globalBootHartId; +uintptr_t globalDeviceTreeData; PlatformInformation PlatformGetInformation() { return (PlatformInformation) { .Name = String("RISC-V"), - .ArchitectureBits = PLATFORM_ARCHITECTURE_BITS + .ArchitectureBits = PLATFORM_ARCHITECTURE_BITS, + .BootCpuId = globalBootHartId + }; +} + +// TODO: Put that in a common binary reader or similar and do tests +// TODO: We should have a create binary reader that take the encoding and the pointer +// TODO: It would be cool if it could work with streams but it seems too much +// TODO: This function should take into account the endianness of the platform +uint32_t BinaryReadUint32Old(uintptr_t pointer) +{ + // TODO: For now big endian -> little endian conversion + auto result = *(uint32_t*)pointer; + + if (PLATFORM_BYTE_ORDER == ByteOrder_LittleEndian) + { + result = __builtin_bswap32(result); + } + + return result; +} + +typedef struct +{ + ReadOnlySpanUint8 Data; + ByteOrder ByteOrder; + size_t CurrentOffset; +} BinaryReader; + +BinaryReader CreateBinaryReader(ReadOnlySpanUint8 data, ByteOrder byteOrder) +{ + return (BinaryReader) + { + .Data = data, + .ByteOrder = byteOrder, + .CurrentOffset = 0 }; } +uint32_t BinaryReadUint32(BinaryReader* reader) +{ + auto span = SpanSliceFrom(reader->Data, reader->CurrentOffset); + // TODO: For now big endian -> little endian conversion + // TODO: Do the other conversions + auto result = *(uint32_t*)span.Pointer; + + if (PLATFORM_BYTE_ORDER == ByteOrder_LittleEndian) + { + result = __builtin_bswap32(result); + } + + reader->CurrentOffset += sizeof(uint32_t); + + return result; +} + +// TODO: When we have memoryarena we can maybe do better +void BinaryReadString(BinaryReader* reader, SpanChar* output) +{ + auto span = SpanSliceFrom(reader->Data, reader->CurrentOffset); + // TODO: For now big endian -> little endian conversion + // TODO: Do the other conversions + + uint32_t length = 0; + + while (span.Pointer[length] != '\0') + { + output->Pointer[length] = span.Pointer[length]; + length++; + } + + output->Length = length; + reader->CurrentOffset += length + 1; +} + +void BinarySetOffset(BinaryReader* reader, size_t offset) +{ + reader->CurrentOffset = offset; +} + +void DeviceTreeReadNode(BinaryReader* reader, size_t stringDataOffset) +{ + auto testNode = BinaryReadUint32(reader); + + if (testNode == 0x01) + { + auto name = StackAllocChar(1024); + BinaryReadString(reader, &name); + BinarySetOffset(reader, MemoryAlignUp(reader->CurrentOffset, 4)); + + KernelConsolePrint(String("BeginNode: '%s'\n"), name); + } + else if (testNode == 0x02) + { + KernelConsolePrint(String("EndNode\n")); + } + else if (testNode == 0x03) + { + auto length = BinaryReadUint32(reader); + auto nameOffset = BinaryReadUint32(reader); + + if (length != 4) + { + KernelConsolePrint(String("Unknown length: %d\n"), length); + } + + auto value = BinaryReadUint32(reader); + + auto offset = reader->CurrentOffset; + BinarySetOffset(reader, stringDataOffset + nameOffset); + + auto name = StackAllocChar(1024); + BinaryReadString(reader, &name); + KernelConsolePrint(String("Test: %s\n"), name); + + BinarySetOffset(reader, MemoryAlignUp(offset, 4)); + KernelConsolePrint(String("Property: %s, %d\n"), name, value); + } + else + { + KernelConsolePrint(String("Unknown Node: %d\n"), testNode); + } +} + +PlatformDevices PlatformGetDevices() +{ + auto dtbMagic = BinaryReadUint32Old(globalDeviceTreeData); + auto sizeInBytes = BinaryReadUint32Old(globalDeviceTreeData + sizeof(uint32_t)); + + // TODO: Check magic + // TODO: Check boot_cpuid_phys + + auto dataSpan = CreateReadOnlySpanUint8((const uint8_t*)globalDeviceTreeData, sizeInBytes); + auto reader = CreateBinaryReader(dataSpan, ByteOrder_BigEndian); + BinarySetOffset(&reader, sizeof(uint32_t) * 2); + + auto structureOffset = BinaryReadUint32(&reader); + auto stringDataOffset = BinaryReadUint32(&reader); + + // TODO: Parse the rest of the header + + BinarySetOffset(&reader, structureOffset); + + DeviceTreeReadNode(&reader, stringDataOffset); + DeviceTreeReadNode(&reader, stringDataOffset); + DeviceTreeReadNode(&reader, stringDataOffset); + + DeviceTreeReadNode(&reader, stringDataOffset); + DeviceTreeReadNode(&reader, stringDataOffset); + DeviceTreeReadNode(&reader, stringDataOffset); + + + /* This is a property node parsing + testNode = BinaryReadUint32(&reader); + length = BinaryReadUint32(&reader); + nameOffset = BinaryReadUint32(&reader); + KernelConsolePrint(String("TestNode: %d, %d, %d\n"), testNode, length, nameOffset); + auto test = SpanSliceFrom(dataSpan, stringDataOffset + nameOffset); + KernelConsolePrint(String("Test: %s\n"), test); + */ + + + // TODO: We parse DTB here for now but it will be moved in Kernel/Devices/DTB + return (PlatformDevices) + { + }; +} diff --git a/src/Kernel/Platforms/RiscV/Sbi.c b/src/Kernel/Platforms/RiscV/Sbi.c index d14ddbe..53ee71c 100644 --- a/src/Kernel/Platforms/RiscV/Sbi.c +++ b/src/Kernel/Platforms/RiscV/Sbi.c @@ -69,16 +69,10 @@ void BiosDebugConsoleWrite(ReadOnlySpanChar message) void BiosSetTimer(uint64_t timeValue) { #if PLATFORM_ARCHITECTURE_BITS == 32 - auto rc = SbiCallFunction(SbiExtension_Time, 0x00, (uintptr_t)timeValue, (uintptr_t)(timeValue >> 32), 0, 0, 0, 0); + SbiCallFunction(SbiExtension_Time, 0x00, (uintptr_t)timeValue, (uintptr_t)(timeValue >> 32), 0, 0, 0, 0); #else - auto rc = SbiCallFunction(SbiExtension_Time, 0x00, timeValue, 0, 0, 0, 0, 0); + SbiCallFunction(SbiExtension_Time, 0x00, timeValue, 0, 0, 0, 0, 0); #endif - - uint64_t now = CpuReadTime(); -uint64_t deadline = timeValue; /* 2.5 s @ 4 MHz */ - -KernelConsolePrint(String("set_timer: err=%d val=%lx now=%lx dl=%lx\n"), - rc.ReturnCode, rc.Value, now, deadline); } void BiosReset(BiosResetType resetType, BiosResetReason reason) From 3bb1253eac2a666aa3ecedd6e016019aafc0cb1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Decroy=C3=A8re?= Date: Mon, 16 Jun 2025 21:49:11 +0200 Subject: [PATCH 18/18] Fix Hardware bug --- .github/workflows/release-riscv64_pine64_star64.yml | 1 - src/Kernel/KernelMain.c | 2 +- src/Kernel/Platforms/RiscV/Platform.c | 5 ++--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release-riscv64_pine64_star64.yml b/.github/workflows/release-riscv64_pine64_star64.yml index 9ac792b..f228b03 100644 --- a/.github/workflows/release-riscv64_pine64_star64.yml +++ b/.github/workflows/release-riscv64_pine64_star64.yml @@ -42,7 +42,6 @@ jobs: run: | make -C u-boot starfive_visionfive2_defconfig make -C u-boot -j$(nproc) spl/u-boot-spl.bin - make -C u-boot -j$(nproc) dtbs - name: Pack SPL image with StarFive spl_tool run: | diff --git a/src/Kernel/KernelMain.c b/src/Kernel/KernelMain.c index 31bce80..64ffc7c 100644 --- a/src/Kernel/KernelMain.c +++ b/src/Kernel/KernelMain.c @@ -95,7 +95,7 @@ void KernelMain() CpuSetTrapHandler(KernelTrapHandler); // TODO: Test Timer only when the hardware is running fine - CpuEnableInterrupts(CpuInterruptType_All); + CpuEnableInterrupts(CpuInterruptType_Timer); while (true) { diff --git a/src/Kernel/Platforms/RiscV/Platform.c b/src/Kernel/Platforms/RiscV/Platform.c index f4bb542..a14ad09 100644 --- a/src/Kernel/Platforms/RiscV/Platform.c +++ b/src/Kernel/Platforms/RiscV/Platform.c @@ -116,7 +116,7 @@ void DeviceTreeReadNode(BinaryReader* reader, size_t stringDataOffset) if (length != 4) { - KernelConsolePrint(String("Unknown length: %d\n"), length); + KernelConsolePrint(String(" Unknown length: %d\n"), length); } auto value = BinaryReadUint32(reader); @@ -126,10 +126,9 @@ void DeviceTreeReadNode(BinaryReader* reader, size_t stringDataOffset) auto name = StackAllocChar(1024); BinaryReadString(reader, &name); - KernelConsolePrint(String("Test: %s\n"), name); BinarySetOffset(reader, MemoryAlignUp(offset, 4)); - KernelConsolePrint(String("Property: %s, %d\n"), name, value); + KernelConsolePrint(String(" Property: %s, %d\n"), name, value); } else {