From 716a16ce61a33dd922238873471fb7d9b58fc0df Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Tue, 3 Jan 2006 13:30:23 +0000 Subject: [PATCH] * Find out a few interesting information about the system (like CPU, bus, and time base frequency) in the PPC boot loader, and propagate them to the kernel via kernel_args. * Now we use the correct time base frequency for timer calculations. * Implemented PPC specific system info stuff. Added a few PPC CPU types to . git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15817 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/kernel/OS.h | 28 ++++++ headers/private/kernel/arch/ppc/arch_cpu.h | 37 ++++++++ .../kernel/arch/ppc/arch_kernel_args.h | 4 + .../platform/openfirmware/arch/ppc/cpu.cpp | 48 +++++++++- src/system/kernel/arch/ppc/arch_cpu.c | 14 --- src/system/kernel/arch/ppc/arch_cpu_asm.S | 8 +- src/system/kernel/arch/ppc/arch_system_info.c | 88 ++++++++++++++++--- src/system/kernel/arch/ppc/arch_timer.c | 2 +- 8 files changed, 196 insertions(+), 33 deletions(-) diff --git a/headers/os/kernel/OS.h b/headers/os/kernel/OS.h index ebc77ffa7b..3e48f04086 100644 --- a/headers/os/kernel/OS.h +++ b/headers/os/kernel/OS.h @@ -379,13 +379,41 @@ typedef enum cpu_types { // ToDo: add latest models /* Motorola/IBM */ + B_CPU_PPC_UNKNOWN = 0, B_CPU_PPC_601 = 1, + B_CPU_PPC_602 = 7, B_CPU_PPC_603 = 2, B_CPU_PPC_603e = 3, + B_CPU_PPC_603ev = 8, B_CPU_PPC_604 = 4, B_CPU_PPC_604e = 5, + B_CPU_PPC_604ev = 9, + B_CPU_PPC_620 = 10, B_CPU_PPC_750 = 6, B_CPU_PPC_686 = 13, + B_CPU_PPC_860 = 25, + B_CPU_PPC_7400 = 26, + B_CPU_PPC_7410 = 27, + B_CPU_PPC_7447A = 28, + B_CPU_PPC_7448 = 29, + B_CPU_PPC_7450 = 30, + B_CPU_PPC_7455 = 31, + B_CPU_PPC_7457 = 32, + B_CPU_PPC_8240 = 33, + B_CPU_PPC_8245 = 34, + + B_CPU_PPC_IBM_401A1 = 35, + B_CPU_PPC_IBM_401B2 = 36, + B_CPU_PPC_IBM_401C2 = 37, + B_CPU_PPC_IBM_401D2 = 38, + B_CPU_PPC_IBM_401E2 = 39, + B_CPU_PPC_IBM_401F2 = 40, + B_CPU_PPC_IBM_401G2 = 41, + B_CPU_PPC_IBM_403 = 42, + B_CPU_PPC_IBM_405GP = 43, + B_CPU_PPC_IBM_405L = 44, + B_CPU_PPC_IBM_750FX = 45, + B_CPU_PPC_IBM_POWER3 = 46, /* Intel */ diff --git a/headers/private/kernel/arch/ppc/arch_cpu.h b/headers/private/kernel/arch/ppc/arch_cpu.h index 717ece8fd7..407ba61028 100644 --- a/headers/private/kernel/arch/ppc/arch_cpu.h +++ b/headers/private/kernel/arch/ppc/arch_cpu.h @@ -77,6 +77,7 @@ extern uint32 get_sr(void *virtualAddress); extern void set_sr(void *virtualAddress, uint32 value); extern uint32 get_msr(void); extern uint32 set_msr(uint32 value); +extern uint32 get_pvr(void); extern void set_ibat0(struct block_address_translation *bat); extern void set_ibat1(struct block_address_translation *bat); @@ -117,4 +118,40 @@ extern void ppc_context_switch(void **_oldStackPointer, void *newStackPointer); #define tlbia() asm volatile("tlbia") #define tlbie(addr) asm volatile("tlbie %0" :: "r" (addr)) + +// PowerPC processor version (the upper 16 bits of the PVR). +enum ppc_processor_version { + MPC601 = 0x0001, + MPC603 = 0x0003, + MPC604 = 0x0004, + MPC602 = 0x0005, + MPC603e = 0x0006, + MPC603ev = 0x0007, + MPC750 = 0x0008, + MPC604ev = 0x0009, + MPC7400 = 0x000c, + MPC620 = 0x0014, + IBM403 = 0x0020, + IBM401A1 = 0x0021, + IBM401B2 = 0x0022, + IBM401C2 = 0x0023, + IBM401D2 = 0x0024, + IBM401E2 = 0x0025, + IBM401F2 = 0x0026, + IBM401G2 = 0x0027, + IBMPOWER3 = 0x0041, + MPC860 = 0x0050, + MPC8240 = 0x0081, + IBM405GP = 0x4011, + IBM405L = 0x4161, + IBM750FX = 0x7000, + MPC7450 = 0x8000, + MPC7455 = 0x8001, + MPC7457 = 0x8002, + MPC7447A = 0x8003, + MPC7448 = 0x8004, + MPC7410 = 0x800c, + MPC8245 = 0x8081, +}; + #endif /* _KERNEL_ARCH_PPC_CPU_H */ diff --git a/headers/private/kernel/arch/ppc/arch_kernel_args.h b/headers/private/kernel/arch/ppc/arch_kernel_args.h index 74d1e7251a..7780bfe7c9 100644 --- a/headers/private/kernel/arch/ppc/arch_kernel_args.h +++ b/headers/private/kernel/arch/ppc/arch_kernel_args.h @@ -16,6 +16,10 @@ // kernel args typedef struct { // architecture specific + uint64 cpu_frequency; + uint64 bus_frequency; + uint64 time_base_frequency; + addr_range page_table; // virtual address and size of the page table addr_range exception_handlers; addr_range framebuffer; // maps where the framebuffer is located, in physical memory diff --git a/src/system/boot/platform/openfirmware/arch/ppc/cpu.cpp b/src/system/boot/platform/openfirmware/arch/ppc/cpu.cpp index 4e103e8899..bbe753e83b 100644 --- a/src/system/boot/platform/openfirmware/arch/ppc/cpu.cpp +++ b/src/system/boot/platform/openfirmware/arch/ppc/cpu.cpp @@ -30,7 +30,7 @@ boot_arch_cpu_init(void) // iterate through the "/cpus" node to find all CPUs int cpus = of_finddevice("/cpus"); if (cpus == OF_FAILED) { - printf("arch_cpu_init(): Failed to open \"/cpus\"!\n"); + printf("boot_arch_cpu_init(): Failed to open \"/cpus\"!\n"); return B_ERROR; } @@ -41,11 +41,53 @@ boot_arch_cpu_init(void) 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; + } + int32 busFrequency; + if (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: %ld\n", clockFrequency)); + TRACE((" bus clock frequency: %ld\n", busFrequency)); + TRACE((" time base frequency: %ld\n", timeBaseFrequency)); + } + cpuCount++; } if (cpuCount == 0) { - printf("arch_cpu_init(): Found no CPUs!\n"); + printf("boot_arch_cpu_init(): Found no CPUs!\n"); return B_ERROR; } @@ -56,7 +98,7 @@ boot_arch_cpu_init(void) addr_t stack = (addr_t)arch_mmu_allocate((void*)0x80000000, cpuCount * KERNEL_STACK_SIZE, B_READ_AREA | B_WRITE_AREA, false); if (!stack) { - printf("arch_cpu_init(): Failed to allocate kernel stack(s)!\n"); + printf("boot_arch_cpu_init(): Failed to allocate kernel stack(s)!\n"); return B_NO_MEMORY; } diff --git a/src/system/kernel/arch/ppc/arch_cpu.c b/src/system/kernel/arch/ppc/arch_cpu.c index e933bc5bc2..8c76e90a9c 100644 --- a/src/system/kernel/arch/ppc/arch_cpu.c +++ b/src/system/kernel/arch/ppc/arch_cpu.c @@ -116,19 +116,6 @@ arch_cpu_user_TLB_invalidate(void) } -// ToDo: doesn't belong here! -#if 0 -long long -system_time(void) -{ - bigtime_t time_base = get_time_base(); - - return (time_base * 1000000) / ((66*1000*1000) / 4); - // ToDo: remove hard coded -} -#endif - - status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *fault_handler) { @@ -218,4 +205,3 @@ arch_cpu_idle(void) { } - diff --git a/src/system/kernel/arch/ppc/arch_cpu_asm.S b/src/system/kernel/arch/ppc/arch_cpu_asm.S index dd19c4acba..a13ae7e480 100644 --- a/src/system/kernel/arch/ppc/arch_cpu_asm.S +++ b/src/system/kernel/arch/ppc/arch_cpu_asm.S @@ -1,5 +1,5 @@ /* -** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Copyright 2003, Axel D�fler, axeld@pinc-software.de. All rights reserved. ** Distributed under the terms of the OpenBeOS License. */ @@ -47,6 +47,12 @@ FUNCTION(set_msr): mtmsr %r3 blr +/* uint32 get_pvr(void); + */ +FUNCTION(get_pvr): + mfpvr %r3 + blr + #define get_ibat(num) \ mfibatu %r4, num; \ diff --git a/src/system/kernel/arch/ppc/arch_system_info.c b/src/system/kernel/arch/ppc/arch_system_info.c index bf3892eb43..1248f3681a 100644 --- a/src/system/kernel/arch/ppc/arch_system_info.c +++ b/src/system/kernel/arch/ppc/arch_system_info.c @@ -1,29 +1,71 @@ /* - * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2006, Ingo Weinhold . + * All rights reserved. Distributed under the terms of the MIT License. */ - -#include #include -#include -#include +#include #include #include -#include + +static uint64 sCPUClockFrequency; +static uint64 sBusClockFrequency; +static enum cpu_types sCPUType; +static uint16 sCPURevision; + +struct cpu_model { + uint16 version; + enum cpu_types beos_type; +}; + +// mapping of CPU versions to BeOS enum cpu_types +struct cpu_model kCPUModels[] = { + { MPC601, B_CPU_PPC_601 }, + { MPC603, B_CPU_PPC_603 }, + { MPC604, B_CPU_PPC_604 }, + { MPC602, B_CPU_PPC_603ev }, + { MPC603e, B_CPU_PPC_603e }, + { MPC603ev, B_CPU_PPC_603ev }, + { MPC750, B_CPU_PPC_750 }, + { MPC604ev, B_CPU_PPC_604ev }, + { MPC7400, B_CPU_PPC_7400 }, + { MPC620, B_CPU_PPC_620 }, + { IBM403, B_CPU_PPC_IBM_403 }, + { IBM401A1, B_CPU_PPC_IBM_401A1 }, + { IBM401B2, B_CPU_PPC_IBM_401B2 }, + { IBM401C2, B_CPU_PPC_IBM_401C2 }, + { IBM401D2, B_CPU_PPC_IBM_401D2 }, + { IBM401E2, B_CPU_PPC_IBM_401E2 }, + { IBM401F2, B_CPU_PPC_IBM_401F2 }, + { IBM401G2, B_CPU_PPC_IBM_401G2 }, + { IBMPOWER3, B_CPU_PPC_IBM_POWER3 }, + { MPC860, B_CPU_PPC_860 }, + { MPC8240, B_CPU_PPC_8240 }, + { IBM405GP, B_CPU_PPC_IBM_405GP }, + { IBM405L, B_CPU_PPC_IBM_405L }, + { IBM750FX, B_CPU_PPC_IBM_750FX }, + { MPC7450, B_CPU_PPC_7450 }, + { MPC7455, B_CPU_PPC_7455 }, + { MPC7457, B_CPU_PPC_7457 }, + { MPC7447A, B_CPU_PPC_7447A }, + { MPC7448, B_CPU_PPC_7448 }, + { MPC7410, B_CPU_PPC_7410 }, + { MPC8245, B_CPU_PPC_8245 }, + { 0, B_CPU_PPC_UNKNOWN } +}; status_t arch_get_system_info(system_info *info, size_t size) { - //info->cpu_type = sCpuType; - //info->cpu_revision = sCpuRevision; + info->cpu_type = sCPUType; + info->cpu_revision = sCPURevision; + + info->cpu_clock_speed = sCPUClockFrequency; + info->bus_clock_speed = sBusClockFrequency; - // - various cpu_info - //info->cpu_clock_speed = sCpuClockSpeed; - // - bus_clock_speed info->platform_type = B_MAC_PLATFORM; return B_OK; @@ -33,7 +75,25 @@ arch_get_system_info(system_info *info, size_t size) status_t arch_system_info_init(struct kernel_args *args) { - //sCpuClockSpeed = args->arch_args.cpu_clock_speed; + int i; + + sCPUClockFrequency = args->arch_args.cpu_frequency; + sBusClockFrequency = args->arch_args.bus_frequency; + + // The PVR (processor version register) contains processor version and + // revision. + uint32 pvr = get_pvr(); + uint16 version = (uint16)(pvr >> 16); + sCPURevision = (uint16)(pvr & 0xffff); + + // translate the version to a BeOS cpu_types constant + sCPUType = B_CPU_PPC_UNKNOWN; + for (i = 0; kCPUModels[i].beos_type != B_CPU_PPC_UNKNOWN; i++) { + if (version == kCPUModels[i].version) { + sCPUType = kCPUModels[i].beos_type; + break; + } + } + return B_OK; } - diff --git a/src/system/kernel/arch/ppc/arch_timer.c b/src/system/kernel/arch/ppc/arch_timer.c index ce18fc4aad..d8bc17fc0d 100644 --- a/src/system/kernel/arch/ppc/arch_timer.c +++ b/src/system/kernel/arch/ppc/arch_timer.c @@ -39,7 +39,7 @@ arch_timer_clear_hardware_timer() int arch_init_timer(kernel_args *ka) { - sTickRate = (66*1000*1000) / 4; // ToDo: fix + sTickRate = ka->arch_args.time_base_frequency; return 0; }