Annotation of XNU/osfmk/ppc/savearea.c, revision 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.