📄 prom.c
字号:
if (call_prom(RELOC("getprop"), 4, 1, node, RELOC("tce-table-minsize"), &minsize, sizeof(minsize)) < 0) { minsize = 4UL << 20; } /* Even though we read what OF wants, we just set the table * size to 4 MB. This is enough to map 2GB of PCI DMA space. * By doing this, we avoid the pitfalls of trying to DMA to * MMIO space and the DMA alias hole. */ minsize = 4UL << 20; /* Align to the greater of the align or size */ align = (minalign < minsize) ? minsize : minalign; /* Carve out storage for the TCE table. */ base = lmb_alloc(minsize, align); if ( !base ) { prom_print(RELOC("ERROR, cannot find space for TCE table.\n")); prom_exit(); } vbase = absolute_to_virt(base); /* Save away the TCE table attributes for later use. */ 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_struct *_naca = RELOC(naca); struct paca_struct *_xPaca = PTRRELOC(&paca[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}#ifdef CONFIG_PPCDBGextern char *trace_names[]; /* defined in udbg.c -- need a better interface */static void parse_ppcdbg_optionlist(const char *cmd, const char *cmdend){ unsigned long offset = reloc_offset(); char **_trace_names = PTRRELOC(&trace_names[0]); const char *all = RELOC("all"); struct naca_struct *_naca = RELOC(naca); const char *p, *pend; int onoff, i, cmdidx; unsigned long mask; char cmdbuf[30]; for (p = cmd, pend = strchr(p, ','); p < cmdend; pend = strchr(p, ',')) { if (pend == NULL || pend > cmdend) pend = cmdend; onoff = 1; /* default */ if (*p == '+' || *p == '-') { /* explicit on or off */ onoff = (*p == '+'); p++; } /* parse out p..pend here */ if (pend - p < sizeof(cmdbuf)) { strncpy(cmdbuf, p, pend - p); cmdbuf[pend - p] = '\0'; for (cmdidx = -1, i = 0; i < PPCDBG_NUM_FLAGS; i++) { if (_trace_names[i] && (strcmp(PTRRELOC(_trace_names[i]), cmdbuf) == 0)) { cmdidx = i; break; } } mask = 0; if (cmdidx >= 0) { mask = (1 << cmdidx); } else if (strcmp(cmdbuf, all) == 0) { mask = PPCDBG_ALL; } else { prom_print(RELOC("ppcdbg: unknown debug: ")); prom_print(cmdbuf); prom_print_nl(); } if (mask) { if (onoff) _naca->debug_switch |= mask; else _naca->debug_switch &= ~mask; } } p = pend+1; }}/* * Parse ppcdbg= cmdline option. * * Option names are listed in <asm/ppcdebug.h> in the trace_names * table. Multiple names may be listed separated by commas (no whitespace), * and each option may be preceeded by a + or - to force on or off state. * The special option "all" may also be used. They are processed strictly * left to right. Multiple ppcdbg= options are the command line are treated * as a single option list. * * Examples: ppcdbg=phb_init,buswalk * ppcdbg=all,-mm,-tce * * ToDo: add "group" names that map to common combinations of flags. */void parse_ppcdbg_cmd_line(const char *line){ unsigned long offset = reloc_offset(); const char *ppcdbgopt = RELOC("ppcdbg="); struct naca_struct *_naca = RELOC(naca); const char *cmd, *end; _naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */ cmd = line; while (cmd && (cmd = strstr(cmd, ppcdbgopt)) != NULL) { cmd += 7; /* skip ppcdbg= */ for (end = cmd; *end != '\0' && *end != '\t' && *end != ' '; end++) ; /* scan to whitespace or end */ parse_ppcdbg_optionlist(cmd, end); }}#endif /* CONFIG_PPCDBG *//* * Do minimal cmd_line parsing for early boot options. */static void __initprom_parse_cmd_line(char *line){#ifdef CONFIG_PPCDBG parse_ppcdbg_cmd_line(line);#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, sz; char *p, *d; unsigned long phys; u32 getprop_rval; struct naca_struct *_naca = RELOC(naca); struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct prom_t *_prom = PTRRELOC(&prom); char *_cmd_line = PTRRELOC(&cmd_line[0]); /* Default machine type. */ _naca->platform = PLATFORM_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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -