Annotation of XNU/osfmk/ppc/cpu.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:  *     File:   ppc/cpu.c
        !            24:  *
        !            25:  *     cpu specific  routines
        !            26:  */
        !            27: 
        !            28: #include <kern/machine.h>
        !            29: #include <kern/misc_protos.h>
        !            30: #include <kern/thread.h>
        !            31: #include <kern/processor.h>
        !            32: #include <mach/machine.h>
        !            33: #include <mach/processor_info.h>
        !            34: #include <mach/mach_types.h>
        !            35: #include <ppc/proc_reg.h>
        !            36: #include <ppc/misc_protos.h>
        !            37: #include <ppc/machine_routines.h>
        !            38: #include <ppc/machine_cpu.h>
        !            39: #include <ppc/exception.h>
        !            40: #include <pexpert/pexpert.h>
        !            41: #include <pexpert/ppc/powermac.h>
        !            42: 
        !            43: /* TODO: BOGUS TO BE REMOVED */
        !            44: int real_ncpus = 1;
        !            45: 
        !            46: int wncpu = NCPUS;
        !            47: resethandler_t resethandler_target;
        !            48: 
        !            49: #define MMCR0_SUPPORT_MASK 0xf83f1fff
        !            50: #define MMCR1_SUPPORT_MASK 0xffc00000
        !            51: #define MMCR2_SUPPORT_MASK 0x80000000
        !            52: 
        !            53: extern int debugger_pending[NCPUS];    
        !            54: extern int debugger_is_slave[NCPUS];
        !            55: extern int debugger_holdoff[NCPUS];
        !            56: extern int debugger_sync;
        !            57: 
        !            58: 
        !            59: kern_return_t
        !            60: cpu_control(
        !            61:        int                     slot_num,
        !            62:        processor_info_t        info,
        !            63:        unsigned int            count)
        !            64: {
        !            65:         cpu_type_t        cpu_type;
        !            66:         cpu_subtype_t     cpu_subtype;
        !            67:        processor_pm_regs_t  perf_regs;
        !            68:        processor_control_cmd_t cmd;
        !            69:        boolean_t oldlevel;
        !            70: 
        !            71:        cpu_type = machine_slot[slot_num].cpu_type;
        !            72:        cpu_subtype = machine_slot[slot_num].cpu_subtype;
        !            73:        cmd = (processor_control_cmd_t) info;
        !            74: 
        !            75:        if (count < PROCESSOR_CONTROL_CMD_COUNT)
        !            76:          return(KERN_FAILURE);
        !            77: 
        !            78:        if ( cpu_type != cmd->cmd_cpu_type ||
        !            79:             cpu_subtype != cmd->cmd_cpu_subtype)
        !            80:          return(KERN_FAILURE);
        !            81: 
        !            82:        switch (cmd->cmd_op)
        !            83:          {
        !            84:          case PROCESSOR_PM_CLR_PMC:       /* Clear Performance Monitor Counters */
        !            85:            switch (cpu_subtype)
        !            86:              {
        !            87:              case CPU_SUBTYPE_POWERPC_604:
        !            88:                {
        !            89:                  oldlevel = ml_set_interrupts_enabled(FALSE);    /* disable interrupts */
        !            90:                  mtpmc1(0x0);
        !            91:                  mtpmc2(0x0);
        !            92:                  ml_set_interrupts_enabled(oldlevel);     /* enable interrupts */
        !            93:                  return(KERN_SUCCESS);
        !            94:                }
        !            95:              case CPU_SUBTYPE_POWERPC_604e:
        !            96:              case CPU_SUBTYPE_POWERPC_750:
        !            97:              case CPU_SUBTYPE_POWERPC_Max:
        !            98:                {
        !            99:                  oldlevel = ml_set_interrupts_enabled(FALSE);    /* disable interrupts */
        !           100:                  mtpmc1(0x0);
        !           101:                  mtpmc2(0x0);
        !           102:                  mtpmc3(0x0);
        !           103:                  mtpmc4(0x0);
        !           104:                  ml_set_interrupts_enabled(oldlevel);     /* enable interrupts */
        !           105:                  return(KERN_SUCCESS);
        !           106:                }
        !           107:              default:
        !           108:                return(KERN_FAILURE);
        !           109:              } /* cpu_subtype */
        !           110:          case PROCESSOR_PM_SET_REGS:      /* Set Performance Monitor Registors */
        !           111:            switch (cpu_subtype)
        !           112:              {
        !           113:              case CPU_SUBTYPE_POWERPC_604:
        !           114:                if (count <  (PROCESSOR_CONTROL_CMD_COUNT 
        !           115:                               + PROCESSOR_PM_REGS_COUNT_POWERPC_604))
        !           116:                  return(KERN_FAILURE);
        !           117:                else
        !           118:                  {
        !           119:                    perf_regs = (processor_pm_regs_t)cmd->cmd_pm_regs;
        !           120:                    oldlevel = ml_set_interrupts_enabled(FALSE);    /* disable interrupts */
        !           121:                    mtmmcr0(PERFMON_MMCR0(perf_regs) & MMCR0_SUPPORT_MASK);
        !           122:                    mtpmc1(PERFMON_PMC1(perf_regs));
        !           123:                    mtpmc2(PERFMON_PMC2(perf_regs));
        !           124:                    ml_set_interrupts_enabled(oldlevel);     /* enable interrupts */
        !           125:                    return(KERN_SUCCESS);
        !           126:                  }
        !           127:              case CPU_SUBTYPE_POWERPC_604e:
        !           128:              case CPU_SUBTYPE_POWERPC_750:
        !           129:                if (count <  (PROCESSOR_CONTROL_CMD_COUNT +
        !           130:                       PROCESSOR_PM_REGS_COUNT_POWERPC_750))
        !           131:                  return(KERN_FAILURE);
        !           132:                else
        !           133:                  {
        !           134:                    perf_regs = (processor_pm_regs_t)cmd->cmd_pm_regs;
        !           135:                    oldlevel = ml_set_interrupts_enabled(FALSE);    /* disable interrupts */
        !           136:                    mtmmcr0(PERFMON_MMCR0(perf_regs) & MMCR0_SUPPORT_MASK);
        !           137:                    mtpmc1(PERFMON_PMC1(perf_regs));
        !           138:                    mtpmc2(PERFMON_PMC2(perf_regs));
        !           139:                    mtmmcr1(PERFMON_MMCR1(perf_regs) & MMCR1_SUPPORT_MASK);
        !           140:                    mtpmc3(PERFMON_PMC3(perf_regs));
        !           141:                    mtpmc4(PERFMON_PMC4(perf_regs));
        !           142:                    ml_set_interrupts_enabled(oldlevel);     /* enable interrupts */
        !           143:                    return(KERN_SUCCESS);
        !           144:                  }
        !           145:              case CPU_SUBTYPE_POWERPC_Max:
        !           146:                if (count <  (PROCESSOR_CONTROL_CMD_COUNT +
        !           147:                       PROCESSOR_PM_REGS_COUNT_POWERPC_Max))
        !           148:                  return(KERN_FAILURE);
        !           149:                else
        !           150:                  {
        !           151:                    perf_regs = (processor_pm_regs_t)cmd->cmd_pm_regs;
        !           152:                    oldlevel = ml_set_interrupts_enabled(FALSE);    /* disable interrupts */
        !           153:                    mtmmcr0(PERFMON_MMCR0(perf_regs) & MMCR0_SUPPORT_MASK);
        !           154:                    mtpmc1(PERFMON_PMC1(perf_regs));
        !           155:                    mtpmc2(PERFMON_PMC2(perf_regs));
        !           156:                    mtmmcr1(PERFMON_MMCR1(perf_regs) & MMCR1_SUPPORT_MASK);
        !           157:                    mtpmc3(PERFMON_PMC3(perf_regs));
        !           158:                    mtpmc4(PERFMON_PMC4(perf_regs));
        !           159:                    mtmmcr2(PERFMON_MMCR2(perf_regs) & MMCR2_SUPPORT_MASK);
        !           160:                    ml_set_interrupts_enabled(oldlevel);     /* enable interrupts */
        !           161:                    return(KERN_SUCCESS);
        !           162:                  }
        !           163:              default:
        !           164:                return(KERN_FAILURE);
        !           165:              } /* switch cpu_subtype */
        !           166:          case PROCESSOR_PM_SET_MMCR:
        !           167:            switch (cpu_subtype)
        !           168:              {
        !           169:              case CPU_SUBTYPE_POWERPC_604:
        !           170:                if (count < (PROCESSOR_CONTROL_CMD_COUNT +
        !           171:                       PROCESSOR_PM_REGS_COUNT_POWERPC_604))
        !           172:                  return(KERN_FAILURE);
        !           173:                else
        !           174:                  {
        !           175:                    perf_regs = (processor_pm_regs_t)cmd->cmd_pm_regs;
        !           176:                    mtmmcr0(PERFMON_MMCR0(perf_regs) & MMCR0_SUPPORT_MASK);
        !           177:                    return(KERN_SUCCESS);
        !           178:                  }
        !           179:              case CPU_SUBTYPE_POWERPC_604e:
        !           180:              case CPU_SUBTYPE_POWERPC_750:
        !           181:                if (count < (PROCESSOR_CONTROL_CMD_COUNT +
        !           182:                      PROCESSOR_PM_REGS_COUNT_POWERPC_750))
        !           183:                  return(KERN_FAILURE);
        !           184:                else
        !           185:                  {
        !           186:                    perf_regs = (processor_pm_regs_t)cmd->cmd_pm_regs;
        !           187:                    oldlevel = ml_set_interrupts_enabled(FALSE);    /* disable interrupts */
        !           188:                    mtmmcr0(PERFMON_MMCR0(perf_regs) & MMCR0_SUPPORT_MASK);
        !           189:                    mtmmcr1(PERFMON_MMCR1(perf_regs) & MMCR1_SUPPORT_MASK);
        !           190:                    ml_set_interrupts_enabled(oldlevel);     /* enable interrupts */
        !           191:                    return(KERN_SUCCESS);
        !           192:                  }
        !           193:              case CPU_SUBTYPE_POWERPC_Max:
        !           194:                if (count < (PROCESSOR_CONTROL_CMD_COUNT +
        !           195:                      PROCESSOR_PM_REGS_COUNT_POWERPC_Max))
        !           196:                  return(KERN_FAILURE);
        !           197:                else
        !           198:                  {
        !           199:                    perf_regs = (processor_pm_regs_t)cmd->cmd_pm_regs;
        !           200:                    oldlevel = ml_set_interrupts_enabled(FALSE);    /* disable interrupts */
        !           201:                    mtmmcr0(PERFMON_MMCR0(perf_regs) & MMCR0_SUPPORT_MASK);
        !           202:                    mtmmcr1(PERFMON_MMCR1(perf_regs) & MMCR1_SUPPORT_MASK);
        !           203:                    mtmmcr2(PERFMON_MMCR2(perf_regs) & MMCR2_SUPPORT_MASK);
        !           204:                    ml_set_interrupts_enabled(oldlevel);     /* enable interrupts */
        !           205:                    return(KERN_SUCCESS);
        !           206:                  }
        !           207:              default:
        !           208:                return(KERN_FAILURE);
        !           209:              } /* cpu_subtype */
        !           210:          default:
        !           211:            return(KERN_FAILURE);
        !           212:          } /* switch cmd_op */
        !           213: }
        !           214: 
        !           215: kern_return_t
        !           216: cpu_info(
        !           217:        processor_flavor_t      flavor,
        !           218:        int                     slot_num,
        !           219:        processor_info_t        info,
        !           220:        unsigned int            *count)
        !           221: {
        !           222:         cpu_subtype_t     cpu_subtype;
        !           223:        processor_pm_regs_t  perf_regs;
        !           224:        boolean_t oldlevel;
        !           225: 
        !           226:        cpu_subtype = machine_slot[slot_num].cpu_subtype;
        !           227: 
        !           228:        switch (flavor)
        !           229:          {
        !           230:          case PROCESSOR_PM_REGS_INFO:
        !           231:            {
        !           232:              perf_regs = (processor_pm_regs_t) info;
        !           233: 
        !           234:              switch (cpu_subtype)
        !           235:                {
        !           236:                case CPU_SUBTYPE_POWERPC_604:
        !           237:                  {
        !           238:                    if (*count < PROCESSOR_PM_REGS_COUNT_POWERPC_604)
        !           239:                      return(KERN_FAILURE);
        !           240:              
        !           241:                    oldlevel = ml_set_interrupts_enabled(FALSE);    /* disable interrupts */
        !           242:                    PERFMON_MMCR0(perf_regs) = mfmmcr0();
        !           243:                    PERFMON_PMC1(perf_regs)  = mfpmc1();
        !           244:                    PERFMON_PMC2(perf_regs)  = mfpmc2();
        !           245:                    ml_set_interrupts_enabled(oldlevel);     /* enable interrupts */
        !           246: 
        !           247:                    *count = PROCESSOR_PM_REGS_COUNT_POWERPC_604;
        !           248:                    return(KERN_SUCCESS);
        !           249:                  }
        !           250:                case CPU_SUBTYPE_POWERPC_604e:
        !           251:                case CPU_SUBTYPE_POWERPC_750:
        !           252:                  {
        !           253:                    if (*count < PROCESSOR_PM_REGS_COUNT_POWERPC_750)
        !           254:                      return(KERN_FAILURE);
        !           255:              
        !           256:                    oldlevel = ml_set_interrupts_enabled(FALSE);    /* disable interrupts */
        !           257:                    PERFMON_MMCR0(perf_regs) = mfmmcr0();
        !           258:                    PERFMON_PMC1(perf_regs)  = mfpmc1();
        !           259:                    PERFMON_PMC2(perf_regs)  = mfpmc2();
        !           260:                    PERFMON_MMCR1(perf_regs) = mfmmcr1();
        !           261:                    PERFMON_PMC3(perf_regs)  = mfpmc3();
        !           262:                    PERFMON_PMC4(perf_regs)  = mfpmc4();
        !           263:                    ml_set_interrupts_enabled(oldlevel);     /* enable interrupts */
        !           264: 
        !           265:                    *count = PROCESSOR_PM_REGS_COUNT_POWERPC_750;
        !           266:                    return(KERN_SUCCESS);
        !           267:                  }
        !           268:                case CPU_SUBTYPE_POWERPC_Max:
        !           269:                  {
        !           270:                    if (*count < PROCESSOR_PM_REGS_COUNT_POWERPC_Max)
        !           271:                      return(KERN_FAILURE);
        !           272:              
        !           273:                    oldlevel = ml_set_interrupts_enabled(FALSE);    /* disable interrupts */
        !           274:                    PERFMON_MMCR0(perf_regs) = mfmmcr0();
        !           275:                    PERFMON_PMC1(perf_regs)  = mfpmc1();
        !           276:                    PERFMON_PMC2(perf_regs)  = mfpmc2();
        !           277:                    PERFMON_MMCR1(perf_regs) = mfmmcr1();
        !           278:                    PERFMON_PMC3(perf_regs)  = mfpmc3();
        !           279:                    PERFMON_PMC4(perf_regs)  = mfpmc4();
        !           280:                    PERFMON_MMCR2(perf_regs) = mfmmcr2();
        !           281:                    ml_set_interrupts_enabled(oldlevel);     /* enable interrupts */
        !           282: 
        !           283:                    *count = PROCESSOR_PM_REGS_COUNT_POWERPC_Max;
        !           284:                    return(KERN_SUCCESS);
        !           285:                  }
        !           286:                default:
        !           287:                  return(KERN_FAILURE);
        !           288:                } /* switch cpu_subtype */
        !           289:            } /* PROCESSOR_PM_REGS_INFO */
        !           290:          default:
        !           291:            return(KERN_INVALID_ARGUMENT);
        !           292:          } /* flavor */
        !           293: }
        !           294: 
        !           295: cpu_init()
        !           296: {
        !           297:        int     cpu;
        !           298:        cpu_subtype_t   t;
        !           299: 
        !           300:        cpu = cpu_number();
        !           301: 
        !           302:        machine_slot[cpu].running = TRUE;
        !           303:        machine_slot[cpu].cpu_type = CPU_TYPE_POWERPC;
        !           304: 
        !           305:        switch (PROCESSOR_VERSION) {
        !           306:                case PROCESSOR_VERSION_601:             /* 601 */
        !           307:                        t = CPU_SUBTYPE_POWERPC_601; break;
        !           308:                case PROCESSOR_VERSION_603:             /* ? */
        !           309:                        t = CPU_SUBTYPE_POWERPC_603; break;
        !           310:                case PROCESSOR_VERSION_604:             /* ? */
        !           311:                        t = CPU_SUBTYPE_POWERPC_604; break;
        !           312:                case 5:                                 /* ? */
        !           313:                        t = CPU_SUBTYPE_POWERPC_602; break;
        !           314:                case PROCESSOR_VERSION_603e:            /* ? */
        !           315:                        t = CPU_SUBTYPE_POWERPC_603e; break;
        !           316:                case 7:                                 /* ? */
        !           317:                        t = CPU_SUBTYPE_POWERPC_603ev; break;
        !           318:                case PROCESSOR_VERSION_604e:            /* ? */
        !           319:                case PROCESSOR_VERSION_604ev:           /* ? */
        !           320:                        __asm__ volatile("mtspr 1023,%0" : : "r" (cpu));        /* Set logical CPU into the PIR */
        !           321:                        t = CPU_SUBTYPE_POWERPC_604e; break;
        !           322:                case PROCESSOR_VERSION_750:             /* ? */
        !           323:                        t = CPU_SUBTYPE_POWERPC_750; break;
        !           324:                case PROCESSOR_VERSION_Max:            /* Max */
        !           325:                        __asm__ volatile("mtspr 1023,%0" : : "r" (cpu));        /* Set logical CPU into the PIR */
        !           326:                        t = CPU_SUBTYPE_POWERPC_Max; break;
        !           327:                default:
        !           328:                        t = CPU_SUBTYPE_POWERPC_ALL; break;
        !           329:        }
        !           330:        machine_slot[cpu].cpu_subtype = t;
        !           331: 
        !           332: }
        !           333: 
        !           334: void
        !           335: cpu_machine_init(
        !           336:        void)
        !           337: {
        !           338:        /* TODO: realese mutex lock reset_handler_lock */
        !           339: 
        !           340:        PE_cpu_machine_init(per_proc_info[cpu_number()].cpu_id);
        !           341: }
        !           342: 
        !           343: kern_return_t
        !           344: cpu_register(
        !           345:        int *target_cpu
        !           346: )
        !           347: {
        !           348:        int cpu;
        !           349: 
        !           350:        /* 
        !           351:         * TODO: 
        !           352:         * - Run cpu_register() in exclusion mode 
        !           353:         */
        !           354: 
        !           355:        *target_cpu = -1;
        !           356:        for(cpu=0; cpu < wncpu; cpu++) {
        !           357:                if(!machine_slot[cpu].is_cpu) {
        !           358:                        machine_slot[cpu].is_cpu = TRUE;
        !           359:                        *target_cpu = cpu;
        !           360:                        break;
        !           361:                }
        !           362:        }
        !           363:        if (*target_cpu != -1) {
        !           364:                real_ncpus++;
        !           365:                return KERN_SUCCESS;
        !           366:        } else
        !           367:                return KERN_FAILURE;
        !           368: }
        !           369: 
        !           370: kern_return_t
        !           371: cpu_start(
        !           372:        int cpu)
        !           373: {
        !           374:        struct per_proc_info    *proc_info;
        !           375:        kern_return_t           ret;
        !           376: 
        !           377:        extern void (*exception_handlers[])(void);
        !           378:        extern vm_offset_t      intstack;
        !           379:        extern vm_offset_t      debstack;
        !           380: 
        !           381:        if (cpu == master_cpu) {
        !           382:          PE_cpu_machine_init(per_proc_info[cpu].cpu_id);
        !           383:          
        !           384:          return KERN_SUCCESS;
        !           385:        }
        !           386: 
        !           387:        proc_info = &per_proc_info[cpu];
        !           388: 
        !           389:        proc_info->cpu_number = cpu;
        !           390:        proc_info->cpu_flags = 0;
        !           391:        proc_info->istackptr = (vm_offset_t)&intstack + (INTSTACK_SIZE*(cpu+1)) - sizeof (struct ppc_saved_state);
        !           392:        proc_info->intstack_top_ss = proc_info->istackptr;
        !           393: #if     MACH_KDP || MACH_KDB
        !           394:        proc_info->debstackptr = (vm_offset_t)&debstack + (KERNEL_STACK_SIZE*(cpu+1)) - sizeof (struct ppc_saved_state);
        !           395:        proc_info->debstack_top_ss = proc_info->debstackptr;
        !           396: #endif  /* MACH_KDP || MACH_KDB */
        !           397:        proc_info->phys_exception_handlers = 
        !           398:                                kvtophys((vm_offset_t)&exception_handlers);
        !           399:        proc_info->get_interrupts_enabled = fake_get_interrupts_enabled;
        !           400:        proc_info->set_interrupts_enabled = fake_set_interrupts_enabled;
        !           401:        proc_info->virt_per_proc_info = (unsigned int)proc_info;
        !           402:        proc_info->active_kloaded = (unsigned int)&active_kloaded[cpu];
        !           403:        proc_info->cpu_data = (unsigned int)&cpu_data[cpu];
        !           404:        proc_info->active_stacks = (unsigned int)&active_stacks[cpu];
        !           405:        proc_info->need_ast = (unsigned int)&need_ast[cpu];
        !           406:        proc_info->FPU_thread = 0;
        !           407: 
        !           408:        if (cpu != cpu_number()) {
        !           409:                extern void _start_cpu(void);
        !           410: 
        !           411:                if (proc_info->start_paddr == EXCEPTION_VECTOR(T_RESET)) {
        !           412: 
        !           413:                        /* TODO: get mutex lock reset_handler_lock */
        !           414: 
        !           415:                        resethandler_target.type = RESET_HANDLER_START;
        !           416:                        resethandler_target.call_paddr = kvtophys((vm_offset_t)_start_cpu); 
        !           417:                        resethandler_target.arg__paddr = kvtophys((vm_offset_t)proc_info);
        !           418:                        
        !           419:                        ml_phys_write((vm_offset_t)&ResetHandler + 0,
        !           420:                                      resethandler_target.type);
        !           421:                        ml_phys_write((vm_offset_t)&ResetHandler + 4,
        !           422:                                      resethandler_target.call_paddr);
        !           423:                        ml_phys_write((vm_offset_t)&ResetHandler + 8,
        !           424:                                      resethandler_target.arg__paddr);
        !           425:                                          
        !           426:                        __asm__ volatile("sync");                               /* Commit to storage */
        !           427:                        __asm__ volatile("isync");                              /* Wait a second */
        !           428:                }
        !           429: 
        !           430:                ret = PE_cpu_start(proc_info->cpu_id, 
        !           431:                                        proc_info->start_paddr, (vm_offset_t)proc_info);
        !           432: 
        !           433:                if (ret != KERN_SUCCESS && 
        !           434:                    proc_info->start_paddr == EXCEPTION_VECTOR(T_RESET)) {
        !           435: 
        !           436:                        /* TODO: realese mutex lock reset_handler_lock */
        !           437:                }
        !           438:        }
        !           439:        else
        !           440:                ret = KERN_SUCCESS;
        !           441: 
        !           442:        return(ret);
        !           443: }
        !           444: 
        !           445: kern_return_t
        !           446: cpu_signal_handler_register()
        !           447: {
        !           448: }
        !           449: 
        !           450: 
        !           451: /*
        !           452:  *     Here is where we implement the receiver of the signaling protocol.
        !           453:  *     We wait for the signal status area to be passed to us. Then we snarf
        !           454:  *     up the status, the sender, and the 3 potential parms. Next we release
        !           455:  *     the lock and signal the other guy.
        !           456:  */
        !           457: 
        !           458: void cpu_signal_handler(void) {
        !           459: 
        !           460:        unsigned int holdStat, holdParm0, holdParm1, holdParm2, mtype;
        !           461:        struct per_proc_info *pproc;                                    /* Area for my per_proc address */
        !           462:        int cpu;
        !           463:        
        !           464:        cpu = cpu_number();                                                             /* Get the CPU number */
        !           465:        pproc = &per_proc_info[cpu];                                    /* Point to our block */
        !           466: 
        !           467: /*
        !           468:  *     Since we've been signaled, wait just under 1ms for the signal lock to pass
        !           469:  */
        !           470:        if(!hw_lock_mbits(&pproc->MPsigpStat, MPsigpMsgp, (MPsigpBusy | MPsigpPass),
        !           471:          (MPsigpBusy | MPsigpPass), (powermac_info.bus_clock_rate_hz >> 7))) {
        !           472:                panic("cpu_signal_handler: Lock pass timed out\n");
        !           473:        }
        !           474:        
        !           475:        holdStat = pproc->MPsigpStat;                                   /* Snarf stat word */
        !           476:        holdParm0 = pproc->MPsigpParm0;                                 /* Snarf parameter */
        !           477:        holdParm1 = pproc->MPsigpParm1;                                 /* Snarf parameter */
        !           478:        holdParm2 = pproc->MPsigpParm2;                                 /* Snarf parameter */
        !           479:        
        !           480:        __asm__ volatile("isync");                                              /* Make sure we don't unlock until memory is in */
        !           481: 
        !           482:        pproc->MPsigpStat = holdStat & ~(MPsigpMsgp | MPsigpFunc);      /* Release lock */
        !           483: 
        !           484:        switch ((holdStat & MPsigpFunc) >> 8) {                 /* Decode function code */
        !           485: 
        !           486:                case MPsigpIdle:                                                        /* Was function cancelled? */
        !           487:                        return;                                                                 /* Yup... */
        !           488:                        
        !           489:                case MPsigpSigp:                                                        /* Signal Processor message? */
        !           490:                        
        !           491:                        switch (holdParm0) {                                    /* Decode SIGP message order */
        !           492: 
        !           493:                                case SIGPast:                                           /* Should we do an AST? */
        !           494: #if 0
        !           495:                                        ast_check();                                    /* Yes, do it */
        !           496: #else
        !           497:                                        kprintf("cpu_signal_handler: AST request disabled\n");
        !           498: #endif
        !           499:                                        return;                                                 /* All done... */
        !           500:        
        !           501:                                case SIGPdebug:                                         /* Enter the debugger? */               
        !           502: 
        !           503:                                        debugger_is_slave[cpu]++;               /* Bump up the count to show we're here */
        !           504:                                        hw_atomic_sub(&debugger_sync, 1);       /* Show we've received the 'rupt */
        !           505:                                        __asm__ volatile("tw 4,r3,r3"); /* Enter the debugger */
        !           506:                                        return;                                                 /* All done now... */
        !           507:                                        
        !           508:                                case SIGPwake:                                          /* Wake up CPU */
        !           509:                                        return;                                                 /* No need to do anything, the interrupt does it all... */
        !           510:                                        
        !           511:                                default:
        !           512: #if DEBUG
        !           513:                                        kprintf("cpu_signal_handler: unknown SIGP message order - %08X\n", holdParm0);
        !           514: #endif                 
        !           515:                                        return;
        !           516:                        
        !           517:                        }
        !           518:        
        !           519:                default:
        !           520: #if DEBUG
        !           521:                        kprintf("cpu_signal_handler: unknown SIGP function - %08X\n", (holdStat & MPsigpFunc) >> 8);
        !           522: #endif                 
        !           523:                        return;
        !           524:        
        !           525:        }
        !           526:        panic("cpu_signal_handler: we should never get here\n");
        !           527: }
        !           528: 
        !           529: /*
        !           530:  *     Here is where we send a message to another processor.  So far we only have two:
        !           531:  *     SIGPast and SIGPdebug.  SIGPast is used to preempt and kick off threads (this is
        !           532:  *     currently disabled). SIGPdebug is used to enter the debugger.
        !           533:  *
        !           534:  *     We set up the SIGP function to indicate that this is a simple message and set the
        !           535:  *     order code (MPsigpParm0) to SIGPast or SIGPdebug). After finding the per_processor
        !           536:  *     block for the target, we lock the message block. Then we set the parameter(s). 
        !           537:  *     Next we change the lock (also called "busy") to "passing" and finally signal
        !           538:  *     the other processor. Note that we only wait about 1ms to get the message lock.  
        !           539:  *     If we time out, we return failure to our caller. It is their responsibility to
        !           540:  *     recover.
        !           541:  */
        !           542: 
        !           543: kern_return_t cpu_signal(int target, int signal) {     /* Signal the target CPU */
        !           544: 
        !           545:        unsigned int holdStat, holdParm0, holdParm1, holdParm2, mtype;
        !           546:        struct per_proc_info *tpproc, *mpproc;                  /* Area for per_proc addresses */
        !           547:        int cpu;
        !           548: 
        !           549: #if DEBUG
        !           550:        if(target > NCPUS) panic("cpu_signal: invalid target CPU - %08X\n", target);
        !           551: #endif
        !           552: 
        !           553:        cpu = cpu_number();                                                             /* Get our CPU number */
        !           554:        if(target == cpu) return KERN_FAILURE;                  /* Don't play with ourselves */
        !           555:        if(!machine_slot[target].running) return KERN_FAILURE;  /* These guys are too young */  
        !           556: 
        !           557:        mpproc = &per_proc_info[cpu];                                   /* Point to our block */
        !           558:        tpproc = &per_proc_info[target];                                /* Point to the target's block */
        !           559:        
        !           560:        if(!hw_lock_mbits(&tpproc->MPsigpStat, MPsigpMsgp, 0, MPsigpBusy, 
        !           561:          (powermac_info.bus_clock_rate_hz >> 7))) {    /* Try to lock the message block */
        !           562:                return KERN_FAILURE;                                            /* Timed out, take your ball and go home... */
        !           563:        }
        !           564: 
        !           565:        holdStat = MPsigpBusy | MPsigpPass | (MPsigpSigp << 8) | cpu;   /* Set up the signal status word */
        !           566:        tpproc->MPsigpParm0 = signal;                                   /* Set message order */
        !           567:        tpproc->MPsigpParm1 = 0;                                                /* Clear additional parms for yuks */
        !           568:        tpproc->MPsigpParm2 = 0;                                                /* Clear additional parms for yuks */
        !           569:        
        !           570:        __asm__ volatile("sync");                                               /* Make sure it's all there */
        !           571:        
        !           572:        tpproc->MPsigpStat = holdStat;                                  /* Set status and pass the lock */
        !           573:        __asm__ volatile("eieio");                                              /* I'm a paraniod freak */
        !           574:        
        !           575:        PE_cpu_signal(mpproc->cpu_id, tpproc->cpu_id);  /* Kick the other processor */
        !           576: 
        !           577:        return KERN_SUCCESS;                                                    /* All is goodness and rainbows... */
        !           578: }
        !           579: 
        !           580: /*
        !           581:  * TODO
        !           582:  */
        !           583: void init_ast_check(processor_t processor) 
        !           584: {}
        !           585: 
        !           586: void cause_ast_check(processor_t processor)
        !           587: {}       
        !           588: 
        !           589: void
        !           590: switch_to_shutdown_context(
        !           591:        thread_t        thread,
        !           592:        void            (*doshutdown)(processor_t),
        !           593:        processor_t     processor)
        !           594: { 
        !           595:        printf("switch_to_shutdown_processor: not implemented\n");
        !           596: }
        !           597:  

unix.superglobalmegacorp.com

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