diff --git a/platform/jh7110/platform.c b/platform/jh7110/platform.c index 47c1eb8f8..e72342f67 100644 --- a/platform/jh7110/platform.c +++ b/platform/jh7110/platform.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #if WITH_LIB_MINIP #include @@ -29,92 +30,11 @@ #include "platform_p.h" -#define LOCAL_TRACE 1 - -#if WITH_KERNEL_VM -#define DEFAULT_MEMORY_SIZE (MEMSIZE) /* try to fetch from the emulator via the fdt */ - -static pmm_arena_t arena = { - .name = "ram", - .base = MEMORY_BASE_PHYS, - .size = DEFAULT_MEMORY_SIZE, - .flags = PMM_ARENA_FLAG_KMAP, -}; -#endif +#define LOCAL_TRACE 0 +static const void *fdt; static volatile uint32_t *power_reset_reg; -// callbacks to the fdt_walk routine -static void memcallback(uint64_t base, uint64_t len, void *cookie) { - bool *found_mem = (bool *)cookie; - - LTRACEF("base %#llx len %#llx cookie %p\n", base, len, cookie); - - /* add another vm arena */ - if (!*found_mem) { - printf("FDT: found memory arena, base %#llx size %#llx\n", base, len); -#if WITH_KERNEL_VM - arena.base = base; - arena.size = len; - pmm_add_arena(&arena); -#else - novm_add_arena("fdt", base, len); -#endif - *found_mem = true; // stop searching after the first one - } -} - -struct reserved_memory_regions { - size_t count; - - struct { - uint64_t base; - uint64_t len; - } regions[16]; -}; - -static void reserved_memory_callback(uint64_t base, uint64_t len, void *cookie) { - struct reserved_memory_regions *mem = cookie; - - LTRACEF("base %#llx len %#llx\n", base, len); - - if (mem->count < countof(mem->regions)) { - mem->regions[mem->count].base = base; - mem->regions[mem->count].len = len; - mem->count++; - } -} - -struct detected_cpus { - size_t count; - - struct { - uint hart; - } cpu[SMP_MAX_CPUS]; -}; - -static void cpucallback(uint64_t id, void *cookie) { - struct detected_cpus *cpus = cookie; - - LTRACEF("hart %#llx\n", id); - - if (cpus->count < SMP_MAX_CPUS) { - cpus->cpu[cpus->count].hart = id; - cpus->count++; - } -} - -struct pcie_detect_state { - struct fdt_walk_pcie_info info; -} pcie_state; - -static void pciecallback(const struct fdt_walk_pcie_info *info, void *cookie) { - struct pcie_detect_state *state = cookie; - - LTRACEF("ecam base %#llx, len %#llx, bus_start %hhu, bus_end %hhu\n", info->ecam_base, info->ecam_len, info->bus_start, info->bus_end); - state->info = *info; -} - void platform_early_init(void) { TRACE; plic_early_init(PLIC_BASE_VIRT, NUM_IRQS, true); @@ -122,98 +42,44 @@ void platform_early_init(void) { LTRACEF("starting FDT scan\n"); /* look for a flattened device tree in the second arg passed to us */ - bool found_mem = false; - struct reserved_memory_regions reserved = {0}; - struct detected_cpus cpus = {0}; - - const void *fdt = (void *)lk_boot_args[1]; -#if WITH_KERNEL_VM - fdt = (const void *)((uintptr_t)fdt + KERNEL_ASPACE_BASE); -#endif + fdt = (void *)lk_boot_args[1]; + fdt = (const void *)((uintptr_t)fdt + PERIPHERAL_BASE_VIRT); - struct fdt_walk_callbacks cb = { - .mem = memcallback, - .memcookie = &found_mem, - .reserved_memory = reserved_memory_callback, - .reserved_memory_cookie = &reserved, - .cpu = cpucallback, - .cpucookie = &cpus, - .pcie = pciecallback, - .pciecookie = &pcie_state, - }; - - status_t err = fdt_walk(fdt, &cb); - LTRACEF("fdt_walk returns %d\n", err); - - if (err != 0) { - printf("FDT: error finding FDT at %p, using default memory & cpu count\n", fdt); + if (LOCAL_TRACE) { + LTRACEF("dumping FDT at %p\n", fdt); + fdt_walk_dump(fdt); } - // Always reserve all of physical memory below the kernel, this is where SBI lives - // TODO: figure out why uboot doesn't always put this here - reserved.regions[reserved.count].base = MEMBASE; - reserved.regions[reserved.count].len = KERNEL_LOAD_OFFSET; - reserved.count++; - - /* add a default memory region if we didn't find it in the FDT */ - if (!found_mem) { -#if WITH_KERNEL_VM - pmm_add_arena(&arena); -#else - novm_add_arena("default", MEMBASE, MEMSIZE); -#endif - } + // detect physical memory layout from the device tree + fdtwalk_setup_memory(fdt, lk_boot_args[1], MEMORY_BASE_PHYS, MEMSIZE); -#if WITH_KERNEL_VM - /* reserve memory described by the FDT */ - for (size_t i = 0; i < reserved.count; i++) { - printf("FDT: reserving memory range [%#llx ... %#llx]\n", - reserved.regions[i].base, reserved.regions[i].base + reserved.regions[i].len - 1); - struct list_node list = LIST_INITIAL_VALUE(list); - pmm_alloc_range(reserved.regions[i].base, reserved.regions[i].len / PAGE_SIZE, &list); - } -#endif - -#if WITH_SMP - // TODO: refactor this code into libfdt - if (cpus.count > 0) { - printf("FDT: found %zu cpu%c\n", cpus.count, cpus.count == 1 ? ' ' : 's'); - uint harts[SMP_MAX_CPUS - 1]; - - // copy from the detected cpu list to an array of harts, excluding the boot hart - size_t hart_index = 0; - for (size_t i = 0; i < cpus.count; i++) { - if (cpus.cpu[i].hart != riscv_current_hart()) { - harts[hart_index++] = cpus.cpu[i].hart; - } - - // we can start MAX CPUS - 1 secondaries - if (hart_index >= SMP_MAX_CPUS - 1) { - break; - } - } - - // tell the riscv layer how many cores we have to start - if (hart_index > 0) { - riscv_set_secondary_harts_to_start(harts, hart_index); - } - } -#endif + // detect secondary cores to start + fdtwalk_setup_cpus_riscv(fdt); LTRACEF("done scanning FDT\n"); /* save a copy of the pointer to the poweroff/reset register */ /* TODO: read it from the FDT */ -#if WITH_KERNEL_VM power_reset_reg = paddr_to_kvaddr(0x100000); -#else - power_reset_reg = (void *)0x100000; -#endif } void platform_init(void) { plic_init(); uart_init(); + + // TODO: fix this, seems to read all zeros from the ecam +#if 0 + /* configure and start pci from device tree */ + status_t err = fdtwalk_setup_pci(fdt); + if (err >= NO_ERROR) { + // start the bus manager + pci_bus_mgr_init(); + + // assign resources to all devices in case they need it + pci_bus_mgr_assign_resources(); + } +#endif + } void platform_halt(platform_halt_action suggested_action, @@ -221,17 +87,13 @@ void platform_halt(platform_halt_action suggested_action, switch (suggested_action) { case HALT_ACTION_SHUTDOWN: dprintf(ALWAYS, "Shutting down... (reason = %d)\n", reason); -#if RISCV_S_MODE // try to use SBI as a cleaner way to stop sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE); -#endif *power_reset_reg = 0x5555; break; case HALT_ACTION_REBOOT: dprintf(ALWAYS, "Rebooting... (reason = %d)\n", reason); -#if RISCV_S_MODE - sbi_system_reset(SBI_RESET_TYPE_COLD_REBOOT, SBI_RESET_REASON_NONE); -#endif + sbi_system_reset(SBI_RESET_TYPE_WARM_REBOOT, SBI_RESET_REASON_NONE); *power_reset_reg = 0x7777; break; case HALT_ACTION_HALT: @@ -250,3 +112,18 @@ void platform_halt(platform_halt_action suggested_action, for (;;) arch_idle(); } + +status_t platform_pci_int_to_vector(unsigned int pci_int, unsigned int *vector) { + // at the moment there's no translation between PCI IRQs and native irqs + *vector = pci_int; + return NO_ERROR; +} + +status_t platform_allocate_interrupts(size_t count, uint align_log2, bool msi, unsigned int *vector) { + return ERR_NOT_SUPPORTED; +} + +status_t platform_compute_msi_values(unsigned int vector, unsigned int cpu, bool edge, + uint64_t *msi_address_out, uint16_t *msi_data_out) { + return ERR_NOT_SUPPORTED; +} diff --git a/platform/jh7110/rules.mk b/platform/jh7110/rules.mk index 54efd72da..b243e6df8 100644 --- a/platform/jh7110/rules.mk +++ b/platform/jh7110/rules.mk @@ -3,21 +3,21 @@ LOCAL_DIR := $(GET_LOCAL_DIR) MODULE := $(LOCAL_DIR) ARCH := riscv -SUBARCH ?= 64 -RISCV_MODE ?= supervisor +SUBARCH := 64 +RISCV_MODE := supervisor WITH_SMP ?= true SMP_MAX_CPUS ?= 4 LK_HEAP_IMPLEMENTATION ?= dlmalloc -RISCV_FPU ?= true -RISCV_MMU ?= sv39 +RISCV_FPU := true +RISCV_MMU := sv39 RISCV_EXTENSION_LIST ?= zba zbb MODULE_DEPS += lib/cbuf MODULE_DEPS += lib/fdt MODULE_DEPS += lib/fdtwalk MODULE_DEPS += dev/interrupt/riscv_plic -#MODULE_DEPS += dev/bus/pci -#MODULE_DEPS += dev/bus/pci/drivers +MODULE_DEPS += dev/bus/pci +MODULE_DEPS += dev/bus/pci/drivers MODULE_SRCS += $(LOCAL_DIR)/platform.c MODULE_SRCS += $(LOCAL_DIR)/uart.c diff --git a/platform/qemu-virt-arm/platform.c b/platform/qemu-virt-arm/platform.c index e79c00532..af635ff07 100644 --- a/platform/qemu-virt-arm/platform.c +++ b/platform/qemu-virt-arm/platform.c @@ -59,56 +59,7 @@ struct mmu_initial_mapping mmu_initial_mappings[] = { { 0 } }; -static pmm_arena_t arena = { - .name = "ram", - .base = MEMORY_BASE_PHYS, - .size = DEFAULT_MEMORY_SIZE, - .flags = PMM_ARENA_FLAG_KMAP, -}; - -// callbacks to the fdt_walk routine -static void memcallback(uint64_t base, uint64_t len, void *cookie) { - bool *found_mem = (bool *)cookie; - - LTRACEF("base %#llx len %#llx cookie %p\n", base, len, cookie); - - /* add another novm arena */ - if (!*found_mem) { - printf("FDT: found memory arena, base %#llx size %#llx\n", base, len); - - /* trim size on certain platforms */ -#if ARCH_ARM - if (len > 1024*1024*1024U) { - len = 1024*1024*1024; /* only use the first 1GB on ARM32 */ - printf("trimming memory to 1GB\n"); - } -#endif - - /* set the size in the pmm arena */ - arena.size = len; - - *found_mem = true; // stop searching after the first one - } -} - -static void cpucallback(uint64_t id, void *cookie) { - int *cpu_count = (int *)cookie; - - LTRACEF("id %#llx cookie %p\n", id, cookie); - - (*cpu_count)++; -} - -struct pcie_detect_state { - struct fdt_walk_pcie_info info; -} pcie_state; - -static void pciecallback(const struct fdt_walk_pcie_info *info, void *cookie) { - struct pcie_detect_state *state = cookie; - - LTRACEF("ecam base %#llx, len %#llx, bus_start %hhu, bus_end %hhu\n", info->ecam_base, info->ecam_len, info->bus_start, info->bus_end); - state->info = *info; -} +const void *fdt = (void *)KERNEL_BASE; void platform_early_init(void) { /* initialize the interrupt controller */ @@ -118,92 +69,32 @@ void platform_early_init(void) { uart_init_early(); - int cpu_count = 0; - bool found_mem = false; - struct fdt_walk_callbacks cb = { - .mem = memcallback, - .memcookie = &found_mem, - .cpu = cpucallback, - .cpucookie = &cpu_count, - .pcie = pciecallback, - .pciecookie = &pcie_state, - }; - - const void *fdt = (void *)KERNEL_BASE; - status_t err = fdt_walk(fdt, &cb); - LTRACEF("fdt_walk returns %d\n", err); - - if (err != 0) { - printf("FDT: error finding FDT at %p, using default memory & cpu count\n", fdt); - } - - /* add the main memory arena */ - pmm_add_arena(&arena); - - /* reserve the first 64k of ram, which should be holding the fdt */ - struct list_node list = LIST_INITIAL_VALUE(list); - pmm_alloc_range(MEMBASE, 0x10000 / PAGE_SIZE, &list); - - /* count the number of secondary cpus */ - if (cpu_count == 0) { - /* if we didn't find any in the FDT, assume max number */ - cpu_count = SMP_MAX_CPUS; - } else if (cpu_count > 0) { - printf("FDT: found %d cpus\n", cpu_count); - cpu_count = MIN(cpu_count, SMP_MAX_CPUS); + if (LOCAL_TRACE) { + LTRACEF("dumping FDT at %p\n", fdt); + fdt_walk_dump(fdt); } - LTRACEF("booting %d cpus\n", cpu_count); - - /* boot the secondary cpus using the Power State Coordintion Interface */ - for (int cpuid = 1; cpuid < cpu_count; cpuid++) { - /* note: assumes cpuids are numbered like MPIDR 0:0:0:N */ - int ret = psci_cpu_on(cpuid, MEMBASE + KERNEL_LOAD_OFFSET); - if (ret != 0) { - printf("ERROR: psci CPU_ON returns %d\n", ret); - } - } + // detect physical memory layout from the device tree + fdtwalk_setup_memory(fdt, MEMORY_BASE_PHYS, MEMORY_BASE_PHYS, DEFAULT_MEMORY_SIZE); } void platform_init(void) { - status_t err; - uart_init(); - /* detect pci */ -#if ARCH_ARM - if (pcie_state.info.ecam_base > (1ULL << 32)) { - // dont try to configure this since we dont have LPAE support - printf("PCIE: skipping pci initialization due to high memory ECAM\n"); - pcie_state.info.ecam_len = 0; - } -#endif - if (pcie_state.info.ecam_len > 0) { - printf("PCIE: initializing pcie with ecam at %#" PRIx64 " found in FDT\n", pcie_state.info.ecam_base); - err = pci_init_ecam(pcie_state.info.ecam_base, pcie_state.info.ecam_len, pcie_state.info.bus_start, pcie_state.info.bus_end); - if (err == NO_ERROR) { - // add some additional resources to the pci bus manager in case it needs to configure - if (pcie_state.info.io_len > 0) { - // we can only deal with a mapping of io base 0 to the mmio base - DEBUG_ASSERT(pcie_state.info.io_base == 0); - pci_bus_mgr_add_resource(PCI_RESOURCE_IO_RANGE, pcie_state.info.io_base, pcie_state.info.io_len); - - // TODO: set the mmio base somehow so pci knows what to do with it - } - if (pcie_state.info.mmio_len > 0) { - pci_bus_mgr_add_resource(PCI_RESOURCE_MMIO_RANGE, pcie_state.info.mmio_base, pcie_state.info.mmio_len); - } - if (pcie_state.info.mmio64_len > 0) { - pci_bus_mgr_add_resource(PCI_RESOURCE_MMIO64_RANGE, pcie_state.info.mmio64_base, pcie_state.info.mmio64_len); - } - - // start the bus manager - pci_bus_mgr_init(); - - pci_bus_mgr_assign_resources(); - } + // start secondary cores + fdtwalk_setup_cpus_arm(fdt); + + /* configure and start pci from device tree */ + status_t err = fdtwalk_setup_pci(fdt); + if (err >= NO_ERROR) { + // start the bus manager + pci_bus_mgr_init(); + + // assign resources to all devices in case they need it + pci_bus_mgr_assign_resources(); } + /* detect any virtio devices */ uint virtio_irqs[NUM_VIRTIO_TRANSPORTS]; for (int i = 0; i < NUM_VIRTIO_TRANSPORTS; i++) { diff --git a/platform/qemu-virt-riscv/platform.c b/platform/qemu-virt-riscv/platform.c index 9048707d0..459f0e5ba 100644 --- a/platform/qemu-virt-riscv/platform.c +++ b/platform/qemu-virt-riscv/platform.c @@ -39,168 +39,30 @@ #define LOCAL_TRACE 0 -#if WITH_KERNEL_VM -#define DEFAULT_MEMORY_SIZE (MEMSIZE) /* try to fetch from the emulator via the fdt */ - -static pmm_arena_t arena = { - .name = "ram", - .base = MEMORY_BASE_PHYS, - .size = DEFAULT_MEMORY_SIZE, - .flags = PMM_ARENA_FLAG_KMAP, -}; -#endif - +static const void *fdt; static volatile uint32_t *power_reset_reg; -// callbacks to the fdt_walk routine -static void memcallback(uint64_t base, uint64_t len, void *cookie) { - bool *found_mem = (bool *)cookie; - - LTRACEF("base %#llx len %#llx cookie %p\n", base, len, cookie); - - /* add another vm arena */ - if (!*found_mem) { - printf("FDT: found memory arena, base %#llx size %#llx\n", base, len); -#if WITH_KERNEL_VM - arena.base = base; - arena.size = len; - pmm_add_arena(&arena); -#else - novm_add_arena("fdt", base, len); -#endif - *found_mem = true; // stop searching after the first one - } -} - -struct reserved_memory_regions { - size_t count; - - struct { - uint64_t base; - uint64_t len; - } regions[16]; -}; - -static void reserved_memory_callback(uint64_t base, uint64_t len, void *cookie) { - struct reserved_memory_regions *mem = cookie; - - LTRACEF("base %#llx len %#llx\n", base, len); - - if (mem->count < countof(mem->regions)) { - mem->regions[mem->count].base = base; - mem->regions[mem->count].len = len; - mem->count++; - } -} - -struct detected_cpus { - size_t count; - - struct { - uint hart; - } cpu[SMP_MAX_CPUS]; -}; - -static void cpucallback(uint64_t id, void *cookie) { - struct detected_cpus *cpus = cookie; - - LTRACEF("hart %#llx\n", id); - - if (cpus->count < SMP_MAX_CPUS) { - cpus->cpu[cpus->count].hart = id; - cpus->count++; - } -} - -struct pcie_detect_state { - struct fdt_walk_pcie_info info; -} pcie_state; - -static void pciecallback(const struct fdt_walk_pcie_info *info, void *cookie) { - struct pcie_detect_state *state = cookie; - - LTRACEF("ecam base %#llx, len %#llx, bus_start %hhu, bus_end %hhu\n", info->ecam_base, info->ecam_len, info->bus_start, info->bus_end); - state->info = *info; -} - void platform_early_init(void) { plic_early_init(PLIC_BASE_VIRT, NUM_IRQS, false); LTRACEF("starting FDT scan\n"); /* look for a flattened device tree in the second arg passed to us */ - bool found_mem = false; - struct reserved_memory_regions reserved = {0}; - struct detected_cpus cpus = {0}; - - const void *fdt = (void *)lk_boot_args[1]; + fdt = (void *)lk_boot_args[1]; #if WITH_KERNEL_VM fdt = (const void *)((uintptr_t)fdt + PERIPHERAL_BASE_VIRT); #endif - struct fdt_walk_callbacks cb = { - .mem = memcallback, - .memcookie = &found_mem, - .reserved_memory = reserved_memory_callback, - .reserved_memory_cookie = &reserved, - .cpu = cpucallback, - .cpucookie = &cpus, - .pcie = pciecallback, - .pciecookie = &pcie_state, - }; - - status_t err = fdt_walk(fdt, &cb); - LTRACEF("fdt_walk returns %d\n", err); - - if (err != 0) { - printf("FDT: error finding FDT at %p, using default memory & cpu count\n", fdt); - } - - /* add a default memory region if we didn't find it in the FDT */ - if (!found_mem) { -#if WITH_KERNEL_VM - pmm_add_arena(&arena); -#else - novm_add_arena("default", MEMBASE, MEMSIZE); -#endif + if (LOCAL_TRACE) { + LTRACEF("dumping FDT at %p\n", fdt); + fdt_walk_dump(fdt); } -#if WITH_KERNEL_VM - /* reserve memory described by the FDT */ - for (size_t i = 0; i < reserved.count; i++) { - printf("FDT: reserving memory range [%#llx ... %#llx]\n", - reserved.regions[i].base, reserved.regions[i].base + reserved.regions[i].len - 1); - struct list_node list = LIST_INITIAL_VALUE(list); - pmm_alloc_range(reserved.regions[i].base, reserved.regions[i].len / PAGE_SIZE, &list); - } -#endif + // detect physical memory layout from the device tree + fdtwalk_setup_memory(fdt, lk_boot_args[1], MEMORY_BASE_PHYS, MEMSIZE); - -#if WITH_SMP - // TODO: refactor this code into libfdt - if (cpus.count > 0) { - printf("FDT: found %zu cpu%c\n", cpus.count, cpus.count == 1 ? ' ' : 's'); - uint harts[SMP_MAX_CPUS - 1]; - - // copy from the detected cpu list to an array of harts, excluding the boot hart - size_t hart_index = 0; - for (size_t i = 0; i < cpus.count; i++) { - if (cpus.cpu[i].hart != riscv_current_hart()) { - harts[hart_index++] = cpus.cpu[i].hart; - } - - // we can start MAX CPUS - 1 secondaries - if (hart_index >= SMP_MAX_CPUS - 1) { - break; - } - } - - // tell the riscv layer how many cores we have to start - if (hart_index > 0) { - riscv_set_secondary_harts_to_start(harts, hart_index); - } - } -#endif + // detect secondary cores to start + fdtwalk_setup_cpus_riscv(fdt); LTRACEF("done scanning FDT\n"); @@ -217,31 +79,14 @@ void platform_init(void) { plic_init(); uart_init(); - /* detect pci */ - if (pcie_state.info.ecam_len > 0) { - printf("PCIE: initializing pcie with ecam at %#" PRIx64 " found in FDT\n", pcie_state.info.ecam_base); - status_t err = pci_init_ecam(pcie_state.info.ecam_base, pcie_state.info.ecam_len, pcie_state.info.bus_start, pcie_state.info.bus_end); - if (err == NO_ERROR) { - // add some additional resources to the pci bus manager in case it needs to configure - if (pcie_state.info.io_len > 0) { - // we can only deal with a mapping of io base 0 to the mmio base - DEBUG_ASSERT(pcie_state.info.io_base == 0); - pci_bus_mgr_add_resource(PCI_RESOURCE_IO_RANGE, pcie_state.info.io_base, pcie_state.info.io_len); - - // TODO: set the mmio base somehow so pci knows what to do with it - } - if (pcie_state.info.mmio_len > 0) { - pci_bus_mgr_add_resource(PCI_RESOURCE_MMIO_RANGE, pcie_state.info.mmio_base, pcie_state.info.mmio_len); - } - if (pcie_state.info.mmio64_len > 0) { - pci_bus_mgr_add_resource(PCI_RESOURCE_MMIO64_RANGE, pcie_state.info.mmio64_base, pcie_state.info.mmio64_len); - } - - // start the bus manager - pci_bus_mgr_init(); + /* configure and start pci from device tree */ + status_t err = fdtwalk_setup_pci(fdt); + if (err >= NO_ERROR) { + // start the bus manager + pci_bus_mgr_init(); - pci_bus_mgr_assign_resources(); // add some additional resources to the pci bus manager in case it needs to configure - }; + // assign resources to all devices in case they need it + pci_bus_mgr_assign_resources(); } /* detect any virtio devices */