# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/10 20:28:04-08:00 kmacy@xxxxxxxxxxxxxxxxxxxx # bug fixes to ptrace emulation # # BitKeeper/etc/logging_ok # 2005/03/10 20:28:04-08:00 kmacy@xxxxxxxxxxxxxxxxxxxx +1 -0 # Logging to logging@xxxxxxxxxxxxxxx accepted # # xen/arch/x86/traps.c # 2005/03/10 20:27:44-08:00 kmacy@xxxxxxxxxxxxxxxxxxxx +20 -9 # handle trace trap as well as int3 # # xen/arch/x86/domain.c # 2005/03/10 20:27:44-08:00 kmacy@xxxxxxxxxxxxxxxxxxxx +8 -8 # move register copying above segment check # # tools/libxc/xc_ptrace.c # 2005/03/10 20:27:44-08:00 kmacy@xxxxxxxxxxxxxxxxxxxx +34 -17 # fix mask handling of pts # fix single-stepping # simplify PEEK and POKE operations # # tools/libxc/xc_linux_build.c # 2005/03/10 20:27:44-08:00 kmacy@xxxxxxxxxxxxxxxxxxxx +1 -1 # move setting of exec_domain to more sensible location # diff -Nru a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c --- a/tools/libxc/xc_linux_build.c 2005-03-11 10:38:12 -08:00 +++ b/tools/libxc/xc_linux_build.c 2005-03-11 10:38:12 -08:00 @@ -369,7 +369,6 @@ op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = (domid_t)domid; - launch_op.u.setdomaininfo.exec_domain = 0; op.u.getdomaininfo.exec_domain = 0; op.u.getdomaininfo.ctxt = ctxt; if ( (do_dom0_op(xc_handle, &op) < 0) || @@ -461,6 +460,7 @@ memset( &launch_op, 0, sizeof(launch_op) ); launch_op.u.setdomaininfo.domain = (domid_t)domid; + launch_op.u.setdomaininfo.exec_domain = 0; launch_op.u.setdomaininfo.ctxt = ctxt; launch_op.cmd = DOM0_SETDOMAININFO; diff -Nru a/tools/libxc/xc_ptrace.c b/tools/libxc/xc_ptrace.c --- a/tools/libxc/xc_ptrace.c 2005-03-11 10:38:12 -08:00 +++ b/tools/libxc/xc_ptrace.c 2005-03-11 10:38:12 -08:00 @@ -110,7 +110,7 @@ #define vtopdi(va) ((va) >> PDRSHIFT) -#define vtopti(va) (((va) >> PAGE_SHIFT) & PAGE_MASK) +#define vtopti(va) (((va) >> PAGE_SHIFT) & BSD_PAGE_MASK) /* XXX application state */ @@ -156,9 +156,7 @@ pde_phys >> PAGE_SHIFT)) == NULL) goto error_out; } - page = pde_virt[ - vtopti(va) -]; + page = pde_virt[vtopti(va)]; if (page != page_phys) { page_phys = page; @@ -169,7 +167,7 @@ page_phys >> PAGE_SHIFT)) == NULL) goto error_out; } - return (void *)(((unsigned long)page_virt) | (va &~ BSD_PAGE_MASK)); + return (void *)(((unsigned long)page_virt) | (va & BSD_PAGE_MASK)); error_out: return 0; @@ -193,13 +191,15 @@ } op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = domain; + op.u.getdomaininfo.exec_domain = 0; op.u.getdomaininfo.ctxt = &ctxt; retry: retval = do_dom0_op(xc_handle, &op); - if (retval) + if (retval) { + printf("getdomaininfo failed\n"); goto done; - + } *status = op.u.getdomaininfo.flags; if (options & WNOHANG) @@ -223,35 +223,39 @@ xc_domaininfo_t info; struct gdb_regs pt; long retval = 0; - char *guest_va; + long *guest_va; + op.interface_version = DOM0_INTERFACE_VERSION; if (!xc_handle) if ((xc_handle = xc_interface_open()) < 0) return -1; -#if 0 +#if 0 printf("%20s %d, %p, %p \n", ptrace_names[request], pid, addr, data); #endif switch (request) { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: - if ((guest_va = map_domain_va(pid, addr)) == NULL) - goto done; - memcpy(data, guest_va, 4); - break; case PTRACE_POKETEXT: case PTRACE_POKEDATA: - if ((guest_va = map_domain_va(pid, addr)) == NULL) + if ((guest_va = (unsigned long *)map_domain_va(pid, addr)) == NULL) goto done; - memcpy(guest_va, data, 4); + + if (request == PTRACE_PEEKTEXT || request == PTRACE_PEEKDATA) + retval = *guest_va; + else + *guest_va = (unsigned long)data; break; case PTRACE_GETREGS: case PTRACE_GETFPREGS: case PTRACE_GETFPXREGS: /* XXX hard-coding UP */ retval = xc_domain_getfullinfo(xc_handle, pid, 0, &info, &ctxt); - if (retval) + + if (retval) { + printf("getfullinfo failed\n"); goto done; + } if (request == PTRACE_GETREGS) { SET_PT_REGS(pt, ctxt.cpu_ctxt); memcpy(data, &pt, sizeof(elf_gregset_t)); @@ -284,8 +288,10 @@ perror("dom0 op failed"); goto done; } - if (op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) + if (op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) { + printf("domain currently paused\n"); goto done; + } printf("domain not currently paused\n"); op.cmd = DOM0_PAUSEDOMAIN; op.u.pausedomain.domain = pid; @@ -293,6 +299,15 @@ break; case PTRACE_SINGLESTEP: ctxt.cpu_ctxt.eflags |= PSL_T; + op.cmd = DOM0_SETDOMAININFO; + op.u.setdomaininfo.domain = pid; + op.u.setdomaininfo.exec_domain = 0; + op.u.setdomaininfo.ctxt = &ctxt; + retval = do_dom0_op(xc_handle, &op); + if (retval) { + perror("dom0 op failed"); + goto done; + } case PTRACE_CONT: case PTRACE_DETACH: regs_valid = 0; @@ -306,7 +321,9 @@ case PTRACE_POKEUSER: case PTRACE_SYSCALL: case PTRACE_KILL: +#ifdef DEBUG printf("unsupported xc_ptrace request %s\n", ptrace_names[request]); +#endif /* XXX not yet supported */ status = ENOSYS; break; diff -Nru a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c 2005-03-11 10:38:12 -08:00 +++ b/xen/arch/x86/domain.c 2005-03-11 10:38:12 -08:00 @@ -431,6 +431,14 @@ unsigned long phys_basetab; int i, rc; + memcpy(&ed->arch.user_ctxt, + &c->cpu_ctxt, + sizeof(ed->arch.user_ctxt)); + + memcpy(&ed->arch.i387, + &c->fpu_ctxt, + sizeof(ed->arch.i387)); + /* * This is sufficient! If the descriptor DPL differs from CS RPL then we'll * #GP. If DS, ES, FS, GS are DPL 0 then they'll be cleared automatically. @@ -440,14 +448,6 @@ if ( ((ed->arch.user_ctxt.cs & 3) == 0) || ((ed->arch.user_ctxt.ss & 3) == 0) ) return -EINVAL; - - memcpy(&ed->arch.user_ctxt, - &c->cpu_ctxt, - sizeof(ed->arch.user_ctxt)); - - memcpy(&ed->arch.i387, - &c->fpu_ctxt, - sizeof(ed->arch.i387)); if (test_bit(EDF_DONEINIT, &ed->ed_flags)) return 0; diff -Nru a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c 2005-03-11 10:38:12 -08:00 +++ b/xen/arch/x86/traps.c 2005-03-11 10:38:12 -08:00 @@ -225,14 +225,13 @@ } else if ( KERNEL_MODE(ed, regs) && ed->domain->id != 0 ) { - regs->eflags &= ~X86_EFLAGS_TF; if ( !test_and_set_bit(EDF_CTRLPAUSE, &ed->ed_flags) ) { while (ed == current) __enter_scheduler(); domain_pause_by_systemcontroller(ed->domain); } - return 0; + goto out; } ti = current->arch.traps + 3; tb->flags = TBF_EXCEPTION; @@ -241,6 +240,7 @@ if ( TI_GET_IF(ti) ) ed->vcpu_info->evtchn_upcall_mask = 1; + out: return 0; } @@ -694,8 +694,8 @@ asmlinkage int do_debug(struct xen_regs *regs) { unsigned long condition; - struct exec_domain *d = current; - struct trap_bounce *tb = &d->arch.trap_bounce; + struct exec_domain *ed = current; + struct trap_bounce *tb = &ed->arch.trap_bounce; DEBUGGER_trap_entry(TRAP_debug, regs); @@ -703,7 +703,7 @@ /* Mask out spurious debug traps due to lazy DR7 setting */ if ( (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) && - (d->arch.debugreg[7] == 0) ) + (ed->arch.debugreg[7] == 0) ) { __asm__("mov %0,%%db7" : : "r" (0UL)); goto out; @@ -720,14 +720,25 @@ * breakpoint, which can't happen to us. */ goto out; - } + } + else if ( KERNEL_MODE(ed, regs) && ed->domain->id != 0 ) + { + regs->eflags &= ~EF_TF; + if ( !test_and_set_bit(EDF_CTRLPAUSE, &ed->ed_flags) ) { + while (ed == current) + __enter_scheduler(); + domain_pause_by_systemcontroller(ed->domain); + } + + goto out; + } /* Save debug status register where guest OS can peek at it */ - d->arch.debugreg[6] = condition; + ed->arch.debugreg[6] = condition; tb->flags = TBF_EXCEPTION; - tb->cs = d->arch.traps[1].cs; - tb->eip = d->arch.traps[1].address; + tb->cs = ed->arch.traps[1].cs; + tb->eip = ed->arch.traps[1].address; out: return EXCRET_not_a_fault;