This is borrowed from OpenHackWare in order to provide hardware data to the client OS.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/ppc/qemu/context.c | 129 +++++++++++++++++++++++++++++++++++++++++++- arch/ppc/qemu/context.h | 1 + include/arch/ppc/residual.h | 116 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 include/arch/ppc/residual.h
diff --git a/arch/ppc/qemu/context.c b/arch/ppc/qemu/context.c index 65cd4e4..03ca173 100644 --- a/arch/ppc/qemu/context.c +++ b/arch/ppc/qemu/context.c @@ -1,12 +1,19 @@ /* * context switching * 2003-10 by SONE Takeshi + * + * Residual data portions: + * Copyright (c) 2004-2005 Jocelyn Mayer */
#include "config.h" #include "kernel/kernel.h" #include "context.h" +#include "arch/ppc/processor.h" +#include "arch/ppc/residual.h" +#include "drivers/drivers.h" #include "libopenbios/bindings.h" +#include "libopenbios/ofmem.h" #include "libopenbios/initprogram.h" #include "libopenbios/sys_info.h"
@@ -97,12 +104,117 @@ init_context(uint8_t *stack, uint32_t stack_size, int num_params) return ctx; }
+ +/* Build PReP residual data */ +static void * +residual_build(uint32_t memsize, uint32_t load_base, uint32_t load_size) +{ + residual_t *res; + const unsigned char model[] = "Qemu\0PPC\0"; + int i; + + res = malloc(sizeof(residual_t)); + if (res == NULL) { + return NULL; + } + + res->length = sizeof(residual_t); + res->version = 1; + res->revision = 0; + memcpy(res->vital.model, model, sizeof(model)); + res->vital.version = 1; + res->vital.revision = 0; + res->vital.firmware = 0x1D1; + res->vital.NVRAM_size = 0x2000; + res->vital.nSIMMslots = 1; + res->vital.nISAslots = 0; + res->vital.nPCIslots = 0; + res->vital.nPCMCIAslots = 0; + res->vital.nMCAslots = 0; + res->vital.nEISAslots = 0; + res->vital.CPUHz = 200 * 1000 * 1000; + res->vital.busHz = 100 * 1000 * 1000; + res->vital.PCIHz = 33 * 1000 * 1000; + res->vital.TBdiv = 1000; + res->vital.wwidth = 32; + res->vital.page_size = 4096; + res->vital.ChBlocSize = 32; + res->vital.GrSize = 32; + res->vital.cache_size = 0; + res->vital.cache_type = 0; /* No cache */ + res->vital.cache_assoc = 8; /* Same as 601 */ + res->vital.cache_lnsize = 32; + res->vital.Icache_size = 0; + res->vital.Icache_assoc = 8; + res->vital.Icache_lnsize = 32; + res->vital.Dcache_size = 0; + res->vital.Dcache_assoc = 8; + res->vital.Dcache_lnsize = 32; + res->vital.TLB_size = 0; + res->vital.TLB_type = 0; /* None */ + res->vital.TLB_assoc = 2; + res->vital.ITLB_size = 0; + res->vital.ITLB_assoc = 2; + res->vital.DTLB_size = 0; + res->vital.DTLB_assoc = 2; + res->vital.ext_vital = NULL; + res->nCPUs = 1; + res->CPUs[0].pvr = mfpvr(); + res->CPUs[0].serial = 0; + res->CPUs[0].L2_size = 0; + res->CPUs[0].L2_assoc = 8; + /* Memory infos */ + res->max_mem = memsize; + res->good_mem = memsize; + /* Memory mappings */ + /* First segment: firmware */ + res->maps[0].usage = 0x0007; + res->maps[0].base = 0xfff00000; + res->maps[0].count = 0x00100000 >> 12; + i = 1; + /* Boot image */ + load_size = (load_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + res->maps[i].usage = 0x0008; + res->maps[i].base = load_base >> 12; + res->maps[i].count = load_size >> 12; + i++; + /* Free memory */ + res->maps[i].usage = 0x0010; + res->maps[i].base = (load_base + load_size) >> 12; + res->maps[i].count = (memsize >> 12) - res->maps[i].base; + i++; + /* ISA IO region : 8MB */ + res->maps[i].usage = 0x0040; + res->maps[i].base = 0x80000000 >> 12; + res->maps[i].count = 0x00800000 >> 12; + i++; + /* System registers : 8MB */ + res->maps[i].usage = 0x0200; + res->maps[i].base = 0xBF800000 >> 12; + res->maps[i].count = 0x00800000 >> 12; + i++; + /* System ROM : 64 kB */ + res->maps[i].usage = 0x2000; + res->maps[i].base = 0xFFFF0000 >> 12; + res->maps[i].count = 0x00010000 >> 12; + i++; + res->nmaps = i; + /* Memory SIMMs */ + res->nmems = 1; + res->memories[0].size = memsize; + /* Describe no devices */ + res->ndevices = 0; + + return res; +} + /* init-program */ int arch_init_program(void) { volatile struct context *ctx = __context; - ucell entry, param; + ucell entry, param, loadbase, loadsize; + ofmem_t *ofmem = ofmem_arch_get_private();
/* According to IEEE 1275, PPC bindings: * @@ -112,7 +224,8 @@ arch_init_program(void) * r6 = address of client program arguments (unused) * r7 = length of client program arguments (unused) * - * Yaboot and Linux use r3 and r4 for initrd address and size + * Yaboot and Linux use r3 and r4 for initrd address and size + * PReP machines use r3 and r4 for residual data and load image */
ctx->regs[REG_R5] = (unsigned long)of_client_callback; @@ -129,6 +242,18 @@ arch_init_program(void) entry = POP(); ctx->pc = entry;
+ /* Residual data for PReP */ + if (!is_apple()) { + fword("load-base"); + loadbase = POP(); + fword("load-size"); + loadsize = POP(); + + ctx->regs[REG_R3] = (uintptr_t)residual_build((uint32_t)ofmem->ramsize, + loadbase, loadsize); + ctx->regs[REG_R4] = loadbase; + } + return 0; }
diff --git a/arch/ppc/qemu/context.h b/arch/ppc/qemu/context.h index 8135bb4..7cf9da8 100644 --- a/arch/ppc/qemu/context.h +++ b/arch/ppc/qemu/context.h @@ -10,6 +10,7 @@ struct context { /* General registers */ unsigned long regs[34]; #define REG_R3 3 +#define REG_R4 7 #define REG_R5 8 #define REG_R6 9 #define REG_R7 10 diff --git a/include/arch/ppc/residual.h b/include/arch/ppc/residual.h new file mode 100644 index 0000000..8e9d89c --- /dev/null +++ b/include/arch/ppc/residual.h @@ -0,0 +1,116 @@ +/* + * residual.h + * + * Structures for build PReP residual data as used in OpenHackWare + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Residual data */ +#define MAX_CPUS 16 +#define MAX_SEGS 64 +#define MAX_MEMS 64 +#define MAX_DEVS 256 + +typedef struct vital_t { + /* Motherboard dependents */ + uint8_t model[32]; + uint8_t serial[64]; + uint16_t version; + uint16_t revision; + uint32_t firmware; + uint32_t NVRAM_size; + uint32_t nSIMMslots; + uint32_t nISAslots; + uint32_t nPCIslots; + uint32_t nPCMCIAslots; + uint32_t nMCAslots; + uint32_t nEISAslots; + uint32_t CPUHz; + uint32_t busHz; + uint32_t PCIHz; + uint32_t TBdiv; + /* CPU infos */ + uint32_t wwidth; + uint32_t page_size; + uint32_t ChBlocSize; + uint32_t GrSize; + /* Cache and TLBs */ + uint32_t cache_size; + uint32_t cache_type; + uint32_t cache_assoc; + uint32_t cache_lnsize; + uint32_t Icache_size; + uint32_t Icache_assoc; + uint32_t Icache_lnsize; + uint32_t Dcache_size; + uint32_t Dcache_assoc; + uint32_t Dcache_lnsize; + uint32_t TLB_size; + uint32_t TLB_type; + uint32_t TLB_assoc; + uint32_t ITLB_size; + uint32_t ITLB_assoc; + uint32_t DTLB_size; + uint32_t DTLB_assoc; + void *ext_vital; +} vital_t; + +typedef struct PPC_CPU_t { + uint32_t pvr; + uint32_t serial; + uint32_t L2_size; + uint32_t L2_assoc; +} PPC_CPU_t; + +typedef struct map_t { + uint32_t usage; + uint32_t base; + uint32_t count; +} map_t; + +typedef struct PPC_mem_t { + uint32_t size; +} PPC_mem_t; + +typedef struct PPC_device_t { + uint32_t busID; + uint32_t devID; + uint32_t serial; + uint32_t flags; + uint32_t type; + uint32_t subtype; + uint32_t interface; + uint32_t spare; +} PPC_device_t; + +typedef struct residual_t { + uint32_t length; + uint16_t version; + uint16_t revision; + vital_t vital; + uint32_t nCPUs; + PPC_CPU_t CPUs[MAX_CPUS]; + uint32_t max_mem; + uint32_t good_mem; + uint32_t nmaps; + map_t maps[MAX_SEGS]; + uint32_t nmems; + PPC_mem_t memories[MAX_MEMS]; + uint32_t ndevices; + PPC_device_t devices[MAX_DEVS]; + /* TOFIX: No PNP devices */ +} residual_t;