/* * Start kdump: We expect here that a store status has been done on our CPU */ static void __do_machine_kdump(void *image) { int (*start_kdump)(int) = (void *)((struct kimage *) image)->start; __load_psw_mask(PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA); start_kdump(1); }
/* * paging_init() sets up the page tables */ void __init paging_init(void) { unsigned long max_zone_pfns[MAX_NR_ZONES]; unsigned long pgd_type, asce_bits; psw_t psw; init_mm.pgd = swapper_pg_dir; if (VMALLOC_END > _REGION2_SIZE) { asce_bits = _ASCE_TYPE_REGION2 | _ASCE_TABLE_LENGTH; pgd_type = _REGION2_ENTRY_EMPTY; } else { asce_bits = _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH; pgd_type = _REGION3_ENTRY_EMPTY; } init_mm.context.asce = (__pa(init_mm.pgd) & PAGE_MASK) | asce_bits; S390_lowcore.kernel_asce = init_mm.context.asce; crst_table_init((unsigned long *) init_mm.pgd, pgd_type); vmem_map_init(); /* enable virtual mapping in kernel mode */ __ctl_load(S390_lowcore.kernel_asce, 1, 1); __ctl_load(S390_lowcore.kernel_asce, 7, 7); __ctl_load(S390_lowcore.kernel_asce, 13, 13); psw.mask = __extract_psw(); psw_bits(psw).dat = 1; psw_bits(psw).as = PSW_BITS_AS_HOME; __load_psw_mask(psw.mask); sparse_memory_present_with_active_regions(MAX_NUMNODES); sparse_init(); memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS); max_zone_pfns[ZONE_NORMAL] = max_low_pfn; free_area_init_nodes(max_zone_pfns); }
void smp_switch_to_ipl_cpu(void (*func)(void *), void *data) { struct _lowcore *lc, *current_lc; struct stack_frame *sf; struct pt_regs *regs; unsigned long sp; if (smp_processor_id() == 0) func(data); __load_psw_mask(PSW_BASE_BITS | PSW_DEFAULT_KEY); /* Disable lowcore protection */ __ctl_clear_bit(0, 28); current_lc = lowcore_ptr[smp_processor_id()]; lc = lowcore_ptr[0]; if (!lc) lc = current_lc; lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) smp_restart_cpu; if (!cpu_online(0)) smp_switch_to_cpu(func, data, 0, stap(), __cpu_logical_map[0]); while (sigp(0, sigp_stop_and_store_status) == sigp_busy) cpu_relax(); sp = lc->panic_stack; sp -= sizeof(struct pt_regs); regs = (struct pt_regs *) sp; memcpy(®s->gprs, ¤t_lc->gpregs_save_area, sizeof(regs->gprs)); regs->psw = lc->psw_save_area; sp -= STACK_FRAME_OVERHEAD; sf = (struct stack_frame *) sp; sf->back_chain = regs->gprs[15]; smp_switch_to_cpu(func, data, sp, stap(), __cpu_logical_map[0]); }
/* * Reset the system, copy boot CPU registers to absolute zero, * and jump to the kdump image */ static void __do_machine_kdump(void *image) { int (*start_kdump)(int); unsigned long prefix; /* store_status() saved the prefix register to lowcore */ prefix = (unsigned long) S390_lowcore.prefixreg_save_area; /* Now do the reset */ s390_reset_system(); /* * Copy dump CPU store status info to absolute zero. * This need to be done *after* s390_reset_system set the * prefix register of this CPU to zero */ memcpy((void *) __LC_FPREGS_SAVE_AREA, (void *)(prefix + __LC_FPREGS_SAVE_AREA), 512); __load_psw_mask(PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA); start_kdump = (void *)((struct kimage *) image)->start; start_kdump(1); /* Die if start_kdump returns */ disabled_wait((unsigned long) __builtin_return_address(0)); }
/* * Start kdump: We expect here that a store status has been done on our CPU */ static void __do_machine_kdump(void *image) { #ifdef CONFIG_CRASH_DUMP int (*start_kdump)(int) = (void *)((struct kimage *) image)->start; setup_regs(); __load_psw_mask(PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA); start_kdump(1); #endif }
static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) { int rc; __ctl_set_bit(0, 9); rc = sclp_service_call(cmd, sccb); if (rc) goto out; __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT | PSW_MASK_WAIT | PSW_DEFAULT_KEY); local_irq_disable(); out: /* Contents of the sccb might have changed. */ barrier(); __ctl_clear_bit(0, 9); return rc; }
static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) { int rc; __ctl_set_bit(0, 9); rc = sclp_service_call(cmd, sccb); if (rc) goto out; __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT); local_irq_disable(); out: barrier(); __ctl_clear_bit(0, 9); return rc; }
/* * Ensure that PSW restart is done on an online CPU */ void smp_restart_with_online_cpu(void) { int cpu; for_each_online_cpu(cpu) { if (stap() == __cpu_logical_map[cpu]) { /* We are online: Enable DAT again and return */ __load_psw_mask(psw_kernel_bits | PSW_MASK_DAT); return; } } /* We are not online: Do PSW restart on an online CPU */ while (sigp(cpu, sigp_restart) == sigp_busy) cpu_relax(); /* And stop ourself */ while (raw_sigp(stap(), sigp_stop) == sigp_busy) cpu_relax(); for (;;); }
void smp_send_stop(void) { int cpu, rc; /* Disable all interrupts/machine checks */ __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); trace_hardirqs_off(); /* stop all processors */ for_each_online_cpu(cpu) { if (cpu == smp_processor_id()) continue; do { rc = sigp(cpu, sigp_stop); } while (rc == sigp_busy); while (!cpu_stopped(cpu)) cpu_relax(); } }