diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-05-02 01:48:10 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-05-02 01:48:10 +0800 |
| commit | ae72f8dcb029eed0f054b4c8b845868229b07038 (patch) | |
| tree | b85a0288afde4f5350e424e6cc0e12a4bad13a95 /na | |
| parent | 12bd3efdbbabde0fda7d56ee82def083006e0c26 (diff) | |
| download | lume-ae72f8dcb029eed0f054b4c8b845868229b07038.tar.gz lume-ae72f8dcb029eed0f054b4c8b845868229b07038.tar.xz | |
feat: update UART handling and memory management parameters for improved functionality
Diffstat (limited to 'na')
| -rw-r--r-- | na/arch/riscv/include/arch/config.h | 4 | ||||
| -rw-r--r-- | na/drivers/uart.cc | 11 | ||||
| -rw-r--r-- | na/fdt/fdt.cc | 35 | ||||
| -rw-r--r-- | na/include/lume/device_node.h | 2 | ||||
| -rw-r--r-- | na/include/lume/fdt.h | 8 | ||||
| -rw-r--r-- | na/include/lume/pmm.h | 6 | ||||
| -rw-r--r-- | na/mm/pmm.cc | 18 |
7 files changed, 58 insertions, 26 deletions
diff --git a/na/arch/riscv/include/arch/config.h b/na/arch/riscv/include/arch/config.h index 2a70f2a..86cd8b1 100644 --- a/na/arch/riscv/include/arch/config.h +++ b/na/arch/riscv/include/arch/config.h @@ -21,8 +21,4 @@ inline constexpr uint64 kVAOffset = 0xFFFFFFC000000000ULL; /* Physical memory base (where RAM starts on RISC-V virt platform) */ inline constexpr uint64 kPhysBase = 0x80000000ULL; -/* Platform default MMIO base addresses (QEMU virt) */ -inline constexpr uint64 kDefaultUartPA = 0x10000000ULL; -inline constexpr uint64 kDefaultPlicPA = 0x0C000000ULL; - } // namespace arch diff --git a/na/drivers/uart.cc b/na/drivers/uart.cc index 802e88d..97c3e38 100644 --- a/na/drivers/uart.cc +++ b/na/drivers/uart.cc @@ -13,7 +13,8 @@ #include <lume/addr.h> #include <arch/config.h> -static uint64 g_uart_pa = arch::kDefaultUartPA; +static uint64 g_uart_pa = 0; +static uint64 g_uart_size = 0; extern "C" void early_putc(char c) { if (!g_uart_pa) return; @@ -27,9 +28,11 @@ extern "C" void early_puts(const char* s) { void console_early_init(uint64 fdt_paddr) { uint64 pa = 0; - FdtManager::early_scan_uart(fdt_paddr, &pa); + uint64 size = 0; + FdtManager::early_scan_uart(fdt_paddr, &pa, &size); if (pa != 0) { g_uart_pa = pa; + if (size != 0) g_uart_size = size; } } @@ -38,7 +41,7 @@ void console_init() { * Once vmm_init() activates the new page table, the 1GB identity map is dropped. * The UART must be explicitly registered into the active page table. */ - if (g_uart_pa != 0) { - vmm_map_kernel_mmio(g_uart_pa, 0x1000); + if (g_uart_pa != 0 && g_uart_size != 0) { + vmm_map_kernel_mmio(g_uart_pa, g_uart_size); } } diff --git a/na/fdt/fdt.cc b/na/fdt/fdt.cc index 8262aeb..a572b1b 100644 --- a/na/fdt/fdt.cc +++ b/na/fdt/fdt.cc @@ -19,7 +19,7 @@ #include <lume/fdt.h> #include <lume/new.h> -#include <lume/panic.h> +#include <lume/klog.h> #include <lume/addr.h> /* ------------------------------------------------------------------ */ @@ -250,9 +250,9 @@ void FdtManager::early_scan_mem(uint64 fdt_paddr, uint64 *base, uint64 *size) * Unlike early_scan_mem, failure here is non-fatal: we fall back to * the platform's default UART address (0x10000000 for QEMU virt). */ -void FdtManager::early_scan_uart(uint64 fdt_paddr, uint64 *uart_addr) +void FdtManager::early_scan_uart(uint64 fdt_paddr, uint64 *uart_addr, uint64 *uart_size) { - if (!uart_addr) + if (!uart_addr || !uart_size) return; const fdt_header *hdr = reinterpret_cast<const fdt_header *>(fdt_paddr); @@ -269,6 +269,9 @@ void FdtManager::early_scan_uart(uint64 fdt_paddr, uint64 *uart_addr) uint32 address_cells[16] = {2}; uint32 size_cells[16] = {1}; bool in_uart_node = false; + bool has_current_node_reg = false; + uint64 current_node_reg = 0; + uint64 current_node_size = 0; while (true) { uint32 token = bswap32( @@ -288,11 +291,13 @@ void FdtManager::early_scan_uart(uint64 fdt_paddr, uint64 *uart_addr) size_cells[depth] = size_cells[depth - 1]; } in_uart_node = false; + has_current_node_reg = false; } else if (token == FDT_END_NODE) { if (depth >= 0) depth--; in_uart_node = false; + has_current_node_reg = false; } else if (token == FDT_PROP) { uint32 len = bswap32( @@ -316,11 +321,24 @@ void FdtManager::early_scan_uart(uint64 fdt_paddr, uint64 *uart_addr) reinterpret_cast<const char *>(prop_val), len, "ns16550a")) { in_uart_node = true; + if (has_current_node_reg) { + *uart_addr = current_node_reg; + *uart_size = current_node_size; + return; + } } - } else if (in_uart_node && str_equals(prop_name, "reg")) { + } else if (str_equals(prop_name, "reg")) { uint32 p_depth = (depth > 0) ? depth - 1 : 0; - *uart_addr = read_cells(prop_val, address_cells[p_depth]); - return; // Found it + current_node_reg = read_cells(prop_val, address_cells[p_depth]); + current_node_size = read_cells( + prop_val + address_cells[p_depth] * 4, + size_cells[p_depth]); + has_current_node_reg = true; + if (in_uart_node) { + *uart_addr = current_node_reg; + *uart_size = current_node_size; + return; // Found it + } } } @@ -336,6 +354,7 @@ void FdtManager::early_scan_uart(uint64 fdt_paddr, uint64 *uart_addr) } *uart_addr = 0; + *uart_size = 0; } /* ------------------------------------------------------------------ */ @@ -549,7 +568,7 @@ void fdt_early_get_mem_info(uint64 *base, uint64 *size) FdtManager::early_scan_mem(g_fdt->get_paddr(), base, size); } -void fdt_early_get_uart_info(uint64 *uart_addr) +void fdt_early_get_uart_info(uint64 *uart_addr, uint64 *uart_size) { - FdtManager::early_scan_uart(g_fdt->get_paddr(), uart_addr); + FdtManager::early_scan_uart(g_fdt->get_paddr(), uart_addr, uart_size); } diff --git a/na/include/lume/device_node.h b/na/include/lume/device_node.h index 14b4a9c..e35f22d 100644 --- a/na/include/lume/device_node.h +++ b/na/include/lume/device_node.h @@ -10,7 +10,7 @@ * Nodes form a parent-children hierarchy via intrusive linked lists. * After unflattening, the tree is globally read-only and requires no locks. * - * Created during Phase 2 (fdt_unflatten) when Slab is available. + * Created when Slab is available. * * Reference: docs/specs/fdt.md §3.2 */ diff --git a/na/include/lume/fdt.h b/na/include/lume/fdt.h index 8da223c..783b030 100644 --- a/na/include/lume/fdt.h +++ b/na/include/lume/fdt.h @@ -33,9 +33,9 @@ public: // Panics if the FDT is invalid or /memory is missing. static void early_scan_mem(uint64 fdt_paddr, uint64 *base, uint64 *size); - // Extract the UART base address by matching compatible = "ns16550a". - // Falls back to platform default (0x10000000) on failure. - static void early_scan_uart(uint64 fdt_paddr, uint64 *uart_addr); + // Extract the UART base address and size by matching compatible = "ns16550a". + // Falls back to platform default on failure. + static void early_scan_uart(uint64 fdt_paddr, uint64 *uart_addr, uint64 *uart_size); // --- Phase 2: Object tree construction (requires Slab) --- @@ -78,4 +78,4 @@ DeviceNode *fdt_get_node_by_path(const char *path); // Early scan wrappers (delegate to FdtManager static methods). void fdt_early_get_mem_info(uint64 *base, uint64 *size); -void fdt_early_get_uart_info(uint64 *uart_addr); +void fdt_early_get_uart_info(uint64 *uart_addr, uint64 *uart_size); diff --git a/na/include/lume/pmm.h b/na/include/lume/pmm.h index 1ac1e17..b970404 100644 --- a/na/include/lume/pmm.h +++ b/na/include/lume/pmm.h @@ -24,8 +24,10 @@ /* Buddy system constants */ inline constexpr int kMaxOrder = 11; // Orders 0..10 → 4KB..4MB -inline constexpr int kPcpHighWatermark = 64; // Max frames cached per CPU -inline constexpr int kPcpBatchSize = 32; // Frames moved per refill/drain + +/* Per-CPU cache dynamic parameters (calculated in pmm_init) */ +extern uint32 g_pcp_high_watermark; +extern uint32 g_pcp_batch_size; /* ================================================================== */ /* Public free-function API */ diff --git a/na/mm/pmm.cc b/na/mm/pmm.cc index fc743a9..00f998c 100644 --- a/na/mm/pmm.cc +++ b/na/mm/pmm.cc @@ -24,7 +24,7 @@ #include <lume/config.h> #include <lume/fdt.h> #include <lume/new.h> -#include <lume/panic.h> +#include <lume/klog.h> #include <lume/types.h> #include <arch/cpu.h> #include <kernel/sync/spinlock.h> @@ -57,6 +57,9 @@ static uint64 g_mem_base = 0; // Physical memory base (from static uint64 g_mem_size = 0; // Total physical memory size static uint64 g_num_frames = 0; // Total managed frames +uint32 g_pcp_high_watermark = 0; +uint32 g_pcp_batch_size = 0; + /* ------------------------------------------------------------------ */ /* Address conversion helpers */ /* ------------------------------------------------------------------ */ @@ -216,7 +219,7 @@ static void buddy_free(Frame* frame, uint8 order) static void refill_pcp(PerCpuCache* pcp) { LockGuard guard(g_pmm_lock); - for (int i = 0; i < kPcpBatchSize; i++) { + for (uint32 i = 0; i < g_pcp_batch_size; i++) { Frame* f = buddy_alloc(0); if (!f) break; @@ -325,7 +328,7 @@ void pmm_free_frame(Frame* frame) pcp->count++; // Drain if over high watermark - if (pcp->count >= kPcpHighWatermark) + if (pcp->count >= g_pcp_high_watermark) drain_pcp(pcp); if (was_on) @@ -406,6 +409,15 @@ void pmm_init() g_num_frames = mem_size / kPageSize; /* + * Dynamically calculate PCP parameters based on memory size. + * Rule of thumb: batch_size = max(16, total_pages / (cpu_count * 1024)) + * This avoids depleting global memory on small RAM systems. + */ + uint32 calc_batch = static_cast<uint32>(g_num_frames / (kMaxCpus * 1024)); + g_pcp_batch_size = (calc_batch > 16) ? calc_batch : 16; + g_pcp_high_watermark = g_pcp_batch_size * 2; + + /* * 2. Place the frame_map array. * * The frame_map lives right after the kernel image (_kernel_end), |
