diff --git a/kern/libkern/badrand.c b/kern/libkern/badrand.c index 2f35c34..b4937b6 100644 --- a/kern/libkern/badrand.c +++ b/kern/libkern/badrand.c @@ -30,8 +30,7 @@ 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); + *(uint64_t *)p = badrand(); p += 8; len -= 8; } diff --git a/kern/rtc.c b/kern/rtc.c index f7d92a0..e351d8a 100644 --- a/kern/rtc.c +++ b/kern/rtc.c @@ -1,3 +1,6 @@ +#include "stdio.h" +#include +#include #include #define VIRT_RTC_BASE 0x0101000UL @@ -8,49 +11,55 @@ #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 +#define RTC_ALARM_STATUS 0x18 +#define RTC_CLEAR_ALARM 0x14 -static inline uint32_t mmio_read32(uintptr_t addr) { - return *(volatile uint32_t *)addr; -} +#define RTC_IRQ_ENABLED 0x10 +#define RTC_IRQ_CLEAR 0x1c -static inline void mmio_write32(uintptr_t addr, uint32_t value) { - *(volatile uint32_t *)addr = value; -} +#define REG32(addr) (*((volatile uint32_t *)(addr))) +#define REG64(addr) (*((volatile uint64_t *)(addr))) +#define GF_REG32(offset) (REG32(VIRT_RTC_BASE + offset)) +#define GF_REG64(offset) (REG64(VIRT_RTC_BASE + offset)) +/* Read the current time of the RTC */ uint64_t rtc_time_read(void) { - uint32_t low = mmio_read32(VIRT_RTC_BASE + RTC_TIME_LOW); - uint32_t high = mmio_read32(VIRT_RTC_BASE + RTC_TIME_HIGH); + uint32_t low = GF_REG32(RTC_TIME_LOW); // mmio_read32(VIRT_RTC_BASE + RTC_TIME_LOW); + uint32_t high = GF_REG32(RTC_TIME_HIGH); return ((uint64_t)high << 32) | low; } +/* Set the time of the RTC */ void rtc_time_set(uint64_t ns) { - mmio_write32(VIRT_RTC_BASE + RTC_TIME_LOW, ns); - mmio_write32(VIRT_RTC_BASE + RTC_TIME_HIGH, ns); + GF_REG32(RTC_TIME_HIGH) = ns >> 32; + GF_REG32(RTC_TIME_LOW) = ns & 0xFFFFFFFF; } +/* Set the alarm. this will automatically enable it. */ 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); + /* Order matters here, low write starts the alarm */ + GF_REG32(RTC_ALARM_HIGH) = ns >> 32; + GF_REG32(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); + uint32_t low = GF_REG32(RTC_ALARM_LOW); + uint32_t high = GF_REG32(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); + return GF_REG32(RTC_ALARM_STATUS) & 0x1; +} + +void rtc_alarm_clear(void) { + GF_REG32(RTC_CLEAR_ALARM) = 1; +} + +void rtc_irq_clear(void) { + GF_REG32(RTC_IRQ_CLEAR) = 1; +} + +uint32_t rtc_irq_enabled(void) { + return GF_REG32(RTC_IRQ_ENABLED) & 0x1; } diff --git a/kern/rtc.h b/kern/rtc.h index b33c748..026db70 100644 --- a/kern/rtc.h +++ b/kern/rtc.h @@ -3,6 +3,9 @@ #include +#define MS_TO_NS(ms) ((uint64_t)(ms) * 1000ULL * 1000ULL) +#define NS_TO_MS(ms) ((uint64_t)(ms) / (1000ULL * 1000ULL)) + struct rtc_class_ops { uint64_t (*read_time)(void); void (*set_time)(uint64_t); @@ -16,8 +19,10 @@ void rtc_time_set(uint64_t ns); 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); +void rtc_alarm_clear(void); + +void rtc_irq_clear(void); +uint32_t rtc_irq_enabled(void); #endif // RTC_H diff --git a/kern/start.c b/kern/start.c index 0452aef..ce37c30 100644 --- a/kern/start.c +++ b/kern/start.c @@ -46,10 +46,10 @@ void start() { if (unlikely(id == 0)) { /* Here we will do a bunch of initialization steps */ + sbadrand(rtc_time_read() ^ swap64(rtc_time_read())); memory_sweep(heap_start, heap_end); buddy_init(heap_start, heap_end); spinlock_init(&sl); - sbadrand(rtc_time_read() ^ swap64(rtc_time_read())); for (int i = 0; i < banner_len; i++) uart_putc(banner[i]); __sync_synchronize(); hold = 0; @@ -83,16 +83,20 @@ void start() { buddy_free(mem); } { - uint64_t time = rtc_time_read(); - time = rtc_time_read(); - 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); + const uint64_t time = rtc_time_read(); + + /* Set alarm and check that its correct */ + rtc_alarm_set(time + MS_TO_NS(1000)); + const uint64_t alrm = rtc_alarm_read(); + assert(alrm == time + MS_TO_NS(1000)); + + /* Should be one provided alarm is not elapsed */ + assert(rtc_alarm_status() == 1); + rtc_alarm_clear(); + assert(rtc_alarm_status() == 0); + + /* Time should have passed */ + assert(time != rtc_time_read()); } { uint64_t rn = badrand();