📄 setup.c
字号:
ppc64_interrupt_controller = IC_INVALID; for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) { typep = (char *)get_property(np, "compatible", NULL); if (strstr(typep, "open-pic")) ppc64_interrupt_controller = IC_OPEN_PIC; else if (strstr(typep, "ppc-xicp")) ppc64_interrupt_controller = IC_PPC_XIC; else printk("pSeries_discover_pic: failed to recognize" " interrupt-controller\n"); break; }}static void pSeries_mach_cpu_die(void){ local_irq_disable(); idle_task_exit(); /* Some hardware requires clearing the CPPR, while other hardware does not * it is safe either way */ pSeriesLP_cppr_info(0, 0); rtas_stop_self(); /* Should never get here... */ BUG(); for(;;);}static int pseries_set_dabr(unsigned long dabr){ return plpar_hcall_norets(H_SET_DABR, dabr);}static int pseries_set_xdabr(unsigned long dabr){ /* We want to catch accesses from kernel and userspace */ return plpar_hcall_norets(H_SET_XDABR, dabr, H_DABRX_KERNEL | H_DABRX_USER);}/* * Early initialization. Relocation is on but do not reference unbolted pages */static void __init pSeries_init_early(void){ void *comport; int iommu_off = 0; unsigned int default_speed; u64 physport; DBG(" -> pSeries_init_early()\n"); fw_feature_init(); if (platform_is_lpar()) hpte_init_lpar(); else { hpte_init_native(); iommu_off = (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)); } generic_find_legacy_serial_ports(&physport, &default_speed); if (platform_is_lpar()) find_udbg_vterm(); else if (physport) { /* Map the uart for udbg. */ comport = (void *)ioremap(physport, 16); udbg_init_uart(comport, default_speed); DBG("Hello World !\n"); } if (firmware_has_feature(FW_FEATURE_DABR)) ppc_md.set_dabr = pseries_set_dabr; else if (firmware_has_feature(FW_FEATURE_XDABR)) ppc_md.set_dabr = pseries_set_xdabr; iommu_init_early_pSeries(); pSeries_discover_pic(); DBG(" <- pSeries_init_early()\n");}static int pSeries_check_legacy_ioport(unsigned int baseport){ struct device_node *np;#define I8042_DATA_REG 0x60#define FDC_BASE 0x3f0 switch(baseport) { case I8042_DATA_REG: np = of_find_node_by_type(NULL, "8042"); if (np == NULL) return -ENODEV; of_node_put(np); break; case FDC_BASE: np = of_find_node_by_type(NULL, "fdc"); if (np == NULL) return -ENODEV; of_node_put(np); break; } return 0;}/* * Called very early, MMU is off, device-tree isn't unflattened */extern struct machdep_calls pSeries_md;static int __init pSeries_probe(int platform){ if (platform != PLATFORM_PSERIES && platform != PLATFORM_PSERIES_LPAR) return 0; /* if we have some ppc_md fixups for LPAR to do, do * it here ... */ return 1;}DECLARE_PER_CPU(unsigned long, smt_snooze_delay);static inline void dedicated_idle_sleep(unsigned int cpu){ struct paca_struct *ppaca = &paca[cpu ^ 1]; /* Only sleep if the other thread is not idle */ if (!(ppaca->lppaca.idle)) { local_irq_disable(); /* * We are about to sleep the thread and so wont be polling any * more. */ clear_thread_flag(TIF_POLLING_NRFLAG); smp_mb__after_clear_bit(); /* * SMT dynamic mode. Cede will result in this thread going * dormant, if the partner thread is still doing work. Thread * wakes up if partner goes idle, an interrupt is presented, or * a prod occurs. Returning from the cede enables external * interrupts. */ if (!need_resched()) cede_processor(); else local_irq_enable(); set_thread_flag(TIF_POLLING_NRFLAG); } else { /* * Give the HV an opportunity at the processor, since we are * not doing any work. */ poll_pending(); }}static void pseries_dedicated_idle(void){ struct paca_struct *lpaca = get_paca(); unsigned int cpu = smp_processor_id(); unsigned long start_snooze; unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay); set_thread_flag(TIF_POLLING_NRFLAG); while (1) { /* * Indicate to the HV that we are idle. Now would be * a good time to find other work to dispatch. */ lpaca->lppaca.idle = 1; if (!need_resched()) { start_snooze = get_tb() + *smt_snooze_delay * tb_ticks_per_usec; while (!need_resched() && !cpu_is_offline(cpu)) { ppc64_runlatch_off(); /* * Go into low thread priority and possibly * low power mode. */ HMT_low(); HMT_very_low(); if (*smt_snooze_delay != 0 && get_tb() > start_snooze) { HMT_medium(); dedicated_idle_sleep(cpu); } } HMT_medium(); } lpaca->lppaca.idle = 0; ppc64_runlatch_on(); preempt_enable_no_resched(); schedule(); preempt_disable(); if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) cpu_die(); }}static void pseries_shared_idle(void){ struct paca_struct *lpaca = get_paca(); unsigned int cpu = smp_processor_id(); while (1) { /* * Indicate to the HV that we are idle. Now would be * a good time to find other work to dispatch. */ lpaca->lppaca.idle = 1; while (!need_resched() && !cpu_is_offline(cpu)) { local_irq_disable(); ppc64_runlatch_off(); /* * Yield the processor to the hypervisor. We return if * an external interrupt occurs (which are driven prior * to returning here) or if a prod occurs from another * processor. When returning here, external interrupts * are enabled. * * Check need_resched() again with interrupts disabled * to avoid a race. */ if (!need_resched()) cede_processor(); else local_irq_enable(); HMT_medium(); } lpaca->lppaca.idle = 0; ppc64_runlatch_on(); preempt_enable_no_resched(); schedule(); preempt_disable(); if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) cpu_die(); }}static int pSeries_pci_probe_mode(struct pci_bus *bus){ if (platform_is_lpar()) return PCI_PROBE_DEVTREE; return PCI_PROBE_NORMAL;}#ifdef CONFIG_KEXECstatic void pseries_kexec_cpu_down(int crash_shutdown, int secondary){ /* Don't risk a hypervisor call if we're crashing */ if (!crash_shutdown) { unsigned long vpa = __pa(&get_paca()->lppaca); if (unregister_vpa(hard_smp_processor_id(), vpa)) { printk("VPA deregistration of cpu %u (hw_cpu_id %d) " "failed\n", smp_processor_id(), hard_smp_processor_id()); } } if (ppc64_interrupt_controller == IC_OPEN_PIC) mpic_teardown_this_cpu(secondary); else xics_teardown_cpu(secondary);}#endifstruct machdep_calls __initdata pSeries_md = { .probe = pSeries_probe, .setup_arch = pSeries_setup_arch, .init_early = pSeries_init_early, .show_cpuinfo = pSeries_show_cpuinfo, .log_error = pSeries_log_error, .pcibios_fixup = pSeries_final_fixup, .pci_probe_mode = pSeries_pci_probe_mode, .irq_bus_setup = pSeries_irq_bus_setup, .restart = rtas_restart, .power_off = rtas_power_off, .halt = rtas_halt, .panic = rtas_os_term, .cpu_die = pSeries_mach_cpu_die, .get_boot_time = rtas_get_boot_time, .get_rtc_time = rtas_get_rtc_time, .set_rtc_time = rtas_set_rtc_time, .calibrate_decr = generic_calibrate_decr, .progress = rtas_progress, .check_legacy_ioport = pSeries_check_legacy_ioport, .system_reset_exception = pSeries_system_reset_exception, .machine_check_exception = pSeries_machine_check_exception,#ifdef CONFIG_KEXEC .kexec_cpu_down = pseries_kexec_cpu_down,#endif};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -