#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/boot.h>
#include <ppc/misc_protos.h>
#include <ppc/pmap.h>
#include <ppc/pmap_internals.h>
#include <ppc/mem.h>
#include <ppc/exception.h>
#include <ppc/gdb_defs.h>
#include <ppc/POWERMAC/video_board.h>
#include <ppc/POWERMAC/video_pdm.h>
#ifdef __MACHO__
#include <mach-o/mach_header.h>
#endif
extern unsigned int intstack[];
extern unsigned int intstack_top_ss;
#if MACH_KGDB
extern unsigned int gdbstackptr;
extern unsigned int gdbstack_top_ss;
#endif
extern vm_offset_t boot_start;
extern vm_size_t boot_size;
extern vm_offset_t boot_region_desc;
extern vm_size_t boot_region_count;
extern int boot_thread_state_flavor;
extern thread_state_t boot_thread_state;
extern unsigned int boot_thread_state_count;
extern void thandler(void);
extern void ihandler(void);
extern void shandler(void);
extern void gdbhandler(void);
extern void fpu_switch(void);
extern void atomic_switch_trap(void);
struct ppc_thread_state boot_task_thread_state;
#if 1
vm_offset_t avail_start;
vm_offset_t avail_end;
#endif
unsigned int avail_remaining = 0;
vm_offset_t first_avail;
#ifdef __MACHO__
extern struct mach_header _mh_execute_header;
void *sectTEXTB;
int sectSizeTEXT;
void *sectDATAB;
int sectSizeDATA;
void *sectOBJCB;
int sectSizeOBJC;
void *sectLINKB;
int sectSizeLINK;
vm_offset_t end, etext, edata;
#define ETEXT etext
#endif
void ppc_vm_init(unsigned int memory_size, boot_args *args)
{
unsigned int htabmask;
unsigned int i;
vm_offset_t addr;
int boot_task_end_offset;
#if NCPUS > 1
const char *cpus;
#endif
printf("mem_size = %d M\n",memory_size / (1024 * 1024));
#ifdef __MACHO__
etext = (vm_offset_t) sectTEXTB + sectSizeTEXT;
edata = (vm_offset_t) sectDATAB + sectSizeDATA;
end = getlastaddr();
#endif
#ifndef __MACHO__
free_regions[free_regions_count].start =
round_page((unsigned int)&_ExceptionVectorsEnd -
(unsigned int)&_ExceptionVectorsStart);
#else
free_regions[free_regions_count].start = round_page((unsigned int)&_ExceptionVectorsEnd) + 4096;
#endif
first_avail = round_page(args->first_avail);
for (i = 0; i < args->kern_info.region_count; i++) {
#if MACH_KDB
if (args->kern_info.regions[i].prot == VM_PROT_NONE &&
i == args->kern_info.region_count - 1) {
kern_sym_start = args->kern_info.regions[i].addr;
kern_sym_size = args->kern_info.regions[i].size;
printf("kernel symbol table at 0x%x size 0x%x\n",
kern_sym_start, kern_sym_size);
args->kern_info.regions[i].prot |=
(VM_PROT_WRITE|VM_PROT_READ);
}
#endif
#ifdef __MACHO__
if (args->kern_info.regions[i].addr == 0)
continue;
#endif
boot_region_count = args->task_info.region_count;
boot_size = 0;
boot_task_end_offset = 0;
for (i = 0; i < boot_region_count; i++) {
if (args->task_info.regions[i].mapped) {
#if DEBUG
printf("mapping virt 0x%08x to phys 0x%08x end 0x%x, prot=0x%b\n",
ppc_trunc_page(args->task_info.base_addr +
args->task_info.regions[i].offset),
ppc_trunc_page(args->task_info.base_addr +
args->task_info.regions[i].offset),
ppc_round_page(args->task_info.base_addr +
args->task_info.regions[i].offset +
args->task_info.regions[i].size),
args->task_info.regions[i].prot,
"\x10\1READ\2WRITE\3EXEC");
#endif
(void)pmap_map(
ppc_trunc_page(args->task_info.base_addr +
args->task_info.regions[i].offset),
ppc_trunc_page(args->task_info.base_addr +
args->task_info.regions[i].offset),
ppc_round_page(args->task_info.base_addr +
args->task_info.regions[i].offset +
args->task_info.regions[i].size),
args->task_info.regions[i].prot);
boot_size += args->task_info.regions[i].size;
if (boot_task_end_offset >
args->task_info.regions[i].offset) {
boot_size -= boot_task_end_offset -
args->task_info.regions[i].offset;
#if DEBUG
printf("WARNING - bootstrap overlaps regions\n");
#endif
}
boot_task_end_offset =
args->task_info.regions[i].offset +
args->task_info.regions[i].size;
}
}
if (boot_region_count) {
args->task_info.regions[boot_region_count].addr =
BOOT_STACK_BASE;
args->task_info.regions[boot_region_count].size =
BOOT_STACK_SIZE;
args->task_info.regions[boot_region_count].mapped = FALSE;
boot_region_count++;
boot_start = args->task_info.base_addr;
boot_region_desc = (vm_offset_t) args->task_info.regions;
boot_task_thread_state.r1 = BOOT_STACK_PTR-0x100;
boot_task_thread_state.srr0 = args->task_info.entry;
boot_task_thread_state.srr1 =
MSR_MARK_SYSCALL(MSR_EXPORT_MASK_SET);
boot_thread_state_flavor = PPC_THREAD_STATE;
boot_thread_state_count = PPC_THREAD_STATE_COUNT;
boot_thread_state =
(thread_state_t)&boot_task_thread_state;
}
}