|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.