Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/kernel-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/release-riscv64_pine64_star64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
6 changes: 3 additions & 3 deletions src/Common/Memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 }; \
} \
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/Common/String.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions src/Common/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 16 additions & 3 deletions src/Kernel/KernelMain.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,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);
Expand All @@ -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;
Expand Down Expand Up @@ -82,13 +86,22 @@ 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() + 10000000);

// TODO: Test Timer only when the hardware is running fine
CpuEnableInterrupts(CpuInterruptType_Timer);

while (true)
{
CpuGenerateInvalidInstruction();
KernelConsolePrint(String("WFI\n"));

//CpuGenerateInvalidInstruction();
CpuWaitForInterrupt();
}
}
16 changes: 11 additions & 5 deletions src/Kernel/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,27 @@ 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
// --------------------------------------------------------------------------------------

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;

Expand Down
8 changes: 7 additions & 1 deletion src/Kernel/Platforms/RiscV/Boot.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 6 additions & 5 deletions src/Kernel/Platforms/RiscV/Cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ inline uint64_t CpuReadCycle()
#endif

inline void CpuGenerateInvalidInstruction()
{
{
__asm__ volatile ("unimp");
}

Expand Down Expand Up @@ -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));
}
Expand All @@ -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"
Expand Down Expand Up @@ -251,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();
Expand Down
2 changes: 1 addition & 1 deletion src/Kernel/Platforms/RiscV/KernelTrapEntry.S
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "AsmCommon.h"

.global kernel_trap_entry # TODO: Rename
.global kernel_trap_entry

.section .text.interrupt

Expand Down
171 changes: 170 additions & 1 deletion src/Kernel/Platforms/RiscV/Platform.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,181 @@
#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);

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)
{
};
}