/* * MMU_init_hw does the chip-specific initialization of the MMU hardware. */ void __init MMU_init_hw(void) { /* * The Zone Protection Register (ZPR) defines how protection will * be applied to every page which is a member of a given zone. At * present, we utilize only two of the 4xx's zones. * The zone index bits (of ZSEL) in the PTE are used for software * indicators, except the LSB. For user access, zone 1 is used, * for kernel access, zone 0 is used. We set all but zone 1 * to zero, allowing only kernel access as indicated in the PTE. * For zone 1, we set a 01 binary (a value of 10 will not work) * to allow user access as indicated in the PTE. This also allows * kernel access as indicated in the PTE. */ mtspr(SPRN_ZPR, 0x10000000); flush_instruction_cache(); /* * Set up the real-mode cache parameters for the exception vector * handlers (which are run in real-mode). */ mtspr(SPRN_DCWR, 0x00000000); /* All caching is write-back */ /* * Cache instruction and data space where the exception * vectors and the kernel live in real-mode. */ mtspr(SPRN_DCCR, 0xF0000000); /* 512 MB of data space at 0x0. */ mtspr(SPRN_ICCR, 0xF0000000); /* 512 MB of instr. space at 0x0. */ }
Val _lib7_runtime_make_codechunk_executable (Task* task, Val arg) { //======================================= // // Mythryl type: (rw_vector_of_one_byte_unts::Rw_Vector, Int) -> (Chunk -> Chunk) // The Int is the entrypoint offset within the bytevector of executable machine code -- currently always zero in practice. // // Turn a previously constructed machine-code bytvector into a closure. // This requires that we flush the I-cache. (This is a no-op on intel32.) // // This fn gets bound as make_executable in: // // src/lib/compiler/execution/code-segments/code-segment.pkg Val seq = GET_TUPLE_SLOT_AS_VAL( arg, 0 ); int entrypoint = GET_TUPLE_SLOT_AS_INT( arg, 1 ); // In practice entrypoint is currently always zero. char* code = GET_VECTOR_DATACHUNK_AS( char*, seq ); Val_Sized_Unt nbytes /* This variable is unused on some platforms, so suppress 'unused var' compiler warning: */ __attribute__((unused)) = GET_VECTOR_LENGTH( seq ); flush_instruction_cache( code, nbytes ); // flush_instruction_cache is a no-op on intel32 // flush_instruction_cache def in src/c/h/flush-instruction-cache-system-dependent.h Val result; REC_ALLOC1(task, result, PTR_CAST( Val, code + entrypoint)); return result; }
void dpm_idle(void) { unsigned long flags; struct dpm_idle_parms *idle_parms = &dpm_idle_parms; struct dpm_opt *idle_task_opt, *idle_opt; current->dpm_state = DPM_NO_STATE; dpm_set_os(DPM_IDLE_TASK_STATE); dpm_md_idle_set_parms(&idle_parms->md); #ifdef EXTREME_WORST_CASE flush_instruction_cache(); flush_dcache_all(); local_flush_tlb_all(); #endif critical_save_and_cli(flags); if (!current->need_resched) { incr_stat(idles); stat_start_time(idle_parms); if (!dpm_enabled) { basic_idle(idle_parms); } else if (dpm_active_state != DPM_IDLE_TASK_STATE) { incr_stat(interrupted_idles); } else { idle_task_opt = dpm_active_policy-> classes[DPM_IDLE_TASK_STATE]->opt; idle_opt = dpm_active_policy-> classes[DPM_IDLE_STATE]->opt; if ((dpm_active_opt != idle_task_opt) || (idle_task_opt == idle_opt) || dpm_trylock()) { quick_idle(idle_parms); } else { dpm_unlock(); full_idle(idle_parms, idle_task_opt, idle_opt); } } latency_stats(idle_parms); } critical_restore_flags(flags); }
void __init MMU_init_hw(void) { mtspr(SPRN_ZPR, 0x10000000); flush_instruction_cache(); mtspr(SPRN_DCWR, 0x00000000); mtspr(SPRN_DCCR, 0xFFFF0000); mtspr(SPRN_ICCR, 0xFFFF0000); }
unsigned long load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp) { char *cp, ch; int timer = 0, zimage_size; unsigned long initrd_size; /* First, capture the embedded board information. Then * initialize the serial console port. */ embed_config(&bp); #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) com_port = serial_init(0, bp); #endif /* Grab some space for the command line and board info. Since * we no longer use the ELF header, but it was loaded, grab * that space. */ #ifdef CONFIG_MBX /* Because of the way the MBX loads the ELF image, we can't * tell where we started. We read a magic variable from the NVRAM * that gives us the intermediate buffer load address. */ load_addr = *(uint *)0xfa000020; load_addr += 0x10000; /* Skip ELF header */ #endif /* copy board data */ if (bp) memcpy(hold_residual,bp,sizeof(bd_t)); /* Set end of memory available to us. It is always the highest * memory address provided by the board information. */ end_avail = (char *)(bp->bi_memsize); puts("\nloaded at: "); puthex(load_addr); puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n"); if ( (unsigned long)load_addr != (unsigned long)&start ) { puts("relocated to: "); puthex((unsigned long)&start); puts(" "); puthex((unsigned long)((unsigned long)&start + (4*num_words))); puts("\n"); } if ( bp ) { puts("board data at: "); puthex((unsigned long)bp); puts(" "); puthex((unsigned long)((unsigned long)bp + sizeof(bd_t))); puts("\nrelocated to: "); puthex((unsigned long)hold_residual); puts(" "); puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t))); puts("\n"); } /* * We link ourself to an arbitrary low address. When we run, we * relocate outself to that address. __image_being points to * the part of the image where the zImage is. -- Tom */ zimage_start = (char *)(unsigned long)(&__image_begin); zimage_size = (unsigned long)(&__image_end) - (unsigned long)(&__image_begin); initrd_size = (unsigned long)(&__ramdisk_end) - (unsigned long)(&__ramdisk_begin); /* * The zImage and initrd will be between start and _end, so they've * already been moved once. We're good to go now. -- Tom */ puts("zimage at: "); puthex((unsigned long)zimage_start); puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n"); if ( initrd_size ) { puts("initrd at: "); puthex((unsigned long)(&__ramdisk_begin)); puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n"); } /* * setup avail_ram - this is the first part of ram usable * by the uncompress code. Anything after this program in RAM * is now fair game. -- Tom */ avail_ram = (char *)PAGE_ALIGN((unsigned long)_end); puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); puthex((unsigned long)end_avail); puts("\n"); puts("\nLinux/PPC load: "); cp = cmd_line; /* This is where we try and pick the right command line for booting. * If we were given one at compile time, use it. It Is Right. * If we weren't, see if we have a ramdisk. If so, thats root. * When in doubt, give them the netroot (root=/dev/nfs rw) -- Tom */ #ifdef CONFIG_CMDLINE_BOOL memcpy (cmd_line, compiled_string, sizeof(compiled_string)); #else if ( initrd_size ) memcpy (cmd_line, ramroot_string, sizeof(ramroot_string)); else memcpy (cmd_line, netroot_string, sizeof(netroot_string)); #endif while ( *cp ) putc(*cp++); while (timer++ < 5*1000) { if (tstc()) { while ((ch = getc()) != '\n' && ch != '\r') { if (ch == '\b' || ch == '\177') { if (cp != cmd_line) { cp--; puts("\b \b"); } } else if (ch == '\030' /* ^x */ || ch == '\025') { /* ^u */ while (cp != cmd_line) { cp--; puts("\b \b"); } } else { *cp++ = ch; putc(ch); } } break; /* Exit 'timer' loop */ } udelay(1000); /* 1 msec */ } *cp = 0; puts("\nUncompressing Linux..."); gunzip(0, 0x400000, zimage_start, &zimage_size); flush_instruction_cache(); puts("done.\n"); { struct bi_record *rec; unsigned long initrd_loc; unsigned long rec_loc = _ALIGN((unsigned long)(zimage_size) + (1 << 20) - 1, (1 << 20)); rec = (struct bi_record *)rec_loc; /* We need to make sure that the initrd and bi_recs do not * overlap. */ if ( initrd_size ) { initrd_loc = (unsigned long)(&__ramdisk_begin); /* If the bi_recs are in the middle of the current * initrd, move the initrd to the next MB * boundary. */ if ((rec_loc > initrd_loc) && ((initrd_loc + initrd_size) > rec_loc)) { initrd_loc = _ALIGN((unsigned long)(zimage_size) + (2 << 20) - 1, (2 << 20)); memmove((void *)initrd_loc, &__ramdisk_begin, initrd_size); puts("initrd moved: "); puthex(initrd_loc); puts(" "); puthex(initrd_loc + initrd_size); puts("\n"); } } rec->tag = BI_FIRST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); rec->tag = BI_CMD_LINE; memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1); rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1; rec = (struct bi_record *)((unsigned long)rec + rec->size); if ( initrd_size ) { rec->tag = BI_INITRD; rec->data[0] = initrd_loc; rec->data[1] = initrd_size; rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); } rec->tag = BI_LAST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); } puts("Now booting the kernel\n"); #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) serial_close(com_port); #endif return (unsigned long)hold_residual; }
static void read_heap ( // ========= // Inbuf* bp, Heap_Header* header, Task* task, Val* externs ){ Heap* heap = task->heap; Sib_Header* sib_headers; Sib_Header* p; Sib_Header* q; int sib_headers_bytesize; int i, j, k; long prevSzB[MAX_PLAIN_SIBS], size; Sibid* oldBOOK2SIBID; Punt addrOffset[MAX_AGEGROUPS][MAX_PLAIN_SIBS]; Hugechunk_Quire_Relocation_Info* boRelocInfo; Addresstable* boRegionTable; // Allocate a book_to_sibid__global for the imported // heap image's address space: // #ifdef TWO_LEVEL_MAP #error two level map not supported #else oldBOOK2SIBID = MALLOC_VEC (Sibid, BOOK2SIBID_TABLE_SIZE_IN_SLOTS); #endif // Read in the hugechunk region descriptors // for the old address space: // { int size; Hugechunk_Quire_Header* boRgnHdr; boRegionTable = make_address_hashtable(LOG2_BOOK_BYTESIZE+1, header->hugechunk_quire_count); size = header->hugechunk_quire_count * sizeof(Hugechunk_Quire_Header); boRgnHdr = (Hugechunk_Quire_Header*) MALLOC (size); heapio__read_block( bp, boRgnHdr, size ); boRelocInfo = MALLOC_VEC(Hugechunk_Quire_Relocation_Info, header->hugechunk_quire_count); for (i = 0; i < header->hugechunk_quire_count; i++) { set_book2sibid_entries_for_range(oldBOOK2SIBID, (Val*)(boRgnHdr[i].base_address), BOOKROUNDED_BYTESIZE(boRgnHdr[i].bytesize), HUGECHUNK_DATA_SIBID(1) ); oldBOOK2SIBID[GET_BOOK_CONTAINING_POINTEE(boRgnHdr[i].base_address)] = HUGECHUNK_RECORD_SIBID(MAX_AGEGROUPS); boRelocInfo[i].first_ram_quantum = boRgnHdr[i].first_ram_quantum; boRelocInfo[i].page_count = (boRgnHdr[i].bytesize - (boRgnHdr[i].first_ram_quantum - boRgnHdr[i].base_address)) >> LOG2_HUGECHUNK_RAM_QUANTUM_IN_BYTES; boRelocInfo[i].hugechunk_page_to_hugechunk = MALLOC_VEC(Hugechunk_Relocation_Info*, boRelocInfo[i].page_count); for (j = 0; j < boRelocInfo[i].page_count; j++) { // boRelocInfo[i].hugechunk_page_to_hugechunk[j] = NULL; } addresstable_insert (boRegionTable, boRgnHdr[i].base_address, &(boRelocInfo[i])); } FREE (boRgnHdr); } // Read the sib headers: // sib_headers_bytesize = header->active_agegroups * TOTAL_SIBS * sizeof( Sib_Header ); // sib_headers = (Sib_Header*) MALLOC( sib_headers_bytesize ); // heapio__read_block( bp, sib_headers, sib_headers_bytesize ); for (i = 0; i < MAX_PLAIN_SIBS; i++) { // prevSzB[i] = task->heap_allocation_buffer_bytesize; } // Allocate the sib buffers and read in the heap image: // for (p = sib_headers, i = 0; i < header->active_agegroups; i++) { // Agegroup* age = heap->agegroup[ i ]; // Compute the space required for this agegroup, // and mark the oldBOOK2SIBID to reflect the old address space: // for (q = p, j = 0; j < MAX_PLAIN_SIBS; j++) { set_book2sibid_entries_for_range ( // oldBOOK2SIBID, (Val*) q->info.o.base_address, BOOKROUNDED_BYTESIZE( q->info.o.bytesize ), age->sib[ j ]->id ); size = q->info.o.bytesize + prevSzB[j]; if (j == RO_CONSCELL_SIB && size > 0 ){ size += 2*WORD_BYTESIZE; } age->sib[ j ]->tospace.bytesize = BOOKROUNDED_BYTESIZE( size ); prevSzB[ j ] = q->info.o.bytesize; q++; } if (set_up_tospace_sib_buffers_for_agegroup(age) == FALSE) { die ("unable to allocated space for agegroup %d\n", i+1); } if (sib_is_active( age->sib[ RW_POINTERS_SIB ] )) { // sib_is_active def in src/c/h/heap.h // make_new_coarse_inter_agegroup_pointers_map_for_agegroup (age); } // Read in the sib buffers for this agegroup // and initialize the address offset table: // for (int j = 0; j < MAX_PLAIN_SIBS; j++) { // Sib* ap = age->sib[ j ]; if (p->info.o.bytesize > 0) { addrOffset[i][j] = (Punt)(ap->tospace.start) - (Punt)(p->info.o.base_address); heapio__seek( bp, (long) p->offset ); heapio__read_block( bp, (ap->tospace.start), p->info.o.bytesize ); ap->tospace.used_end = (Val *)((Punt)(ap->tospace.start) + p->info.o.bytesize); ap->fromspace.seniorchunks_end = ap->tospace.start; } else if (sib_is_active(ap)) { ap->fromspace.seniorchunks_end = ap->tospace.start; } if (verbosity__global > 0) say("."); p++; } // Read in the hugechunk sib buffers (currently just codechunks): // for (int ilk = 0; ilk < MAX_HUGE_SIBS; ilk++) { // MAX_HUGE_SIBS def in src/c/h/sibid.h // Punt totSizeB; Hugechunk* free_chunk; Hugechunk* bdp = NULL; // Without this initialization, gcc -Wall gives a 'possible uninitialized use' warning. Hugechunk_Quire* free_quire; Hugechunk_Header* boHdrs; int boHdrSizeB; int index; Hugechunk_Quire_Relocation_Info* region; if (p->info.bo.hugechunk_quanta_count > 0) { // totSizeB = p->info.bo.hugechunk_quanta_count << LOG2_HUGECHUNK_RAM_QUANTUM_IN_BYTES; free_chunk = allocate_hugechunk_quire( heap, totSizeB ); free_quire = free_chunk->hugechunk_quire; free_quire->age_of_youngest_live_chunk_in_quire = i; set_book2sibid_entries_for_range ( // book_to_sibid__global, (Val*) free_quire, BYTESIZE_OF_QUIRE( free_quire->quire ), HUGECHUNK_DATA_SIBID( i ) ); book_to_sibid__global[ GET_BOOK_CONTAINING_POINTEE( free_quire ) ] = HUGECHUNK_RECORD_SIBID( i ); // Read in the hugechunk headers: // boHdrSizeB = p->info.bo.hugechunk_count * sizeof(Hugechunk_Header); // boHdrs = (Hugechunk_Header*) MALLOC (boHdrSizeB); // heapio__read_block (bp, boHdrs, boHdrSizeB); // Read in the hugechunks: // heapio__read_block( bp, (void *)(free_chunk->chunk), totSizeB ); // if (ilk == CODE__HUGE_SIB) { // ilk = 0 == CODE__HUGE_SIB def in src/c/h/sibid.h // flush_instruction_cache ((void *)(free_chunk->chunk), totSizeB); } // Set up the hugechunk descriptors // and per-chunk relocation info: // for (k = 0; k < p->info.bo.hugechunk_count; k++) { // // Find the region relocation info for the // chunk's region in the exported heap: // for (index = GET_BOOK_CONTAINING_POINTEE(boHdrs[k].base_address); !SIBID_ID_IS_BIGCHUNK_RECORD(oldBOOK2SIBID[index]); index--) continue; region = LOOK_UP_HUGECHUNK_REGION (boRegionTable, index); // Allocate the hugechunk record for // the chunk and link it into the list // of hugechunks for its agegroup. // bdp = allocate_a_hugechunk( free_chunk, &(boHdrs[k]), region ); bdp->next = age->hugechunks[ ilk ]; age->hugechunks[ ilk ] = bdp; ASSERT( bdp->gen == i+1 ); if (codechunk_comment_display_is_enabled__global && ilk == CODE__HUGE_SIB ){ // Dump the comment string of the code chunk. Unt8* namestring; // if ((namestring = get_codechunk_comment_string_else_null( bdp ))) { debug_say ("[%6d bytes] %s\n", bdp->bytesize, (char*)namestring); } } } if (free_chunk != bdp) { // if p->info.bo.hugechunk_count can be zero, 'bdp' value here may be bogus. XXX BUGGO FIXME. // // There was some extra space left in the region: // insert_hugechunk_in_doubly_linked_list( heap->hugechunk_freelist, free_chunk); // insert_hugechunk_in_doubly_linked_list def in src/c/h/heap.h } FREE (boHdrs); } if (verbosity__global > 0) say("."); p++; } } repair_heap (heap, oldBOOK2SIBID, addrOffset, boRegionTable, externs); // Adjust the run-time globals // that point into the heap: // *PTR_CAST( Val*, PERVASIVE_PACKAGE_PICKLE_LIST_REFCELL__GLOBAL ) = repair_word( *PTR_CAST( Val*, PERVASIVE_PACKAGE_PICKLE_LIST_REFCELL__GLOBAL ), oldBOOK2SIBID, addrOffset, boRegionTable, externs ); runtime_package__global = repair_word( runtime_package__global, oldBOOK2SIBID, addrOffset, boRegionTable, externs ); #ifdef ASM_MATH mathvec__global = repair_word (mathvec__global, oldBOOK2SIBID, addrOffset, boRegionTable, externs); #endif // Adjust the Mythryl registers // to the new address space: // ASSIGN( POSIX_INTERPROCESS_SIGNAL_HANDLER_REFCELL__GLOBAL, // repair_word ( // DEREF( POSIX_INTERPROCESS_SIGNAL_HANDLER_REFCELL__GLOBAL ), oldBOOK2SIBID, addrOffset, boRegionTable, externs ) ); task->argument = repair_word( task->argument, oldBOOK2SIBID, addrOffset, boRegionTable, externs ); task->fate = repair_word( task->fate, oldBOOK2SIBID, addrOffset, boRegionTable, externs ); task->current_closure = repair_word( task->current_closure, oldBOOK2SIBID, addrOffset, boRegionTable, externs ); task->program_counter = repair_word( task->program_counter, oldBOOK2SIBID, addrOffset, boRegionTable, externs ); task->link_register = repair_word (task->link_register, oldBOOK2SIBID, addrOffset, boRegionTable, externs ); task->exception_fate = repair_word( task->exception_fate, oldBOOK2SIBID, addrOffset, boRegionTable, externs ); task->current_thread = repair_word( task->current_thread, oldBOOK2SIBID, addrOffset, boRegionTable, externs ); task->callee_saved_registers[0] = repair_word( task->callee_saved_registers[0], oldBOOK2SIBID, addrOffset, boRegionTable, externs ); task->callee_saved_registers[1] = repair_word( task->callee_saved_registers[1], oldBOOK2SIBID, addrOffset, boRegionTable, externs ); task->callee_saved_registers[2] = repair_word( task->callee_saved_registers[2], oldBOOK2SIBID, addrOffset, boRegionTable, externs ); // Release storage: // for (i = 0; i < header->hugechunk_quire_count; i++) { // Hugechunk_Relocation_Info* p; for (p = NULL, j = 0; j < boRelocInfo[i].page_count; j++) { if ((boRelocInfo[i].hugechunk_page_to_hugechunk[j] != NULL) && (boRelocInfo[i].hugechunk_page_to_hugechunk[j] != p)) { FREE (boRelocInfo[i].hugechunk_page_to_hugechunk[j]); p = boRelocInfo[i].hugechunk_page_to_hugechunk[j]; } } } free_address_table( boRegionTable, FALSE ); FREE( boRelocInfo ); FREE( sib_headers ); FREE( oldBOOK2SIBID ); // Reset the tospace.swept_end pointers: // for (int i = 0; i < heap->active_agegroups; i++) { // Agegroup* age = heap->agegroup[i]; // for (int j = 0; j < MAX_PLAIN_SIBS; j++) { // Sib* ap = age->sib[ j ]; // if (sib_is_active(ap)) { // sib_is_active def in src/c/h/heap.h // ap->tospace.swept_end = ap->tospace.used_end; } } } } // fun read_heap
unsigned long decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, RESIDUAL *residual, void *OFW_interface) { int timer; extern unsigned long start; char *cp, ch; unsigned long i; BATU *u; BATL *l; unsigned long TotalMemory; unsigned long orig_MSR; int dev_handle; int mem_info[2]; int res, size; unsigned char board_type; unsigned char base_mod; lines = 25; cols = 80; orig_x = 0; orig_y = 24; /* * IBM's have the MMU on, so we have to disable it or * things get really unhappy in the kernel when * trying to setup the BATs with the MMU on * -- Cort */ flush_instruction_cache(); _put_HID0(_get_HID0() & ~0x0000C000); _put_MSR((orig_MSR = _get_MSR()) & ~0x0030); #if defined(CONFIG_SERIAL_CONSOLE) com_port = (struct NS16550 *)NS16550_init(0); #endif /* CONFIG_SERIAL_CONSOLE */ vga_init(0xC0000000); if (residual) { /* Is this Motorola PPCBug? */ if ((1 & residual->VitalProductData.FirmwareSupports) && (1 == residual->VitalProductData.FirmwareSupplier)) { board_type = inb(0x800) & 0xF0; /* If this is genesis 2 board then check for no * keyboard controller and more than one processor. */ if (board_type == 0xe0) { base_mod = inb(0x803); /* if a MVME2300/2400 or a Sitka then no keyboard */ if((base_mod == 0xFA) || (base_mod == 0xF9) || (base_mod == 0xE1)) { keyb_present = 0; /* no keyboard */ } } } memcpy(hold_residual,residual,sizeof(RESIDUAL)); } else { /* Assume 32M in the absence of more info... */ TotalMemory = 0x02000000; /* * This is a 'best guess' check. We want to make sure * we don't try this on a PReP box without OF * -- Cort */ while (OFW_interface && ((unsigned long)OFW_interface < 0x10000000) ) { /* The MMU needs to be on when we call OFW */ _put_MSR(orig_MSR); of_init(OFW_interface); /* get handle to memory description */ res = of_finddevice("/memory@0", &dev_handle); // puthex(res); puts("\n"); if (res) break; /* get the info */ // puts("get info = "); res = of_getprop(dev_handle, "reg", mem_info, sizeof(mem_info), &size); // puthex(res); puts(", info = "); puthex(mem_info[0]); // puts(" "); puthex(mem_info[1]); puts("\n"); if (res) break; TotalMemory = mem_info[1]; break; } hold_residual->TotalMemory = TotalMemory; residual = hold_residual; /* Turn MMU back off */ _put_MSR(orig_MSR & ~0x0030); } /* assume the chunk below 8M is free */ end_avail = (char *)0x00800000; /* tell the user where we were loaded at and where we * were relocated to for debugging this process */ puts("loaded at: "); puthex(load_addr); puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n"); if ( (unsigned long)load_addr != (unsigned long)&start ) { puts("relocated to: "); puthex((unsigned long)&start); puts(" "); puthex((unsigned long)((unsigned long)&start + (4*num_words))); puts("\n"); } if ( residual ) { puts("board data at: "); puthex((unsigned long)residual); puts(" "); puthex((unsigned long)((unsigned long)residual + sizeof(RESIDUAL))); puts("\n"); puts("relocated to: "); puthex((unsigned long)hold_residual); puts(" "); puthex((unsigned long)((unsigned long)hold_residual + sizeof(RESIDUAL))); puts("\n"); } /* we have to subtract 0x10000 here to correct for objdump including the size of the elf header which we strip -- Cort */ zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET); zimage_size = ZIMAGE_SIZE; if ( INITRD_OFFSET ) initrd_start = load_addr - 0x10000 + INITRD_OFFSET; else initrd_start = 0; initrd_end = INITRD_SIZE + initrd_start; /* * Find a place to stick the zimage and initrd and * relocate them if we have to. -- Cort */ avail_ram = (char *)PAGE_ALIGN((unsigned long)_end); puts("zimage at: "); puthex((unsigned long)zimage_start); puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n"); if ( (unsigned long)zimage_start <= 0x00800000 ) { memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size ); zimage_start = (char *)avail_ram; puts("relocated to: "); puthex((unsigned long)zimage_start); puts(" "); puthex((unsigned long)zimage_size+(unsigned long)zimage_start); puts("\n"); avail_ram += zimage_size; } /* relocate initrd */ if ( initrd_start ) { puts("initrd at: "); puthex(initrd_start); puts(" "); puthex(initrd_end); puts("\n"); if ( (unsigned long)initrd_start <= 0x00800000 ) { memcpy( (void *)avail_ram, (void *)initrd_start, initrd_end-initrd_start ); puts("relocated to: "); initrd_end = (unsigned long) avail_ram + (initrd_end-initrd_start); initrd_start = (unsigned long)avail_ram; puthex((unsigned long)initrd_start); puts(" "); puthex((unsigned long)initrd_end); puts("\n"); } avail_ram = (char *)PAGE_ALIGN((unsigned long)initrd_end); } avail_ram = (char *)0x00400000; end_avail = (char *)0x00800000; puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); puthex((unsigned long)end_avail); puts("\n"); if (keyb_present) CRT_tstc(); /* Forces keyboard to be initialized */ puts("\nLinux/PPC load: "); timer = 0; cp = cmd_line; memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); while ( *cp ) putc(*cp++); while (timer++ < 5*1000) { if (tstc()) { while ((ch = getc()) != '\n' && ch != '\r') { if (ch == '\b') { if (cp != cmd_line) { cp--; puts("\b \b"); } } else { *cp++ = ch; putc(ch); } } break; /* Exit 'timer' loop */ } udelay(1000); /* 1 msec */ } *cp = 0; puts("\n"); puts("Uncompressing Linux..."); gunzip(0, 0x400000, zimage_start, &zimage_size); puts("done.\n"); { struct bi_record *rec; rec = (struct bi_record *)PAGE_ALIGN(zimage_size); rec->tag = BI_FIRST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); rec->tag = BI_BOOTLOADER_ID; memcpy( (void *)rec->data, "prepboot", 9); rec->size = sizeof(struct bi_record) + 8 + 1; rec = (struct bi_record *)((unsigned long)rec + rec->size); rec->tag = BI_MACHTYPE; rec->data[0] = _MACH_prep; rec->data[1] = 1; rec->size = sizeof(struct bi_record) + sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); rec->tag = BI_CMD_LINE; memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1); rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1; rec = (struct bi_record *)((ulong)rec + rec->size); rec->tag = BI_LAST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); } puts("Now booting the kernel\n"); return (unsigned long)hold_residual; }
/* * MMU_init_hw does the chip-specific initialization of the MMU hardware. */ void __init MMU_init_hw(void) { flush_instruction_cache(); }
void __init MMU_init_hw(void) { ppc44x_update_tlb_hwater(); flush_instruction_cache(); }