|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * This file is used to maintain the exception save areas ! 24: * ! 25: */ ! 26: ! 27: #include <cpus.h> ! 28: #include <debug.h> ! 29: #include <mach_kgdb.h> ! 30: #include <mach_vm_debug.h> ! 31: ! 32: #include <kern/thread.h> ! 33: #include <mach/vm_attributes.h> ! 34: #include <mach/vm_param.h> ! 35: #include <vm/vm_kern.h> ! 36: #include <vm/vm_map.h> ! 37: #include <vm/vm_page.h> ! 38: #include <mach/ppc/thread_status.h> ! 39: #include <kern/spl.h> ! 40: #include <kern/simple_lock.h> ! 41: ! 42: #include <kern/misc_protos.h> ! 43: #include <ppc/misc_protos.h> ! 44: #include <ppc/proc_reg.h> ! 45: #include <ppc/mem.h> ! 46: #include <ppc/pmap.h> ! 47: #include <ppc/pmap_internals.h> ! 48: #include <ppc/Firmware.h> ! 49: #include <ppc/mappings.h> ! 50: #include <ppc/exception.h> ! 51: #include <ppc/savearea.h> ! 52: #include <ddb/db_output.h> ! 53: ! 54: ! 55: extern struct Saveanchor saveanchor; /* Aliged savearea anchor */ ! 56: unsigned int debsave0 = 0; /* Debug flag */ ! 57: unsigned int backchain = 0; /* Debug flag */ ! 58: ! 59: /* ! 60: * These routines keep track of exception save areas and keeps the count within specific limits. If there are ! 61: * too few, more are allocated, too many, and they are released. This savearea is where the PCBs are ! 62: * stored. They never span a page boundary and are referenced by both virtual and real addresses. ! 63: * Within the interrupt vectors, the real address is used because at that level, no exceptions ! 64: * can be tolerated. Save areas can be dynamic or permanent. Permanant saveareas are allocated ! 65: * at boot time and must be in place before any type of exception occurs. These are never released, ! 66: * and the number is based upon some arbitrary (yet to be determined) amount times the number of ! 67: * processors. This represents the minimum number required to process a total system failure without ! 68: * destroying valuable and ever-so-handy system debugging information. ! 69: * ! 70: * ! 71: */ ! 72: ! 73: /* ! 74: * This routine allocates a save area. It checks if enough are available. ! 75: * If not, it allocates upward to the target free count. ! 76: * Then, it allocates one and returns it. ! 77: */ ! 78: ! 79: ! 80: ! 81: struct savearea *save_alloc(void) { /* Reserve a save area */ ! 82: ! 83: kern_return_t retr; ! 84: savectl *sctl; /* Previous and current save pages */ ! 85: vm_offset_t vaddr, paddr; ! 86: struct savearea *newbaby; ! 87: ! 88: if(saveanchor.savecount <= (saveanchor.saveneed - saveanchor.saveneghyst)) { /* Start allocating if we drop too far */ ! 89: while(saveanchor.savecount < saveanchor.saveneed) { /* Keep adding until the adjustment is done */ ! 90: ! 91: ! 92: retr = kmem_alloc_wired(kernel_map, &vaddr, PAGE_SIZE); /* Find a virtual address to use */ ! 93: ! 94: if(retr != KERN_SUCCESS) { /* Did we get some memory? */ ! 95: panic("Whoops... Not a bit of wired memory left for saveareas\n"); ! 96: } ! 97: ! 98: paddr = pmap_extract(kernel_pmap, vaddr); /* Get the physical */ ! 99: ! 100: bzero((void *)vaddr, PAGE_SIZE); /* Clear it all to zeros */ ! 101: sctl = (savectl *)(vaddr+PAGE_SIZE-sizeof(savectl)); /* Point to the control area of the new page */ ! 102: sctl->sac_alloc = sac_empty; /* Mark all entries free */ ! 103: sctl->sac_vrswap = (unsigned int)vaddr ^ (unsigned int)paddr; /* Form mask to convert V to R and vice versa */ ! 104: ! 105: sctl->sac_flags |= 0x0000EE00; /* (TEST/DEBUG) */ ! 106: ! 107: if(!save_queue(paddr)) { /* Add the new ones to the free savearea list */ ! 108: panic("Arrgghhhh, time out trying to lock the savearea anchor during upward adjustment\n"); ! 109: } ! 110: } ! 111: } ! 112: ! 113: newbaby = save_get(); /* Get a savearea and return it */ ! 114: if(!((unsigned int)newbaby & 0xFFFFF000)) { /* Whoa... None left??? No, way, no can do... */ ! 115: panic("No saveareas?!?!?! No way! Can't happen! Nuh-uh... I'm dead, done for, kaput...\n"); ! 116: } ! 117: ! 118: return newbaby; /* Bye-bye baby... */ ! 119: ! 120: } ! 121: ! 122: ! 123: /* ! 124: * This routine releases a save area to the free queue. If after that, we have more than our maximum target, ! 125: * we start releasing what we can until we hit the normal target. ! 126: */ ! 127: ! 128: ! 129: ! 130: void save_release(struct savearea *save) { /* Release a save area */ ! 131: ! 132: savectl *csave; /* The just released savearea block */ ! 133: ! 134: save_ret(save); /* Return a savearea to the free list */ ! 135: ! 136: if(saveanchor.savecount > (saveanchor.saveneed + saveanchor.saveposhyst)) { /* Start releasing if we have to many */ ! 137: csave = (savectl *)42; /* Start with some nonzero garbage */ ! 138: while((unsigned int)csave && (saveanchor.savecount > saveanchor.saveneed)) { /* Keep removing until the adjustment is done */ ! 139: ! 140: csave = save_dequeue(); /* Find and dequeue one that is all empty */ ! 141: ! 142: if((unsigned int)csave & 1) { /* Did we timeout trying to get the lock? */ ! 143: panic("Arrgghhhh, time out trying to lock the savearea anchor during downward adjustment\n"); ! 144: return; ! 145: } ! 146: ! 147: if((unsigned int)csave) kmem_free(kernel_map, (vm_offset_t) csave, PAGE_SIZE); /* Release the page if we found one */ ! 148: } ! 149: } ! 150: return; ! 151: ! 152: } ! 153: ! 154: ! 155: /* ! 156: * This routine prints the free savearea block chain for debugging. ! 157: */ ! 158: ! 159: ! 160: ! 161: void save_free_dump(void) { /* Dump the free chain */ ! 162: ! 163: unsigned int *dsv, omsr; ! 164: savectl *dsc; ! 165: ! 166: dsv = save_deb(&omsr); /* Get the virtual of the first and disable interrupts */ ! 167: ! 168: while(dsv) { /* Do 'em all */ ! 169: dsc=(savectl *)((unsigned int)dsv+4096-sizeof(savectl)); /* Point to the control area */ ! 170: // printf("%08X %08X: nxt=%08X; alloc=%08X; flags=%08X\n", dsv, /* Print it all out */ ! 171: // ((unsigned int)dsv)^(dsc->sac_vrswap), dsc->sac_next, dsc->sac_alloc, dsc->sac_flags); ! 172: dsv=(unsigned int *)(((unsigned int) dsc->sac_next)^(dsc->sac_vrswap)); /* On to the next, virtually */ ! 173: ! 174: } ! 175: __asm__ volatile ("mtmsr %0" : : "r" (omsr)); /* Restore the interruption mask */ ! 176: return; ! 177: } ! 178: ! 179: /* ! 180: * This routine prints the free savearea block chain for debugging. ! 181: */ ! 182: ! 183: ! 184: ! 185: void DumpTheSave(struct savearea *save) { /* Dump the free chain */ ! 186: ! 187: unsigned int *r; ! 188: ! 189: printf("savearea at %08X\n", save); ! 190: printf(" srrs: %08X %08X\n", save->save_srr0, save->save_srr1); ! 191: printf(" cr, xer, lr: %08X %08X %08X\n", save->save_cr, save->save_xer, save->save_lr); ! 192: printf("ctr, dar, dsisr: %08X %08X %08X\n", save->save_ctr, save->save_dar, save->save_dsisr); ! 193: printf(" space, copyin: %08X %08X\n", save->save_space, save->save_sr_copyin); ! 194: r=&save->save_r0; ! 195: printf(" regs: %08X %08X %08X %08X %08X %08X %08X %08X\n", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); ! 196: printf(" %08X %08X %08X %08X %08X %08X %08X %08X\n", r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]); ! 197: printf(" %08X %08X %08X %08X %08X %08X %08X %08X\n", r[16], r[17], r[18], r[19], r[20], r[21], r[22], r[23]); ! 198: printf(" %08X %08X %08X %08X %08X %08X %08X %08X\n", r[24], r[25], r[29], r[27], r[28], r[29], r[30], r[31]); ! 199: r=(unsigned int *)&save->save_fp0; ! 200: printf(" floats: %08X%08X %08X%08X %08X%08X %08X%08X\n", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); ! 201: printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]); ! 202: printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r[16], r[17], r[18], r[19], r[20], r[21], r[22], r[23]); ! 203: printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r[24], r[25], r[29], r[27], r[28], r[29], r[30], r[31]); ! 204: printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r[32], r[33], r[34], r[35], r[36], r[37], r[38], r[39]); ! 205: printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r[40], r[41], r[42], r[43], r[44], r[45], r[46], r[47]); ! 206: printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r[48], r[49], r[50], r[51], r[52], r[53], r[54], r[55]); ! 207: printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r[56], r[57], r[58], r[59], r[60], r[61], r[62], r[63]); ! 208: r=&save->save_sr0; ! 209: printf(" srs: %08X %08X %08X %08X %08X %08X %08X %08X\n", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); ! 210: printf(" %08X %08X %08X %08X %08X %08X %08X %08X\n", r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]); ! 211: printf("prev, phys, act: %08X %08X %08X\n", save->save_prev, save->save_phys, save->save_act); ! 212: printf(" flags: %08X\n", save->save_flags); ! 213: return; ! 214: } ! 215: ! 216: ! 217: ! 218: ! 219: /* ! 220: * Dumps out savearea and stack backchains ! 221: */ ! 222: ! 223: void DumpBackChain(struct savearea *save) { /* Prints out back chains */ ! 224: ! 225: unsigned int *r; ! 226: savearea *sv; ! 227: ! 228: if(!backchain) return; ! 229: printf("Proceeding back from savearea at %08X:\n", save); ! 230: sv=save; ! 231: while(sv) { ! 232: printf(" curr=%08X; prev=%08X; stack=%08X\n", sv, sv->save_prev, sv->save_r1); ! 233: sv=sv->save_prev; ! 234: } ! 235: return; ! 236: } ! 237: ! 238: ! 239: ! 240:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.