Compare commits
No commits in common. "ddddf903dc4fa649ed8cbbc30452fedda5364586" and "b8bf28f597c905028e401224d0ba7ff991ddddce" have entirely different histories.
ddddf903dc
...
b8bf28f597
11 changed files with 27 additions and 408 deletions
|
|
@ -2,9 +2,8 @@ BasedOnStyle: LLVM
|
||||||
IndentWidth: 4 # Use 4 spaces for indentation
|
IndentWidth: 4 # Use 4 spaces for indentation
|
||||||
TabWidth: 4 # Tab width is also 4 spaces
|
TabWidth: 4 # Tab width is also 4 spaces
|
||||||
UseTab: Never # Always use spaces instead of tabs
|
UseTab: Never # Always use spaces instead of tabs
|
||||||
ColumnLimit: 120 # Wrap lines after 80 characters
|
ColumnLimit: 80 # Wrap lines after 80 characters
|
||||||
AllowShortLoopsOnASingleLine: true
|
AllowShortLoopsOnASingleLine: true
|
||||||
AllowShortFunctionsOnASingleLine: false
|
|
||||||
AlwaysBreakTemplateDeclarations: true
|
AlwaysBreakTemplateDeclarations: true
|
||||||
BreakConstructorInitializers: BeforeComma
|
BreakConstructorInitializers: BeforeComma
|
||||||
AlignConsecutiveDeclarations:
|
AlignConsecutiveDeclarations:
|
||||||
|
|
@ -15,4 +14,3 @@ AlignConsecutiveDeclarations:
|
||||||
AlignFunctionPointers: false
|
AlignFunctionPointers: false
|
||||||
PadOperators: false
|
PadOperators: false
|
||||||
AlignConsecutiveMacros: true
|
AlignConsecutiveMacros: true
|
||||||
AllowShortCaseLabelsOnASingleLine: true
|
|
||||||
|
|
|
||||||
4
Makefile
4
Makefile
|
|
@ -28,7 +28,7 @@ CFLAGS += -fno-omit-frame-pointer # More reliable backtraces in GDB
|
||||||
|
|
||||||
all: kernel.elf
|
all: kernel.elf
|
||||||
|
|
||||||
kernel.elf: entry.o start.o lib/string.o lib/proc.o lib/proc.o lib/uart.o lib/panic.o kern/kalloc.o lib/memory.o kern/ispinlock.o lib/spinlock.o
|
kernel.elf: entry.o start.o lib/string.o lib/proc.o lib/spinlock.o lib/proc.o lib/uart.o lib/panic.o kern/kalloc.o lib/memory.o
|
||||||
@echo LD $@
|
@echo LD $@
|
||||||
@$(LD) $(LDFLAGS) -o $@ $^
|
@$(LD) $(LDFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
|
@ -48,5 +48,3 @@ clean:
|
||||||
rm -f *.o *.elf *.d lib/*.o lib/*.d
|
rm -f *.o *.elf *.d lib/*.o lib/*.d
|
||||||
|
|
||||||
-include *.d
|
-include *.d
|
||||||
|
|
||||||
.PHONY: all
|
|
||||||
|
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
#include "ispinlock.h"
|
|
||||||
|
|
||||||
void spinlock_init(spinlock_t *l) {
|
|
||||||
l->v = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool spin_trylock(spinlock_t *l) {
|
|
||||||
uint32_t old;
|
|
||||||
// old = xchg_acquire(&l->v, 1) using AMO
|
|
||||||
__asm__ volatile("amoswap.w.aq %0, %2, (%1)\n" : "=&r"(old) : "r"(&l->v), "r"(1u) : "memory");
|
|
||||||
return old == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spin_unlock(spinlock_t *l) {
|
|
||||||
// Release: store 0 with .rl ordering.
|
|
||||||
uint32_t dummy;
|
|
||||||
__asm__ volatile("amoswap.w.rl %0, %2, (%1)\n" : "=&r"(dummy) : "r"(&l->v), "r"(0u) : "memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optional: tiny pause/backoff (works even if Zihintpause isn't present).
|
|
||||||
// See: https://github.com/riscv/riscv-isa-manual/blob/main/src/zihintpause.adoc
|
|
||||||
void cpu_relax(void) {
|
|
||||||
#if defined(__riscv_zihintpause)
|
|
||||||
__asm__ volatile("pause");
|
|
||||||
#else
|
|
||||||
__asm__ volatile("nop");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test-and-test-and-set acquire with polite spinning + exponential backoff.
|
|
||||||
void spin_lock(spinlock_t *l) {
|
|
||||||
unsigned backoff = 1;
|
|
||||||
for (;;) {
|
|
||||||
if (spin_trylock(l))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Contended: spin on plain loads (no AMO) until it looks free.
|
|
||||||
while (__atomic_load_n(&l->v, __ATOMIC_RELAXED) != 0) {
|
|
||||||
for (unsigned i = 0; i < backoff; ++i) cpu_relax();
|
|
||||||
if (backoff < 1u << 12)
|
|
||||||
backoff <<= 1;
|
|
||||||
}
|
|
||||||
// Try again; loop.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
volatile uint32_t v; // 0 = unlocked, 1 = locked
|
|
||||||
} spinlock_t;
|
|
||||||
|
|
||||||
void spinlock_init(spinlock_t *l);
|
|
||||||
bool spin_trylock(spinlock_t *l);
|
|
||||||
void spin_unlock(spinlock_t *l);
|
|
||||||
void cpu_relax(void);
|
|
||||||
void spin_lock(spinlock_t *l);
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#include <ispinlock.h>
|
|
||||||
#include <kalloc.h>
|
#include <kalloc.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <panic.h>
|
#include <panic.h>
|
||||||
#include <riscv.h>
|
#include <riscv.h>
|
||||||
|
#include <spinlock.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
|
|
@ -23,12 +23,12 @@ struct Run {
|
||||||
|
|
||||||
/** Kernel memory allocator. */
|
/** Kernel memory allocator. */
|
||||||
struct {
|
struct {
|
||||||
spinlock_t lock;
|
struct Spinlock lock;
|
||||||
struct Run *freelist;
|
struct Run *freelist;
|
||||||
} kmem;
|
} kmem;
|
||||||
|
|
||||||
void kalloc_init() {
|
void kalloc_init() {
|
||||||
spinlock_init(&kmem.lock);
|
initlock(&kmem.lock, "kmem");
|
||||||
freerange(kernel_end, (void *)PHYSTOP);
|
freerange(kernel_end, (void *)PHYSTOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,7 +43,8 @@ void kfree(void *pa) {
|
||||||
|
|
||||||
// Assert that page is a ligned to a page boundary and that its correctly
|
// Assert that page is a ligned to a page boundary and that its correctly
|
||||||
// sized
|
// sized
|
||||||
if (((u64)pa % PGSIZE) != 0 || (char *)pa < kernel_end || (u64)pa >= PHYSTOP)
|
if (((u64)pa % PGSIZE) != 0 || (char *)pa < kernel_end ||
|
||||||
|
(u64)pa >= PHYSTOP)
|
||||||
panic("kfree");
|
panic("kfree");
|
||||||
|
|
||||||
// Fill with junk to catch dangling refs.
|
// Fill with junk to catch dangling refs.
|
||||||
|
|
@ -51,23 +52,23 @@ void kfree(void *pa) {
|
||||||
|
|
||||||
r = (struct Run *)pa;
|
r = (struct Run *)pa;
|
||||||
|
|
||||||
spin_lock(&kmem.lock);
|
acquire(&kmem.lock);
|
||||||
r->next = kmem.freelist;
|
r->next = kmem.freelist;
|
||||||
kmem.freelist = r;
|
kmem.freelist = r;
|
||||||
spin_unlock(&kmem.lock);
|
release(&kmem.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *kalloc(void) {
|
void *kalloc(void) {
|
||||||
struct Run *r;
|
struct Run *r;
|
||||||
|
|
||||||
spin_lock(&kmem.lock);
|
acquire(&kmem.lock);
|
||||||
|
|
||||||
r = kmem.freelist;
|
r = kmem.freelist;
|
||||||
|
|
||||||
if (r)
|
if (r)
|
||||||
kmem.freelist = r->next;
|
kmem.freelist = r->next;
|
||||||
|
|
||||||
spin_unlock(&kmem.lock);
|
release(&kmem.lock);
|
||||||
|
|
||||||
if (r)
|
if (r)
|
||||||
memset((char *)r, 5, PGSIZE); // fill with junk
|
memset((char *)r, 5, PGSIZE); // fill with junk
|
||||||
|
|
|
||||||
103
kern/kprint.c
103
kern/kprint.c
|
|
@ -1,103 +0,0 @@
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
static void append_char(char **buf, size_t *remaining, char c) {
|
|
||||||
if (*remaining > 1) { // Leave space for null terminator
|
|
||||||
**buf = c;
|
|
||||||
(*buf)++;
|
|
||||||
(*remaining)--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void append_str(char **buf, size_t *remaining, const char *str) {
|
|
||||||
while (*str) {
|
|
||||||
append_char(buf, remaining, *str++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void append_int(char **buf, size_t *remaining, int value, int base) {
|
|
||||||
char tmp[32];
|
|
||||||
const char *digits = "0123456789abcdef";
|
|
||||||
bool neg = false;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (base == 10 && value < 0) {
|
|
||||||
neg = true;
|
|
||||||
value = -value;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
tmp[i++] = digits[value % base];
|
|
||||||
value /= base;
|
|
||||||
} while (value && i < (int)sizeof(tmp));
|
|
||||||
|
|
||||||
if (neg) {
|
|
||||||
tmp[i++] = '-';
|
|
||||||
}
|
|
||||||
|
|
||||||
while (i--) {
|
|
||||||
append_char(buf, remaining, tmp[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int kvsnprintf(char *buf, size_t size, const char *fmt, va_list args) {
|
|
||||||
char *p = buf;
|
|
||||||
size_t remaining = size;
|
|
||||||
|
|
||||||
while (*fmt) {
|
|
||||||
if (*fmt != '%') {
|
|
||||||
append_char(&p, &remaining, *fmt++);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
fmt++; // skip '%'
|
|
||||||
|
|
||||||
switch (*fmt) {
|
|
||||||
case 's':
|
|
||||||
append_str(&p, &remaining, va_arg(args, const char *));
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
append_int(&p, &remaining, va_arg(args, int), 10);
|
|
||||||
break;
|
|
||||||
case 'x':
|
|
||||||
append_int(&p, &remaining, va_arg(args, unsigned int), 16);
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
append_char(&p, &remaining, (char)va_arg(args, int));
|
|
||||||
break;
|
|
||||||
case '%':
|
|
||||||
append_char(&p, &remaining, '%');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
append_char(&p, &remaining, '?');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fmt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remaining > 0) {
|
|
||||||
*p = '\0';
|
|
||||||
} else {
|
|
||||||
buf[size - 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return (int)(p - buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ksnprintf(char *buf, size_t size, const char *fmt, ...) {
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
int ret = kvsnprintf(buf, size, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void kprintf(const char *fmt, ...) {
|
|
||||||
char buffer[256];
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
kvsnprintf(buffer, sizeof(buffer), fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
// Now send buffer to your console/serial output
|
|
||||||
console_write(buffer);
|
|
||||||
}
|
|
||||||
|
|
@ -1,127 +0,0 @@
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
void *memcpy(void *s1, const void *s2, size_t n) {
|
|
||||||
const char *f = s2;
|
|
||||||
char *t = s1;
|
|
||||||
|
|
||||||
while (n-- > 0) *t++ = *f++;
|
|
||||||
return s1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *memmove(void *s1, const void *s2, size_t n) {
|
|
||||||
const char *f = s2;
|
|
||||||
char *t = s1;
|
|
||||||
|
|
||||||
if (f < t) {
|
|
||||||
f += n;
|
|
||||||
t += n;
|
|
||||||
while (n-- > 0) *--t = *--f;
|
|
||||||
} else
|
|
||||||
while (n-- > 0) *t++ = *f++;
|
|
||||||
return s1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *memset(void *dest, int c, size_t n) {
|
|
||||||
unsigned char *s = dest;
|
|
||||||
size_t k;
|
|
||||||
|
|
||||||
/* Fill head and tail with minimal branching. Each
|
|
||||||
* conditional ensures that all the subsequently used
|
|
||||||
* offsets are well-defined and in the dest region. */
|
|
||||||
|
|
||||||
if (!n)
|
|
||||||
return dest;
|
|
||||||
s[0] = c;
|
|
||||||
s[n - 1] = c;
|
|
||||||
if (n <= 2)
|
|
||||||
return dest;
|
|
||||||
s[1] = c;
|
|
||||||
s[2] = c;
|
|
||||||
s[n - 2] = c;
|
|
||||||
s[n - 3] = c;
|
|
||||||
if (n <= 6)
|
|
||||||
return dest;
|
|
||||||
s[3] = c;
|
|
||||||
s[n - 4] = c;
|
|
||||||
if (n <= 8)
|
|
||||||
return dest;
|
|
||||||
|
|
||||||
/* Advance pointer to align it at a 4-byte boundary,
|
|
||||||
* and truncate n to a multiple of 4. The previous code
|
|
||||||
* already took care of any head/tail that get cut off
|
|
||||||
* by the alignment. */
|
|
||||||
|
|
||||||
k = -(uintptr_t)s & 3;
|
|
||||||
s += k;
|
|
||||||
n -= k;
|
|
||||||
n &= -4;
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
typedef uint32_t __attribute__((__may_alias__)) u32;
|
|
||||||
typedef uint64_t __attribute__((__may_alias__)) u64;
|
|
||||||
|
|
||||||
u32 c32 = ((u32)-1) / 255 * (unsigned char)c;
|
|
||||||
|
|
||||||
/* In preparation to copy 32 bytes at a time, aligned on
|
|
||||||
* an 8-byte bounary, fill head/tail up to 28 bytes each.
|
|
||||||
* As in the initial byte-based head/tail fill, each
|
|
||||||
* conditional below ensures that the subsequent offsets
|
|
||||||
* are valid (e.g. !(n<=24) implies n>=28). */
|
|
||||||
|
|
||||||
*(u32 *)(s + 0) = c32;
|
|
||||||
*(u32 *)(s + n - 4) = c32;
|
|
||||||
if (n <= 8)
|
|
||||||
return dest;
|
|
||||||
*(u32 *)(s + 4) = c32;
|
|
||||||
*(u32 *)(s + 8) = c32;
|
|
||||||
*(u32 *)(s + n - 12) = c32;
|
|
||||||
*(u32 *)(s + n - 8) = c32;
|
|
||||||
if (n <= 24)
|
|
||||||
return dest;
|
|
||||||
*(u32 *)(s + 12) = c32;
|
|
||||||
*(u32 *)(s + 16) = c32;
|
|
||||||
*(u32 *)(s + 20) = c32;
|
|
||||||
*(u32 *)(s + 24) = c32;
|
|
||||||
*(u32 *)(s + n - 28) = c32;
|
|
||||||
*(u32 *)(s + n - 24) = c32;
|
|
||||||
*(u32 *)(s + n - 20) = c32;
|
|
||||||
*(u32 *)(s + n - 16) = c32;
|
|
||||||
|
|
||||||
/* Align to a multiple of 8 so we can fill 64 bits at a time,
|
|
||||||
* and avoid writing the same bytes twice as much as is
|
|
||||||
* practical without introducing additional branching. */
|
|
||||||
|
|
||||||
k = 24 + ((uintptr_t)s & 4);
|
|
||||||
s += k;
|
|
||||||
n -= k;
|
|
||||||
|
|
||||||
/* If this loop is reached, 28 tail bytes have already been
|
|
||||||
* filled, so any remainder when n drops below 32 can be
|
|
||||||
* safely ignored. */
|
|
||||||
|
|
||||||
u64 c64 = c32 | ((u64)c32 << 32);
|
|
||||||
for (; n >= 32; n -= 32, s += 32) {
|
|
||||||
*(u64 *)(s + 0) = c64;
|
|
||||||
*(u64 *)(s + 8) = c64;
|
|
||||||
*(u64 *)(s + 16) = c64;
|
|
||||||
*(u64 *)(s + 24) = c64;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* Pure C fallback with no aliasing violations. */
|
|
||||||
for (; n; n--, s++) *s = c;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
int memcmp(const void *s1, const void *s2, size_t n) {
|
|
||||||
if (n != 0) {
|
|
||||||
const unsigned char *p1 = s1, *p2 = s2;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (*p1++ != *p2++)
|
|
||||||
return (*--p1 - *--p2);
|
|
||||||
} while (--n != 0);
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
void *memcpy(void *s1, const void *s2, size_t n);
|
|
||||||
void *memmove(void *s1, const void *s2, size_t n);
|
|
||||||
void *memset(void *dest, int c, size_t n);
|
|
||||||
int memcmp(const void *s1, const void *s2, size_t n);
|
|
||||||
77
kern/proc.h
77
kern/proc.h
|
|
@ -1,77 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
UNUSED,
|
|
||||||
USED,
|
|
||||||
SLEEPING,
|
|
||||||
RUNNABLE,
|
|
||||||
RUNNING,
|
|
||||||
ZOMBIE,
|
|
||||||
} ProcessState;
|
|
||||||
|
|
||||||
/** Saved registers for kernel context switches. */
|
|
||||||
struct Context {
|
|
||||||
uint64_t ra;
|
|
||||||
uint64_t sp;
|
|
||||||
|
|
||||||
// callee-saved
|
|
||||||
uint64_t s0;
|
|
||||||
uint64_t s1;
|
|
||||||
uint64_t s2;
|
|
||||||
uint64_t s3;
|
|
||||||
uint64_t s4;
|
|
||||||
uint64_t s5;
|
|
||||||
uint64_t s6;
|
|
||||||
uint64_t s7;
|
|
||||||
uint64_t s8;
|
|
||||||
uint64_t s9;
|
|
||||||
uint64_t s10;
|
|
||||||
uint64_t s11;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Per-CPU state. */
|
|
||||||
struct Cpu {
|
|
||||||
struct Process *proc; // The process running on this cpu, or null.
|
|
||||||
struct Context context; // swtch() here to enter scheduler().
|
|
||||||
int noff; // Depth of push_off() nesting.
|
|
||||||
int intena; // Were interrupts enabled before push_off()?
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* 0 */ uint64_t kernel_satp; // kernel page table
|
|
||||||
/* 8 */ uint64_t kernel_sp; // top of process's kernel stack
|
|
||||||
/* 16 */ uint64_t kernel_trap; // usertrap()
|
|
||||||
/* 24 */ uint64_t epc; // saved user program counter
|
|
||||||
/* 32 */ uint64_t kernel_hartid; // saved kernel tp
|
|
||||||
/* 40 */ uint64_t ra;
|
|
||||||
/* 48 */ uint64_t sp;
|
|
||||||
/* 56 */ uint64_t gp;
|
|
||||||
/* 64 */ uint64_t tp;
|
|
||||||
/* 72 */ uint64_t t0;
|
|
||||||
/* 80 */ uint64_t t1;
|
|
||||||
/* 88 */ uint64_t t2;
|
|
||||||
/* 96 */ uint64_t s0;
|
|
||||||
/* 104 */ uint64_t s1;
|
|
||||||
/* 112 */ uint64_t a0;
|
|
||||||
/* 120 */ uint64_t a1;
|
|
||||||
/* 128 */ uint64_t a2;
|
|
||||||
/* 136 */ uint64_t a3;
|
|
||||||
/* 144 */ uint64_t a4;
|
|
||||||
/* 152 */ uint64_t a5;
|
|
||||||
/* 160 */ uint64_t a6;
|
|
||||||
/* 168 */ uint64_t a7;
|
|
||||||
/* 176 */ uint64_t s2;
|
|
||||||
/* 184 */ uint64_t s3;
|
|
||||||
/* 192 */ uint64_t s4;
|
|
||||||
/* 200 */ uint64_t s5;
|
|
||||||
/* 208 */ uint64_t s6;
|
|
||||||
/* 216 */ uint64_t s7;
|
|
||||||
/* 224 */ uint64_t s8;
|
|
||||||
/* 232 */ uint64_t s9;
|
|
||||||
/* 240 */ uint64_t s10;
|
|
||||||
/* 248 */ uint64_t s11;
|
|
||||||
/* 256 */ uint64_t t3;
|
|
||||||
/* 264 */ uint64_t t4;
|
|
||||||
/* 272 */ uint64_t t5;
|
|
||||||
/* 280 */ uint64_t t6;
|
|
||||||
} TrapFrame_t;
|
|
||||||
26
start.c
26
start.c
|
|
@ -1,9 +1,9 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <ispinlock.h>
|
|
||||||
#include <kalloc.h>
|
#include <kalloc.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <proc.h>
|
#include <proc.h>
|
||||||
#include <riscv.h>
|
#include <riscv.h>
|
||||||
|
#include <spinlock.h>
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <uart.h>
|
#include <uart.h>
|
||||||
|
|
||||||
|
|
@ -16,8 +16,8 @@
|
||||||
char stack0[4096 * NCPU] __attribute__((aligned(16)));
|
char stack0[4096 * NCPU] __attribute__((aligned(16)));
|
||||||
|
|
||||||
/* Keep this here and sync on it until we have synchronized printf */
|
/* Keep this here and sync on it until we have synchronized printf */
|
||||||
spinlock_t sl = {0};
|
struct Spinlock sl = {0};
|
||||||
volatile int hold = 1;
|
volatile int greeted = 0;
|
||||||
|
|
||||||
/* This is where entry.S drops us of. All cores land here */
|
/* This is where entry.S drops us of. All cores land here */
|
||||||
void start() {
|
void start() {
|
||||||
|
|
@ -29,21 +29,23 @@ void start() {
|
||||||
// cpu (struct Cpu).
|
// cpu (struct Cpu).
|
||||||
write_tp(id);
|
write_tp(id);
|
||||||
|
|
||||||
if (id == 0) {
|
acquire(&sl);
|
||||||
/* Here we will do a bunch of initialization steps */
|
|
||||||
kalloc_init();
|
if (!greeted) {
|
||||||
uart_puts("Hello Neptune!\n");
|
uart_puts("Hello Neptune!\n");
|
||||||
spinlock_init(&sl);
|
greeted = 1;
|
||||||
hold = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (hold);
|
|
||||||
|
|
||||||
spin_lock(&sl);
|
|
||||||
uart_puts("Hart number: ");
|
uart_puts("Hart number: ");
|
||||||
uart_putc(id + '0');
|
uart_putc(id + '0');
|
||||||
uart_putc('\n');
|
uart_putc('\n');
|
||||||
spin_unlock(&sl);
|
|
||||||
|
release(&sl);
|
||||||
|
|
||||||
|
if (id == 0) {
|
||||||
|
/* Here we will do a bunch of initialization steps */
|
||||||
|
kalloc_init();
|
||||||
|
}
|
||||||
|
|
||||||
// We should not arrive here, but if we do, hang in a while on wfi.
|
// We should not arrive here, but if we do, hang in a while on wfi.
|
||||||
while (1) __asm__ volatile("wfi"); // (Wait For Interrupt)
|
while (1) __asm__ volatile("wfi"); // (Wait For Interrupt)
|
||||||
|
|
|
||||||
11
types.h
11
types.h
|
|
@ -4,13 +4,4 @@ typedef unsigned char u8;
|
||||||
typedef unsigned short u16;
|
typedef unsigned short u16;
|
||||||
typedef unsigned int u32;
|
typedef unsigned int u32;
|
||||||
typedef unsigned long u64;
|
typedef unsigned long u64;
|
||||||
|
typedef u64 size_t;
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
typedef unsigned short uint16_t;
|
|
||||||
typedef unsigned int uint32_t;
|
|
||||||
typedef unsigned long uint64_t;
|
|
||||||
typedef uint64_t size_t;
|
|
||||||
|
|
||||||
typedef uint64_t uintptr_t;
|
|
||||||
|
|
||||||
typedef u8 bool;
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue