mirror of
https://review.haiku-os.org/haiku
synced 2025-01-20 05:21:28 +01:00
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 <waddlesplash@gmail.com>
This commit is contained in:
parent
834a613e53
commit
e8f58ba4be
15
headers/private/kernel/arch/sparc/arch_mmu.h
Normal file
15
headers/private/kernel/arch/sparc/arch_mmu.h
Normal file
@ -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 <SupportDefs.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arch_cpu.h>
|
||||
|
||||
|
||||
#endif /* _KERNEL_ARCH_SPARC_MMU_H */
|
@ -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
|
||||
;
|
||||
|
||||
|
@ -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 <OS.h>
|
||||
#include <config_manager.h>
|
||||
|
||||
int config_manager_scan_hardcoded(struct device_info **info, int32 *count)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
16
src/add-ons/kernel/bus_managers/pci/arch/sparc/Jamfile
Normal file
16
src/add-ons/kernel/bus_managers/pci/arch/sparc/Jamfile
Normal file
@ -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
|
||||
;
|
||||
|
@ -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 =
|
||||
<src!system!kernel!lib!arch!$(TARGET_ARCH)>byteorder.o
|
||||
<src!system!kernel!lib!arch!$(TARGET_ARCH)>memcpy.o
|
||||
<src!system!kernel!lib!arch!$(TARGET_ARCH)>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 ] ;
|
||||
}
|
||||
}
|
||||
|
@ -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 ;
|
||||
|
@ -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 ]
|
||||
|
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
|
||||
* 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
|
125
src/system/boot/platform/openfirmware/arch/sparc/cpu.cpp
Normal file
125
src/system/boot/platform/openfirmware/arch/sparc/cpu.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <boot/platform/openfirmware/platform_arch.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <boot/kernel_args.h>
|
||||
#include <boot/stage2.h>
|
||||
#include <kernel.h>
|
||||
#include <platform/openfirmware/devices.h>
|
||||
#include <platform/openfirmware/openfirmware.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
457
src/system/boot/platform/openfirmware/arch/sparc/mmu.cpp
Normal file
457
src/system/boot/platform/openfirmware/arch/sparc/mmu.cpp
Normal file
@ -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 <OS.h>
|
||||
|
||||
#include <platform_arch.h>
|
||||
#include <boot/addr_range.h>
|
||||
#include <boot/kernel_args.h>
|
||||
#include <boot/platform.h>
|
||||
#include <boot/stage2.h>
|
||||
#include <boot/stdio.h>
|
||||
#include <platform/openfirmware/openfirmware.h>
|
||||
#include <arch_cpu.h>
|
||||
#include <arch_mmu.h>
|
||||
#include <kernel.h>
|
||||
|
||||
#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<uint64> 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<uint32> 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;
|
||||
}
|
||||
|
45
src/system/ldscripts/sparc/boot_loader_openfirmware.ld
Normal file
45
src/system/ldscripts/sparc/boot_loader_openfirmware.ld
Normal file
@ -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) }
|
||||
}
|
@ -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
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -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) ;
|
||||
|
||||
|
21
src/system/runtime_loader/arch/sparc/Jamfile
Normal file
21
src/system/runtime_loader/arch/sparc/Jamfile
Normal file
@ -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
|
||||
:
|
||||
<src!system!libroot!os!arch!$(TARGET_ARCH)!$(architecture)>thread.o
|
||||
|
||||
<src!system!libroot!posix!string!arch!$(TARGET_ARCH)!$(architecture)>memset.o
|
||||
;
|
||||
}
|
||||
}
|
30
src/system/runtime_loader/arch/sparc/arch_relocate.cpp
Normal file
30
src/system/runtime_loader/arch/sparc/arch_relocate.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2012-2018, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Ithamar R. Adema <ithamar@upgrade-android.com>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "runtime_loader_private.h"
|
||||
|
||||
#include <runtime_loader.h>
|
||||
|
||||
//#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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user