direct-io.hg

changeset 4567:793cb54d3745

bitkeeper revision 1.1321 (42642eb1DhlDvDKcX1gTZhvys-xHJQ)

fix single-stepping
make persistent context per-cpu
Signed-off-by: Kip Macy <kmacy@fsmware.com>
Signed-off-by: ian@xensource.com
author iap10@freefall.cl.cam.ac.uk
date Mon Apr 18 22:03:29 2005 +0000 (2005-04-18)
parents 7edc9d4fa41e
children 756991cc6c70
files tools/libxc/xc_ptrace.c
line diff
     1.1 --- a/tools/libxc/xc_ptrace.c	Mon Apr 18 21:59:54 2005 +0000
     1.2 +++ b/tools/libxc/xc_ptrace.c	Mon Apr 18 22:03:29 2005 +0000
     1.3 @@ -10,6 +10,7 @@
     1.4  #define PDRSHIFT        22
     1.5  #define	PSL_T		0x00000100	/* trace enable bit */
     1.6  
     1.7 +#define VCPU            0               /* XXX */
     1.8  
     1.9  /*
    1.10   * long  
    1.11 @@ -67,6 +68,17 @@ struct gdb_regs {
    1.12      long esp;    /* 60 */     
    1.13      int  xss;    /* 64 */
    1.14  };
    1.15 +
    1.16 +#define FETCH_REGS(cpu) \
    1.17 +    if (!regs_valid[cpu]) \
    1.18 +    {                \
    1.19 +	int retval = xc_domain_getfullinfo(xc_handle, domid, cpu, NULL, &ctxt[cpu]); \
    1.20 +	if (retval) \
    1.21 +	    goto error_out; \
    1.22 +	cr3[cpu] = ctxt[cpu].pt_base; \
    1.23 +	regs_valid[cpu] = 1; \
    1.24 +    } \
    1.25 +
    1.26  #define printval(x) printf("%s = %lx\n", #x, (long)x);
    1.27  #define SET_PT_REGS(pt, xc) \
    1.28  { \
    1.29 @@ -115,74 +127,70 @@ struct gdb_regs {
    1.30  /* XXX application state */
    1.31  
    1.32  
    1.33 -static int xc_handle;
    1.34 -static int regs_valid;
    1.35 -static unsigned long cr3;
    1.36 -static full_execution_context_t ctxt;
    1.37 +static int                      xc_handle;
    1.38 +static int                      regs_valid[MAX_VIRT_CPUS];
    1.39 +static unsigned long            cr3[MAX_VIRT_CPUS];
    1.40 +static full_execution_context_t ctxt[MAX_VIRT_CPUS];
    1.41 +
    1.42  
    1.43  /* --------------------- */
    1.44  
    1.45  static void *
    1.46 -map_domain_va(unsigned long domid, void * guest_va, int perm)
    1.47 +map_domain_va(unsigned long domid, int cpu, void * guest_va, int perm)
    1.48  {
    1.49      unsigned long pde, page;
    1.50      unsigned long va = (unsigned long)guest_va;
    1.51  
    1.52 -    static unsigned long cr3_phys;
    1.53 -    static unsigned long *cr3_virt;
    1.54 -    static unsigned long pde_phys;
    1.55 -    static unsigned long *pde_virt;
    1.56 -    static unsigned long page_phys;
    1.57 -    static unsigned long *page_virt;
    1.58 +    static unsigned long  cr3_phys[MAX_VIRT_CPUS];
    1.59 +    static unsigned long *cr3_virt[MAX_VIRT_CPUS];
    1.60 +    static unsigned long  pde_phys[MAX_VIRT_CPUS];
    1.61 +    static unsigned long *pde_virt[MAX_VIRT_CPUS];
    1.62 +    static unsigned long  page_phys[MAX_VIRT_CPUS];
    1.63 +    static unsigned long *page_virt[MAX_VIRT_CPUS];
    1.64      
    1.65 -    static int prev_perm;
    1.66 -    if (!regs_valid) 
    1.67 +    static int            prev_perm[MAX_VIRT_CPUS];
    1.68 +
    1.69 +    FETCH_REGS(cpu);
    1.70 +
    1.71 +    if (cr3[cpu] != cr3_phys[cpu]) 
    1.72      {
    1.73 -	int retval = xc_domain_getfullinfo(xc_handle, domid, 0, NULL, &ctxt);
    1.74 -	if (retval)
    1.75 -	    goto error_out;
    1.76 -	cr3 = ctxt.pt_base;
    1.77 -	regs_valid = 1;
    1.78 -    }
    1.79 -    if (cr3 != cr3_phys) 
    1.80 -    {
    1.81 -	cr3_phys = cr3;
    1.82 -	if (cr3_virt)
    1.83 -	    munmap(cr3_virt, PAGE_SIZE);
    1.84 -	if ((cr3_virt = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
    1.85 +	cr3_phys[cpu] = cr3[cpu];
    1.86 +	if (cr3_virt[cpu])
    1.87 +	    munmap(cr3_virt[cpu], PAGE_SIZE);
    1.88 +	if ((cr3_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
    1.89  					     PROT_READ,
    1.90 -					     cr3_phys >> PAGE_SHIFT)) == NULL)
    1.91 +					     cr3_phys[cpu] >> PAGE_SHIFT)) == NULL)
    1.92  	    goto error_out;
    1.93      } 
    1.94 -    if ((pde = cr3_virt[vtopdi(va)]) == 0)
    1.95 +    if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0)
    1.96  	goto error_out;
    1.97 -    if (pde != pde_phys) 
    1.98 +    if (pde != pde_phys[cpu]) 
    1.99      {
   1.100 -	pde_phys = pde;
   1.101 -	if (pde_virt)
   1.102 -	    munmap(pde_virt, PAGE_SIZE);
   1.103 -	if ((pde_virt = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
   1.104 +	pde_phys[cpu] = pde;
   1.105 +	if (pde_virt[cpu])
   1.106 +	    munmap(pde_virt[cpu], PAGE_SIZE);
   1.107 +	if ((pde_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
   1.108  					     PROT_READ,
   1.109 -					     pde_phys >> PAGE_SHIFT)) == NULL)
   1.110 +					     pde_phys[cpu] >> PAGE_SHIFT)) == NULL)
   1.111  	    goto error_out;
   1.112      }
   1.113 -    if ((page = pde_virt[vtopti(va)]) == 0)
   1.114 +    if ((page = pde_virt[cpu][vtopti(va)]) == 0)
   1.115  	goto error_out;
   1.116 -    if (page != page_phys || perm != prev_perm) 
   1.117 +    if (page != page_phys[cpu] || perm != prev_perm[cpu]) 
   1.118      {
   1.119 -	page_phys = page;
   1.120 -	if (page_virt)
   1.121 -	    munmap(page_virt, PAGE_SIZE);
   1.122 -	if ((page_virt = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
   1.123 -					     perm,
   1.124 -					      page_phys >> PAGE_SHIFT)) == NULL) {
   1.125 -	    printf("cr3 %lx pde %lx page %lx pti %lx\n", cr3, pde, page, vtopti(va));
   1.126 -	    page_phys = 0;
   1.127 +	page_phys[cpu] = page;
   1.128 +	if (page_virt[cpu])
   1.129 +	    munmap(page_virt[cpu], PAGE_SIZE);
   1.130 +	if ((page_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
   1.131 +					      perm,
   1.132 +					      page_phys[cpu] >> PAGE_SHIFT)) == NULL) {
   1.133 +	    printf("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, vtopti(va));
   1.134 +	    page_phys[cpu] = 0;
   1.135  	    goto error_out;
   1.136  	}
   1.137 -	prev_perm = perm;
   1.138 +	prev_perm[cpu] = perm;
   1.139      }	
   1.140 -    return (void *)(((unsigned long)page_virt) | (va & BSD_PAGE_MASK));
   1.141 +    return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK));
   1.142  
   1.143   error_out:
   1.144      return 0;
   1.145 @@ -231,14 +239,14 @@ waitdomain(int domain, int *status, int 
   1.146  }
   1.147  
   1.148  long
   1.149 -xc_ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data)
   1.150 +xc_ptrace(enum __ptrace_request request, pid_t domid, void *addr, void *data)
   1.151  {
   1.152 -    dom0_op_t op;
   1.153 -    int status = 0;
   1.154 -    xc_domaininfo_t info;
   1.155 +    dom0_op_t       op;
   1.156 +    int             status = 0;
   1.157      struct gdb_regs pt;
   1.158 -    long retval = 0;
   1.159 -    unsigned long *guest_va;
   1.160 +    long            retval = 0;
   1.161 +    unsigned long  *guest_va;
   1.162 +    int             cpu = VCPU;
   1.163  
   1.164      op.interface_version = DOM0_INTERFACE_VERSION;
   1.165      
   1.166 @@ -246,23 +254,23 @@ xc_ptrace(enum __ptrace_request request,
   1.167  	if ((xc_handle = xc_interface_open()) < 0)
   1.168  	    return -1;
   1.169  #if 0
   1.170 -    printf("%20s %d, %p, %p \n", ptrace_names[request], pid, addr, data);
   1.171 +    printf("%20s %d, %p, %p \n", ptrace_names[request], domid, addr, data);
   1.172  #endif
   1.173      switch (request) {	
   1.174      case PTRACE_PEEKTEXT:
   1.175      case PTRACE_PEEKDATA:
   1.176 -	if ((guest_va = (unsigned long *)map_domain_va(pid, addr, PROT_READ)) == NULL) {
   1.177 +	if ((guest_va = (unsigned long *)map_domain_va(domid, cpu, addr, PROT_READ)) == NULL) {
   1.178  	    status = EFAULT;
   1.179 -	    goto done;
   1.180 +	    goto error_out;
   1.181  	}
   1.182  
   1.183  	retval = *guest_va;
   1.184  	break;
   1.185      case PTRACE_POKETEXT:
   1.186      case PTRACE_POKEDATA:
   1.187 -	if ((guest_va = (unsigned long *)map_domain_va(pid, addr, PROT_READ|PROT_WRITE)) == NULL) {
   1.188 +	if ((guest_va = (unsigned long *)map_domain_va(domid, cpu, addr, PROT_READ|PROT_WRITE)) == NULL) {
   1.189  	    status = EFAULT;
   1.190 -	    goto done;
   1.191 +	    goto error_out;
   1.192  	}
   1.193  
   1.194  	*guest_va = (unsigned long)data;
   1.195 @@ -270,70 +278,79 @@ xc_ptrace(enum __ptrace_request request,
   1.196      case PTRACE_GETREGS:
   1.197      case PTRACE_GETFPREGS:
   1.198      case PTRACE_GETFPXREGS:
   1.199 -	/* XXX hard-coding UP */
   1.200 -	retval = xc_domain_getfullinfo(xc_handle, pid, 0, &info, &ctxt);
   1.201 +	FETCH_REGS(cpu);
   1.202  
   1.203 -	if (retval) {
   1.204 -	    printf("getfullinfo failed\n");
   1.205 -	    goto done;
   1.206 -	}
   1.207  	if (request == PTRACE_GETREGS) {
   1.208 -		SET_PT_REGS(pt, ctxt.cpu_ctxt); 
   1.209 +		SET_PT_REGS(pt, ctxt[cpu].cpu_ctxt); 
   1.210  		memcpy(data, &pt, sizeof(elf_gregset_t));
   1.211  	} else if (request == PTRACE_GETFPREGS)
   1.212 -	    memcpy(data, &ctxt.fpu_ctxt, sizeof(ctxt.fpu_ctxt));
   1.213 +	    memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
   1.214  	else /*if (request == PTRACE_GETFPXREGS)*/
   1.215 -	    memcpy(data, &ctxt.fpu_ctxt, sizeof(ctxt.fpu_ctxt));
   1.216 -	cr3 = ctxt.pt_base;
   1.217 -	regs_valid = 1;
   1.218 +	    memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
   1.219  	break;
   1.220      case PTRACE_SETREGS:
   1.221  	op.cmd = DOM0_SETDOMAININFO;
   1.222 -	SET_XC_REGS(((struct gdb_regs *)data), ctxt.cpu_ctxt);
   1.223 -	op.u.setdomaininfo.domain = pid;
   1.224 +	SET_XC_REGS(((struct gdb_regs *)data), ctxt[VCPU].cpu_ctxt);
   1.225 +	op.u.setdomaininfo.domain = domid;
   1.226  	/* XXX need to understand multiple exec_domains */
   1.227 -	op.u.setdomaininfo.exec_domain = 0;
   1.228 -	op.u.setdomaininfo.ctxt = &ctxt;
   1.229 +	op.u.setdomaininfo.exec_domain = cpu;
   1.230 +	op.u.setdomaininfo.ctxt = &ctxt[cpu];
   1.231  	retval = do_dom0_op(xc_handle, &op);
   1.232  	if (retval)
   1.233 -	    goto done;
   1.234 +	    goto error_out;
   1.235  
   1.236  	break;
   1.237      case PTRACE_ATTACH:
   1.238  	op.cmd = DOM0_GETDOMAININFO;
   1.239 -	op.u.getdomaininfo.domain = pid;
   1.240 +	op.u.getdomaininfo.domain = domid;
   1.241  	op.u.getdomaininfo.exec_domain = 0;
   1.242 -	op.u.getdomaininfo.ctxt = &ctxt;
   1.243 +	op.u.getdomaininfo.ctxt = NULL;
   1.244  	retval = do_dom0_op(xc_handle, &op);
   1.245  	if (retval) {
   1.246  	    perror("dom0 op failed");
   1.247 -	    goto done;
   1.248 +	    goto error_out;
   1.249  	}
   1.250  	if (op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) {
   1.251  	    printf("domain currently paused\n");
   1.252 -	    goto done;
   1.253 +	    goto error_out;
   1.254  	}
   1.255  	printf("domain not currently paused\n");
   1.256  	op.cmd = DOM0_PAUSEDOMAIN;
   1.257 -	op.u.pausedomain.domain = pid;
   1.258 +	op.u.pausedomain.domain = domid;
   1.259  	retval = do_dom0_op(xc_handle, &op);
   1.260  	break;
   1.261      case PTRACE_SINGLESTEP:
   1.262 -	ctxt.cpu_ctxt.eflags |= PSL_T;
   1.263 +	ctxt[VCPU].cpu_ctxt.eflags |= PSL_T;
   1.264  	op.cmd = DOM0_SETDOMAININFO;
   1.265 -	op.u.setdomaininfo.domain = pid;
   1.266 +	op.u.setdomaininfo.domain = domid;
   1.267  	op.u.setdomaininfo.exec_domain = 0;
   1.268 -	op.u.setdomaininfo.ctxt = &ctxt;
   1.269 +	op.u.setdomaininfo.ctxt = &ctxt[cpu];
   1.270  	retval = do_dom0_op(xc_handle, &op);	
   1.271  	if (retval) {
   1.272  	    perror("dom0 op failed");
   1.273 -	    goto done;
   1.274 +	    goto error_out;
   1.275  	}
   1.276      case PTRACE_CONT:
   1.277      case PTRACE_DETACH:
   1.278 -	regs_valid = 0;
   1.279 +	if (request != PTRACE_SINGLESTEP) {
   1.280 +	    FETCH_REGS(cpu);
   1.281 +	    /* Clear trace flag */
   1.282 +	    if (ctxt[cpu].cpu_ctxt.eflags & PSL_T) {
   1.283 +		ctxt[cpu].cpu_ctxt.eflags &= ~PSL_T;
   1.284 +		op.cmd = DOM0_SETDOMAININFO;
   1.285 +		op.u.setdomaininfo.domain = domid;
   1.286 +		op.u.setdomaininfo.exec_domain = cpu;
   1.287 +		op.u.setdomaininfo.ctxt = &ctxt[cpu];
   1.288 +		retval = do_dom0_op(xc_handle, &op);	
   1.289 +		if (retval) {
   1.290 +		    perror("dom0 op failed");
   1.291 +		    goto error_out;
   1.292 +		}
   1.293 +	    }
   1.294 +	}
   1.295 +	regs_valid[cpu] = 0;
   1.296  	op.cmd = DOM0_UNPAUSEDOMAIN;
   1.297 -	op.u.unpausedomain.domain = pid > 0 ? pid : -pid;
   1.298 +	op.u.unpausedomain.domain = domid > 0 ? domid : -domid;
   1.299  	retval = do_dom0_op(xc_handle, &op);
   1.300  	break;
   1.301      case PTRACE_SETFPREGS:
   1.302 @@ -357,6 +374,6 @@ xc_ptrace(enum __ptrace_request request,
   1.303  	errno = status;
   1.304  	retval = -1;
   1.305      }
   1.306 - done:
   1.307 + error_out:
   1.308      return retval;
   1.309  }