#include <mach_debug.h>
#include <mach_kdb.h>
#include <mach_kdp.h>
#include <debug.h>
#include <cpus.h>
#include <mach/vm_types.h>
#include <mach/vm_param.h>
#include <mach/thread_status.h>
#include <kern/misc_protos.h>
#include <kern/assert.h>
#include <kern/cpu_number.h>
#include <ppc/proc_reg.h>
#include <ppc/Firmware.h>
#include <ppc/boot.h>
#include <ppc/misc_protos.h>
#include <ppc/pmap.h>
#include <ppc/mem.h>
#include <ppc/mappings.h>
#include <ppc/exception.h>
#include <ppc/mp.h>
#include <ppc/lowglobals.h>
#include <mach-o/mach_header.h>
extern const char version[];
extern const char version_variant[];
extern unsigned int intstack[];
extern unsigned int intstack_top_ss;
addr64_t hash_table_base;
unsigned int hash_table_size;
vm_offset_t taproot_addr;
unsigned int taproot_size;
unsigned int serialmode;
extern int disableConsoleOutput;
struct shadowBAT shadow_BAT;
vm_offset_t mem_size;
uint64_t mem_actual;
uint64_t max_mem;
uint64_t sane_size;
mem_region_t pmap_mem_regions[PMAP_MEM_REGION_MAX + 1];
int pmap_mem_regions_count = 0;
unsigned int avail_remaining = 0;
vm_offset_t first_avail;
vm_offset_t static_memory_end;
addr64_t vm_last_addr = VM_MAX_KERNEL_ADDRESS;
extern struct mach_header _mh_execute_header;
vm_offset_t sectTEXTB;
int sectSizeTEXT;
vm_offset_t sectDATAB;
int sectSizeDATA;
vm_offset_t sectLINKB;
int sectSizeLINK;
vm_offset_t sectKLDB;
int sectSizeKLD;
vm_offset_t sectPRELINKB;
int sectSizePRELINK;
vm_offset_t end, etext, edata;
extern unsigned long exception_entry;
extern unsigned long exception_end;
void ppc_vm_init(uint64_t mem_limit, boot_args *args)
{
unsigned int htabmask;
unsigned int i, j, batsize, kmapsize, pvr;
vm_offset_t addr, ioAddr, videoAddr;
int boot_task_end_offset;
const char *cpus;
mapping *mp;
vm_offset_t sizeadj, oldstart;
unsigned int *xtaproot, bank_shift;
uint64_t cbsize, xhid0;
shadow_BAT.IBATs[0].upper=BAT_INVALID;
shadow_BAT.IBATs[0].lower=BAT_INVALID;
shadow_BAT.IBATs[1].upper=BAT_INVALID;
shadow_BAT.IBATs[1].lower=BAT_INVALID;
shadow_BAT.IBATs[2].upper=BAT_INVALID;
shadow_BAT.IBATs[2].lower=BAT_INVALID;
shadow_BAT.IBATs[3].upper=BAT_INVALID;
shadow_BAT.IBATs[3].lower=BAT_INVALID;
shadow_BAT.DBATs[0].upper=BAT_INVALID;
shadow_BAT.DBATs[0].lower=BAT_INVALID;
shadow_BAT.DBATs[1].upper=BAT_INVALID;
shadow_BAT.DBATs[1].lower=BAT_INVALID;
shadow_BAT.DBATs[2].upper=BAT_INVALID;
shadow_BAT.DBATs[2].lower=BAT_INVALID;
shadow_BAT.DBATs[3].upper=BAT_INVALID;
shadow_BAT.DBATs[3].lower=BAT_INVALID;
bank_shift = 0;
if (args->Version == kBootArgsVersion1) bank_shift = 12;
pmap_mem_regions_count = 0;
max_mem = 0;
mem_actual = 0;
if (mem_limit == 0) mem_limit = 0xFFFFFFFFFFFFFFFFULL;
for (i = 0; i < kMaxDRAMBanks; i++) {
cbsize = (uint64_t)args->PhysicalDRAM[i].size << (12 - bank_shift);
if (!cbsize) continue;
mem_actual = mem_actual + cbsize;
if(mem_limit == 0) continue;
if (cbsize > mem_limit) cbsize = mem_limit;
max_mem += cbsize;
mem_limit = mem_limit - cbsize;
pmap_mem_regions[pmap_mem_regions_count].mrStart = args->PhysicalDRAM[i].base >> bank_shift;
pmap_mem_regions[pmap_mem_regions_count].mrAStart = pmap_mem_regions[pmap_mem_regions_count].mrStart;
pmap_mem_regions[pmap_mem_regions_count].mrEnd = ((uint64_t)args->PhysicalDRAM[i].base >> bank_shift) + (cbsize >> 12) - 1;
pmap_mem_regions[pmap_mem_regions_count].mrAEnd = pmap_mem_regions[pmap_mem_regions_count].mrEnd;
assert ((pmap_mem_regions_count == 0) ||
pmap_mem_regions[pmap_mem_regions_count].mrStart >
pmap_mem_regions[pmap_mem_regions_count-1].mrStart);
pmap_mem_regions_count++;
}
mem_size = (unsigned int)max_mem;
if(max_mem > 0x0000000080000000ULL) mem_size = 0x80000000;
sane_size = max_mem;
if(sane_size > (addr64_t)(VM_MAX_KERNEL_ADDRESS + 1))
sane_size = (addr64_t)(VM_MAX_KERNEL_ADDRESS + 1);
first_avail = static_memory_end;
sectTEXTB = (vm_offset_t)getsegdatafromheader(
&_mh_execute_header, "__TEXT", §SizeTEXT);
sectDATAB = (vm_offset_t)getsegdatafromheader(
&_mh_execute_header, "__DATA", §SizeDATA);
sectLINKB = (vm_offset_t)getsegdatafromheader(
&_mh_execute_header, "__LINKEDIT", §SizeLINK);
sectKLDB = (vm_offset_t)getsegdatafromheader(
&_mh_execute_header, "__KLD", §SizeKLD);
sectPRELINKB = (vm_offset_t)getsegdatafromheader(
&_mh_execute_header, "__PRELINK", §SizePRELINK);
etext = (vm_offset_t) sectTEXTB + sectSizeTEXT;
edata = (vm_offset_t) sectDATAB + sectSizeDATA;
end = round_page_32(getlastaddr());
kmapsize = (round_page_32(exception_end) - trunc_page_32(exception_entry)) +
(round_page_32(sectTEXTB+sectSizeTEXT) - trunc_page_32(sectTEXTB)) +
(round_page_32(sectDATAB+sectSizeDATA) - trunc_page_32(sectDATAB)) +
(round_page_32(sectLINKB+sectSizeLINK) - trunc_page_32(sectLINKB)) +
(round_page_32(sectKLDB+sectSizeKLD) - trunc_page_32(sectKLDB)) +
(round_page_32(sectPRELINKB+sectSizePRELINK) - trunc_page_32(sectPRELINKB)) +
(round_page_32(static_memory_end) - trunc_page_32(end));
pmap_bootstrap(max_mem, &first_avail, kmapsize);
pmap_map(trunc_page_32(exception_entry), trunc_page_32(exception_entry),
round_page_32(exception_end), VM_PROT_READ|VM_PROT_EXECUTE);
pmap_map(trunc_page_32(sectTEXTB), trunc_page_32(sectTEXTB),
round_page_32(sectTEXTB+sectSizeTEXT), VM_PROT_READ|VM_PROT_EXECUTE);
pmap_map(trunc_page_32(sectDATAB), trunc_page_32(sectDATAB),
round_page_32(sectDATAB+sectSizeDATA), VM_PROT_READ|VM_PROT_WRITE);
for (addr = trunc_page_32(sectPRELINKB);
addr < round_page_32(sectPRELINKB+sectSizePRELINK);
addr += PAGE_SIZE) {
pmap_enter(kernel_pmap, addr, addr>>12,
VM_PROT_READ|VM_PROT_WRITE,
VM_WIMG_USE_DEFAULT, TRUE);
}
for (addr = trunc_page_32(sectKLDB);
addr < round_page_32(sectKLDB+sectSizeKLD);
addr += PAGE_SIZE) {
pmap_enter(kernel_pmap, addr, addr>>12,
VM_PROT_READ|VM_PROT_WRITE,
VM_WIMG_USE_DEFAULT, TRUE);
}
for (addr = trunc_page_32(sectLINKB);
addr < round_page_32(sectLINKB+sectSizeLINK);
addr += PAGE_SIZE) {
pmap_enter(kernel_pmap, addr, addr>>12,
VM_PROT_READ|VM_PROT_WRITE,
VM_WIMG_USE_DEFAULT, TRUE);
}
pmap_enter(kernel_pmap, &sharedPage, (unsigned int)&sharedPage >> 12,
VM_PROT_READ|VM_PROT_WRITE,
VM_WIMG_USE_DEFAULT, TRUE);
pmap_enter(kernel_pmap, &lowGlo, (unsigned int)&lowGlo >> 12,
VM_PROT_READ|VM_PROT_WRITE,
VM_WIMG_USE_DEFAULT, TRUE);
for(addr = trunc_page_32(end); addr < round_page_32(static_memory_end); addr += PAGE_SIZE) {
pmap_enter(kernel_pmap, addr, addr>>12,
VM_PROT_READ|VM_PROT_WRITE,
VM_WIMG_USE_DEFAULT, TRUE);
}
MapUserAddressSpaceInit();
hw_start_trans();
#if 0
GratefulDebInit((bootBumbleC *)&(args->Video));
#endif
printf_init();
panic_init();
PE_init_kprintf(TRUE);
kprintf("kprintf initialized\n");
serialmode = 0;
if(PE_parse_boot_arg("serial", &serialmode)) {
kprintf("Serial mode specified: %08X\n", serialmode);
}
if(serialmode & 1) {
(void)switch_to_serial_console();
disableConsoleOutput = FALSE;
}
kprintf("max_mem: %ld M\n", (unsigned long)(max_mem >> 20));
kprintf("version_variant = %s\n", version_variant);
kprintf("version = %s\n\n", version);
__asm__ ("mfpvr %0" : "=r" (pvr));
kprintf("proc version = %08x\n", pvr);
if(per_proc_info[0].pf.Available & pf64Bit) {
xhid0 = hid0get64();
if(xhid0 & (1ULL << (63 - 19))) kprintf("Time base is externally clocked\n");
else kprintf("Time base is internally clocked\n");
}
taproot_size = PE_init_taproot(&taproot_addr);
if(taproot_size) {
kprintf("TapRoot card configured to use vaddr = %08X, size = %08X\n", taproot_addr, taproot_size);
bcopy_nc((void *)version, (void *)(taproot_addr + 16), strlen(version));
__asm__ volatile("eieio");
xtaproot = (unsigned int *)taproot_addr;
xtaproot[0] = 1;
__asm__ volatile("eieio");
}
PE_create_console();
PE_init_printf(FALSE);
#if DEBUG
printf("\n\n\nThis program was compiled using gcc %d.%d for powerpc\n",
__GNUC__,__GNUC_MINOR__);
{
unsigned int pvr;
__asm__ ("mfpvr %0" : "=r" (pvr));
printf("processor version register : %08X\n", pvr);
}
kprintf("Args at %08X\n", args);
for (i = 0; i < pmap_mem_regions_count; i++) {
printf("DRAM at %08X size %08X\n",
args->PhysicalDRAM[i].base,
args->PhysicalDRAM[i].size);
}
#endif
#if DEBUG
kprintf("Mapped memory:\n");
kprintf(" exception vector: %08X, %08X - %08X\n", trunc_page_32(exception_entry),
trunc_page_32(exception_entry), round_page_32(exception_end));
kprintf(" sectTEXTB: %08X, %08X - %08X\n", trunc_page_32(sectTEXTB),
trunc_page_32(sectTEXTB), round_page_32(sectTEXTB+sectSizeTEXT));
kprintf(" sectDATAB: %08X, %08X - %08X\n", trunc_page_32(sectDATAB),
trunc_page_32(sectDATAB), round_page_32(sectDATAB+sectSizeDATA));
kprintf(" sectLINKB: %08X, %08X - %08X\n", trunc_page_32(sectLINKB),
trunc_page_32(sectLINKB), round_page_32(sectLINKB+sectSizeLINK));
kprintf(" sectKLDB: %08X, %08X - %08X\n", trunc_page_32(sectKLDB),
trunc_page_32(sectKLDB), round_page_32(sectKLDB+sectSizeKLD));
kprintf(" end: %08X, %08X - %08X\n", trunc_page_32(end),
trunc_page_32(end), static_memory_end);
#endif
return;
}
void ppc_vm_cpu_init(
struct per_proc_info *proc_info)
{
hw_setup_trans();
hw_start_trans();
}