diff --git a/Makefile b/Makefile index b316fc2..5622f00 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,7 @@ LDFLAGS += -m elf64lriscv CFLAGS = -Wall -Werror -O CFLAGS += -Wno-unused-result +CFLAGS += -Wno-unused-variable CFLAGS += -mcmodel=medany CFLAGS += -march=rv64gc -mabi=lp64 CFLAGS += -ffreestanding @@ -55,6 +56,7 @@ quickstart: KERNEL_OBJ := \ kern/entry.o \ kern/start.o \ + kern/rtc.o \ kern/libkern/freelist.o \ kern/libkern/string.o \ kern/libkern/proc.o \ @@ -65,7 +67,8 @@ KERNEL_OBJ := \ kern/libkern/mini-printf.o \ kern/libkern/stdio.o \ kern/libkern/buddy.o \ - kern/libkern/badrand.o + kern/libkern/badrand.o \ + kern/libkern/hexdump.o kern/kernel.elf: $(KERNEL_OBJ) @echo LD $@ diff --git a/kern/libkern/badrand.c b/kern/libkern/badrand.c index 48df698..f7c06f8 100644 --- a/kern/libkern/badrand.c +++ b/kern/libkern/badrand.c @@ -1,5 +1,6 @@ #include "badrand.h" #include +#include #define PRAND_BUILD_SEED \ ((uint64_t)(__TIME__[0]) * (uint64_t)(__TIME__[1]) * (uint64_t)(__TIME__[3]) * (uint64_t)(__TIME__[4]) * \ @@ -24,7 +25,23 @@ uint64_t badrand_range(uint64_t min, uint64_t max) { return min + (x % range); } -void sbadprand(uint64_t s) { +void badrand_buf(char *buf, size_t len) { + unsigned char *p = (unsigned char *)buf; + + while (len >= 8) { + uint64_t r = badrand(); + memcpy(p, &r, 8); + p += 8; + len -= 8; + } + + if (len > 0) { + uint64_t r = badrand(); + memcpy(p, &r, len); + } +} + +void sbadrand(uint64_t s) { if (s) { seed ^= (s * 0x9e3779b97f4a7c15ULL) + (seed << 6) + (seed >> 2); } else { diff --git a/kern/libkern/badrand.h b/kern/libkern/badrand.h index 8a0ab9c..6710b89 100644 --- a/kern/libkern/badrand.h +++ b/kern/libkern/badrand.h @@ -40,4 +40,9 @@ uint64_t badrand(); */ uint64_t badrand_range(uint64_t min, uint64_t max); +/** + * @brief Fills buffer with random data + */ +void badrand_buf(char *buf, size_t len); + #endif // BADRAND_H diff --git a/kern/libkern/buddy.c b/kern/libkern/buddy.c index 3b49bb0..36f1ff4 100644 --- a/kern/libkern/buddy.c +++ b/kern/libkern/buddy.c @@ -104,7 +104,7 @@ int buddy_free(void *ptr) { block_header_t *hdr = (block_header_t *)ptr - 1; int order = hdr->order; - assert_msg(order != MAX_ORDER, "The buddy freelist header seems to have been corrupted."); + assert_msg(order <= MAX_ORDER, "The buddy freelist header seems to have been corrupted."); uintptr_t addr = (uintptr_t)ptr; diff --git a/kern/libkern/ctype.h b/kern/libkern/ctype.h new file mode 100644 index 0000000..56ebbed --- /dev/null +++ b/kern/libkern/ctype.h @@ -0,0 +1,8 @@ +#ifndef CTYPE_H +#define CTYPE_H + +static inline int isprint(int c) { + return (unsigned)c - 0x20 < 0x5f; +} + +#endif // CTYPE_H diff --git a/kern/libkern/hexdump.c b/kern/libkern/hexdump.c new file mode 100644 index 0000000..6eaa377 --- /dev/null +++ b/kern/libkern/hexdump.c @@ -0,0 +1,34 @@ +#include +#include +#include + +void hexdump(const void *data, size_t size) { + const unsigned char *p = (const unsigned char *)data; + size_t i, j; + + for (i = 0; i < size; i += 16) { + // Print offset + kprintf("%08x ", i); + + // Print hex bytes + for (j = 0; j < 16; j++) { + if (i + j < size) { + kprintf("%02X ", p[i + j]); + } else { + kprintf(" "); // padding for incomplete lines + } + if (j == 7) + kprintf(" "); // extra space in middle + } + + kprintf(" |"); + + // Print ASCII characters + for (j = 0; j < 16 && i + j < size; j++) { + unsigned char c = p[i + j]; + kprintf("%c", isprint(c) ? c : '.'); + } + + kprintf("|\n"); + } +} diff --git a/kern/libkern/hexdump.h b/kern/libkern/hexdump.h new file mode 100644 index 0000000..d01a907 --- /dev/null +++ b/kern/libkern/hexdump.h @@ -0,0 +1,8 @@ +#ifndef HEXDUMP_H +#define HEXDUMP_H + +#include + +void hexdump(const void *data, size_t size); + +#endif // HEXDUMP_H diff --git a/kern/rtc.c b/kern/rtc.c new file mode 100644 index 0000000..acc4c09 --- /dev/null +++ b/kern/rtc.c @@ -0,0 +1,51 @@ +#include + +#define VIRT_RTC_BASE 0x0101000UL +#define VIRT_RTC_SIZE 0x1000 + +#define RTC_TIME_LOW 0x00 +#define RTC_TIME_HIGH 0x04 +#define RTC_ALARM_LOW 0x08 +#define RTC_ALARM_HIGH 0x0c + +#define RTC_IRQ_ENABLED 0x10 +#define RTC_CLEAR_ALARM 0x14 +#define RTC_ALARM_STATUS 0x18 +#define RTC_CLEAR_INTERRUPT 0x1c + +static inline uint32_t mmio_read32(uintptr_t addr) { + return *(volatile uint32_t *)addr; +} + +static inline void mmio_write32(uintptr_t addr, uint32_t value) { + *(volatile uint32_t *)addr = value; +} + +uint64_t rtc_read_time(void) { + uint32_t low = mmio_read32(VIRT_RTC_BASE + RTC_TIME_LOW); + uint32_t high = mmio_read32(VIRT_RTC_BASE + RTC_TIME_HIGH); + return ((uint64_t)high << 32) | low; +} + +void rtc_alarm_set(uint64_t ns) { + mmio_write32(VIRT_RTC_BASE + RTC_ALARM_HIGH, ns >> 32); + mmio_write32(VIRT_RTC_BASE + RTC_ALARM_LOW, ns & 0xffffffff); +} + +uint64_t rtc_alarm_read(void) { + uint32_t low = mmio_read32(VIRT_RTC_BASE + RTC_ALARM_LOW); + uint32_t high = mmio_read32(VIRT_RTC_BASE + RTC_ALARM_HIGH); + return ((uint64_t)high << 32) | low; +} + +void rtc_alarm_enable(void) { + mmio_write32(VIRT_RTC_BASE + RTC_IRQ_ENABLED, 1); +} + +void rtc_alarm_disable(void) { + mmio_write32(VIRT_RTC_BASE + RTC_IRQ_ENABLED, 0); +} + +uint32_t rtc_alarm_status(void) { + return mmio_read32(VIRT_RTC_BASE + RTC_IRQ_ENABLED); +} diff --git a/kern/rtc.h b/kern/rtc.h new file mode 100644 index 0000000..656cf04 --- /dev/null +++ b/kern/rtc.h @@ -0,0 +1,14 @@ +#ifndef RTC_H +#define RTC_H + +#include + +uint64_t rtc_read_time(void); + +void rtc_alarm_set(uint64_t ns); +uint64_t rtc_alarm_read(void); +void rtc_alarm_enable(void); +void rtc_alarm_disable(void); +uint32_t rtc_alarm_status(void); + +#endif // RTC_H diff --git a/kern/start.c b/kern/start.c index 7d0e855..38f2922 100644 --- a/kern/start.c +++ b/kern/start.c @@ -1,3 +1,6 @@ +#include +#include +#include #include #include #include @@ -7,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -30,8 +34,7 @@ volatile int max_hart = 0; /* This is where entry.S drops us of. All cores land here */ void start() { // Do this first - __sync_fetch_and_add(&max_hart, 1); - __sync_synchronize(); + __atomic_fetch_add(&max_hart, 1, __ATOMIC_SEQ_CST); u64 id = read_mhartid(); @@ -46,6 +49,7 @@ void start() { memory_sweep(heap_start, heap_end); buddy_init(heap_start, heap_end); spinlock_init(&sl); + sbadrand(rtc_read_time() ^ swap64(rtc_read_time())); for (int i = 0; i < banner_len; i++) uart_putc(banner[i]); __sync_synchronize(); hold = 0; @@ -68,16 +72,37 @@ void start() { fl_init(&fl, (uintptr_t)mem, 4096, sizeof(int)); uint32_t *hello = fl_alloc(&fl); - *hello = UINT32_MAX; + fl_free(&fl, hello); int a = fl_available(&fl); assert_msg(fl_check(&fl) > 0, "FreeList checking failed, might be corrupt."); - kprintf("Available: %d\n", a); - kprintf("Size: %d\n", fl.size); + kprintf("Freelist available: %d\n", a); + kprintf("Freelist item size: %d\n", fl.size); buddy_free(mem); } + { + uint64_t time = rtc_read_time(); + time = rtc_read_time(); + rtc_alarm_set(time + 3000000000); + uint64_t alrm = rtc_alarm_read(); + assert(alrm > time); + uint32_t astatus = rtc_alarm_status(); + assert(astatus == 0); + rtc_alarm_enable(); + astatus = rtc_alarm_status(); + assert(astatus == 1); + } + { + uint64_t rn = badrand(); + assert(rn != badrand()); + } + { + char buffer[128]; + badrand_buf(buffer, 128); + hexdump(buffer, 128); + } kprintf("To exit qemu, press CTRL+a followed by x\n"); spin_unlock(&sl);