static inline unsigned long __remote_syscall(pid_t pid, int syscall_no, char *syscall_name, int use_ebx, unsigned long ebx, int use_ecx, unsigned long ecx, int use_edx, unsigned long edx, int use_esi, unsigned long esi, int use_edi, unsigned long edi) { struct user_regs_struct orig_regs, regs; unsigned long ret; int status; if (!syscall_loc) { fprintf(stderr, "No syscall locations found! Cannot do remote syscall.\n"); abort(); } if (save_registers(pid, &orig_regs) < 0) abort(); memcpy(®s, &orig_regs, sizeof(regs)); regs.eax = syscall_no; if (use_ebx) regs.ebx = ebx; if (use_ecx) regs.ecx = ecx; if (use_edx) regs.edx = edx; if (use_esi) regs.esi = esi; if (use_edi) regs.edi = edi; /* Set up registers for ptrace syscall */ regs.eip = syscall_loc; if (restore_registers(pid, ®s) < 0) abort(); /* Execute call */ if (ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL) < 0) { perror("ptrace singlestep"); abort(); } ret = waitpid(pid, &status, 0); if (ret == -1) { perror("Failed to wait for child"); abort(); } /* Get our new registers */ if (save_registers(pid, ®s) < 0) abort(); /* Return everything back to normal */ if (restore_registers(pid, &orig_regs) < 0) abort(); if (regs.eax < 0) { errno = -regs.eax; return -1; } return regs.eax; }
void userspace(union uml_pt_regs *regs) { int err, status, op, pid = userspace_pid[0]; restore_registers(regs); err = ptrace(PTRACE_SYSCALL, pid, 0, 0); if(err) panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", errno); while(1){ CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); if(err < 0) panic("userspace - waitpid failed, errno = %d\n", errno); regs->skas.is_user = 1; save_registers(regs); if(WIFSTOPPED(status)){ switch(WSTOPSIG(status)){ case SIGSEGV: handle_segv(pid); break; case SIGTRAP: handle_trap(pid, regs); break; case SIGIO: case SIGVTALRM: case SIGILL: case SIGBUS: case SIGFPE: case SIGWINCH: user_signal(WSTOPSIG(status), regs); break; default: printk("userspace - child stopped with signal " "%d\n", WSTOPSIG(status)); } interrupt_end(); } restore_registers(regs); op = singlestepping_skas() ? PTRACE_SINGLESTEP : PTRACE_SYSCALL; err = ptrace(op, pid, 0, 0); if(err) panic("userspace - PTRACE_SYSCALL failed, " "errno = %d\n", errno); } }
void vp9_short_idct10_16x16_add_neon(int16_t *input, uint8_t *dest, int dest_stride) { int16_t pass1_output[16*16] = {0}; int16_t row_idct_output[16*16] = {0}; // save d8-d15 register values. save_registers(); /* Parallel idct on the upper 8 rows */ // First pass processes even elements 0, 2, 4, 6, 8, 10, 12, 14 and save the // stage 6 result in pass1_output. vp9_short_idct10_16x16_add_neon_pass1(input, pass1_output, 8); // Second pass processes odd elements 1, 3, 5, 7, 9, 11, 13, 15 and combines // with result in pass1(pass1_output) to calculate final result in stage 7 // which will be saved into row_idct_output. vp9_short_idct10_16x16_add_neon_pass2(input+1, row_idct_output, pass1_output, 0, dest, dest_stride); /* Skip Parallel idct on the lower 8 rows as they are all 0s */ /* Parallel idct on the left 8 columns */ // First pass processes even elements 0, 2, 4, 6, 8, 10, 12, 14 and save the // stage 6 result in pass1_output. vp9_short_idct16x16_add_neon_pass1(row_idct_output, pass1_output, 8); // Second pass processes odd elements 1, 3, 5, 7, 9, 11, 13, 15 and combines // with result in pass1(pass1_output) to calculate final result in stage 7. // Then add the result to the destination data. vp9_short_idct16x16_add_neon_pass2(row_idct_output+1, row_idct_output, pass1_output, 1, dest, dest_stride); /* Parallel idct on the right 8 columns */ // First pass processes even elements 0, 2, 4, 6, 8, 10, 12, 14 and save the // stage 6 result in pass1_output. vp9_short_idct16x16_add_neon_pass1(row_idct_output+8*16, pass1_output, 8); // Second pass processes odd elements 1, 3, 5, 7, 9, 11, 13, 15 and combines // with result in pass1(pass1_output) to calculate final result in stage 7. // Then add the result to the destination data. vp9_short_idct16x16_add_neon_pass2(row_idct_output+8*16+1, row_idct_output+8, pass1_output, 1, dest+8, dest_stride); // restore d8-d15 register values. restore_registers(); return; }
static void pre_ckpt() { int r; DPRINTF("\n*** Before checkpointing. ***\n"); if (dummy == 1) { r = save_registers(); if (r < 0) { DPRINTF("ERROR: Querying CPU state from the kernel returned: %d\n", r); DPRINTF("WARNING: Please try checkpointing again\n"); } r = save_pit2(); if (r < 0) { DPRINTF("ERROR: Querying PIT state from the kernel returned: %d\n", r); DPRINTF("WARNING: Please try checkpointing again\n"); } r = save_irqchip(); if (r < 0) { DPRINTF("ERROR: Querying IRQCHIP state from the kernel returned: %d\n", r); DPRINTF("WARNING: Please try checkpointing again\n"); } // dummy = 2; } else if (dummy >= 2) { r = restore_registers(); if (r < 0) { DPRINTF("ERROR: Restoring the registers returned: %d\n", r); DPRINTF("WARNING: Cannot continue\n"); exit(-1); } } }
void userspace(union uml_pt_regs *regs) { int err, status, op, pid = userspace_pid[0]; int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ while(1){ restore_registers(pid, regs); /* Now we set local_using_sysemu to be used for one loop */ local_using_sysemu = get_using_sysemu(); op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL)); err = ptrace(op, pid, 0, 0); if(err) panic("userspace - could not resume userspace process, " "pid=%d, ptrace operation = %d, errno = %d\n", op, errno); CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); if(err < 0) panic("userspace - waitpid failed, errno = %d\n", errno); regs->skas.is_user = 1; save_registers(pid, regs); UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ if(WIFSTOPPED(status)){ switch(WSTOPSIG(status)){ case SIGSEGV: handle_segv(pid, regs); break; case SIGTRAP + 0x80: handle_trap(pid, regs, local_using_sysemu); break; case SIGTRAP: relay_signal(SIGTRAP, regs); break; case SIGIO: case SIGVTALRM: case SIGILL: case SIGBUS: case SIGFPE: case SIGWINCH: user_signal(WSTOPSIG(status), regs, pid); break; default: printk("userspace - child stopped with signal " "%d\n", WSTOPSIG(status)); } interrupt_end(); /* Avoid -ERESTARTSYS handling in host */ PT_SYSCALL_NR(regs->skas.regs) = -1; } } }
void get_process(pid_t pid, int flags, struct list *process_image, long *bin_offset) { int success = 0; char* pagebackup; struct user_regs_struct r; struct cp_chunk *libcgp; start_ptrace(pid); if (save_registers(pid, &r) < 0) { fprintf(stderr, "Unable to save process's registers!\n"); goto out_ptrace; } /* The order below is very important. Do not change without good reason and * careful thought. */ fetch_chunks_tls(pid, flags, process_image); /* this gives us a scribble zone: */ fetch_chunks_vma(pid, flags, process_image, bin_offset); if (!scribble_zone) { fprintf(stderr, "[-] No suitable scribble zone could be found. Aborting.\n"); goto out_ptrace; } pagebackup = backup_page(pid, (void*)scribble_zone); fetch_chunks_fd(pid, flags, process_image); fetch_chunks_sighand(pid, flags, process_image); fetch_chunks_i387_data(pid, flags, process_image); fetch_chunks_regs(pid, flags, process_image, process_was_stopped); /* add __getpid chunk to the image list, if requested by the user */ if ((flags & REFRESH_PID) && fetch_chunk_libcgp(&libcgp) == 0) list_append(process_image, libcgp); success = 1; restore_page(pid, (void*)scribble_zone, pagebackup); restore_registers(pid, &r); out_ptrace: end_ptrace(pid, flags); if (!success) abort(); }
long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) { unsigned long *ptr = addr, tmp; long ret; int pid = task->mm->context.id.u.pid; /* * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to * be safe), we need to call arch_prctl on the host because * setting %fs may result in something else happening (like a * GDT or thread.fs being set instead). So, we let the host * fiddle the registers and thread struct and restore the * registers afterwards. * * So, the saved registers are stored to the process (this * needed because a stub may have been the last thing to run), * arch_prctl is run on the host, then the registers are read * back. */ switch (code) { case ARCH_SET_FS: case ARCH_SET_GS: ret = restore_registers(pid, ¤t->thread.regs.regs); if (ret) return ret; break; case ARCH_GET_FS: case ARCH_GET_GS: /* * With these two, we read to a local pointer and * put_user it to the userspace pointer that we were * given. If addr isn't valid (because it hasn't been * faulted in or is just bogus), we want put_user to * fault it in (or return -EFAULT) instead of having * the host return -EFAULT. */ ptr = &tmp; } ret = os_arch_prctl(pid, code, ptr); if (ret) return ret; switch (code) { case ARCH_SET_FS: current->thread.arch.fs = (unsigned long) ptr; ret = save_registers(pid, ¤t->thread.regs.regs); break; case ARCH_SET_GS: ret = save_registers(pid, ¤t->thread.regs.regs); break; case ARCH_GET_FS: ret = put_user(tmp, addr); break; case ARCH_GET_GS: ret = put_user(tmp, addr); break; } return ret; }
long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) { unsigned long *ptr = addr, tmp; long ret; int pid = task->mm->context.id.u.pid; /* */ switch (code) { case ARCH_SET_FS: case ARCH_SET_GS: ret = restore_registers(pid, ¤t->thread.regs.regs); if (ret) return ret; break; case ARCH_GET_FS: case ARCH_GET_GS: /* */ ptr = &tmp; } ret = os_arch_prctl(pid, code, ptr); if (ret) return ret; switch (code) { case ARCH_SET_FS: current->thread.arch.fs = (unsigned long) ptr; ret = save_registers(pid, ¤t->thread.regs.regs); break; case ARCH_SET_GS: ret = save_registers(pid, ¤t->thread.regs.regs); break; case ARCH_GET_FS: ret = put_user(tmp, addr); break; case ARCH_GET_GS: ret = put_user(tmp, addr); break; } return ret; }
void userspace(union uml_pt_regs *regs) { int err, status, op, pt_syscall_parm, pid = userspace_pid[0]; int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ restore_registers(regs); local_using_sysemu = get_using_sysemu(); pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL; err = ptrace(pt_syscall_parm, pid, 0, 0); if(err) panic("userspace - PTRACE_%s failed, errno = %d\n", local_using_sysemu ? "SYSEMU" : "SYSCALL", errno); while(1){ CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); if(err < 0) panic("userspace - waitpid failed, errno = %d\n", errno); regs->skas.is_user = 1; save_registers(regs); if(WIFSTOPPED(status)){ switch(WSTOPSIG(status)){ case SIGSEGV: handle_segv(pid); break; case SIGTRAP: handle_trap(pid, regs, local_using_sysemu); break; case SIGIO: case SIGVTALRM: case SIGILL: case SIGBUS: case SIGFPE: case SIGWINCH: user_signal(WSTOPSIG(status), regs); break; default: printk("userspace - child stopped with signal " "%d\n", WSTOPSIG(status)); } interrupt_end(); } restore_registers(regs); /*Now we ended the syscall, so re-read local_using_sysemu.*/ local_using_sysemu = get_using_sysemu(); pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL; op = singlestepping(NULL) ? PTRACE_SINGLESTEP : pt_syscall_parm; err = ptrace(op, pid, 0, 0); if(err) panic("userspace - PTRACE_%s failed, " "errno = %d\n", local_using_sysemu ? "SYSEMU" : "SYSCALL", errno); } }
static void restart() { int r; DPRINTF("Restarting from checkpoint.\n"); if (g_kvm_fd > 0 && g_vm_fd > 0 && g_vcpu_fd > 0) { r = create_vm(); if (r < 0) { DPRINTF("ERROR: Creating VMFD returned: %d\n", r); DPRINTF("WARNING: Please try checkpointing again\n"); exit(-1); } else if (r > 0) { int i = 0; int t = 0; r = restore_id_map_addr(); if (r < 0) { DPRINTF("ERROR: Restoring identity map addr returned: %d\n", r); DPRINTF("WARNING: Please try checkpointing again\n"); exit(-1); } r = restore_tss_addr(); if (r < 0) { DPRINTF("ERROR: Restoring tss addr returned: %d\n", r); DPRINTF("WARNING: Please try checkpointing again\n"); exit(-1); } r = create_irqchip(); if (r < 0) { DPRINTF("ERROR: Creating IRQCHIP returned: %d\n", r); DPRINTF("WARNING: Please try checkpointing again\n"); exit(-1); } r = create_vcpu(); if (r < 0) { DPRINTF("ERROR: Creating new VCPU returned: %d\n", r); DPRINTF("WARNING: Cannot continue\n"); exit(-1); } if (NEXT_FNC(mmap)(g_vcpu_mmap_addr, g_vcpu_mmap_length, g_vcpu_mmap_prot, g_vcpu_mmap_flags | MAP_FIXED, g_vcpu_fd, 0) == MAP_FAILED) { DPRINTF("ERROR: Mapping the new VCPU returned MAP_FAILED\n"); DPRINTF("WARNING: Cannot continue\n"); exit(-1); } r = NEXT_FNC(ioctl)(g_vcpu_fd, KVM_SET_SIGNAL_MASK, &g_kvm_sigmask); if (r < 0) { DPRINTF("ERROR: Setting VCPU Signal Mask returned: %d\n", r); exit(-1); } r = NEXT_FNC(ioctl)(g_vm_fd, KVM_IRQ_LINE_STATUS, &g_kvm_irq_level); if (r < 0) { DPRINTF("ERROR: Setting IRQ LINE status returned: %d\n", r); exit(-1); } r = NEXT_FNC(ioctl)(g_vm_fd, KVM_REGISTER_COALESCED_MMIO, &g_kvm_coalesced_mmio_zone); if (r < 0) { DPRINTF("ERROR: Setting Coalesced MMIO Zone returned: %d\n", r); exit(-1); } DPRINTF("Setting #%d memory regions\n", g_num_of_memory_regions); struct kvm_userspace_memory_region *mem; for (i = 0; i < g_num_of_memory_regions; i++) { mem = &g_kvm_mem_region[i]; DPRINTF("slot:%X, flags:%X, start:%llX, size:%llX, ram:%llX)\n", mem->slot, mem->flags, mem->guest_phys_addr, mem->memory_size, mem->userspace_addr); r = NEXT_FNC(ioctl)(g_vm_fd, KVM_SET_USER_MEMORY_REGION, &g_kvm_mem_region[i]); if (r < 0) { DPRINTF("ERROR: Creating memory region #%d returned: \n", i, r); perror("ioctl(KVM_SET_USER_MEMORY_REGION)"); } } /* See note in the ioctl() wrapper. */ DPRINTF("Setting routing tables. ptr: %p...\n", g_kvm_gsi_routing_table); r = NEXT_FNC(ioctl)(g_vm_fd, KVM_SET_GSI_ROUTING, g_kvm_gsi_routing_table); if (r < 0) { DPRINTF("ERROR: Setting routing table (#routes=%d) returned: " "%d\n", g_kvm_gsi_routing_table->nr, r); } r = create_pit2(); if (r < 0) { DPRINTF("Creating PIT2 returned: %d\n", r); } r = restore_pit2(); if (r < 0) { DPRINTF("ERROR: Restoring PIT2 returned: %d\n", r); DPRINTF("WARNING: Cannot continue\n"); exit(-1); } int array[] = { 0, 1, 4, 8, 12 }; g_kvm_irq_level.level = 0; for (i = 0; i < 5; i++) { g_kvm_irq_level.irq = array[i]; r = NEXT_FNC(ioctl)(g_vm_fd, KVM_IRQ_LINE_STATUS, &g_kvm_irq_level); if (r < 0) { DPRINTF("ERROR: Resetting IRQ#%d LINE returned: %d\n", g_kvm_irq_level.irq, r); exit(-1); } } r = restore_irqchip(); if (r < 0) { DPRINTF("ERROR: Restoring IRQCHIP returned: %d\n", r); DPRINTF("WARNING: Cannot continue\n"); exit(-1); } r = NEXT_FNC(ioctl)(g_vcpu_fd, KVM_TPR_ACCESS_REPORTING, &g_kvm_tpr_access_ctl); if (r < 0) { DPRINTF("ERROR: Restoring the tpr access reporting returned: %d\n", r); DPRINTF("WARNING: Cannot continue\n"); exit(-1); } r = NEXT_FNC(ioctl)(g_vcpu_fd, KVM_SET_VAPIC_ADDR, &g_kvm_vapic_addr); if (r < 0) { DPRINTF("ERROR: Restoring the vapic addr returned: %d\n", r); DPRINTF("WARNING: Cannot continue\n"); exit(-1); } r = restore_registers(); if (r < 0) { DPRINTF("ERROR: Restoring the registers returned: %d\n", r); DPRINTF("WARNING: Cannot continue\n"); exit(-1); } } } }