From 8b919b30e924ea8be3d2f3b24c1542edbad95dfb Mon Sep 17 00:00:00 2001 From: Julian Scheffers Date: Wed, 25 Dec 2024 16:49:21 +0100 Subject: [PATCH] Fix before merge --- kernel/cpu/riscv/include/cpu/interrupt.h | 1 + kernel/cpu/riscv/include/cpu/isr_ctx.h | 1 + kernel/cpu/riscv/include/cpu/mmu.h | 2 +- kernel/cpu/riscv/include/cpu/riscv.h | 14 +++ kernel/cpu/riscv/include/cpu/riscv_pmp.h | 1 + kernel/cpu/riscv/include/cpu/riscv_sbi.h | 2 + kernel/cpu/riscv/src/sbi_time.c | 14 ++- kernel/cpu/riscv/src/smp.c | 40 ++++-- kernel/include/cpulocal.h | 2 + kernel/port/esp32c6/include/port/port.h | 2 + kernel/port/esp32c6/src/memprotect.c | 4 + kernel/port/esp32c6/src/port.c | 4 + kernel/port/esp32p4/include/port/port.h | 2 + kernel/port/esp32p4/src/interrupt.c | 2 +- kernel/port/esp32p4/src/memprotect.c | 4 + kernel/port/esp32p4/src/port.c | 25 +--- kernel/port/esp_common/include/port/time.h | 7 ++ kernel/port/esp_common/src/hwtimer.c | 2 + kernel/port/esp_common/src/time.c | 134 +++------------------ kernel/port/generic/src/port.c | 6 - kernel/src/badgelib/badge_format_str.c | 16 ++- kernel/src/badgelib/mutex.c | 2 +- kernel/src/main.c | 3 - kernel/src/process/proc_memmap.c | 2 +- kernel/src/scheduler/scheduler.c | 24 ++-- kernel/src/time.c | 22 ++-- 26 files changed, 152 insertions(+), 186 deletions(-) create mode 100644 kernel/port/esp_common/include/port/time.h diff --git a/kernel/cpu/riscv/include/cpu/interrupt.h b/kernel/cpu/riscv/include/cpu/interrupt.h index 7252a008..aacca1bd 100644 --- a/kernel/cpu/riscv/include/cpu/interrupt.h +++ b/kernel/cpu/riscv/include/cpu/interrupt.h @@ -4,6 +4,7 @@ #pragma once #include "cpu/regs.h" +#include "cpu/riscv.h" #include diff --git a/kernel/cpu/riscv/include/cpu/isr_ctx.h b/kernel/cpu/riscv/include/cpu/isr_ctx.h index fb96f529..3aa6fa0d 100644 --- a/kernel/cpu/riscv/include/cpu/isr_ctx.h +++ b/kernel/cpu/riscv/include/cpu/isr_ctx.h @@ -4,6 +4,7 @@ #pragma once #include "cpu/regs.h" +#include "cpu/riscv.h" #ifndef __ASSEMBLER__ #include "cpulocal.h" diff --git a/kernel/cpu/riscv/include/cpu/mmu.h b/kernel/cpu/riscv/include/cpu/mmu.h index a2d6833f..5e70cb8b 100644 --- a/kernel/cpu/riscv/include/cpu/mmu.h +++ b/kernel/cpu/riscv/include/cpu/mmu.h @@ -3,8 +3,8 @@ #pragma once +#include "cpu/riscv.h" #include "memprotect.h" -#include "riscv.h" #include #include diff --git a/kernel/cpu/riscv/include/cpu/riscv.h b/kernel/cpu/riscv/include/cpu/riscv.h index 88e7fa82..de4fb58e 100644 --- a/kernel/cpu/riscv/include/cpu/riscv.h +++ b/kernel/cpu/riscv/include/cpu/riscv.h @@ -3,6 +3,20 @@ #pragma once +// Undef x86 macros because intellisense doesn't recognise RISC-V. +#ifndef __riscv_xlen +#ifdef __x86_64__ +#define __riscv_xlen 64 +#else +#define __riscv_xlen 32 +#endif +#endif +#undef __x86_64__ +#undef __i386__ +#ifndef __riscv +#define __riscv +#endif + /* ==== RISC-V MSTATUS DEFINITION ==== */ diff --git a/kernel/cpu/riscv/include/cpu/riscv_pmp.h b/kernel/cpu/riscv/include/cpu/riscv_pmp.h index e80f052a..ed01fde5 100644 --- a/kernel/cpu/riscv/include/cpu/riscv_pmp.h +++ b/kernel/cpu/riscv/include/cpu/riscv_pmp.h @@ -7,6 +7,7 @@ #include "assertions.h" #include "attributes.h" +#include "cpu/riscv.h" #include "meta.h" #include "port/hardware.h" #include "port/hardware_allocation.h" diff --git a/kernel/cpu/riscv/include/cpu/riscv_sbi.h b/kernel/cpu/riscv/include/cpu/riscv_sbi.h index b4cc201e..60f80264 100644 --- a/kernel/cpu/riscv/include/cpu/riscv_sbi.h +++ b/kernel/cpu/riscv/include/cpu/riscv_sbi.h @@ -3,6 +3,8 @@ #pragma once +#include "cpu/riscv.h" + // Completed successfully. diff --git a/kernel/cpu/riscv/src/sbi_time.c b/kernel/cpu/riscv/src/sbi_time.c index 11e9ffb1..8ed7f5ae 100644 --- a/kernel/cpu/riscv/src/sbi_time.c +++ b/kernel/cpu/riscv/src/sbi_time.c @@ -25,10 +25,16 @@ static uint64_t base_tick; // Get the current time in ticks. static inline uint64_t time_ticks() { #if __riscv_xlen == 32 - uint32_t ticks_lo; - uint32_t ticks_hi; - asm("rdtime %0; rdtimeh %1" : "=r"(ticks_lo), "=r"(ticks_hi)); - uint64_t ticks = ((uint64_t)ticks_hi << 32) | ticks_lo; + uint32_t ticks_lo0, ticks_lo1; + uint32_t ticks_hi0, ticks_hi1; + asm("rdtimeh %0; rdtime %1" : "=r"(ticks_hi0), "=r"(ticks_lo0)); + asm("rdtimeh %0; rdtime %1" : "=r"(ticks_hi1), "=r"(ticks_lo1)); + uint64_t ticks; + if (ticks_hi0 != ticks_hi1) { + ticks = ((uint64_t)ticks_hi1 << 32) | ticks_lo1; + } else { + ticks = ((uint64_t)ticks_hi0 << 32) | ticks_lo0; + } #else uint64_t ticks; asm("rdtime %0" : "=r"(ticks)); diff --git a/kernel/cpu/riscv/src/smp.c b/kernel/cpu/riscv/src/smp.c index 23af87df..f130ea78 100644 --- a/kernel/cpu/riscv/src/smp.c +++ b/kernel/cpu/riscv/src/smp.c @@ -113,6 +113,7 @@ void smp_init_dtb(dtb_handle_t *dtb) { uint32_t cpu_acells = dtb_read_uint(dtb, cpus, "#address-cells"); assert_always(cpu_acells && cpu_acells <= sizeof(size_t) / 4); assert_always(dtb_read_uint(dtb, cpus, "#size-cells") == 0); + size_t bsp_hartid = smp_req.response->bsp_hartid; while (cpu) { // Detect usable architecture. @@ -139,11 +140,18 @@ void smp_init_dtb(dtb_handle_t *dtb) { dtb_prop_t *reg = dtb_get_prop(dtb, cpu, "reg"); assert_always(reg && reg->content_len == 4 * cpu_acells); size_t cpuid = dtb_prop_read_uint(dtb, reg); - logkf(LOG_INFO, "Detected CPU #%{d} ID %{size;d}", cpu_index, cpuid); + int detected_cpu; + if (cpuid == bsp_hartid) { + detected_cpu = 0; + } else { + detected_cpu = smp_count; + smp_count++; + } + logkf(LOG_INFO, "Detected CPU #%{d} ID %{size;d}", detected_cpu, cpuid); // Add to the maps. smp_map_t new_ent = { - .cpu = cpu_index++, + .cpu = detected_cpu, .cpuid = cpuid, }; assert_always(array_len_sorted_insert(&smp_map, sizeof(smp_map_t), &smp_map_len, &new_ent, smp_cpuid_cmp)); @@ -151,13 +159,23 @@ void smp_init_dtb(dtb_handle_t *dtb) { cpu = cpu->next; } + int cur_cpu = smp_cur_cpu(); + // Allocate status per CPU. cpu_status = calloc(smp_count, sizeof(smp_status_t)); assert_always(cpu_status); - cpu_status[smp_cur_cpu()] = (smp_status_t){ + cpu_status[cur_cpu] = (smp_status_t){ .did_jump = true, .is_up = true, }; + + // Transfer booting CPU's CPU-local data to this array. + bool ie = irq_disable(); + + cpu_status[cur_cpu].cpulocal = *isr_ctx_get()->cpulocal; + isr_ctx_get()->cpulocal = &cpu_status[cur_cpu].cpulocal; + + irq_enable_if(ie); } // The the SMP CPU index of the calling CPU. @@ -165,7 +183,7 @@ int smp_cur_cpu() { if (!smp_map_len) { return 0; } - return smp_get_cpu(isr_ctx_get()->cpulocal->cpuid); + return isr_ctx_get()->cpulocal->cpu; } // Get the SMP CPU index from the CPU ID value. @@ -206,9 +224,15 @@ static NAKED void cpu1_init0_limine(struct limine_smp_info *info) { // Second stage entrypoint for secondary CPUs. static void cpu1_init1_limine(struct limine_smp_info *info) { - isr_ctx_t tmp_ctx = {0}; - tmp_ctx.flags = ISR_CTX_FLAG_KERNEL; - __builtin_unreachable(); + int cur_cpu = (int)info->extra_argument; + isr_ctx_t tmp_ctx = {0}; + tmp_ctx.flags = ISR_CTX_FLAG_KERNEL; + tmp_ctx.cpulocal = &cpu_status[cur_cpu].cpulocal; + tmp_ctx.cpulocal->cpuid = info->hartid; + tmp_ctx.cpulocal->cpu = cur_cpu; + asm("csrw sscratch, %0" ::"r"(&tmp_ctx)); + cpu_status[cur_cpu].entrypoint(); + __builtin_trap(); } // Power on another CPU. @@ -224,7 +248,7 @@ bool smp_poweron(int cpu, void *entrypoint, void *stack) { // Start the CPU up. if (!cpu_status[cpu].did_jump) { for (uint64_t i = 0; i < smp_req.response->cpu_count; i++) { - if (smp_req.response->cpus[i]->processor_id == smp_map[cpu].cpuid) { + if (smp_req.response->cpus[i]->hartid == smp_map[cpu].cpuid) { smp_req.response->cpus[i]->extra_argument = cpu; atomic_store(&smp_req.response->cpus[i]->goto_address, &cpu1_init0_limine); cpu_status[cpu].did_jump = true; diff --git a/kernel/include/cpulocal.h b/kernel/include/cpulocal.h index 0fb97abf..af5e18f9 100644 --- a/kernel/include/cpulocal.h +++ b/kernel/include/cpulocal.h @@ -14,6 +14,8 @@ typedef struct { // Current CPU ID. size_t cpuid; + // Current SMP CPU inder. + int cpu; // ISR stack top. size_t isr_stack_top; // ISR stack bottom. diff --git a/kernel/port/esp32c6/include/port/port.h b/kernel/port/esp32c6/include/port/port.h index 44dd9ee6..a6c89ffc 100644 --- a/kernel/port/esp32c6/include/port/port.h +++ b/kernel/port/esp32c6/include/port/port.h @@ -9,6 +9,8 @@ // Early hardware initialization. void port_early_init(); +// Post-heap hardware initialization. +void port_postheap_init(); // Full hardware initialization. void port_init(); // Power off. diff --git a/kernel/port/esp32c6/src/memprotect.c b/kernel/port/esp32c6/src/memprotect.c index f5858f4a..a29f11e9 100644 --- a/kernel/port/esp32c6/src/memprotect.c +++ b/kernel/port/esp32c6/src/memprotect.c @@ -81,6 +81,10 @@ void memprotect_early_init() { ); } +// Initialise memory protection driver. +void memprotect_postheap_init() { +} + // Initialise memory protection driver. void memprotect_init() { } diff --git a/kernel/port/esp32c6/src/port.c b/kernel/port/esp32c6/src/port.c index bb6fb3a8..043b54ea 100644 --- a/kernel/port/esp32c6/src/port.c +++ b/kernel/port/esp32c6/src/port.c @@ -48,6 +48,10 @@ void port_early_init() { PCR.uart0_conf.uart0_clk_en = true; } +// Post-heap hardware initialization. +void port_postheap_init() { +} + // Full hardware initialization. void port_init() { extern void esp_i2c_isr(); diff --git a/kernel/port/esp32p4/include/port/port.h b/kernel/port/esp32p4/include/port/port.h index 1b78e7ab..ce5e4d84 100644 --- a/kernel/port/esp32p4/include/port/port.h +++ b/kernel/port/esp32p4/include/port/port.h @@ -9,6 +9,8 @@ // Early hardware initialization. void port_early_init(); +// Post-heap hardware initialization. +void port_postheap_init(); // Full hardware initialization. void port_init(); // Power off. diff --git a/kernel/port/esp32p4/src/interrupt.c b/kernel/port/esp32p4/src/interrupt.c index 5bb1e854..79536dc6 100644 --- a/kernel/port/esp32p4/src/interrupt.c +++ b/kernel/port/esp32p4/src/interrupt.c @@ -162,7 +162,7 @@ void riscv_interrupt_handler() { intmtx_t *intmtx = intmtx_local(); - for (size_t i = 0; i < IRQ_GROUPS; i++) { + for (int i = 0; i < IRQ_GROUPS; i++) { uint32_t pending = intmtx->pending[i] & atomic_load(&enable_mask[i]); while (pending) { int lsb_pos = __builtin_ctz(pending); diff --git a/kernel/port/esp32p4/src/memprotect.c b/kernel/port/esp32p4/src/memprotect.c index f5858f4a..a29f11e9 100644 --- a/kernel/port/esp32p4/src/memprotect.c +++ b/kernel/port/esp32p4/src/memprotect.c @@ -81,6 +81,10 @@ void memprotect_early_init() { ); } +// Initialise memory protection driver. +void memprotect_postheap_init() { +} + // Initialise memory protection driver. void memprotect_init() { } diff --git a/kernel/port/esp32p4/src/port.c b/kernel/port/esp32p4/src/port.c index a51b2e76..d5898c62 100644 --- a/kernel/port/esp32p4/src/port.c +++ b/kernel/port/esp32p4/src/port.c @@ -28,25 +28,6 @@ cpulocal_t port_cpu1_local = {.cpuid = 1}; -void lolfunc() { - asm(".option push;" - ".option norelax;" - "la gp, __global_pointer$;" - ".option pop;"); - logk_from_isr(LOG_INFO, "This be CPU1"); - while (1) asm("wfi"); -} - -// Start CPU1. -void port_start_cpu1() { - cpu_utility_ll_stall_cpu(1); - HP_SYS_CLKRST.soc_clk_ctrl0.reg_core1_cpu_clk_en = true; - HP_SYS_CLKRST.hp_rst_en0.reg_rst_en_core1_global = false; - cpu_utility_ll_reset_cpu(1); - ets_set_appcpu_boot_addr((uint32_t)&lolfunc); - cpu_utility_ll_unstall_cpu(1); -} - // Early hardware initialization. void port_early_init() { // Set CPU-local data pointer. @@ -55,10 +36,12 @@ void port_early_init() { pmu_init(); } +// Post-heap hardware initialization. +void port_postheap_init() { +} + // Full hardware initialization. void port_init() { - // port_start_cpu1(); - // while (1) asm("wfi"); extern void esp_i2c_isr(); irq_ch_set_isr(ETS_I2C0_INTR_SOURCE, esp_i2c_isr); irq_ch_enable(ETS_I2C0_INTR_SOURCE); diff --git a/kernel/port/esp_common/include/port/time.h b/kernel/port/esp_common/include/port/time.h new file mode 100644 index 00000000..a23a15c9 --- /dev/null +++ b/kernel/port/esp_common/include/port/time.h @@ -0,0 +1,7 @@ + +// SPDX-License-Identifier: MIT + +#pragma once + +// Initialise timer and watchdog subsystem. +void time_init_dtb(); diff --git a/kernel/port/esp_common/src/hwtimer.c b/kernel/port/esp_common/src/hwtimer.c index 9ffee109..3f666910 100644 --- a/kernel/port/esp_common/src/hwtimer.c +++ b/kernel/port/esp_common/src/hwtimer.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #ifdef CONFIG_TARGET_esp32c6 @@ -105,6 +106,7 @@ void timer_set_freq(int timerno, frequency_hz_t freq) { case 1: clksrc = HP_SYS_CLKRST.peri_clk_ctrl20.reg_timergrp0_t1_src_sel; break; case 2: clksrc = HP_SYS_CLKRST.peri_clk_ctrl21.reg_timergrp1_t0_src_sel; break; case 3: clksrc = HP_SYS_CLKRST.peri_clk_ctrl21.reg_timergrp1_t1_src_sel; break; + default: __builtin_unreachable(); } #endif #ifdef CONFIG_TARGET_esp32c6 diff --git a/kernel/port/esp_common/src/time.c b/kernel/port/esp_common/src/time.c index 64bcff8f..2eabdf0b 100644 --- a/kernel/port/esp_common/src/time.c +++ b/kernel/port/esp_common/src/time.c @@ -11,13 +11,14 @@ #include "mutex.h" #include "scheduler/isr.h" #include "smp.h" +#include "time_private.h" #ifdef CONFIG_TARGET_esp32p4 // Timer used for task list items. -#define TT_TIMER 2 +#define TIMER_COUNT 2 #else // Timer used for task list items. -#define TT_TIMER 1 +#define TIMER_COUNT 1 #endif @@ -27,75 +28,21 @@ void timer_isr_timer_alarm() { int cpu = smp_cur_cpu(); timer_alarm_disable(cpu); timer_int_clear(cpu); - sched_request_switch_from_isr(); + time_cpu_timer_isr(); } -// Timer task list entry. -typedef struct { - // Task ID. - int64_t taskno; - // Task timestamp; - timestamp_us_t time; - // Task function. - timer_fn_t callback; - // Task cookie. - void *cookie; -} timertask_t; - -// Timer task mutex. -static mutex_t tt_mtx = MUTEX_T_INIT; -// Next timer task ID. -static int64_t next_taskno = 1; -// Timer task list capacity. -static size_t tt_list_cap; -// Timer task list length. -static size_t tt_list_len; -// Timer task list. -static timertask_t *tt_list; -// Current limit of task list timer. -static timestamp_us_t tt_limit = TIMESTAMP_US_MAX; - -// Sort `timertask_t` by timestamp. -int tt_cmp(void const *a, void const *b) { - timertask_t const *a_ptr = a; - timertask_t const *b_ptr = b; - if (a_ptr->time < b_ptr->time) { - return -1; - } else if (a_ptr->time > b_ptr->time) { - return 1; - } else { - return 0; - } +// Set the CPU's timer to a certain timestamp. +void time_set_cpu_timer(timestamp_us_t timestamp) { + timer_alarm_config(smp_cur_cpu(), timestamp, false); } -// Timer task ISR. -void tt_isr(int irq) { - (void)irq; - mutex_acquire_from_isr(NULL, &tt_mtx, TIMESTAMP_US_MAX); - - // Disable alarm. - timer_alarm_disable(TT_TIMER); - timer_int_clear(TT_TIMER); - - // Consume all tasks for this timestamp. - timestamp_us_t now = time_us(); - size_t i; - for (i = 0; i < tt_list_len && tt_list[i].time <= now; i++) { - tt_list[i].callback(tt_list[i].cookie); - } - array_lencap_remove_n(&tt_list, sizeof(timertask_t), &tt_list_len, &tt_list_cap, NULL, 0, i); - - if (tt_list_len) { - // Set next timer. - tt_limit = tt_list[0].time; - timer_alarm_config(TT_TIMER, tt_limit, false); - } else { - tt_limit = TIMESTAMP_US_MAX; - } - - mutex_release_from_isr(NULL, &tt_mtx); +// Clear the CPU's timer. +void time_clear_cpu_timer() { + int cpu = smp_cur_cpu(); + timer_alarm_disable(cpu); + timer_int_clear(cpu); } @@ -105,7 +52,7 @@ void time_init() { timer_init(); // Configure system timers. - for (int i = 0; i <= TT_TIMER; i++) { + for (int i = 0; i <= TIMER_COUNT; i++) { timer_stop(i); timer_value_set(i, 0); timer_alarm_disable(i); @@ -115,65 +62,16 @@ void time_init() { } // Assign timer IRQs. - for (int i = 0; i < TT_TIMER; i++) { + for (int i = 0; i < TIMER_COUNT; i++) { set_cpu_timer_irq(i, timer_get_irq(i)); } - int tt_irq = timer_get_irq(TT_TIMER); - irq_ch_set_isr(tt_irq, tt_isr); - irq_ch_enable(tt_irq); // Start timers at close to the same time. - for (int i = 0; i <= TT_TIMER; i++) { + for (int i = 0; i <= TIMER_COUNT; i++) { timer_start(i); } -} - -// Sets the alarm time when the next task switch should occur. -void time_set_next_task_switch(timestamp_us_t timestamp) { - timer_alarm_config(smp_cur_cpu(), timestamp, false); -} - -// Attach a task to a timer interrupt. -int64_t time_add_async_task(timestamp_us_t timestamp, timer_fn_t taskfn, void *cookie) { - if (timestamp <= 0) { - return 0; - } - bool ie = irq_disable(); - mutex_acquire_from_isr(NULL, &tt_mtx, TIMESTAMP_US_MAX); - timertask_t task = { - .callback = taskfn, - .cookie = cookie, - .time = timestamp, - .taskno = next_taskno, - }; - int64_t taskno = 0; - if (array_lencap_sorted_insert(&tt_list, sizeof(timertask_t), &tt_list_len, &tt_list_cap, &task, tt_cmp)) { - taskno = next_taskno; - next_taskno++; - } - if (tt_limit > timestamp) { - tt_limit = timestamp; - timer_alarm_config(TT_TIMER, tt_limit, false); - } - mutex_release_from_isr(NULL, &tt_mtx); - irq_enable_if(ie); - return taskno; -} -// Cancel a task created with `time_add_async_task`. -bool time_cancel_async_task(int64_t taskno) { - bool ie = irq_disable(); - bool success = false; - mutex_acquire_from_isr(NULL, &tt_mtx, TIMESTAMP_US_MAX); - for (size_t i = 0; i < tt_list_len; i++) { - if (tt_list[i].taskno == taskno) { - array_lencap_remove(&tt_list, sizeof(timertask_t), &tt_list_len, &tt_list_cap, NULL, i); - success = true; - } - } - mutex_release_from_isr(NULL, &tt_mtx); - irq_enable_if(ie); - return success; + time_init_generic(); } // Get current time in microseconds. diff --git a/kernel/port/generic/src/port.c b/kernel/port/generic/src/port.c index 67a3078e..4c4c2d55 100644 --- a/kernel/port/generic/src/port.c +++ b/kernel/port/generic/src/port.c @@ -200,12 +200,6 @@ void port_postheap_init() { } } -// Power off. -void port_poweroff(bool restart) { - irq_disable(); - while (1); -} - // Full hardware initialization. void port_init() { } diff --git a/kernel/src/badgelib/badge_format_str.c b/kernel/src/badgelib/badge_format_str.c index cd0e243c..4f6d1dbe 100644 --- a/kernel/src/badgelib/badge_format_str.c +++ b/kernel/src/badgelib/badge_format_str.c @@ -116,7 +116,9 @@ static bool format_str_parse_type(char const *substr, size_t length, format_str_ *type_out = FMT_TYPE_SIZE; *is_signed_out = false; return true; - } else if (length == 7 && lower(substr[0]) == 'p' && lower(substr[1]) == 't' && lower(substr[2]) == 'r' && lower(substr[3]) == 'd' && lower(substr[4]) == 'i' && lower(substr[5]) == 'f' && lower(substr[6]) == 'f') { + } else if (length == 7 && lower(substr[0]) == 'p' && lower(substr[1]) == 't' && lower(substr[2]) == 'r' && + lower(substr[3]) == 'd' && lower(substr[4]) == 'i' && lower(substr[5]) == 'f' && + lower(substr[6]) == 'f') { // size *type_out = FMT_TYPE_SIZE; *is_signed_out = true; @@ -140,7 +142,8 @@ static bool format_str_parse_type(char const *substr, size_t length, format_str_ *is_signed_out = is_signed; return true; - } else if (length == 4 && lower(substr[0]) == 'l' && lower(substr[1]) == 'o' && lower(substr[2]) == 'n' && lower(substr[3]) == 'g') { + } else if (length == 4 && lower(substr[0]) == 'l' && lower(substr[1]) == 'o' && lower(substr[2]) == 'n' && + lower(substr[3]) == 'g') { // long int *type_out = FMT_TYPE_LONG; *is_signed_out = is_signed; @@ -152,13 +155,15 @@ static bool format_str_parse_type(char const *substr, size_t length, format_str_ *is_signed_out = is_signed; return true; - } else if (length == 5 && lower(substr[0]) == 's' && lower(substr[1]) == 'h' && lower(substr[2]) == 'o' && lower(substr[3]) == 'r' && lower(substr[4]) == 't') { + } else if (length == 5 && lower(substr[0]) == 's' && lower(substr[1]) == 'h' && lower(substr[2]) == 'o' && + lower(substr[3]) == 'r' && lower(substr[4]) == 't') { // long int *type_out = FMT_TYPE_SHORT; *is_signed_out = is_signed; return true; - } else if (length == 4 && lower(substr[0]) == 'c' && lower(substr[1]) == 'h' && lower(substr[2]) == 'a' && lower(substr[3]) == 'r') { + } else if (length == 4 && lower(substr[0]) == 'c' && lower(substr[1]) == 'h' && lower(substr[2]) == 'a' && + lower(substr[3]) == 'r') { // char *type_out = FMT_TYPE_CHAR; *is_signed_out = is_signed; @@ -176,7 +181,8 @@ static bool format_str_parse_mult(char const *substr, size_t length, format_str_ *mult_out = FMT_MULT_ARR; return true; - } else if ((length == 4 && cstr_prefix_equals_case(substr, "null", 4)) || (length == 3 && cstr_prefix_equals_case(substr, "nul", 3))) { + } else if ((length == 4 && cstr_prefix_equals_case(substr, "null", 4)) || + (length == 3 && cstr_prefix_equals_case(substr, "nul", 3))) { // Null-terminated array. *mult_out = FMT_MULT_NUL; return true; diff --git a/kernel/src/badgelib/mutex.c b/kernel/src/badgelib/mutex.c index 48537ba0..a4593b1c 100644 --- a/kernel/src/badgelib/mutex.c +++ b/kernel/src/badgelib/mutex.c @@ -71,7 +71,7 @@ static void mutex_wait(mutex_t *mutex, timestamp_us_t timeout) { self->blocking_obj.mutex.mutex = mutex; if (timeout < TIMESTAMP_US_MAX) { // Set timeout interrupt for mutex. - self->blocking_obj.mutex.timer_id = time_add_async_task(timeout, mutex_resume_timer, self); + self->blocking_obj.mutex.timer_id = time_add_async_task(time_us() + timeout, mutex_resume_timer, self); } else { // No timeout; no timer interrupt is added. self->blocking_obj.mutex.timer_id = -1; diff --git a/kernel/src/main.c b/kernel/src/main.c index 868df987..9aa5c7a4 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -136,9 +136,6 @@ static void kernel_init() { // Full hardware initialization. port_init(); - logk(LOG_DEBUG, "Waiting for a second"); - thread_sleep(1000000); - // Temporary filesystem image. fs_mount(&ec, FS_TYPE_RAMFS, NULL, "/", 0); badge_err_assert_always(&ec); diff --git a/kernel/src/process/proc_memmap.c b/kernel/src/process/proc_memmap.c index d1628e22..d73f7c4b 100644 --- a/kernel/src/process/proc_memmap.c +++ b/kernel/src/process/proc_memmap.c @@ -160,7 +160,7 @@ void proc_unmap_raw(badge_err_t *ec, process_t *proc, size_t base) { virt2phys_t v2p = memprotect_virt2phys(&map->mpu_ctx, vaddr); assert_dev_drop(v2p.flags & MEMPROTECT_FLAG_RWX); assert_dev_drop(!(v2p.flags & MEMPROTECT_FLAG_KERNEL)); - vaddr += phys_page_size(v2p.paddr / MEMMAP_PAGE_SIZE); + vaddr += phys_page_size(v2p.paddr / MEMMAP_PAGE_SIZE) * MEMMAP_PAGE_SIZE; phys_page_free(v2p.paddr / MEMMAP_PAGE_SIZE); } diff --git a/kernel/src/scheduler/scheduler.c b/kernel/src/scheduler/scheduler.c index a02b0909..ed5361ef 100644 --- a/kernel/src/scheduler/scheduler.c +++ b/kernel/src/scheduler/scheduler.c @@ -70,13 +70,13 @@ static void set_switch(sched_cpulocal_t *info, sched_thread_t *thread) { isr_ctx_switch_set(next); // Set preemption timer. - timestamp_us_t timeout = SCHED_MIN_US + SCHED_INC_US * thread->priority; + timestamp_us_t now = time_us(); + timestamp_us_t timeout = now + SCHED_MIN_US + SCHED_INC_US * thread->priority; if (timeout > info->load_measure_time) { timeout = info->load_measure_time; } - timestamp_us_t now = time_us(); info->last_preempt = now; - time_set_next_task_switch(now + timeout); + time_set_next_task_switch(timeout); } // Try to hand a thread off to another CPU. @@ -186,7 +186,7 @@ static void sw_measure_load(timestamp_us_t now, int cur_cpu, sched_cpulocal_t *i while (thread) { timestamp_us_t cpu_time = thread->timeusage.cycle_time; thread->timeusage.cycle_time = 0; - int cpu_permil = cpu_time * 10000 / total_time; + int cpu_permil = (int)(cpu_time * 10000 / total_time); total_load += cpu_permil; atomic_store(&thread->timeusage.cpu_usage, cpu_permil); thread = (sched_thread_t *)thread->node.next; @@ -264,7 +264,7 @@ void sched_request_switch_from_isr() { } } - // Check for load measurement tiemr. + // Check for load measurement timer. if (now >= info->load_measure_time) { // Measure load on this CPU. sw_measure_load(now, cur_cpu, info); @@ -426,9 +426,12 @@ void sched_init() { // Power on and start scheduler on secondary CPUs. void sched_start_altcpus() { int cpu = smp_cur_cpu(); - for (int i = 0; i < smp_count; i++) { - if (i != cpu) { - sched_start_on(i); + if (smp_count > 1) { + logkf(LOG_INFO, "Starting scheduler on %{d} alt CPU(s)", smp_count - 1); + for (int i = 0; i < smp_count; i++) { + if (i != cpu) { + sched_start_on(i); + } } } } @@ -442,7 +445,10 @@ bool sched_start_on(int cpu) { void *tmp_stack = malloc(CONFIG_STACK_SIZE); bool poweron_ok = smp_poweron(cpu, sched_exec, tmp_stack); if (poweron_ok) { + logkf(LOG_INFO, "Started CPU%{d}", cpu); while (!(atomic_load(&cpu_ctx[cpu].flags) & SCHED_RUNNING)) continue; + } else { + logkf(LOG_ERROR, "Starting CPU%{d} failed", cpu); } free(tmp_stack); @@ -459,7 +465,7 @@ void sched_exec() { cpulocal_t *cpulocal = isr_ctx_get()->cpulocal; sched_cpulocal_t *info = cpu_ctx + smp_get_cpu(cpulocal->cpuid); cpulocal->sched = info; - logkf_from_isr(LOG_INFO, "Starting scheduler on CPU%{d}", smp_cur_cpu()); + logkf(LOG_INFO, "Scheduler started on CPU%{d}", smp_cur_cpu()); // Set next timestamp to measure load average. info->load_average = 0; diff --git a/kernel/src/time.c b/kernel/src/time.c index 15819725..d3b7a944 100644 --- a/kernel/src/time.c +++ b/kernel/src/time.c @@ -25,13 +25,13 @@ static timertask_t **tasks; // Timer task counter. -static atomic_int_least64_t taskno_counter; +static int64_t taskno_counter; // Comparator for timer tasks by timestamp. -int timertask_timestamp_cmp(void const *_a, void const *_b) { - timertask_t const *a = *(void *const *)_a; - timertask_t const *b = *(void *const *)_b; +int timertask_timestamp_cmp(void const *a_ptr, void const *b_ptr) { + timertask_t const *a = *(void *const *)a_ptr; + timertask_t const *b = *(void *const *)b_ptr; if (a->timestamp < b->timestamp) { return 1; } else if (a->timestamp > b->timestamp) { @@ -42,9 +42,9 @@ int timertask_timestamp_cmp(void const *_a, void const *_b) { } // Comparator for timer tasks by ID. -int timertask_id_cmp(void const *_a, void const *_b) { - timertask_t const *a = *(void *const *)_a; - timertask_t const *b = *(void *const *)_b; +int timertask_id_cmp(void const *a_ptr, void const *b_ptr) { + timertask_t const *a = *(void *const *)a_ptr; + timertask_t const *b = *(void *const *)b_ptr; if (a->taskno < b->taskno) { return -1; } else if (a->taskno > b->taskno) { @@ -87,7 +87,10 @@ int64_t time_add_async_task(timestamp_us_t timestamp, timer_fn_t callback, void if (!task) { return -1; } - int64_t taskno = atomic_fetch_add(&taskno_counter, 1); + spinlock_take(&tasks_spinlock); + int64_t taskno = taskno_counter; + taskno_counter++; + spinlock_release(&tasks_spinlock); task->taskno = taskno; task->timestamp = timestamp; task->callback = callback; @@ -137,6 +140,7 @@ bool time_cancel_async_task(int64_t taskno) { found = true; timertask_t *task; array_lencap_remove(&tasks, sizeof(void *), &tasks_len, &tasks_cap, &task, i); + // NOLINTNEXTLINE free(task); break; } @@ -174,6 +178,8 @@ void time_cpu_timer_isr() { spinlock_take(&tasks_spinlock); if (tasks_len && now >= tasks[tasks_len - 1]->timestamp) { task = tasks[--tasks_len]; + } else { + task = NULL; } spinlock_release(&tasks_spinlock);