sync
This commit is contained in:
parent
11e4187a22
commit
a7173040de
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
/disk/*
|
||||
!/disk/.gitkeep
|
||||
*.map
|
||||
*.tar
|
||||
*.o
|
||||
*.elf
|
||||
*.bin
|
||||
*.log
|
||||
*.pcap
|
||||
116
common.c
Normal file
116
common.c
Normal file
@ -0,0 +1,116 @@
|
||||
#include "common.h"
|
||||
|
||||
void putchar(char ch);
|
||||
|
||||
void printf(const char *fmt, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
va_start(vargs, fmt);
|
||||
|
||||
while (*fmt)
|
||||
{
|
||||
if (*fmt == '%')
|
||||
{
|
||||
fmt++; // skip '%'
|
||||
switch (*fmt)
|
||||
{ // Read the next char
|
||||
case '\0': // '%' at the end of the format string
|
||||
putchar('%');
|
||||
goto end;
|
||||
case '%': // Print '%'
|
||||
putchar('%');
|
||||
break;
|
||||
case 's':
|
||||
{ // Print a null terminated string
|
||||
const char *s = va_arg(vargs, const char *);
|
||||
while (*s)
|
||||
{
|
||||
putchar(*s);
|
||||
s++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'd':
|
||||
{ // Print an integer in decimal
|
||||
int value = va_arg(vargs, int);
|
||||
if (value < 0)
|
||||
{
|
||||
putchar('-');
|
||||
value = -value;
|
||||
}
|
||||
|
||||
int divisor = 1;
|
||||
while (value / divisor > 9)
|
||||
divisor *= 10;
|
||||
|
||||
while (divisor > 0)
|
||||
{
|
||||
putchar('0' + value / divisor);
|
||||
value %= divisor;
|
||||
divisor /= 10;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'x':
|
||||
{ // Print an integer in hexadecimal
|
||||
int value = va_arg(vargs, int);
|
||||
for (int i = 7; i >= 0; i--)
|
||||
{
|
||||
int nibble = (value >> (i * 4)) & 0xf;
|
||||
putchar("0123456789abcdef"[nibble]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
putchar(*fmt);
|
||||
}
|
||||
|
||||
fmt++;
|
||||
}
|
||||
end:
|
||||
va_end(vargs);
|
||||
}
|
||||
|
||||
void *memcpy(void *dst, const void *src, size_t n)
|
||||
{
|
||||
uint8_t *d = (uint8_t *)dst;
|
||||
const uint8_t *s = (const uint8_t *)src;
|
||||
while (n--)
|
||||
*d++ = *s++;
|
||||
return dst;
|
||||
}
|
||||
|
||||
void *memset(void *buf, char c, size_t n)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)buf;
|
||||
while (n--)
|
||||
{
|
||||
*p++ = c;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *strcpy(char *dst, const char *src)
|
||||
{
|
||||
char *d = dst;
|
||||
while (*src)
|
||||
*d++ = *src++;
|
||||
*d = '\0';
|
||||
return dst;
|
||||
}
|
||||
|
||||
int strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
while (*s1 && *s2)
|
||||
{
|
||||
if (*s1 != *s2)
|
||||
break;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
||||
return *(unsigned char *)s1 - *(unsigned char *)s2;
|
||||
}
|
||||
27
common.h
Normal file
27
common.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
typedef int bool;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef uint32_t size_t;
|
||||
typedef uint32_t paddr_t;
|
||||
typedef uint32_t vaddr_t;
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define NULL ((void *)0)
|
||||
#define align_up(value, align) __builtin_align_up(value, align)
|
||||
#define is_aligned(value, align) __builtin_is_aligned(value, align)
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
#define va_list __builtin_va_list
|
||||
#define va_start __builtin_va_start
|
||||
#define va_end __builtin_va_end
|
||||
#define va_arg __builtin_va_arg
|
||||
|
||||
void *memset(void *buf, char c, size_t n);
|
||||
void *memcpy(void *dst, const void *src, size_t n);
|
||||
char *strcpy(char *dst, const char *src);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
void printf(const char *fmt, ...);
|
||||
199
kernel.c
Normal file
199
kernel.c
Normal file
@ -0,0 +1,199 @@
|
||||
#include "kernel.h"
|
||||
#include "common.h"
|
||||
|
||||
extern char __bss[], __bss_end[], __stack_top[];
|
||||
extern char __free_ram[], __free_ram_end[];
|
||||
|
||||
paddr_t alloc_pages(uint32_t n)
|
||||
{
|
||||
static paddr_t next_paddr = (paddr_t)__free_ram;
|
||||
paddr_t paddr = next_paddr;
|
||||
next_paddr += n * PAGE_SIZE;
|
||||
|
||||
if (next_paddr > (paddr_t)__free_ram_end)
|
||||
PANIC("OOM BABY");
|
||||
|
||||
memset((void *)paddr, 0, n * PAGE_SIZE);
|
||||
return paddr;
|
||||
}
|
||||
|
||||
struct sbiret sbi_call(long arg0, long arg1, long arg2, long arg3, long arg4,
|
||||
long arg5, long fid, long eid)
|
||||
{
|
||||
register long a0 __asm__("a0") = arg0;
|
||||
register long a1 __asm__("a1") = arg1;
|
||||
register long a2 __asm__("a2") = arg2;
|
||||
register long a3 __asm__("a3") = arg3;
|
||||
register long a4 __asm__("a4") = arg4;
|
||||
register long a5 __asm__("a5") = arg5;
|
||||
register long a6 __asm__("a6") = fid;
|
||||
register long a7 __asm__("a7") = eid;
|
||||
|
||||
__asm__ __volatile__("ecall"
|
||||
: "=r"(a0), "=r"(a1)
|
||||
: "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5),
|
||||
"r"(a6), "r"(a7)
|
||||
: "memory");
|
||||
|
||||
return (struct sbiret){.error = a0, .value = a1};
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
__attribute__((aligned(4))) void
|
||||
kernel_entry(void)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"csrw sscratch, sp\n"
|
||||
"addi sp, sp, -4 * 31\n"
|
||||
"sw ra, 4 * 0(sp)\n"
|
||||
"sw gp, 4 * 1(sp)\n"
|
||||
"sw tp, 4 * 2(sp)\n"
|
||||
"sw t0, 4 * 3(sp)\n"
|
||||
"sw t1, 4 * 4(sp)\n"
|
||||
"sw t2, 4 * 5(sp)\n"
|
||||
"sw t3, 4 * 6(sp)\n"
|
||||
"sw t4, 4 * 7(sp)\n"
|
||||
"sw t5, 4 * 8(sp)\n"
|
||||
"sw t6, 4 * 9(sp)\n"
|
||||
"sw a0, 4 * 10(sp)\n"
|
||||
"sw a1, 4 * 11(sp)\n"
|
||||
"sw a2, 4 * 12(sp)\n"
|
||||
"sw a3, 4 * 13(sp)\n"
|
||||
"sw a4, 4 * 14(sp)\n"
|
||||
"sw a5, 4 * 15(sp)\n"
|
||||
"sw a6, 4 * 16(sp)\n"
|
||||
"sw a7, 4 * 17(sp)\n"
|
||||
"sw s0, 4 * 18(sp)\n"
|
||||
"sw s1, 4 * 19(sp)\n"
|
||||
"sw s2, 4 * 20(sp)\n"
|
||||
"sw s3, 4 * 21(sp)\n"
|
||||
"sw s4, 4 * 22(sp)\n"
|
||||
"sw s5, 4 * 23(sp)\n"
|
||||
"sw s6, 4 * 24(sp)\n"
|
||||
"sw s7, 4 * 25(sp)\n"
|
||||
"sw s8, 4 * 26(sp)\n"
|
||||
"sw s9, 4 * 27(sp)\n"
|
||||
"sw s10, 4 * 28(sp)\n"
|
||||
"sw s11, 4 * 29(sp)\n"
|
||||
|
||||
"csrr a0, sscratch\n"
|
||||
"sw a0, 4 * 30(sp)\n"
|
||||
|
||||
"mv a0, sp\n"
|
||||
"call handle_trap\n"
|
||||
|
||||
"lw ra, 4 * 0(sp)\n"
|
||||
"lw gp, 4 * 1(sp)\n"
|
||||
"lw tp, 4 * 2(sp)\n"
|
||||
"lw t0, 4 * 3(sp)\n"
|
||||
"lw t1, 4 * 4(sp)\n"
|
||||
"lw t2, 4 * 5(sp)\n"
|
||||
"lw t3, 4 * 6(sp)\n"
|
||||
"lw t4, 4 * 7(sp)\n"
|
||||
"lw t5, 4 * 8(sp)\n"
|
||||
"lw t6, 4 * 9(sp)\n"
|
||||
"lw a0, 4 * 10(sp)\n"
|
||||
"lw a1, 4 * 11(sp)\n"
|
||||
"lw a2, 4 * 12(sp)\n"
|
||||
"lw a3, 4 * 13(sp)\n"
|
||||
"lw a4, 4 * 14(sp)\n"
|
||||
"lw a5, 4 * 15(sp)\n"
|
||||
"lw a6, 4 * 16(sp)\n"
|
||||
"lw a7, 4 * 17(sp)\n"
|
||||
"lw s0, 4 * 18(sp)\n"
|
||||
"lw s1, 4 * 19(sp)\n"
|
||||
"lw s2, 4 * 20(sp)\n"
|
||||
"lw s3, 4 * 21(sp)\n"
|
||||
"lw s4, 4 * 22(sp)\n"
|
||||
"lw s5, 4 * 23(sp)\n"
|
||||
"lw s6, 4 * 24(sp)\n"
|
||||
"lw s7, 4 * 25(sp)\n"
|
||||
"lw s8, 4 * 26(sp)\n"
|
||||
"lw s9, 4 * 27(sp)\n"
|
||||
"lw s10, 4 * 28(sp)\n"
|
||||
"lw s11, 4 * 29(sp)\n"
|
||||
"lw sp, 4 * 30(sp)\n"
|
||||
"sret\n");
|
||||
}
|
||||
|
||||
__attribute__((naked)) void switch_context(uint32_t *prev_sp,
|
||||
uint32_t *next_sp)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"addi sp, sp, -13 * 4\n" // Allocate stack space for 13 4 byte registers
|
||||
"sw ra, 0 * 4(sp)\n" // Save callee-saved registers only
|
||||
"sw s0, 1 * 4(sp)\n"
|
||||
"sw s1, 2 * 4(sp)\n"
|
||||
"sw s2, 3 * 4(sp)\n"
|
||||
"sw s3, 4 * 4(sp)\n"
|
||||
"sw s4, 5 * 4(sp)\n"
|
||||
"sw s5, 6 * 4(sp)\n"
|
||||
"sw s6, 7 * 4(sp)\n"
|
||||
"sw s7, 8 * 4(sp)\n"
|
||||
"sw s8, 9 * 4(sp)\n"
|
||||
"sw s9, 10 * 4(sp)\n"
|
||||
"sw s10, 11 * 4(sp)\n"
|
||||
"sw s11, 12 * 4(sp)\n"
|
||||
"sw sp, (a0)\n" // *prev_sp = sp;
|
||||
"lw sp, (a1)\n" // Switch stack pointer (sp) here
|
||||
"lw ra, 0 * 4(sp)\n" // Restore callee-saved-registers only
|
||||
"lw s0, 1 * 4(sp)\n"
|
||||
"lw s1, 2 * 4(sp)\n"
|
||||
"lw s2, 3 * 4(sp)\n"
|
||||
"lw s3, 4 * 4(sp)\n"
|
||||
"lw s4, 5 * 4(sp)\n"
|
||||
"lw s5, 6 * 4(sp)\n"
|
||||
"lw s6, 7 * 4(sp)\n"
|
||||
"lw s7, 8 * 4(sp)\n"
|
||||
"lw s8, 9 * 4(sp)\n"
|
||||
"lw s9, 10 * 4(sp)\n"
|
||||
"lw s10, 11 * 4(sp)\n"
|
||||
"lw s11, 12 * 4(sp)\n"
|
||||
"addi sp, sp * 4\n"
|
||||
"ret\n"
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
void handle_trap(struct trap_frame *f)
|
||||
{
|
||||
uint32_t scause = READ_CSR(scause);
|
||||
uint32_t stval = READ_CSR(stval);
|
||||
uint32_t user_pc = READ_CSR(sepc);
|
||||
|
||||
PANIC("unexpected trap scause=%x, stval=%x, user_pc=%x\n", scause, stval, user_pc);
|
||||
}
|
||||
|
||||
void putchar(char ch)
|
||||
{
|
||||
sbi_call(ch, 0, 0, 0, 0, 0, 0, 1 /* Console Putchar */);
|
||||
}
|
||||
|
||||
void kernel_main(void)
|
||||
{
|
||||
memset(__bss, 0, (size_t)__bss_end - (size_t)__bss);
|
||||
WRITE_CSR(stvec, (uint32_t)kernel_entry);
|
||||
|
||||
paddr_t paddr0 = alloc_pages(2);
|
||||
paddr_t paddr1 = alloc_pages(1);
|
||||
printf("alloc_pages test: paddr0=%x\n", paddr0);
|
||||
printf("alloc_pages test: paddr1=%x\n", paddr1);
|
||||
|
||||
PANIC("Booted");
|
||||
for (;;)
|
||||
{
|
||||
__asm__ __volatile__("wfi");
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((section(".text.boot")))
|
||||
__attribute__((naked)) void
|
||||
boot(void)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"mv sp, %[stack_top]\n" // Set the stack pointer
|
||||
"j kernel_main\n" // Jump to the kernel main function
|
||||
:
|
||||
: [stack_top] "r"(__stack_top) // Pass the stack top address as %[stack_top]
|
||||
);
|
||||
}
|
||||
79
kernel.h
Normal file
79
kernel.h
Normal file
@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
#define PANIC(fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
printf("KERNEL IS PANICING AT THE DISCO: %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
|
||||
while (1) \
|
||||
{ \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct sbiret
|
||||
{
|
||||
long error;
|
||||
long value;
|
||||
};
|
||||
|
||||
struct trap_frame
|
||||
{
|
||||
uint32_t ra;
|
||||
uint32_t gp;
|
||||
uint32_t tp;
|
||||
uint32_t t0;
|
||||
uint32_t t1;
|
||||
uint32_t t2;
|
||||
uint32_t t3;
|
||||
uint32_t t4;
|
||||
uint32_t t5;
|
||||
uint32_t t6;
|
||||
uint32_t a0;
|
||||
uint32_t a1;
|
||||
uint32_t a2;
|
||||
uint32_t a3;
|
||||
uint32_t a4;
|
||||
uint32_t a5;
|
||||
uint32_t a6;
|
||||
uint32_t s0;
|
||||
uint32_t s1;
|
||||
uint32_t s2;
|
||||
uint32_t s3;
|
||||
uint32_t s4;
|
||||
uint32_t s5;
|
||||
uint32_t s6;
|
||||
uint32_t s7;
|
||||
uint32_t s8;
|
||||
uint32_t s9;
|
||||
uint32_t s10;
|
||||
uint32_t s11;
|
||||
uint32_t sp;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define READ_CSR(reg) \
|
||||
({ \
|
||||
unsigned long __tmp; \
|
||||
__asm__ __volatile__("csrr %0, " #reg : "=r"(__tmp)); \
|
||||
__tmp; \
|
||||
})
|
||||
|
||||
#define WRITE_CSR(reg, value) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t __tmp = (value); \
|
||||
__asm__ __volatile__("csrw " #reg ", %0" ::"r"(__tmp)); \
|
||||
} while (0)
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
#define PROCS_MAX 8 // Maximum number of processes
|
||||
#define PROC_UNUSED 0 // Unused process control structure
|
||||
#define PROC_RUNNABLE 1 // Runnable process
|
||||
|
||||
struct process
|
||||
{
|
||||
int pid; // Process ID
|
||||
int state; // Process state
|
||||
vaddr_t sp; // Stack pointer
|
||||
uint8_t stack[8192]; // Kernel stack
|
||||
};
|
||||
33
kernel.ld
Normal file
33
kernel.ld
Normal file
@ -0,0 +1,33 @@
|
||||
ENTRY(boot)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x80200000;
|
||||
|
||||
.text :{
|
||||
KEEP(*(.text.BOOT));
|
||||
*(text .text.*);
|
||||
}
|
||||
|
||||
.rodata : ALIGN(4) {
|
||||
*(.rodata .rodata.*);
|
||||
}
|
||||
|
||||
.data : ALIGN(4) {
|
||||
*(.data .data.*);
|
||||
}
|
||||
|
||||
.bss : ALIGN(4) {
|
||||
__bss = .;
|
||||
*(.bss .bss.* .sbss .sbss.*);
|
||||
__bss_end = .;
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
. += 128 * 1024; /* 128KB */
|
||||
__stack_top = .;
|
||||
|
||||
. = ALIGN(4096);
|
||||
__free_ram = .;
|
||||
. += 64 * 1024 * 1024; /* 64MB */
|
||||
__free_ram_end = .;
|
||||
}
|
||||
17
run.sh
Executable file
17
run.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
set -xue
|
||||
|
||||
# QEMU binary
|
||||
QEMU=qemu-system-riscv32
|
||||
|
||||
# Path to clang and compiler flags
|
||||
CC=/usr/bin/clang
|
||||
CFLAGS="-std=c11 -o@ -g3 -Wall -Wextra --target=riscv32 -ffreestanding -nostdlib"
|
||||
|
||||
$CC $CFLAGS -Wl,-Tkernel.ld -Wl,-Map=kernel.map -o kernel.elf \
|
||||
kernel.c common.c
|
||||
|
||||
|
||||
# Start QEMU
|
||||
$QEMU -machine virt -bios default -nographic -serial mon:stdio --no-reboot \
|
||||
-kernel kernel.elf
|
||||
Loading…
x
Reference in New Issue
Block a user