📄 prom.c
字号:
prom_tce_table[table].node = node; prom_tce_table[table].base = vbase; prom_tce_table[table].size = minsize;#ifdef DEBUG_PROM prom_print(RELOC("TCE table: 0x")); prom_print_hex(table); prom_print_nl(); prom_print(RELOC("\tnode = 0x")); prom_print_hex(node); prom_print_nl(); prom_print(RELOC("\tbase = 0x")); prom_print_hex(vbase); prom_print_nl(); prom_print(RELOC("\tsize = 0x")); prom_print_hex(minsize); prom_print_nl();#endif /* Initialize the table to have a one-to-one mapping * over the allocated size. */ tce_entryp = (unsigned long *)base; for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) { tce_entry = (i << PAGE_SHIFT); tce_entry |= 0x3; *tce_entryp = tce_entry; } /* Call OF to setup the TCE hardware */ if (call_prom(RELOC("package-to-path"), 3, 1, node, path, 255) <= 0) { prom_print(RELOC("package-to-path failed\n")); } else { prom_print(RELOC("opened ")); prom_print(path); prom_print_nl(); } phb_node = (ihandle)call_prom(RELOC("open"), 1, 1, path); if ( (long)phb_node <= 0) { prom_print(RELOC("open failed\n")); } else { prom_print(RELOC("open success\n")); } call_prom(RELOC("call-method"), 6, 0, RELOC("set-64-bit-addressing"), phb_node, -1, minsize, base & 0xffffffff, (base >> 32) & 0xffffffff); call_prom(RELOC("close"), 1, 0, phb_node); table++; } /* Flag the first invalid entry */ prom_tce_table[table].node = 0;#ifdef DEBUG_PROM prom_print(RELOC("ending prom_initialize_tce_table\n"));#endif}/* * With CHRP SMP we need to use the OF to start the other * processors so we can't wait until smp_boot_cpus (the OF is * trashed by then) so we have to put the processors into * a holding pattern controlled by the kernel (not OF) before * we destroy the OF. * * This uses a chunk of low memory, puts some holding pattern * code there and sends the other processors off to there until * smp_boot_cpus tells them to do something. The holding pattern * checks that address until its cpu # is there, when it is that * cpu jumps to __secondary_start(). smp_boot_cpus() takes care * of setting those values. * * We also use physical address 0x4 here to tell when a cpu * is in its holding pattern code. * * Fixup comment... DRENG / PPPBBB - Peter * * -- Cort */static voidprom_hold_cpus(unsigned long mem){ unsigned long i; unsigned int reg; phandle node; unsigned long offset = reloc_offset(); char type[64], *path; int cpuid = 0; extern void __secondary_hold(void); extern unsigned long __secondary_hold_spinloop; extern unsigned long __secondary_hold_acknowledge; unsigned long *spinloop = __v2a(&__secondary_hold_spinloop); unsigned long *acknowledge = __v2a(&__secondary_hold_acknowledge); unsigned long secondary_hold = (unsigned long)__v2a(*PTRRELOC((unsigned long *)__secondary_hold)); struct Naca *_naca = RELOC(naca); struct Paca *_xPaca = PTRRELOC(&xPaca[0]); struct prom_t *_prom = PTRRELOC(&prom); /* Initially, we must have one active CPU. */ _naca->processorCount = 1;#ifdef DEBUG_PROM prom_print(RELOC("prom_hold_cpus: start...\n")); prom_print(RELOC(" 1) spinloop = 0x")); prom_print_hex(spinloop); prom_print_nl(); prom_print(RELOC(" 1) *spinloop = 0x")); prom_print_hex(*spinloop); prom_print_nl(); prom_print(RELOC(" 1) acknowledge = 0x")); prom_print_hex(acknowledge); prom_print_nl(); prom_print(RELOC(" 1) *acknowledge = 0x")); prom_print_hex(*acknowledge); prom_print_nl(); prom_print(RELOC(" 1) secondary_hold = 0x")); prom_print_hex(secondary_hold); prom_print_nl();#endif /* Set the common spinloop variable, so all of the secondary cpus * will block when they are awakened from their OF spinloop. * This must occur for both SMP and non SMP kernels, since OF will * be trashed when we move the kernel. */ *spinloop = 0;#ifdef CONFIG_HMT for (i=0; i < NR_CPUS; i++) { RELOC(hmt_thread_data)[i].pir = 0xdeadbeef; }#endif /* look for cpus */ for (node = 0; prom_next_node(&node); ) { type[0] = 0; call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"), type, sizeof(type)); if (strcmp(type, RELOC("cpu")) != 0) continue; /* Skip non-configured cpus. */ call_prom(RELOC("getprop"), 4, 1, node, RELOC("status"), type, sizeof(type)); if (strcmp(type, RELOC("okay")) != 0) continue; reg = -1; call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"), ®, sizeof(reg)); /* Only need to start secondary procs, not ourself. */ if ( reg == _prom->cpu ) continue; path = (char *) mem; memset(path, 0, 256); if ((long) call_prom(RELOC("package-to-path"), 3, 1, node, path, 255) < 0) continue; cpuid++;#ifdef DEBUG_PROM prom_print_nl(); prom_print(RELOC("cpuid = 0x")); prom_print_hex(cpuid); prom_print_nl(); prom_print(RELOC("cpu hw idx = 0x")); prom_print_hex(reg); prom_print_nl();#endif _xPaca[cpuid].xHwProcNum = reg; prom_print(RELOC("starting cpu ")); prom_print(path); /* Init the acknowledge var which will be reset by * the secondary cpu when it awakens from its OF * spinloop. */ *acknowledge = (unsigned long)-1;#ifdef DEBUG_PROM prom_print(RELOC(" 3) spinloop = 0x")); prom_print_hex(spinloop); prom_print_nl(); prom_print(RELOC(" 3) *spinloop = 0x")); prom_print_hex(*spinloop); prom_print_nl(); prom_print(RELOC(" 3) acknowledge = 0x")); prom_print_hex(acknowledge); prom_print_nl(); prom_print(RELOC(" 3) *acknowledge = 0x")); prom_print_hex(*acknowledge); prom_print_nl(); prom_print(RELOC(" 3) secondary_hold = 0x")); prom_print_hex(secondary_hold); prom_print_nl(); prom_print(RELOC(" 3) cpuid = 0x")); prom_print_hex(cpuid); prom_print_nl();#endif call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, cpuid); prom_print(RELOC("...")); for ( i = 0 ; (i < 100000000) && (*acknowledge == ((unsigned long)-1)); i++ ) ;#ifdef DEBUG_PROM { unsigned long *p = 0x0; prom_print(RELOC(" 4) 0x0 = 0x")); prom_print_hex(*p); prom_print_nl(); }#endif if (*acknowledge == cpuid) { prom_print(RELOC("ok\n")); /* Set the number of active processors. */ _naca->processorCount++; } else { prom_print(RELOC("failed: ")); prom_print_hex(*acknowledge); prom_print_nl(); } }#ifdef CONFIG_HMT /* Only enable HMT on processors that provide support. */ if (__is_processor(PV_PULSAR) || __is_processor(PV_ICESTAR) || __is_processor(PV_SSTAR)) { prom_print(RELOC(" starting secondary threads\n")); for (i=0; i < _naca->processorCount ;i++) { unsigned long threadid = _naca->processorCount*2-1-i; if (i == 0) { unsigned long pir = _get_PIR(); if (__is_processor(PV_PULSAR)) { RELOC(hmt_thread_data)[i].pir = pir & 0x1f; } else { RELOC(hmt_thread_data)[i].pir = pir & 0x3ff; } } RELOC(hmt_thread_data)[i].threadid = threadid;#ifdef DEBUG_PROM prom_print(RELOC(" cpuid 0x")); prom_print_hex(i); prom_print(RELOC(" maps to threadid 0x")); prom_print_hex(threadid); prom_print_nl(); prom_print(RELOC(" pir 0x")); prom_print_hex(RELOC(hmt_thread_data)[i].pir); prom_print_nl();#endif _xPaca[threadid].xHwProcNum = _xPaca[i].xHwProcNum+1; } _naca->processorCount *= 2; } else { prom_print(RELOC("Processor is not HMT capable\n")); }#endif #ifdef DEBUG_PROM prom_print(RELOC("prom_hold_cpus: end...\n"));#endif}/* * We enter here early on, when the Open Firmware prom is still * handling exceptions and the MMU hash table for us. */unsigned long __initprom_init(unsigned long r3, unsigned long r4, unsigned long pp, unsigned long r6, unsigned long r7, yaboot_debug_t *yaboot){ int chrp = 0; unsigned long mem; ihandle prom_mmu, prom_op, prom_root, prom_cpu; phandle cpu_pkg; unsigned long offset = reloc_offset(); long l; char *p, *d; unsigned long phys; u32 getprop_rval; struct Naca *_naca = RELOC(naca); struct Paca *_xPaca = PTRRELOC(&xPaca[0]); struct prom_t *_prom = PTRRELOC(&prom); /* Default machine type. */ RELOC(_machine) = _MACH_pSeries; /* Reset klimit to take into account the embedded system map */ if (RELOC(embedded_sysmap_end)) RELOC(klimit) = __va(PAGE_ALIGN(RELOC(embedded_sysmap_end))); /* Get a handle to the prom entry point before anything else */ _prom->entry = pp; _prom->bi_recs = prom_bi_rec_verify((struct bi_record *)r6); if ( _prom->bi_recs != NULL ) { RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs + _prom->bi_recs->data[1]); }#ifdef DEBUG_YABOOT call_yaboot(yaboot->dummy,offset>>32,offset&0xffffffff); call_yaboot(yaboot->printf, RELOC("offset = 0x%08x%08x\n"), LONG_MSW(offset), LONG_LSW(offset));#endif /* Default */ phys = KERNELBASE - offset;#ifdef DEBUG_YABOOT call_yaboot(yaboot->printf, RELOC("phys = 0x%08x%08x\n"), LONG_MSW(phys), LONG_LSW(phys));#endif#ifdef DEBUG_YABOOT _prom->yaboot = yaboot; call_yaboot(yaboot->printf, RELOC("pp = 0x%08x%08x\n"), LONG_MSW(pp), LONG_LSW(pp)); call_yaboot(yaboot->printf, RELOC("prom = 0x%08x%08x\n"), LONG_MSW(_prom->entry), LONG_LSW(_prom->entry));#endif /* First get a handle for the stdout device */ _prom->chosen = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/chosen"));#ifdef DEBUG_YABOOT call_yaboot(yaboot->printf, RELOC("prom->chosen = 0x%08x%08x\n"), LONG_MSW(_prom->chosen), LONG_LSW(_prom->chosen));#endif if ((long)_prom->chosen <= 0) prom_exit(); if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen, RELOC("stdout"), &getprop_rval, sizeof(getprop_rval)) <= 0) prom_exit(); _prom->stdout = (ihandle)(unsigned long)getprop_rval;#ifdef DEBUG_YABOOT if (_prom->stdout == 0) { call_yaboot(yaboot->printf, RELOC("prom->stdout = 0x%08x%08x\n"), LONG_MSW(_prom->stdout), LONG_LSW(_prom->stdout)); } call_yaboot(yaboot->printf, RELOC("prom->stdout = 0x%08x%08x\n"), LONG_MSW(_prom->stdout), LONG_LSW(_prom->stdout));#endif#ifdef DEBUG_YABOOT call_yaboot(yaboot->printf, RELOC("Location: 0x11\n"));#endif mem = RELOC(klimit) - offset; #ifdef DEBUG_YABOOT call_yaboot(yaboot->printf, RELOC("Location: 0x11b\n"));#endif /* Get the full OF pathname of the stdout device */ p = (char *) mem; memset(p, 0, 256); call_prom(RELOC("instance-to-path"), 3, 1, _prom->stdout, p, 255); RELOC(of_stdout_device) = PTRUNRELOC(p); mem += strlen(p) + 1; getprop_rval = 1; prom_root = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/")); if (prom_root != (ihandle)-1) { call_prom(RELOC("getprop"), 4, 1, prom_root, RELOC("#size-cells"), &getprop_rval, sizeof(getprop_rval)); } _prom->encode_phys_size = (getprop_rval==1) ? 32 : 64;#ifdef DEBUG_PROM prom_print(RELOC("DRENG: Detect OF version...\n"));#endif /* Find the OF version */ prom_op = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/openprom")); if (prom_op != (ihandle)-1) { char model[64]; long sz; sz = (long)call_prom(RELOC("getprop"), 4, 1, prom_op, RELOC("model"), model, 64); if (sz > 0) { char *c; /* hack to skip the ibm chrp firmware # */ if ( strncmp(model,RELOC("IBM"),3) ) { for (c = model; *c; c++) if (*c >= '0' && *c <= '9') { _prom->version = *c - '0'; break; } } else chrp = 1; } } if (_prom->version >= 3) prom_print(RELOC("OF Version 3 detected.\n")); /* Determine which cpu is actually running right _now_ */ if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen, RELOC("cpu"), &getprop_rval, sizeof(getprop_rval)) <= 0) prom_exit(); prom_cpu = (ihandle)(unsigned long)getprop_rval; cpu_pkg = call_prom(RELOC("instance-to-package"), 1, 1, prom_cpu); call_prom(RELOC("getprop"), 4, 1, cpu_pkg, RELOC("reg"), &getprop_rval, sizeof(getprop_rval)); _prom->cpu = (int)(unsigned long)getprop_rval; _xPaca[0].xHwProcNum = _prom->cpu;#ifdef DEBUG_PROM prom_print(RELOC("Booting CPU hw index = 0x")); prom_print_hex(_prom->cpu); prom_print_nl();#endif /* Get the boot device and translate it to a full OF pathname. */ p = (char *) mem; l = (long) call_prom(RELOC("getprop"), 4, 1, _prom->chosen, RELOC("bootpath"), p, 1<<20); if (l > 0) { p[l] = 0; /* should already be null-terminated */ RELOC(bootpath) = PTRUNRELOC(p); mem += l + 1; d = (char *) mem; *d = 0; call_prom(RELOC("canon"), 3, 1, p, d, 1<<20); RELOC(bootdevice) = PTRUNRELOC(d); mem = DOUBLEWORD_ALIGN(mem + strlen(d) + 1); } mem = prom_initialize_lmb(mem); mem = prom_bi_rec_reserve(mem); mem = prom_instantiate_rtas(mem); /* Initialize some system info into the Naca early... */ mem = prom_initialize_naca(mem); /* If we are on an SMP machine, then we *MUST* do the * following, regardless of whether we have an SMP * kernel or not. */ if ( _naca->processorCount > 1 ) prom_hold_cpus(mem); mem = check_display(mem);#ifdef DEBUG_PROM prom_print(RELOC("copying OF device tree...\n"));#endif mem = copy_device_tree(mem); RELOC(klimit) = mem + offset;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -