Annotation of XNU/osfmk/ppc/savearea.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.