From e8f58ba4beb77a0a6c42e17bcf89cce7a999f8d8 Mon Sep 17 00:00:00 2001 From: PulkoMandy Date: Thu, 28 Mar 2019 08:07:33 +0100 Subject: [PATCH] sparc: fix bootloader build - Add various missing jamfiles - Add required implementation stubs - Update openfirmware jamfiles for multiboot support - Update linker rules for sparc loader Change-Id: I2d06c7a4d33827f58d82946687003f9a0dcb1b7d Reviewed-on: https://review.haiku-os.org/c/1329 Reviewed-by: waddlesplash --- headers/private/kernel/arch/sparc/arch_mmu.h | 15 + .../boot/platform/openfirmware/support.h | 0 .../config_manager/arch/sparc/Jamfile | 11 + .../arch/sparc/config_manager_arch.c | 18 + .../bus_managers/pci/arch/sparc/Jamfile | 16 + src/system/boot/arch/sparc/Jamfile | 42 +- src/system/boot/platform/openfirmware/Jamfile | 45 +- .../platform/openfirmware/arch/sparc/Jamfile | 5 +- .../arch/sparc/arch_start_kernel.S | 16 + .../platform/openfirmware/arch/sparc/cpu.cpp | 125 +++++ .../platform/openfirmware/arch/sparc/mmu.cpp | 457 ++++++++++++++++++ .../sparc/boot_loader_openfirmware.ld | 45 ++ .../libroot/posix/string/arch/sparc/Jamfile | 19 +- src/system/runtime_loader/Jamfile | 2 +- src/system/runtime_loader/arch/sparc/Jamfile | 21 + .../arch/sparc/arch_relocate.cpp | 30 ++ 16 files changed, 825 insertions(+), 42 deletions(-) create mode 100644 headers/private/kernel/arch/sparc/arch_mmu.h rename {src/system => headers/private/kernel}/boot/platform/openfirmware/support.h (100%) create mode 100644 src/add-ons/kernel/bus_managers/config_manager/arch/sparc/Jamfile create mode 100644 src/add-ons/kernel/bus_managers/config_manager/arch/sparc/config_manager_arch.c create mode 100644 src/add-ons/kernel/bus_managers/pci/arch/sparc/Jamfile create mode 100644 src/system/boot/platform/openfirmware/arch/sparc/arch_start_kernel.S create mode 100644 src/system/boot/platform/openfirmware/arch/sparc/cpu.cpp create mode 100644 src/system/boot/platform/openfirmware/arch/sparc/mmu.cpp create mode 100644 src/system/ldscripts/sparc/boot_loader_openfirmware.ld create mode 100644 src/system/runtime_loader/arch/sparc/Jamfile create mode 100644 src/system/runtime_loader/arch/sparc/arch_relocate.cpp diff --git a/headers/private/kernel/arch/sparc/arch_mmu.h b/headers/private/kernel/arch/sparc/arch_mmu.h new file mode 100644 index 0000000000..e271186bcd --- /dev/null +++ b/headers/private/kernel/arch/sparc/arch_mmu.h @@ -0,0 +1,15 @@ +/* +** Copyright 2019, Adrien Destugues, pulkomandy@pulkomandy.tk +** Distributed under the terms of the MIT License. +*/ +#ifndef _KERNEL_ARCH_SPARC_MMU_H +#define _KERNEL_ARCH_SPARC_MMU_H + + +#include +#include + +#include + + +#endif /* _KERNEL_ARCH_SPARC_MMU_H */ diff --git a/src/system/boot/platform/openfirmware/support.h b/headers/private/kernel/boot/platform/openfirmware/support.h similarity index 100% rename from src/system/boot/platform/openfirmware/support.h rename to headers/private/kernel/boot/platform/openfirmware/support.h diff --git a/src/add-ons/kernel/bus_managers/config_manager/arch/sparc/Jamfile b/src/add-ons/kernel/bus_managers/config_manager/arch/sparc/Jamfile new file mode 100644 index 0000000000..f1ee9bbc15 --- /dev/null +++ b/src/add-ons/kernel/bus_managers/config_manager/arch/sparc/Jamfile @@ -0,0 +1,11 @@ +SubDir HAIKU_TOP src add-ons kernel bus_managers config_manager arch $(TARGET_ARCH) ; + +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ; + +UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ] ; + +KernelStaticLibrary config_manager_arch : + config_manager_arch.c + ; + + diff --git a/src/add-ons/kernel/bus_managers/config_manager/arch/sparc/config_manager_arch.c b/src/add-ons/kernel/bus_managers/config_manager/arch/sparc/config_manager_arch.c new file mode 100644 index 0000000000..1996ba4daf --- /dev/null +++ b/src/add-ons/kernel/bus_managers/config_manager/arch/sparc/config_manager_arch.c @@ -0,0 +1,18 @@ +/* + * Copyright 2009 Haiku, Inc. + * Distributed under the terms of the MIT License. + * + * arch-specific config manager + * + * Authors (in chronological order): + * François Revol (revol@free.fr) + */ + +#include +#include + +int config_manager_scan_hardcoded(struct device_info **info, int32 *count) +{ + return B_OK; +} + diff --git a/src/add-ons/kernel/bus_managers/pci/arch/sparc/Jamfile b/src/add-ons/kernel/bus_managers/pci/arch/sparc/Jamfile new file mode 100644 index 0000000000..3a4790e24e --- /dev/null +++ b/src/add-ons/kernel/bus_managers/pci/arch/sparc/Jamfile @@ -0,0 +1,16 @@ +SubDir HAIKU_TOP src add-ons kernel bus_managers pci arch sparc ; + +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ; +UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ] + [ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ; + +SEARCH_SOURCE += [ FDirName $(SUBDIR) openfirmware ] ; + +KernelStaticLibrary pci_arch_bus_manager : + pci_controller.cpp + pci_io.c + + # openfirmware + # TODO +; + diff --git a/src/system/boot/arch/sparc/Jamfile b/src/system/boot/arch/sparc/Jamfile index 0ff3a31120..5ce2dbe955 100644 --- a/src/system/boot/arch/sparc/Jamfile +++ b/src/system/boot/arch/sparc/Jamfile @@ -1,33 +1,29 @@ SubDir HAIKU_TOP src system boot arch sparc ; -{ - local defines = _BOOT_MODE ; - - defines = [ FDefines $(defines) ] ; - SubDirCcFlags $(defines) ; - SubDirC++Flags $(defines) -fno-rtti ; -} - - local kernelLibArchObjects = - byteorder.o memcpy.o memset.o ; -BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o : - debug_uart_8250.cpp - #arch_uart_8250.cpp - arch_elf.cpp - : # additional flags - : - $(kernelArchObjects) - $(kernelLibArchObjects) -; +local platform ; +for platform in [ MultiBootSubDirSetup openfirmware ] { + on $(platform) { + DEFINES += _BOOT_MODE ; -SEARCH on [ FGristFiles arch_elf.cpp arch_uart_8250.cpp ] - = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH) ] ; + BootMergeObject [ FGristFiles boot_arch_$(TARGET_KERNEL_ARCH).o ] : + debug_uart_8250.cpp + #arch_uart_8250.cpp + arch_elf.cpp + : # additional flags + : + $(kernelArchObjects) + $(kernelLibArchObjects) + ; -SEARCH on [ FGristFiles debug_uart_8250.cpp ] - = [ FDirName $(HAIKU_TOP) src system kernel arch generic ] ; + SEARCH on [ FGristFiles arch_elf.cpp arch_uart_8250.cpp ] + = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH) ] ; + SEARCH on [ FGristFiles debug_uart_8250.cpp ] + = [ FDirName $(HAIKU_TOP) src system kernel arch generic ] ; + } +} diff --git a/src/system/boot/platform/openfirmware/Jamfile b/src/system/boot/platform/openfirmware/Jamfile index 43f2f2c765..736258595b 100644 --- a/src/system/boot/platform/openfirmware/Jamfile +++ b/src/system/boot/platform/openfirmware/Jamfile @@ -4,9 +4,14 @@ SubDirC++Flags -D_BOOT_MODE -fno-rtti ; UsePrivateHeaders [ FDirName graphics common ] ; -SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ; +{ + local defines = _BOOT_MODE _BOOT_PLATFORM_OPENFIRMWARE ; + defines = [ FDefines $(defines) ] ; + SubDirCcFlags $(defines) ; + SubDirC++Flags $(defines) -fno-rtti ; +} -BootMergeObject boot_platform_openfirmware.o : +local platform_src = console.cpp debug.cpp devices.cpp @@ -19,23 +24,41 @@ BootMergeObject boot_platform_openfirmware.o : start.cpp support.cpp video.cpp +; +local kernel_src = openfirmware.cpp openfirmware_devices.cpp +; +local vesa_src = # VESA/DDC EDID decode_edid.c dump_edid.c - - : - : - boot_platform_generic.a - boot_platform_openfirmware_$(TARGET_ARCH).a ; -SEARCH on [ FGristFiles $(genericPlatformSources) ] - = [ FDirName $(HAIKU_TOP) src system boot platform generic ] ; -SEARCH on [ FGristFiles openfirmware.cpp openfirmware_devices.cpp ] - = [ FDirName $(HAIKU_TOP) src system kernel platform openfirmware ] ; +local platform ; +for platform in [ MultiBootSubDirSetup openfirmware ] { + on $(platform) { + BootMergeObject boot_platform_openfirmware.o : + + $(platform_src) + $(kernel_src) + $(vesa_src) + : + : + boot_platform_generic_openfirmware.a + boot_platform_openfirmware_$(TARGET_ARCH).a + ; + +# SEARCH on [ FGristFiles $(genericPlatformSources) ] +# = [ FDirName $(HAIKU_TOP) src system boot platform generic ] ; + SEARCH on [ FGristFiles $(kernel_src) ] + = [ FDirName $(HAIKU_TOP) src system kernel platform openfirmware ] ; + SEARCH on [ FGristFiles $(vesa_src) ] + = [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ; + + } +} SubInclude HAIKU_TOP src system boot platform openfirmware arch ; diff --git a/src/system/boot/platform/openfirmware/arch/sparc/Jamfile b/src/system/boot/platform/openfirmware/arch/sparc/Jamfile index b081899dd7..4871b0cb49 100644 --- a/src/system/boot/platform/openfirmware/arch/sparc/Jamfile +++ b/src/system/boot/platform/openfirmware/arch/sparc/Jamfile @@ -1,6 +1,6 @@ SubDir HAIKU_TOP src system boot platform openfirmware arch sparc ; -SubDirHdrs $(HAIKU_TOP) src system boot platform $(TARGET_BOOT_PLATFORM) ; +SubDirHdrs $(HAIKU_TOP) src system boot platform $(HAIKU_BOOT_PLATFORM) ; UsePrivateSystemHeaders ; UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ] [ FDirName kernel boot platform $(HAIKU_KERNEL_PLATFORM) ] @@ -9,6 +9,9 @@ UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ] SubDirC++Flags -fno-rtti ; BootStaticLibrary boot_platform_openfirmware_sparc : + arch_start_kernel.S + cpu.cpp + mmu.cpp ; SEARCH on [ FGristFiles arch_cpu_asm.S arch_mmu.cpp ] diff --git a/src/system/boot/platform/openfirmware/arch/sparc/arch_start_kernel.S b/src/system/boot/platform/openfirmware/arch/sparc/arch_start_kernel.S new file mode 100644 index 0000000000..54bc658dbc --- /dev/null +++ b/src/system/boot/platform/openfirmware/arch/sparc/arch_start_kernel.S @@ -0,0 +1,16 @@ +/* + * Copyright 2005, Ingo Weinhold . + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#define FUNCTION(x) .global x; .type x,@function; x + +/* status_t arch_start_kernel(struct kernel_args *kernelArgs, + addr_t kernelEntry, addr_t kernelStackTop); + + r3 - kernelArgs + r4 - kernelEntry + r5 - kernelStackTop +*/ +FUNCTION(arch_start_kernel): + return diff --git a/src/system/boot/platform/openfirmware/arch/sparc/cpu.cpp b/src/system/boot/platform/openfirmware/arch/sparc/cpu.cpp new file mode 100644 index 0000000000..517c228add --- /dev/null +++ b/src/system/boot/platform/openfirmware/arch/sparc/cpu.cpp @@ -0,0 +1,125 @@ +/* + * Copyright 2005, Ingo Weinhold . + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#define TRACE_CPU +#ifdef TRACE_CPU +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + + +status_t +boot_arch_cpu_init(void) +{ + int32 busFrequency = 0; + + int root = of_finddevice("/"); + if (root == OF_FAILED) { + printf("boot_arch_cpu_init(): Failed to open \"/\"!\n"); + return B_ERROR; + } + + of_getprop(root, "clock-frequency", &busFrequency, 4); + // we might find it in /cpus instead + + // iterate through the "/cpus" node to find all CPUs + int cpus = of_finddevice("/cpus"); + if (cpus == OF_FAILED) { + printf("boot_arch_cpu_init(): Failed to open \"/cpus\"!\n"); + return B_ERROR; + } + + char cpuPath[256]; + int cookie = 0; + int cpuCount = 0; + while (of_get_next_device(&cookie, cpus, "cpu", cpuPath, + sizeof(cpuPath)) == B_OK) { + TRACE(("found CPU: %s\n", cpuPath)); + + // For the first CPU get the frequencies of CPU, bus, and time base. + // We assume they are the same for all CPUs. + if (cpuCount == 0) { + int cpu = of_finddevice(cpuPath); + if (cpu == OF_FAILED) { + printf("boot_arch_cpu_init: Failed get CPU device node!\n"); + return B_ERROR; + } + + // TODO: Does encode-int really encode quadlet (32 bit numbers) + // only? + int32 clockFrequency; + if (of_getprop(cpu, "clock-frequency", &clockFrequency, 4) + == OF_FAILED) { + printf("boot_arch_cpu_init: Failed to get CPU clock " + "frequency!\n"); + return B_ERROR; + } + if (busFrequency == 0 + && of_getprop(cpu, "bus-frequency", &busFrequency, 4) + == OF_FAILED) { + printf("boot_arch_cpu_init: Failed to get bus clock " + "frequency!\n"); + return B_ERROR; + } + int32 timeBaseFrequency; + if (of_getprop(cpu, "timebase-frequency", &timeBaseFrequency, 4) + == OF_FAILED) { + printf("boot_arch_cpu_init: Failed to get time base " + "frequency!\n"); + return B_ERROR; + } + + gKernelArgs.arch_args.cpu_frequency = clockFrequency; + gKernelArgs.arch_args.bus_frequency = busFrequency; + gKernelArgs.arch_args.time_base_frequency = timeBaseFrequency; + + TRACE((" CPU clock frequency: %d\n", clockFrequency)); + TRACE((" bus clock frequency: %d\n", busFrequency)); + TRACE((" time base frequency: %d\n", timeBaseFrequency)); + } + + cpuCount++; + } + + if (cpuCount == 0) { + printf("boot_arch_cpu_init(): Found no CPUs!\n"); + return B_ERROR; + } + + gKernelArgs.num_cpus = cpuCount; + + // allocate the kernel stacks (the memory stuff is already initialized + // at this point) + addr_t stack = (addr_t)arch_mmu_allocate((void*)0x80000000, + cpuCount * (KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE), + B_READ_AREA | B_WRITE_AREA, false); + if (!stack) { + printf("boot_arch_cpu_init(): Failed to allocate kernel stack(s)!\n"); + return B_NO_MEMORY; + } + + for (int i = 0; i < cpuCount; i++) { + gKernelArgs.cpu_kstack[i].start = stack; + gKernelArgs.cpu_kstack[i].size = KERNEL_STACK_SIZE + + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE; + stack += KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE; + } + + return B_OK; +} + diff --git a/src/system/boot/platform/openfirmware/arch/sparc/mmu.cpp b/src/system/boot/platform/openfirmware/arch/sparc/mmu.cpp new file mode 100644 index 0000000000..7d5f4bde6b --- /dev/null +++ b/src/system/boot/platform/openfirmware/arch/sparc/mmu.cpp @@ -0,0 +1,457 @@ +/* + * Copyright 2003-2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2010-2011, Haiku, Inc. All Rights Reserved. + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de. + * Alexander von Gluck, kallisti5@unixzen.com + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "support.h" + + +// set protection to WIMGNPP: -----PP +// PP: 00 - no access +// 01 - read only +// 10 - read/write +// 11 - read only +#define PAGE_READ_ONLY 0x01 +#define PAGE_READ_WRITE 0x02 + +// NULL is actually a possible physical address... +//#define PHYSINVAL ((void *)-1) +#define PHYSINVAL NULL + +//#define TRACE_MMU +#ifdef TRACE_MMU +# define TRACE(x...) dprintf(x) +#else +# define TRACE(x...) ; +#endif + + +uint32 sPageTableHashMask; + + +// begin and end of the boot loader +extern "C" uint8 __text_begin; +extern "C" uint8 _end; + + +static status_t +find_physical_memory_ranges(size_t &total) +{ + int memory; + dprintf("checking for memory...\n"); + if (of_getprop(gChosen, "memory", &memory, sizeof(int)) == OF_FAILED) + return B_ERROR; + int package = of_instance_to_package(memory); + + total = 0; + + // Memory base addresses are provided in 32 or 64 bit flavors + // #address-cells and #size-cells matches the number of 32-bit 'cells' + // representing the length of the base address and size fields + int root = of_finddevice("/"); + int32 regAddressCells = of_address_cells(root); + int32 regSizeCells = of_size_cells(root); + if (regAddressCells == OF_FAILED || regSizeCells == OF_FAILED) { + dprintf("finding base/size length counts failed, assume 32-bit.\n"); + regAddressCells = 1; + regSizeCells = 1; + } + + // NOTE : Size Cells of 2 is possible in theory... but I haven't seen it yet. + if (regAddressCells > 2 || regSizeCells > 1) { + panic("%s: Unsupported OpenFirmware cell count detected.\n" + "Address Cells: %" B_PRId32 "; Size Cells: %" B_PRId32 + " (CPU > 64bit?).\n", __func__, regAddressCells, regSizeCells); + return B_ERROR; + } + + // On 64-bit PowerPC systems (G5), our mem base range address is larger + if (regAddressCells == 2) { + struct of_region regions[64]; + int count = of_getprop(package, "reg", regions, sizeof(regions)); + if (count == OF_FAILED) + count = of_getprop(memory, "reg", regions, sizeof(regions)); + if (count == OF_FAILED) + return B_ERROR; + count /= sizeof(regions[0]); + + for (int32 i = 0; i < count; i++) { + if (regions[i].size <= 0) { + dprintf("%d: empty region\n", i); + continue; + } + dprintf("%" B_PRIu32 ": base = %" B_PRIu64 "," + "size = %" B_PRIu32 "\n", i, regions[i].base, regions[i].size); + + total += regions[i].size; + + if (insert_physical_memory_range((addr_t)regions[i].base, + regions[i].size) != B_OK) { + dprintf("cannot map physical memory range " + "(num ranges = %" B_PRIu32 ")!\n", + gKernelArgs.num_physical_memory_ranges); + return B_ERROR; + } + } + return B_OK; + } + + // Otherwise, normal 32-bit PowerPC G3 or G4 have a smaller 32-bit one + struct of_region regions[64]; + int count = of_getprop(package, "reg", regions, sizeof(regions)); + if (count == OF_FAILED) + count = of_getprop(memory, "reg", regions, sizeof(regions)); + if (count == OF_FAILED) + return B_ERROR; + count /= sizeof(regions[0]); + + for (int32 i = 0; i < count; i++) { + if (regions[i].size <= 0) { + dprintf("%d: empty region\n", i); + continue; + } + dprintf("%" B_PRIu32 ": base = %" B_PRIu32 "," + "size = %" B_PRIu32 "\n", i, regions[i].base, regions[i].size); + + total += regions[i].size; + + if (insert_physical_memory_range((addr_t)regions[i].base, + regions[i].size) != B_OK) { + dprintf("cannot map physical memory range " + "(num ranges = %" B_PRIu32 ")!\n", + gKernelArgs.num_physical_memory_ranges); + return B_ERROR; + } + } + + return B_OK; +} + + +static bool +is_virtual_allocated(void *address, size_t size) +{ + uint64 foundBase; + return !get_free_address_range(gKernelArgs.virtual_allocated_range, + gKernelArgs.num_virtual_allocated_ranges, (addr_t)address, size, + &foundBase) || foundBase != (addr_t)address; +} + + +static bool +is_physical_allocated(void *address, size_t size) +{ + uint64 foundBase; + return !get_free_address_range(gKernelArgs.physical_allocated_range, + gKernelArgs.num_physical_allocated_ranges, (addr_t)address, size, + &foundBase) || foundBase != (addr_t)address; +} + + +static bool +is_physical_memory(void *address, size_t size) +{ + return is_address_range_covered(gKernelArgs.physical_memory_range, + gKernelArgs.num_physical_memory_ranges, (addr_t)address, size); +} + + +static bool +is_physical_memory(void *address) +{ + return is_physical_memory(address, 1); +} + + +static void +map_page(void *virtualAddress, void *physicalAddress, uint8 mode) +{ + panic("%s: out of page table entries!\n", __func__); +} + + +static void +map_range(void *virtualAddress, void *physicalAddress, size_t size, uint8 mode) +{ + for (uint32 offset = 0; offset < size; offset += B_PAGE_SIZE) { + map_page((void *)(intptr_t(virtualAddress) + offset), + (void *)(intptr_t(physicalAddress) + offset), mode); + } +} + + +static void * +find_physical_memory_range(size_t size) +{ + for (uint32 i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) { + if (gKernelArgs.physical_memory_range[i].size > size) + return (void *)(addr_t)gKernelArgs.physical_memory_range[i].start; + } + return PHYSINVAL; +} + + +static void * +find_free_physical_range(size_t size) +{ + // just do a simple linear search at the end of the allocated + // ranges (dumb memory allocation) + if (gKernelArgs.num_physical_allocated_ranges == 0) { + if (gKernelArgs.num_physical_memory_ranges == 0) + return PHYSINVAL; + + return find_physical_memory_range(size); + } + + for (uint32 i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) { + void *address + = (void *)(addr_t)(gKernelArgs.physical_allocated_range[i].start + + gKernelArgs.physical_allocated_range[i].size); + if (!is_physical_allocated(address, size) + && is_physical_memory(address, size)) + return address; + } + return PHYSINVAL; +} + + +static void * +find_free_virtual_range(void *base, size_t size) +{ + if (base && !is_virtual_allocated(base, size)) + return base; + + void *firstFound = NULL; + void *firstBaseFound = NULL; + for (uint32 i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { + void *address + = (void *)(addr_t)(gKernelArgs.virtual_allocated_range[i].start + + gKernelArgs.virtual_allocated_range[i].size); + if (!is_virtual_allocated(address, size)) { + if (!base) + return address; + + if (firstFound == NULL) + firstFound = address; + if (address >= base + && (firstBaseFound == NULL || address < firstBaseFound)) { + firstBaseFound = address; + } + } + } + return (firstBaseFound ? firstBaseFound : firstFound); +} + + +extern "C" void * +arch_mmu_allocate(void *_virtualAddress, size_t size, uint8 _protection, + bool exactAddress) +{ + // we only know page sizes + size = ROUNDUP(size, B_PAGE_SIZE); + + uint8 protection = 0; + if (_protection & B_WRITE_AREA) + protection = PAGE_READ_WRITE; + else + protection = PAGE_READ_ONLY; + + // If no address is given, use the KERNEL_BASE as base address, since + // that avoids trouble in the kernel, when we decide to keep the region. + void *virtualAddress = _virtualAddress; + if (!virtualAddress) + virtualAddress = (void*)KERNEL_BASE; + + // find free address large enough to hold "size" + virtualAddress = find_free_virtual_range(virtualAddress, size); + if (virtualAddress == NULL) + return NULL; + + // fail if the exact address was requested, but is not free + if (exactAddress && _virtualAddress && virtualAddress != _virtualAddress) { + dprintf("arch_mmu_allocate(): exact address requested, but virtual " + "range (base: %p, size: %" B_PRIuSIZE ") is not free.\n", + _virtualAddress, size); + return NULL; + } + + // we have a free virtual range for the allocation, now + // have a look for free physical memory as well (we assume + // that a) there is enough memory, and b) failing is fatal + // so that we don't have to optimize for these cases :) + + void *physicalAddress = find_free_physical_range(size); + if (physicalAddress == PHYSINVAL) { + dprintf("arch_mmu_allocate(base: %p, size: %" B_PRIuSIZE ") " + "no free physical address\n", virtualAddress, size); + return NULL; + } + + // everything went fine, so lets mark the space as used. + + dprintf("mmu_alloc: va %p, pa %p, size %" B_PRIuSIZE "\n", virtualAddress, + physicalAddress, size); + insert_virtual_allocated_range((addr_t)virtualAddress, size); + insert_physical_allocated_range((addr_t)physicalAddress, size); + + map_range(virtualAddress, physicalAddress, size, protection); + + return virtualAddress; +} + + +extern "C" status_t +arch_mmu_free(void *address, size_t size) +{ + // TODO: implement freeing a region! + return B_OK; +} + + +// #pragma mark - OpenFirmware callbacks and public API + + +static int +map_callback(struct of_arguments *args) +{ + void *physicalAddress = (void *)args->Argument(0); + void *virtualAddress = (void *)args->Argument(1); + int length = args->Argument(2); + int mode = args->Argument(3); + intptr_t &error = args->ReturnValue(0); + + // insert range in physical allocated if needed + + if (is_physical_memory(physicalAddress) + && insert_physical_allocated_range((addr_t)physicalAddress, length) + != B_OK) { + error = -1; + return OF_FAILED; + } + + // insert range in virtual allocated + + if (insert_virtual_allocated_range((addr_t)virtualAddress, length) + != B_OK) { + error = -2; + return OF_FAILED; + } + + // map range into the page table + + map_range(virtualAddress, physicalAddress, length, mode); + + return B_OK; +} + + +static int +unmap_callback(struct of_arguments *args) +{ +/* void *address = (void *)args->Argument(0); + int length = args->Argument(1); + int &error = args->ReturnValue(0); +*/ + // TODO: to be implemented + + return OF_FAILED; +} + + +static int +translate_callback(struct of_arguments *args) +{ + // could not find the translation + return OF_FAILED; +} + + +static int +alloc_real_mem_callback(struct of_arguments *args) +{ +/* addr_t minAddress = (addr_t)args->Argument(0); + addr_t maxAddress = (addr_t)args->Argument(1); + int length = args->Argument(2); + int mode = args->Argument(3); + int &error = args->ReturnValue(0); + int &physicalAddress = args->ReturnValue(1); +*/ + // ToDo: to be implemented + + return OF_FAILED; +} + + +/** Dispatches the callback to the responsible function */ + +static int +callback(struct of_arguments *args) +{ + const char *name = args->name; + TRACE("OF CALLBACK: %s\n", name); + + if (!strcmp(name, "map")) + return map_callback(args); + else if (!strcmp(name, "unmap")) + return unmap_callback(args); + else if (!strcmp(name, "translate")) + return translate_callback(args); + else if (!strcmp(name, "alloc-real-mem")) + return alloc_real_mem_callback(args); + + return OF_FAILED; +} + + +extern "C" status_t +arch_set_callback(void) +{ + // set OpenFirmware callbacks - it will ask us for memory after that + // instead of maintaining it itself + + void *oldCallback = NULL; + if (of_call_client_function("set-callback", 1, 1, &callback, &oldCallback) + == OF_FAILED) { + dprintf("Error: OpenFirmware set-callback failed\n"); + return B_ERROR; + } + TRACE("old callback = %p; new callback = %p\n", oldCallback, callback); + + return B_OK; +} + + +extern "C" status_t +arch_mmu_init(void) +{ + // get map of physical memory (fill in kernel_args structure) + + size_t total; + if (find_physical_memory_ranges(total) != B_OK) { + dprintf("Error: could not find physical memory ranges!\n"); + return B_ERROR; + } + dprintf("total physical memory = %luMB\n", total / (1024 * 1024)); + + return B_OK; +} + diff --git a/src/system/ldscripts/sparc/boot_loader_openfirmware.ld b/src/system/ldscripts/sparc/boot_loader_openfirmware.ld new file mode 100644 index 0000000000..656f3689a2 --- /dev/null +++ b/src/system/ldscripts/sparc/boot_loader_openfirmware.ld @@ -0,0 +1,45 @@ +OUTPUT_FORMAT("elf64-sparc") +OUTPUT_ARCH(sparc:v9) + +ENTRY(_start) + +SECTIONS +{ + . = 0x202000 + SIZEOF_HEADERS; + + __text_begin = .; + + /* text/read-only data */ + .text : { *(.text .text.* .gnu.linkonce.t.*) + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.sdata2) } + + /* writable data */ + /* align to the same offset in the next page (for performance reasons + (not that it really matters in the boot loader)) */ + . = ALIGN(0x1000) + 0x1000 + (. & (0x1000 - 1)); + + .data : { + __ctor_list = .; + *(.ctors) + __ctor_end = .; + + __data_start = .; + *(.data .gnu.linkonce.d.*) + *(.data.rel.ro.local .data.rel.ro*) + *(.got .got2) + *(.sdata .sdata.* .gnu.linkonce.s.* .fixup) } + + /* uninitialized data (in same segment as writable data) */ + __bss_start = .; + .bss : { *(.sbss .sbss.* .gnu.linkonce.sb.*) + + *(.bss .bss.* .gnu.linkonce.b.*) + . = ALIGN(0x1000); + } + + _end = . ; + + /* Strip unnecessary stuff */ + /DISCARD/ : { *(.comment .note .eh_frame .dtors .debug_* .gnu.attributes) } +} diff --git a/src/system/libroot/posix/string/arch/sparc/Jamfile b/src/system/libroot/posix/string/arch/sparc/Jamfile index e19b60f834..466ca203f0 100644 --- a/src/system/libroot/posix/string/arch/sparc/Jamfile +++ b/src/system/libroot/posix/string/arch/sparc/Jamfile @@ -1,10 +1,17 @@ SubDir HAIKU_TOP src system libroot posix string arch sparc ; -UsePrivateSystemHeaders ; +local architectureObject ; +for architectureObject in [ MultiArchSubDirSetup sparc ] { + on $(architectureObject) { + local architecture = $(TARGET_PACKAGING_ARCH) ; -SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ; + UsePrivateSystemHeaders ; -MergeObject <$(TARGET_ARCH)>posix_string_arch_$(TARGET_ARCH).o : - memcpy.c - memset.c -; + SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ; + + MergeObject <$(TARGET_ARCH)>posix_string_arch_$(TARGET_ARCH).o : + memcpy.c + memset.c + ; + } +} diff --git a/src/system/runtime_loader/Jamfile b/src/system/runtime_loader/Jamfile index 46239d120e..eda9a47d25 100644 --- a/src/system/runtime_loader/Jamfile +++ b/src/system/runtime_loader/Jamfile @@ -7,7 +7,7 @@ if $(TARGET_ARCH) = x86_64 } local architectureObject ; -for architectureObject in [ MultiArchSubDirSetup ] { +for architectureObject in [ MultiArchSubDirSetup sparc ] { on $(architectureObject) { local architecture = $(TARGET_PACKAGING_ARCH) ; diff --git a/src/system/runtime_loader/arch/sparc/Jamfile b/src/system/runtime_loader/arch/sparc/Jamfile new file mode 100644 index 0000000000..319053761a --- /dev/null +++ b/src/system/runtime_loader/arch/sparc/Jamfile @@ -0,0 +1,21 @@ +SubDir HAIKU_TOP src system runtime_loader arch sparc ; + +local architectureObject ; +for architectureObject in [ MultiArchSubDirSetup sparc ] { + on $(architectureObject) { + local architecture = $(TARGET_PACKAGING_ARCH) ; + + UsePrivateHeaders runtime_loader ; + UsePrivateSystemHeaders ; + + SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ; + + StaticLibrary <$(architecture)>libruntime_loader_$(TARGET_ARCH).a : + arch_relocate.cpp + : + thread.o + + memset.o + ; + } +} diff --git a/src/system/runtime_loader/arch/sparc/arch_relocate.cpp b/src/system/runtime_loader/arch/sparc/arch_relocate.cpp new file mode 100644 index 0000000000..3a57919364 --- /dev/null +++ b/src/system/runtime_loader/arch/sparc/arch_relocate.cpp @@ -0,0 +1,30 @@ +/* + * Copyright 2012-2018, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ithamar R. Adema + */ + +#include +#include +#include + +#include "runtime_loader_private.h" + +#include + +//#define TRACE_RLD +#ifdef TRACE_RLD +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + +status_t +arch_relocate_image(image_t *rootImage, image_t *image, + SymbolLookupCache* cache) +{ + debugger("arch_relocate_image: Not Yet Implemented!"); + return B_OK; +}