static void setup_frame(int signr, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs) { /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ func_descr_t *funct_desc_ptr; struct sigframe *frame; unsigned long newsp; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) goto badframe; err |= setup_sigcontext(&frame->sc, regs, signr, set, (unsigned long)ka->sa.sa_handler); /* Set up to return from userspace. */ err |= setup_trampoline(__NR_sigreturn, &frame->tramp[0]); if (err) goto badframe; funct_desc_ptr = (func_descr_t *) ka->sa.sa_handler; /* Allocate a dummy caller frame for the signal handler. */ newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; err |= put_user(0, (unsigned long *)newsp); /* Set up "regs" so we "return" to the signal handler. */ err |= get_user(regs->nip, &funct_desc_ptr->entry); regs->link = (unsigned long) &frame->tramp[0]; regs->gpr[1] = newsp; err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); regs->gpr[3] = signr; regs->gpr[4] = (unsigned long) &frame->sc; if (err) goto badframe; return; badframe: #if DEBUG_SIG printk("badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif do_exit(SIGSEGV); }
/* Our close handler, 64-bit */ static int efab_linux_trampoline_close64(int fd) { /* Firstly, is this one our sockets? If not, do the usual thing */ struct file *f; int rc; TRAMP_DEBUG("close64: %d\n", fd); efab_syscall_enter(); f = fget (fd); if (f) { if (FILE_IS_ENDPOINT(f)) { /* Yep -- it's one of ours. This means current process must be using the * module (otherwise how did one of our sockets get in this proc's fd * table?). It seems it didn't get intercepted -- trampoline back up. * However, only set up trampoline if this has been called via the * correct sys-call entry point */ if (setup_trampoline (PT_REGS_FROM_SYSCALL(), CI_TRAMP_OPCODE_CLOSE, fd, TRAMPOLINE_BITS_64) == 0) { /* The trampoline will get run. Let it handle the rest. */ fput(f); efab_syscall_exit(); return 0; } } /* Undo the fget above */ fput(f); } TRAMP_DEBUG("going unto %p\n", THUNKPTR(state.replace_close->original_entry64)); /* Not one of our FDs -- usual close */ rc = ((int (*)(int))THUNKPTR(state.replace_close->original_entry64))(fd); TRAMP_DEBUG("Close64: Chain returns %d \n", rc); efab_syscall_exit(); return rc; }
int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ func_descr_t __user *funct_desc_ptr; struct rt_sigframe __user *frame; unsigned long newsp = 0; long err = 0; frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 0); if (unlikely(frame == NULL)) goto badframe; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); if (err) goto badframe; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]); #ifdef CONFIG_PPC_TRANSACTIONAL_MEM if (MSR_TM_ACTIVE(regs->msr)) { /* The ucontext_t passed to userland points to the second * ucontext_t (for transactional state) with its uc_link ptr. */ err |= __put_user(&frame->uc_transact, &frame->uc.uc_link); err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext, &frame->uc_transact.uc_mcontext, regs, signr, NULL, (unsigned long)ka->sa.sa_handler); } else #endif { err |= __put_user(0, &frame->uc.uc_link); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL, (unsigned long)ka->sa.sa_handler, 1); } err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto badframe; /* Make sure signal handler doesn't get spurious FP exceptions */ current->thread.fp_state.fpscr = 0; #ifdef CONFIG_PPC_TRANSACTIONAL_MEM /* Remove TM bits from thread's MSR. The MSR in the sigcontext * just indicates to userland that we were doing a transaction, but we * don't want to return in transactional state: */ regs->msr &= ~MSR_TS_MASK; #endif /* Set up to return from userspace. */ if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp; } else { err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); if (err) goto badframe; regs->link = (unsigned long) &frame->tramp[0]; } funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; /* Allocate a dummy caller frame for the signal handler. */ newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); /* Set up "regs" so we "return" to the signal handler. */ err |= get_user(regs->nip, &funct_desc_ptr->entry); /* enter the signal handler in big-endian mode */ regs->msr &= ~MSR_LE; regs->gpr[1] = newsp; err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); regs->gpr[3] = signr; regs->result = 0; if (ka->sa.sa_flags & SA_SIGINFO) { err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo); err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc); regs->gpr[6] = (unsigned long) frame; } else { regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext; } if (err) goto badframe; return 1; badframe: #if DEBUG_SIG printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif if (show_unhandled_signals) printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32, current->comm, current->pid, "setup_rt_frame", (long)frame, regs->nip, regs->link); force_sigsegv(signr, current); return 0; }
/** * acpi_save_state_mem - save kernel state * * Create an identity mapped page table and copy the wakeup routine to * low memory. * * Note that this is too late to change acpi_wakeup_address. */ int acpi_save_state_mem(void) { struct wakeup_header *header; if (!acpi_realmode) { printk(KERN_ERR "Could not allocate memory during boot, " "S3 disabled\n"); return -ENOMEM; } memcpy((void *)acpi_realmode, &wakeup_code_start, WAKEUP_SIZE); header = (struct wakeup_header *)(acpi_realmode + HEADER_OFFSET); if (header->signature != 0x51ee1111) { printk(KERN_ERR "wakeup header does not match\n"); return -EINVAL; } header->video_mode = saved_video_mode; header->wakeup_jmp_seg = acpi_wakeup_address >> 4; /* * Set up the wakeup GDT. We set these up as Big Real Mode, * that is, with limits set to 4 GB. At least the Lenovo * Thinkpad X61 is known to need this for the video BIOS * initialization quirk to work; this is likely to also * be the case for other laptops or integrated video devices. */ /* GDT[0]: GDT self-pointer */ header->wakeup_gdt[0] = (u64)(sizeof(header->wakeup_gdt) - 1) + ((u64)(acpi_wakeup_address + ((char *)&header->wakeup_gdt - (char *)acpi_realmode)) << 16); /* GDT[1]: big real mode-like code segment */ header->wakeup_gdt[1] = GDT_ENTRY(0x809b, acpi_wakeup_address, 0xfffff); /* GDT[2]: big real mode-like data segment */ header->wakeup_gdt[2] = GDT_ENTRY(0x8093, acpi_wakeup_address, 0xfffff); #ifndef CONFIG_64BIT store_gdt((struct desc_ptr *)&header->pmode_gdt); header->pmode_efer_low = nx_enabled; if (header->pmode_efer_low & 1) { /* This is strange, why not save efer, always? */ rdmsr(MSR_EFER, header->pmode_efer_low, header->pmode_efer_high); } #endif /* !CONFIG_64BIT */ header->pmode_cr0 = read_cr0(); header->pmode_cr4 = read_cr4_safe(); header->realmode_flags = acpi_realmode_flags; header->real_magic = 0x12345678; #ifndef CONFIG_64BIT header->pmode_entry = (u32)&wakeup_pmode_return; header->pmode_cr3 = (u32)(swsusp_pg_dir - __PAGE_OFFSET); saved_magic = 0x12345678; #else /* CONFIG_64BIT */ header->trampoline_segment = setup_trampoline() >> 4; #ifdef CONFIG_SMP stack_start.sp = temp_stack + sizeof(temp_stack); early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(smp_processor_id()); #endif initial_code = (unsigned long)wakeup_long64; saved_magic = 0x123456789abcdef0; #endif /* CONFIG_64BIT */ return 0; }
int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, struct task_struct *tsk) { struct rt_sigframe __user *frame; unsigned long newsp = 0; long err = 0; struct pt_regs *regs = tsk->thread.regs; BUG_ON(tsk != current); frame = get_sigframe(ksig, get_tm_stackpointer(tsk), sizeof(*frame), 0); if (unlikely(frame == NULL)) goto badframe; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, &ksig->info); if (err) goto badframe; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]); #ifdef CONFIG_PPC_TRANSACTIONAL_MEM if (MSR_TM_ACTIVE(regs->msr)) { /* The ucontext_t passed to userland points to the second * ucontext_t (for transactional state) with its uc_link ptr. */ err |= __put_user(&frame->uc_transact, &frame->uc.uc_link); err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext, &frame->uc_transact.uc_mcontext, tsk, ksig->sig, NULL, (unsigned long)ksig->ka.sa.sa_handler); } else #endif { err |= __put_user(0, &frame->uc.uc_link); err |= setup_sigcontext(&frame->uc.uc_mcontext, tsk, ksig->sig, NULL, (unsigned long)ksig->ka.sa.sa_handler, 1); } err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto badframe; /* Make sure signal handler doesn't get spurious FP exceptions */ tsk->thread.fp_state.fpscr = 0; /* Set up to return from userspace. */ if (vdso64_rt_sigtramp && tsk->mm->context.vdso_base) { regs->link = tsk->mm->context.vdso_base + vdso64_rt_sigtramp; } else { err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); if (err) goto badframe; regs->link = (unsigned long) &frame->tramp[0]; } /* Allocate a dummy caller frame for the signal handler. */ newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); /* Set up "regs" so we "return" to the signal handler. */ if (is_elf2_task()) { regs->nip = (unsigned long) ksig->ka.sa.sa_handler; regs->gpr[12] = regs->nip; } else { /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ func_descr_t __user *funct_desc_ptr = (func_descr_t __user *) ksig->ka.sa.sa_handler; err |= get_user(regs->nip, &funct_desc_ptr->entry); err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); } /* enter the signal handler in native-endian mode */ regs->msr &= ~MSR_LE; regs->msr |= (MSR_KERNEL & MSR_LE); regs->gpr[1] = newsp; regs->gpr[3] = ksig->sig; regs->result = 0; if (ksig->ka.sa.sa_flags & SA_SIGINFO) { err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo); err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc); regs->gpr[6] = (unsigned long) frame; } else { regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext; } if (err) goto badframe; return 0; badframe: if (show_unhandled_signals) printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32, tsk->comm, tsk->pid, "setup_rt_frame", (long)frame, regs->nip, regs->link); return 1; }
int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ func_descr_t __user *funct_desc_ptr; struct rt_sigframe __user *frame; unsigned long newsp = 0; long err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); if (unlikely(frame == NULL)) goto badframe; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); if (err) goto badframe; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->gpr[1]), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL, (unsigned long)ka->sa.sa_handler); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto badframe; /* Make sure signal handler doesn't get spurious FP exceptions */ current->thread.fpscr.val = 0; /* Set up to return from userspace. */ if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp; } else { err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); if (err) goto badframe; regs->link = (unsigned long) &frame->tramp[0]; } funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; /* Allocate a dummy caller frame for the signal handler. */ newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); /* Set up "regs" so we "return" to the signal handler. */ err |= get_user(regs->nip, &funct_desc_ptr->entry); /* enter the signal handler in big-endian mode */ regs->msr &= ~MSR_LE; regs->gpr[1] = newsp; err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); regs->gpr[3] = signr; regs->result = 0; if (ka->sa.sa_flags & SA_SIGINFO) { err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo); err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc); regs->gpr[6] = (unsigned long) frame; } else { regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext; } if (err) goto badframe; return 1; badframe: #if DEBUG_SIG printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif force_sigsegv(signr, current); return 0; }
int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { func_descr_t __user *funct_desc_ptr; struct rt_sigframe __user *frame; unsigned long newsp = 0; long err = 0; frame = get_sigframe(ka, regs, sizeof(*frame), 0); if (unlikely(frame == NULL)) goto badframe; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); if (err) goto badframe; err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->gpr[1]), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL, (unsigned long)ka->sa.sa_handler, 1); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto badframe; current->thread.fpscr.val = 0; if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp; } else { err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); if (err) goto badframe; regs->link = (unsigned long) &frame->tramp[0]; } funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); err |= get_user(regs->nip, &funct_desc_ptr->entry); regs->msr &= ~MSR_LE; regs->gpr[1] = newsp; err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); regs->gpr[3] = signr; regs->result = 0; if (ka->sa.sa_flags & SA_SIGINFO) { err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo); err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc); regs->gpr[6] = (unsigned long) frame; } else { regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext; } if (err) goto badframe; return 1; badframe: #if DEBUG_SIG printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif if (show_unhandled_signals) printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32, current->comm, current->pid, "setup_rt_frame", (long)frame, regs->nip, regs->link); force_sigsegv(signr, current); return 0; }
static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ func_descr_t *funct_desc_ptr; struct rt_sigframe *frame; unsigned long newsp; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); if (err) goto give_sigsegv; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->gpr[1]), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL, (unsigned long)ka->sa.sa_handler); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto give_sigsegv; /* Set up to return from userspace. */ err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); if (err) goto give_sigsegv; funct_desc_ptr = (func_descr_t *) ka->sa.sa_handler; /* Allocate a dummy caller frame for the signal handler. */ newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; err |= put_user(0, (unsigned long *)newsp); /* Set up "regs" so we "return" to the signal handler. */ err |= get_user(regs->nip, &funct_desc_ptr->entry); regs->link = (unsigned long) &frame->tramp[0]; regs->gpr[1] = newsp; err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); regs->gpr[3] = signr; err |= get_user(regs->gpr[4], (unsigned long *)&frame->pinfo); err |= get_user(regs->gpr[5], (unsigned long *)&frame->puc); regs->gpr[6] = (unsigned long) frame; if (err) goto give_sigsegv; return; give_sigsegv: #if DEBUG_SIG printk("badframe in setup_rt_frame, regs=%p frame=%p, newsp=0x%lx\n", regs, frame, newsp); #endif do_exit(SIGSEGV); }
static int __init do_boot_cpu(int apicid) /* * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad * (ie clustered apic addressing mode), this is a LOGICAL apic ID. * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu. */ { struct task_struct *idle; unsigned long boot_error; int timeout, cpu; unsigned long start_eip; unsigned short nmi_high = 0, nmi_low = 0; cpu = ++cpucount; /* * We can't use kernel_thread since we must avoid to * reschedule the child. */ idle = fork_idle(cpu); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); idle->thread.eip = (unsigned long) start_secondary; /* start_eip had better be page-aligned! */ start_eip = setup_trampoline(); /* So we see what's up */ printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); /* Stack for startup_32 can be just as for start_secondary onwards */ stack_start.esp = (void *) idle->thread.esp; irq_ctx_init(cpu); /* * This grunge runs the startup process for * the targeted processor. */ atomic_set(&init_deasserted, 0); Dprintk("Setting warm reset code and vector.\n"); store_NMI_vector(&nmi_high, &nmi_low); smpboot_setup_warm_reset_vector(start_eip); /* * Starting actual IPI sequence... */ boot_error = wakeup_secondary_cpu(apicid, start_eip); if (!boot_error) { /* * allow APs to start initializing. */ Dprintk("Before Callout %d.\n", cpu); cpu_set(cpu, cpu_callout_map); Dprintk("After Callout %d.\n", cpu); /* * Wait 5s total for a response */ for (timeout = 0; timeout < 50000; timeout++) { if (cpu_isset(cpu, cpu_callin_map)) break; /* It has booted */ udelay(100); } if (cpu_isset(cpu, cpu_callin_map)) { /* number CPUs logically, starting from 1 (BSP is 0) */ Dprintk("OK.\n"); printk("CPU%d: ", cpu); print_cpu_info(&cpu_data[cpu]); Dprintk("CPU has booted.\n"); } else { boot_error= 1; if (*((volatile unsigned char *)trampoline_base) == 0xA5) /* trampoline started but...? */ printk("Stuck ??\n"); else /* trampoline code not run */ printk("Not responding.\n"); inquire_remote_apic(apicid); } } x86_cpu_to_apicid[cpu] = apicid; if (boot_error) { /* Try to put things back the way they were before ... */ unmap_cpu_to_logical_apicid(cpu); cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */ cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */ cpucount--; } /* mark "stuck" area as not stuck */ *((volatile unsigned long *)trampoline_base) = 0; return boot_error; }
static void __init do_boot_cpu (int apicid) { struct task_struct *idle; unsigned long boot_error; int timeout, cpu; unsigned long start_rip; cpu = ++cpucount; /* * We can't use kernel_thread since we must avoid to * reschedule the child. */ idle = fork_idle(cpu); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); x86_cpu_to_apicid[cpu] = apicid; cpu_pda[cpu].pcurrent = idle; start_rip = setup_trampoline(); init_rsp = idle->thread.rsp; per_cpu(init_tss,cpu).rsp0 = init_rsp; initial_code = start_secondary; clear_ti_thread_flag(idle->thread_info, TIF_FORK); printk(KERN_INFO "Booting processor %d/%d rip %lx rsp %lx\n", cpu, apicid, start_rip, init_rsp); /* * This grunge runs the startup process for * the targeted processor. */ atomic_set(&init_deasserted, 0); Dprintk("Setting warm reset code and vector.\n"); CMOS_WRITE(0xa, 0xf); local_flush_tlb(); Dprintk("1.\n"); *((volatile unsigned short *) phys_to_virt(0x469)) = start_rip >> 4; Dprintk("2.\n"); *((volatile unsigned short *) phys_to_virt(0x467)) = start_rip & 0xf; Dprintk("3.\n"); /* * Be paranoid about clearing APIC errors. */ if (APIC_INTEGRATED(apic_version[apicid])) { apic_read_around(APIC_SPIV); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); } /* * Status is now clean */ boot_error = 0; /* * Starting actual IPI sequence... */ boot_error = wakeup_secondary_via_INIT(apicid, start_rip); if (!boot_error) { /* * allow APs to start initializing. */ Dprintk("Before Callout %d.\n", cpu); cpu_set(cpu, cpu_callout_map); Dprintk("After Callout %d.\n", cpu); /* * Wait 5s total for a response */ for (timeout = 0; timeout < 50000; timeout++) { if (cpu_isset(cpu, cpu_callin_map)) break; /* It has booted */ udelay(100); } if (cpu_isset(cpu, cpu_callin_map)) { /* number CPUs logically, starting from 1 (BSP is 0) */ Dprintk("OK.\n"); print_cpu_info(&cpu_data[cpu]); Dprintk("CPU has booted.\n"); } else { boot_error = 1; if (*((volatile unsigned char *)phys_to_virt(SMP_TRAMPOLINE_BASE)) == 0xA5) /* trampoline started but...? */ printk("Stuck ??\n"); else /* trampoline code not run */ printk("Not responding.\n"); #if APIC_DEBUG inquire_remote_apic(apicid); #endif } } if (boot_error) { cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */ clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */ cpucount--; x86_cpu_to_apicid[cpu] = BAD_APICID; x86_cpu_to_log_apicid[cpu] = BAD_APICID; } }
/** * acpi_save_state_mem - save kernel state * * Create an identity mapped page table and copy the wakeup routine to * low memory. * * Note that this is too late to change acpi_wakeup_address. */ int acpi_save_state_mem(void) { struct wakeup_header *header; if (!acpi_realmode) { printk(KERN_ERR "Could not allocate memory during boot, " "S3 disabled\n"); return -ENOMEM; } memcpy((void *)acpi_realmode, &wakeup_code_start, WAKEUP_SIZE); header = (struct wakeup_header *)(acpi_realmode + HEADER_OFFSET); if (header->signature != 0x51ee1111) { printk(KERN_ERR "wakeup header does not match\n"); return -EINVAL; } header->video_mode = saved_video_mode; header->wakeup_jmp_seg = acpi_wakeup_address >> 4; /* GDT[0]: GDT self-pointer */ header->wakeup_gdt[0] = (u64)(sizeof(header->wakeup_gdt) - 1) + ((u64)(acpi_wakeup_address + ((char *)&header->wakeup_gdt - (char *)acpi_realmode)) << 16); /* GDT[1]: real-mode-like code segment */ header->wakeup_gdt[1] = GDT_ENTRY(0x809b, acpi_wakeup_address, 0xfffff); /* GDT[2]: real-mode-like data segment */ header->wakeup_gdt[2] = GDT_ENTRY(0x8093, acpi_wakeup_address, 0xfffff); #ifndef CONFIG_64BIT store_gdt((struct desc_ptr *)&header->pmode_gdt); header->pmode_efer_low = nx_enabled; if (header->pmode_efer_low & 1) { /* This is strange, why not save efer, always? */ rdmsr(MSR_EFER, header->pmode_efer_low, header->pmode_efer_high); } #endif /* !CONFIG_64BIT */ header->pmode_cr0 = read_cr0(); header->pmode_cr4 = read_cr4(); header->realmode_flags = acpi_realmode_flags; header->real_magic = 0x12345678; #ifndef CONFIG_64BIT header->pmode_entry = (u32)&wakeup_pmode_return; header->pmode_cr3 = (u32)(swsusp_pg_dir - __PAGE_OFFSET); saved_magic = 0x12345678; #else /* CONFIG_64BIT */ header->trampoline_segment = setup_trampoline() >> 4; init_rsp = (unsigned long)temp_stack + 4096; initial_code = (unsigned long)wakeup_long64; saved_magic = 0x123456789abcdef0; #endif /* CONFIG_64BIT */ return 0; }