static int save_task_regs(CoreEntry *core, user_regs_struct_t *regs, user_fpregs_struct_t *fpregs) { // Save the ARM CPU state assign_reg(core->ti_arm->gpregs, regs, r0); assign_reg(core->ti_arm->gpregs, regs, r1); assign_reg(core->ti_arm->gpregs, regs, r2); assign_reg(core->ti_arm->gpregs, regs, r3); assign_reg(core->ti_arm->gpregs, regs, r4); assign_reg(core->ti_arm->gpregs, regs, r5); assign_reg(core->ti_arm->gpregs, regs, r6); assign_reg(core->ti_arm->gpregs, regs, r7); assign_reg(core->ti_arm->gpregs, regs, r8); assign_reg(core->ti_arm->gpregs, regs, r9); assign_reg(core->ti_arm->gpregs, regs, r10); assign_reg(core->ti_arm->gpregs, regs, fp); assign_reg(core->ti_arm->gpregs, regs, ip); assign_reg(core->ti_arm->gpregs, regs, sp); assign_reg(core->ti_arm->gpregs, regs, lr); assign_reg(core->ti_arm->gpregs, regs, pc); assign_reg(core->ti_arm->gpregs, regs, cpsr); core->ti_arm->gpregs->orig_r0 = regs->ARM_ORIG_r0; // Save the VFP state memcpy(CORE_THREAD_ARCH_INFO(core)->fpstate->vfp_regs, &fpregs->fpregs, sizeof(fpregs->fpregs)); CORE_THREAD_ARCH_INFO(core)->fpstate->fpscr = fpregs->fpscr; return 0; }
int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core) { struct aux_sigframe *aux = (struct aux_sigframe *)&sigframe->sig.uc.uc_regspace; memcpy(&aux->vfp.ufp.fpregs, CORE_THREAD_ARCH_INFO(core)->fpstate->vfp_regs, sizeof(aux->vfp.ufp.fpregs)); aux->vfp.ufp.fpscr = CORE_THREAD_ARCH_INFO(core)->fpstate->fpscr; aux->vfp.magic = VFP_MAGIC; aux->vfp.size = VFP_STORAGE_SIZE; return 0; }
int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core) { int ret = 0; if (CORE_THREAD_ARCH_INFO(core)->fpstate) put_fpu_regs(&sigframe->uc.uc_mcontext, CORE_THREAD_ARCH_INFO(core)->fpstate); if (CORE_THREAD_ARCH_INFO(core)->vrstate) ret = put_altivec_regs(&sigframe->uc.uc_mcontext, CORE_THREAD_ARCH_INFO(core)->vrstate); else if (core->ti_ppc64->gpregs->msr & MSR_VEC) { pr_err("Register's data mismatch, corrupted image ?\n"); ret = -1; } if (!ret && CORE_THREAD_ARCH_INFO(core)->vsxstate) ret = put_vsx_regs(&sigframe->uc.uc_mcontext, CORE_THREAD_ARCH_INFO(core)->vsxstate); else if (core->ti_ppc64->gpregs->msr & MSR_VSX) { pr_err("VSX register's data mismatch, corrupted image ?\n"); ret = -1; } if (!ret && CORE_THREAD_ARCH_INFO(core)->tmstate) ret = put_tm_regs(sigframe, CORE_THREAD_ARCH_INFO(core)->tmstate); else if (MSR_TM_ACTIVE(core->ti_ppc64->gpregs->msr)) { pr_err("TM register's data mismatch, corrupted image ?\n"); ret = -1; } return ret; }
int construct_sigframe(struct rt_sigframe *sigframe, struct rt_sigframe *rsigframe, k_rtsigset_t *blkset, CoreEntry *core) { /* * Copy basic register set in the first place: this will set * rt_sigframe type: native/compat. */ if (restore_gpregs(sigframe, CORE_THREAD_ARCH_INFO(core)->gpregs)) return -1; if (blkset) rt_sigframe_copy_sigset(sigframe, blkset); else rt_sigframe_erase_sigset(sigframe); if (restore_fpu(sigframe, core)) return -1; if (RT_SIGFRAME_HAS_FPU(sigframe)) if (sigreturn_prep_fpu_frame(sigframe, rsigframe)) return -1; setup_sas(sigframe, core->thread_core->sas); return 0; }
int arch_alloc_thread_info(CoreEntry *core) { ThreadInfoPpc64 *ti_ppc64; UserPpc64RegsEntry *regs; ti_ppc64 = xmalloc(sizeof(*ti_ppc64)); if(!ti_ppc64) goto err; thread_info_ppc64__init(ti_ppc64); CORE_THREAD_ARCH_INFO(core) = ti_ppc64; /* user_ppc64_regs_entry */ regs = xmalloc(sizeof(*regs)); if (!regs) goto err; user_ppc64_regs_entry__init(regs); regs->gpr = xmalloc(32*sizeof(uint64_t)); if (!regs->gpr) goto err; regs->n_gpr = 32; ti_ppc64->gpregs = regs; return 0; err: return -1; }
int construct_sigframe(struct rt_sigframe *sigframe, struct rt_sigframe *rsigframe, CoreEntry *core) { k_rtsigset_t *blk_sigset = (k_rtsigset_t*)&RT_SIGFRAME_UC(sigframe).uc_sigmask; if (core->tc) memcpy(blk_sigset, &core->tc->blk_sigset, sizeof(k_rtsigset_t)); else if (core->thread_core->has_blk_sigset) { memcpy(blk_sigset, &core->thread_core->blk_sigset, sizeof(k_rtsigset_t)); } else memset(blk_sigset, 0, sizeof(k_rtsigset_t)); if (restore_fpu(sigframe, core)) return -1; if (RT_SIGFRAME_HAS_FPU(sigframe)) if (sigreturn_prep_fpu_frame(sigframe, &RT_SIGFRAME_FPU(rsigframe))) return -1; if (restore_gpregs(sigframe, CORE_THREAD_ARCH_INFO(core)->gpregs)) return -1; setup_sas(sigframe, core->thread_core->sas); return 0; }
void arch_free_thread_info(CoreEntry *core) { if (CORE_THREAD_ARCH_INFO(core)) { if (CORE_THREAD_ARCH_INFO(core)->fpsimd) { xfree(CORE_THREAD_ARCH_INFO(core)->fpsimd->vregs); xfree(CORE_THREAD_ARCH_INFO(core)->fpsimd); } xfree(CORE_THREAD_ARCH_INFO(core)->gpregs->regs); xfree(CORE_THREAD_ARCH_INFO(core)->gpregs); xfree(CORE_THREAD_ARCH_INFO(core)); CORE_THREAD_ARCH_INFO(core) = NULL; } }
int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core) { int ret = 0; if (CORE_THREAD_ARCH_INFO(core)->fpstate) put_fpu_regs(&sigframe->uc.uc_mcontext, CORE_THREAD_ARCH_INFO(core)->fpstate); if (CORE_THREAD_ARCH_INFO(core)->vrstate) ret = put_altivec_regs(&sigframe->uc.uc_mcontext, CORE_THREAD_ARCH_INFO(core)->vrstate); else if (core->ti_ppc64->gpregs->msr & MSR_VEC) { pr_err("Internal error\n"); ret = -1; } if (!ret && CORE_THREAD_ARCH_INFO(core)->vsxstate) ret = put_vsx_regs(&sigframe->uc.uc_mcontext, CORE_THREAD_ARCH_INFO(core)->vsxstate); else if (core->ti_ppc64->gpregs->msr & MSR_VSX) { pr_err("Internal error\n"); ret = -1; } return ret; }
void arch_free_thread_info(CoreEntry *core) { if (CORE_THREAD_ARCH_INFO(core)) { if (CORE_THREAD_ARCH_INFO(core)->fpstate) { xfree(CORE_THREAD_ARCH_INFO(core)->fpstate->vfp_regs); xfree(CORE_THREAD_ARCH_INFO(core)->fpstate); } xfree(CORE_THREAD_ARCH_INFO(core)->gpregs); xfree(CORE_THREAD_ARCH_INFO(core)); CORE_THREAD_ARCH_INFO(core) = NULL; } }
int parasite_dump_thread_seized(struct parasite_ctl *ctl, struct pid *tid, CoreEntry *core) { struct parasite_dump_thread *args; int ret; args = parasite_args(ctl, struct parasite_dump_thread); ret = parasite_execute_by_pid(PARASITE_CMD_DUMP_THREAD, ctl, tid->real); memcpy(&core->thread_core->blk_sigset, &args->blocked, sizeof(args->blocked)); CORE_THREAD_ARCH_INFO(core)->clear_tid_addr = encode_pointer(args->tid_addr); tid->virt = args->tid; core_put_tls(core, args->tls); return ret; }
int arch_alloc_thread_info(CoreEntry *core) { ThreadInfoPpc64 *ti_ppc64; ti_ppc64 = xmalloc(sizeof(*ti_ppc64)); if(!ti_ppc64) return -1; thread_info_ppc64__init(ti_ppc64); ti_ppc64->gpregs = allocate_gp_regs(); if (!ti_ppc64->gpregs) { xfree(ti_ppc64); return -1; } CORE_THREAD_ARCH_INFO(core) = ti_ppc64; return 0; }
void arch_free_thread_info(CoreEntry *core) { if (CORE_THREAD_ARCH_INFO(core)) { if (CORE_THREAD_ARCH_INFO(core)->fpstate) { xfree(CORE_THREAD_ARCH_INFO(core)->fpstate->fpregs); xfree(CORE_THREAD_ARCH_INFO(core)->fpstate); } if (CORE_THREAD_ARCH_INFO(core)->vrstate) { xfree(CORE_THREAD_ARCH_INFO(core)->vrstate->vrregs); xfree(CORE_THREAD_ARCH_INFO(core)->vrstate); } if (CORE_THREAD_ARCH_INFO(core)->vsxstate) { xfree(CORE_THREAD_ARCH_INFO(core)->vsxstate->vsxregs); xfree(CORE_THREAD_ARCH_INFO(core)->vsxstate); } xfree_tm_state(CORE_THREAD_ARCH_INFO(core)->tmstate); xfree(CORE_THREAD_ARCH_INFO(core)->gpregs->gpr); xfree(CORE_THREAD_ARCH_INFO(core)->gpregs); xfree(CORE_THREAD_ARCH_INFO(core)); CORE_THREAD_ARCH_INFO(core) = NULL; } }
int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core) { int i; pr_info("Dumping GP/FPU registers for %d\n", pid); /* * This is inspired by kernel function check_syscall_restart in * arch/powerpc/kernel/signal.c */ #ifndef TRAP #define TRAP(r) ((r).trap & ~0xF) #endif if (TRAP(regs) == 0x0C00 && regs.ccr & 0x10000000) { /* Restart the system call */ switch (regs.gpr[3]) { case ERESTARTNOHAND: case ERESTARTSYS: case ERESTARTNOINTR: regs.gpr[3] = regs.orig_gpr3; regs.nip -= 4; break; case ERESTART_RESTARTBLOCK: regs.gpr[0] = __NR_restart_syscall; regs.nip -= 4; break; } } /* Resetting trap since we are now comming from user space. */ regs.trap = 0; #define assign_reg(dst, src, e) do { \ dst->e = (__typeof__(dst->e))src.e; \ } while (0) for (i=0; i<32; i++) assign_reg(core->ti_ppc64->gpregs, regs, gpr[i]); assign_reg(core->ti_ppc64->gpregs, regs, nip); assign_reg(core->ti_ppc64->gpregs, regs, msr); assign_reg(core->ti_ppc64->gpregs, regs, orig_gpr3); assign_reg(core->ti_ppc64->gpregs, regs, ctr); assign_reg(core->ti_ppc64->gpregs, regs, link); assign_reg(core->ti_ppc64->gpregs, regs, xer); assign_reg(core->ti_ppc64->gpregs, regs, ccr); assign_reg(core->ti_ppc64->gpregs, regs, trap); #undef assign_reg if (get_fpu_regs(pid, core)) return -1; if (get_altivec_regs(pid, core)) return -1; /* * Don't save the VSX registers if Altivec registers are not * supported */ if (CORE_THREAD_ARCH_INFO(core)->vrstate && get_vsx_regs(pid, core)) return -1; return 0; }
int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core) { struct user_vfp vfp; int ret = -1; pr_info("Dumping GP/FPU registers for %d\n", pid); if (ptrace(PTRACE_GETVFPREGS, pid, NULL, &vfp)) { pr_perror("Can't obtain FPU registers for %d", pid); goto err; } /* Did we come from a system call? */ if ((int)regs.ARM_ORIG_r0 >= 0) { /* Restart the system call */ switch ((long)(int)regs.ARM_r0) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: regs.ARM_r0 = regs.ARM_ORIG_r0; regs.ARM_pc -= 4; break; case -ERESTART_RESTARTBLOCK: regs.ARM_r0 = __NR_restart_syscall; regs.ARM_pc -= 4; break; } } // Save the ARM CPU state assign_reg(core->ti_arm->gpregs, regs, r0); assign_reg(core->ti_arm->gpregs, regs, r1); assign_reg(core->ti_arm->gpregs, regs, r2); assign_reg(core->ti_arm->gpregs, regs, r3); assign_reg(core->ti_arm->gpregs, regs, r4); assign_reg(core->ti_arm->gpregs, regs, r5); assign_reg(core->ti_arm->gpregs, regs, r6); assign_reg(core->ti_arm->gpregs, regs, r7); assign_reg(core->ti_arm->gpregs, regs, r8); assign_reg(core->ti_arm->gpregs, regs, r9); assign_reg(core->ti_arm->gpregs, regs, r10); assign_reg(core->ti_arm->gpregs, regs, fp); assign_reg(core->ti_arm->gpregs, regs, ip); assign_reg(core->ti_arm->gpregs, regs, sp); assign_reg(core->ti_arm->gpregs, regs, lr); assign_reg(core->ti_arm->gpregs, regs, pc); assign_reg(core->ti_arm->gpregs, regs, cpsr); core->ti_arm->gpregs->orig_r0 = regs.ARM_ORIG_r0; // Save the VFP state memcpy(CORE_THREAD_ARCH_INFO(core)->fpstate->vfp_regs, &vfp.fpregs, sizeof(vfp.fpregs)); CORE_THREAD_ARCH_INFO(core)->fpstate->fpscr = vfp.fpscr; ret = 0; err: return ret; }