📄 setup.c
字号:
moreChunks = totalChunks; while (moreChunks) { map = HvCallSm_get64BitsOfAccessMap(itLpNaca.xLpIndex, currDword); thisChunk = currChunk; while (map) { chunkBit = map >> 63; map <<= 1; if (chunkBit) { --moreChunks; while (thisChunk >= mb[curBlock].logicalEnd) { ++curBlock; if (curBlock >= numMemoryBlocks) panic("out of memory blocks"); } if (thisChunk < mb[curBlock].logicalStart) panic("memory block error"); absChunk = mb[curBlock].absStart + (thisChunk - mb[curBlock].logicalStart); if (((absChunk < hptFirstChunk) || (absChunk > hptLastChunk)) && ((absChunk < loadAreaFirstChunk) || (absChunk > loadAreaLastChunk))) { mschunks_map.mapping[nextPhysChunk] = absChunk; ++nextPhysChunk; } } ++thisChunk; } ++currDword; currChunk += 64; } /* * main store size (in chunks) is * totalChunks - hptSizeChunks * which should be equal to * nextPhysChunk */ return chunk_to_addr(nextPhysChunk);}/* * Document me. */static void __init iSeries_setup_arch(void){ if (get_paca()->lppaca.shared_proc) { ppc_md.idle_loop = iseries_shared_idle; printk(KERN_INFO "Using shared processor idle loop\n"); } else { ppc_md.idle_loop = iseries_dedicated_idle; printk(KERN_INFO "Using dedicated idle loop\n"); } /* Setup the Lp Event Queue */ setup_hvlpevent_queue(); printk("Max logical processors = %d\n", itVpdAreas.xSlicMaxLogicalProcs); printk("Max physical processors = %d\n", itVpdAreas.xSlicMaxPhysicalProcs);}static void iSeries_show_cpuinfo(struct seq_file *m){ seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n");}/* * Document me. * and Implement me. */static int iSeries_get_irq(struct pt_regs *regs){ /* -2 means ignore this interrupt */ return -2;}/* * Document me. */static void iSeries_restart(char *cmd){ mf_reboot();}/* * Document me. */static void iSeries_power_off(void){ mf_power_off();}/* * Document me. */static void iSeries_halt(void){ mf_power_off();}static void __init iSeries_progress(char * st, unsigned short code){ printk("Progress: [%04x] - %s\n", (unsigned)code, st); if (!piranha_simulator && mf_initialized) { if (code != 0xffff) mf_display_progress(code); else mf_clear_src(); }}static void __init iSeries_fixup_klimit(void){ /* * Change klimit to take into account any ram disk * that may be included */ if (naca.xRamDisk) klimit = KERNELBASE + (u64)naca.xRamDisk + (naca.xRamDiskSize * HW_PAGE_SIZE); else { /* * No ram disk was included - check and see if there * was an embedded system map. Change klimit to take * into account any embedded system map */ if (embedded_sysmap_end) klimit = KERNELBASE + ((embedded_sysmap_end + 4095) & 0xfffffffffffff000); }}static int __init iSeries_src_init(void){ /* clear the progress line */ ppc_md.progress(" ", 0xffff); return 0;}late_initcall(iSeries_src_init);static inline void process_iSeries_events(void){ asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");}static void yield_shared_processor(void){ unsigned long tb; HvCall_setEnabledInterrupts(HvCall_MaskIPI | HvCall_MaskLpEvent | HvCall_MaskLpProd | HvCall_MaskTimeout); tb = get_tb(); /* Compute future tb value when yield should expire */ HvCall_yieldProcessor(HvCall_YieldTimed, tb+tb_ticks_per_jiffy); /* * The decrementer stops during the yield. Force a fake decrementer * here and let the timer_interrupt code sort out the actual time. */ get_paca()->lppaca.int_dword.fields.decr_int = 1; process_iSeries_events();}static void iseries_shared_idle(void){ while (1) { while (!need_resched() && !hvlpevent_is_pending()) { local_irq_disable(); ppc64_runlatch_off(); /* Recheck with irqs off */ if (!need_resched() && !hvlpevent_is_pending()) yield_shared_processor(); HMT_medium(); local_irq_enable(); } ppc64_runlatch_on(); if (hvlpevent_is_pending()) process_iSeries_events(); preempt_enable_no_resched(); schedule(); preempt_disable(); }}static void iseries_dedicated_idle(void){ set_thread_flag(TIF_POLLING_NRFLAG); while (1) { if (!need_resched()) { while (!need_resched()) { ppc64_runlatch_off(); HMT_low(); if (hvlpevent_is_pending()) { HMT_medium(); ppc64_runlatch_on(); process_iSeries_events(); } } HMT_medium(); } ppc64_runlatch_on(); preempt_enable_no_resched(); schedule(); preempt_disable(); }}#ifndef CONFIG_PCIvoid __init iSeries_init_IRQ(void) { }#endifstatic int __init iseries_probe(int platform){ return PLATFORM_ISERIES_LPAR == platform;}struct machdep_calls __initdata iseries_md = { .setup_arch = iSeries_setup_arch, .show_cpuinfo = iSeries_show_cpuinfo, .init_IRQ = iSeries_init_IRQ, .get_irq = iSeries_get_irq, .init_early = iSeries_init_early, .pcibios_fixup = iSeries_pci_final_fixup, .restart = iSeries_restart, .power_off = iSeries_power_off, .halt = iSeries_halt, .get_boot_time = iSeries_get_boot_time, .set_rtc_time = iSeries_set_rtc_time, .get_rtc_time = iSeries_get_rtc_time, .calibrate_decr = generic_calibrate_decr, .progress = iSeries_progress, .probe = iseries_probe, /* XXX Implement enable_pmcs for iSeries */};struct blob { unsigned char data[PAGE_SIZE]; unsigned long next;};struct iseries_flat_dt { struct boot_param_header header; u64 reserve_map[2]; struct blob dt; struct blob strings;};struct iseries_flat_dt iseries_dt;void dt_init(struct iseries_flat_dt *dt){ dt->header.off_mem_rsvmap = offsetof(struct iseries_flat_dt, reserve_map); dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt); dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings); dt->header.totalsize = sizeof(struct iseries_flat_dt); dt->header.dt_strings_size = sizeof(struct blob); /* There is no notion of hardware cpu id on iSeries */ dt->header.boot_cpuid_phys = smp_processor_id(); dt->dt.next = (unsigned long)&dt->dt.data; dt->strings.next = (unsigned long)&dt->strings.data; dt->header.magic = OF_DT_HEADER; dt->header.version = 0x10; dt->header.last_comp_version = 0x10; dt->reserve_map[0] = 0; dt->reserve_map[1] = 0;}void dt_check_blob(struct blob *b){ if (b->next >= (unsigned long)&b->next) { DBG("Ran out of space in flat device tree blob!\n"); BUG(); }}void dt_push_u32(struct iseries_flat_dt *dt, u32 value){ *((u32*)dt->dt.next) = value; dt->dt.next += sizeof(u32); dt_check_blob(&dt->dt);}void dt_push_u64(struct iseries_flat_dt *dt, u64 value){ *((u64*)dt->dt.next) = value; dt->dt.next += sizeof(u64); dt_check_blob(&dt->dt);}unsigned long dt_push_bytes(struct blob *blob, char *data, int len){ unsigned long start = blob->next - (unsigned long)blob->data; memcpy((char *)blob->next, data, len); blob->next = _ALIGN(blob->next + len, 4); dt_check_blob(blob); return start;}void dt_start_node(struct iseries_flat_dt *dt, char *name){ dt_push_u32(dt, OF_DT_BEGIN_NODE); dt_push_bytes(&dt->dt, name, strlen(name) + 1);}#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len){ unsigned long offset; dt_push_u32(dt, OF_DT_PROP); /* Length of the data */ dt_push_u32(dt, len); /* Put the property name in the string blob. */ offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1); /* The offset of the properties name in the string blob. */ dt_push_u32(dt, (u32)offset); /* The actual data. */ dt_push_bytes(&dt->dt, data, len);}void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data){ dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */}void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data){ dt_prop(dt, name, (char *)&data, sizeof(u32));}void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data){ dt_prop(dt, name, (char *)&data, sizeof(u64));}void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n){ dt_prop(dt, name, (char *)data, sizeof(u64) * n);}void dt_prop_empty(struct iseries_flat_dt *dt, char *name){ dt_prop(dt, name, NULL, 0);}void dt_cpus(struct iseries_flat_dt *dt){ unsigned char buf[32]; unsigned char *p; unsigned int i, index; struct IoHriProcessorVpd *d; /* yuck */ snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name); p = strchr(buf, ' '); if (!p) p = buf + strlen(buf); dt_start_node(dt, "cpus"); dt_prop_u32(dt, "#address-cells", 1); dt_prop_u32(dt, "#size-cells", 0); for (i = 0; i < NR_CPUS; i++) { if (paca[i].lppaca.dyn_proc_status >= 2) continue; snprintf(p, 32 - (p - buf), "@%d", i); dt_start_node(dt, buf); dt_prop_str(dt, "device_type", "cpu"); index = paca[i].lppaca.dyn_hv_phys_proc_index; d = &xIoHriProcessorVpd[index]; dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize); dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024); dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize); /* magic conversions to Hz copied from old code */ dt_prop_u32(dt, "clock-frequency", ((1UL << 34) * 1000000) / d->xProcFreq); dt_prop_u32(dt, "timebase-frequency", ((1UL << 32) * 1000000) / d->xTimeBaseFreq); dt_prop_u32(dt, "reg", i); dt_end_node(dt); } dt_end_node(dt);}void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size){ u64 tmp[2]; dt_init(dt); dt_start_node(dt, ""); dt_prop_u32(dt, "#address-cells", 2); dt_prop_u32(dt, "#size-cells", 2); /* /memory */ dt_start_node(dt, "memory@0"); dt_prop_str(dt, "name", "memory"); dt_prop_str(dt, "device_type", "memory"); tmp[0] = 0; tmp[1] = phys_mem_size; dt_prop_u64_list(dt, "reg", tmp, 2); dt_end_node(dt); /* /chosen */ dt_start_node(dt, "chosen"); dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR); if (cmd_mem_limit) dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit); dt_end_node(dt); dt_cpus(dt); dt_end_node(dt); dt_push_u32(dt, OF_DT_END);}void * __init iSeries_early_setup(void){ unsigned long phys_mem_size; iSeries_fixup_klimit(); /* * Initialize the table which translate Linux physical addresses to * AS/400 absolute addresses */ phys_mem_size = build_iSeries_Memory_Map(); iSeries_get_cmdline(); /* Save unparsed command line copy for /proc/cmdline */ strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); /* Parse early parameters, in particular mem=x */ parse_early_param(); build_flat_dt(&iseries_dt, phys_mem_size); return (void *) __pa(&iseries_dt);}/* * On iSeries we just parse the mem=X option from the command line. * On pSeries it's a bit more complicated, see prom_init_mem() */static int __init early_parsemem(char *p){ if (p) cmd_mem_limit = ALIGN(memparse(p, &p), PAGE_SIZE); return 0;}early_param("mem", early_parsemem);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -