ia64/xen-unstable

changeset 4020:b74c86e36644

bitkeeper revision 1.1236.12.11 (422de58bI6Rru29oYT0ipOgZZhpqZw)

resolve of grant tables merge
author cwc22@centipede.cl.cam.ac.uk
date Tue Mar 08 17:48:59 2005 +0000 (2005-03-08)
parents 62ae1c72e905 b4a40ce41618
children 2c4150137150
files .rootkeys linux-2.6.10-xen-sparse/arch/xen/kernel/gnttab.c linux-2.6.10-xen-sparse/include/asm-xen/gnttab.h linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h tools/libxc/Makefile tools/libxc/xc.h tools/libxc/xc_gnttab.c tools/libxc/xc_vmx_build.c xen/arch/x86/mm.c xen/common/grant_table.c xen/include/asm-x86/mm.h xen/include/asm-x86/shadow.h xen/include/public/grant_table.h xen/include/xen/grant_table.h
line diff
     1.1 --- a/.rootkeys	Tue Mar 08 17:12:15 2005 +0000
     1.2 +++ b/.rootkeys	Tue Mar 08 17:48:59 2005 +0000
     1.3 @@ -558,6 +558,7 @@ 3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/lib
     1.4  3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/libxc/xc_domain.c
     1.5  40278d99BLsfUv3qxv0I8C1sClZ0ow tools/libxc/xc_elf.h
     1.6  403e0977Bjsm_e82pwvl9VvaJxh8Gg tools/libxc/xc_evtchn.c
     1.7 +4227c129ZKjJPNYooHVzBCyinf7Y6Q tools/libxc/xc_gnttab.c
     1.8  40e03333Eegw8czSWvHsbKxrRZJjRA tools/libxc/xc_io.c
     1.9  40e03333vrWGbLAhyJjXlqCHaJt7eA tools/libxc/xc_io.h
    1.10  3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/libxc/xc_linux_build.c
     2.1 --- a/linux-2.6.10-xen-sparse/arch/xen/kernel/gnttab.c	Tue Mar 08 17:12:15 2005 +0000
     2.2 +++ b/linux-2.6.10-xen-sparse/arch/xen/kernel/gnttab.c	Tue Mar 08 17:48:59 2005 +0000
     2.3 @@ -6,6 +6,7 @@
     2.4   * 2. Accessing others' memory reservations via grant references.
     2.5   * (i.e., mechanisms for both sender and recipient of grant references)
     2.6   * 
     2.7 + * Copyright (c) 2005, Christopher Clark
     2.8   * Copyright (c) 2004, K A Fraser
     2.9   */
    2.10  
    2.11 @@ -14,6 +15,9 @@
    2.12  #include <linux/sched.h>
    2.13  #include <asm/pgtable.h>
    2.14  #include <asm/fixmap.h>
    2.15 +#include <asm/uaccess.h>
    2.16 +#include <asm-xen/xen_proc.h>
    2.17 +#include <asm-xen/linux-public/privcmd.h>
    2.18  #include <asm-xen/gnttab.h>
    2.19  
    2.20  #ifndef set_fixmap_ma
    2.21 @@ -28,8 +32,13 @@
    2.22  #define ASSERT(_p) ((void)0)
    2.23  #endif
    2.24  
    2.25 +#define WPRINTK(fmt, args...) \
    2.26 +    printk(KERN_WARNING "xen_grant: " fmt, ##args)
    2.27 +
    2.28 +
    2.29  EXPORT_SYMBOL(gnttab_grant_foreign_access);
    2.30  EXPORT_SYMBOL(gnttab_end_foreign_access);
    2.31 +EXPORT_SYMBOL(gnttab_query_foreign_access);
    2.32  EXPORT_SYMBOL(gnttab_grant_foreign_transfer);
    2.33  EXPORT_SYMBOL(gnttab_end_foreign_transfer);
    2.34  
    2.35 @@ -39,6 +48,10 @@ static grant_ref_t gnttab_free_head;
    2.36  
    2.37  static grant_entry_t *shared;
    2.38  
    2.39 +/* /proc/xen/grant */
    2.40 +static struct proc_dir_entry *grant_pde;
    2.41 +
    2.42 +
    2.43  /*
    2.44   * Lock-free grant-entry allocator
    2.45   */
    2.46 @@ -84,9 +97,18 @@ gnttab_grant_foreign_access(
    2.47      return ref;
    2.48  }
    2.49  
    2.50 +int
    2.51 +gnttab_query_foreign_access( grant_ref_t ref )
    2.52 +{
    2.53 +    u16 nflags;
    2.54 +
    2.55 +    nflags = shared[ref].flags;
    2.56 +
    2.57 +    return ( nflags & (GTF_reading|GTF_writing) );
    2.58 +}
    2.59 +
    2.60  void
    2.61 -gnttab_end_foreign_access(
    2.62 -    grant_ref_t ref, int readonly)
    2.63 +gnttab_end_foreign_access( grant_ref_t ref, int readonly )
    2.64  {
    2.65      u16 flags, nflags;
    2.66  
    2.67 @@ -141,7 +163,72 @@ gnttab_end_foreign_transfer(
    2.68      return frame;
    2.69  }
    2.70  
    2.71 -void __init gnttab_init(void)
    2.72 +static int grant_ioctl(struct inode *inode, struct file *file,
    2.73 +                       unsigned int cmd, unsigned long data)
    2.74 +{
    2.75 +    int                     ret;
    2.76 +    privcmd_hypercall_t     hypercall;
    2.77 +                                                                                        
    2.78 +    if ( cmd != IOCTL_PRIVCMD_HYPERCALL )
    2.79 +        return -ENOSYS;
    2.80 +
    2.81 +    if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
    2.82 +        return -EFAULT;
    2.83 +
    2.84 +    if ( hypercall.op != __HYPERVISOR_grant_table_op )
    2.85 +        return -ENOSYS;
    2.86 +
    2.87 +    /* hypercall-invoking asm taken from privcmd.c */
    2.88 +    __asm__ __volatile__ (
    2.89 +        "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; "
    2.90 +        "movl  4(%%eax),%%ebx ;"
    2.91 +        "movl  8(%%eax),%%ecx ;"
    2.92 +        "movl 12(%%eax),%%edx ;"
    2.93 +        "movl 16(%%eax),%%esi ;"
    2.94 +        "movl 20(%%eax),%%edi ;"
    2.95 +        "movl   (%%eax),%%eax ;"
    2.96 +        TRAP_INSTR "; "
    2.97 +        "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
    2.98 +        : "=a" (ret) : "0" (&hypercall) : "memory" );
    2.99 +                                                                                    
   2.100 +    return ret;
   2.101 +}
   2.102 +
   2.103 +static struct file_operations grant_file_ops = {
   2.104 +    ioctl:  grant_ioctl,
   2.105 +};
   2.106 +
   2.107 +static int grant_read(char *page, char **start, off_t off,
   2.108 +                      int count, int *eof, void *data)
   2.109 +{
   2.110 +    int             len;
   2.111 +    unsigned int    i;
   2.112 +    grant_entry_t  *gt;
   2.113 +
   2.114 +    gt = (grant_entry_t *)shared;
   2.115 +    len = 0;
   2.116 +
   2.117 +    for ( i = 0; i < NR_GRANT_REFS; i++ )
   2.118 +        if ( gt[i].flags )
   2.119 +            len += sprintf( page + len,
   2.120 +                    "Grant: ref (0x%x) flags (0x%hx) dom (0x%hx) frame (0x%x)\n", 
   2.121 +                    i,
   2.122 +                    gt[i].flags,
   2.123 +                    gt[i].domid,
   2.124 +                    gt[i].frame );
   2.125 +
   2.126 +    *eof = 1;
   2.127 +    return len;
   2.128 +}
   2.129 +
   2.130 +static int grant_write(struct file *file, const char __user *buffer,
   2.131 +                       unsigned long count, void *data)
   2.132 +{
   2.133 +    /* TODO: implement this */
   2.134 +    return -ENOSYS;
   2.135 +}
   2.136 +
   2.137 +static int __init gnttab_init(void)
   2.138  {
   2.139      gnttab_setup_table_t setup;
   2.140      unsigned long        frame;
   2.141 @@ -160,4 +247,25 @@ void __init gnttab_init(void)
   2.142  
   2.143      set_fixmap_ma(FIX_GNTTAB, frame << PAGE_SHIFT);
   2.144      shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB);
   2.145 +
   2.146 +    /*
   2.147 +     *  /proc/xen/grant : used by libxc to access grant tables
   2.148 +     */
   2.149 +    if ( (grant_pde = create_xen_proc_entry("grant", 0600)) == NULL )
   2.150 +    {
   2.151 +        WPRINTK("Unable to create grant xen proc entry\n");
   2.152 +        return -1;
   2.153 +    }
   2.154 +
   2.155 +    grant_file_ops.read   = grant_pde->proc_fops->read;
   2.156 +    grant_file_ops.write  = grant_pde->proc_fops->write;
   2.157 +
   2.158 +    grant_pde->proc_fops  = &grant_file_ops;
   2.159 +
   2.160 +    grant_pde->read_proc  = &grant_read;
   2.161 +    grant_pde->write_proc = &grant_write;
   2.162 +
   2.163 +    return 0;
   2.164  }
   2.165 +
   2.166 +__initcall(gnttab_init);
     3.1 --- a/linux-2.6.10-xen-sparse/include/asm-xen/gnttab.h	Tue Mar 08 17:12:15 2005 +0000
     3.2 +++ b/linux-2.6.10-xen-sparse/include/asm-xen/gnttab.h	Tue Mar 08 17:48:59 2005 +0000
     3.3 @@ -32,4 +32,8 @@ unsigned long
     3.4  gnttab_end_foreign_transfer(
     3.5      grant_ref_t ref);
     3.6  
     3.7 +int
     3.8 +gnttab_query_foreign_access( 
     3.9 +    grant_ref_t ref );
    3.10 +
    3.11  #endif /* __ASM_GNTTAB_H__ */
     4.1 --- a/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h	Tue Mar 08 17:12:15 2005 +0000
     4.2 +++ b/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h	Tue Mar 08 17:48:59 2005 +0000
     4.3 @@ -536,7 +536,7 @@ HYPERVISOR_grant_table_op(
     4.4      __asm__ __volatile__ (
     4.5          TRAP_INSTR
     4.6          : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
     4.7 -	: "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (count), "3" (uop)
     4.8 +	: "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (uop), "3" (count)
     4.9  	: "memory" );
    4.10  
    4.11      return ret;
     5.1 --- a/tools/libxc/Makefile	Tue Mar 08 17:12:15 2005 +0000
     5.2 +++ b/tools/libxc/Makefile	Tue Mar 08 17:48:59 2005 +0000
     5.3 @@ -20,6 +20,7 @@ SRCS     += xc_atropos.c
     5.4  SRCS     += xc_bvtsched.c
     5.5  SRCS     += xc_domain.c
     5.6  SRCS     += xc_evtchn.c
     5.7 +SRCS     += xc_gnttab.c
     5.8  SRCS     += xc_io.c
     5.9  SRCS     += xc_linux_build.c
    5.10  SRCS     += xc_plan9_build.c
     6.1 --- a/tools/libxc/xc.h	Tue Mar 08 17:12:15 2005 +0000
     6.2 +++ b/tools/libxc/xc.h	Tue Mar 08 17:48:59 2005 +0000
     6.3 @@ -411,4 +411,61 @@ void *xc_map_foreign_batch(int xc_handle
     6.4  int xc_get_pfn_list(int xc_handle, u32 domid, unsigned long *pfn_buf, 
     6.5  		    unsigned long max_pfns);
     6.6  
     6.7 +/*\
     6.8 + *  GRANT TABLE FUNCTIONS
     6.9 +\*/ 
    6.10 +
    6.11 +/**
    6.12 + * This function opens a handle to the more restricted grant table hypervisor
    6.13 + * interface. This may be used where the standard interface is not
    6.14 + * available because the domain is not privileged.
    6.15 + * This function can  be called multiple times within a single process.
    6.16 + * Multiple processes can have an open hypervisor interface at the same time.
    6.17 + *
    6.18 + * Each call to this function should have a corresponding call to
    6.19 + * xc_grant_interface_close().
    6.20 + *
    6.21 + * This function can fail if a Xen-enabled kernel is not currently running.
    6.22 + *
    6.23 + * @return a handle to the hypervisor grant table interface or -1 on failure
    6.24 + */
    6.25 +int xc_grant_interface_open(void);
    6.26 +
    6.27 +/**
    6.28 + * This function closes an open grant table hypervisor interface.
    6.29 + *
    6.30 + * This function can fail if the handle does not represent an open interface or
    6.31 + * if there were problems closing the interface.
    6.32 + *
    6.33 + * @parm xc_handle a handle to an open grant table hypervisor interface
    6.34 + * @return 0 on success, -1 otherwise.
    6.35 + */
    6.36 +int xc_grant_interface_close(int xc_handle);
    6.37 +
    6.38 +int xc_gnttab_map_grant_ref(int         xc_handle,
    6.39 +                            memory_t    host_virt_addr,
    6.40 +                            u32         dom,
    6.41 +                            u16         ref,
    6.42 +                            u16         flags,
    6.43 +                            s16        *handle,
    6.44 +                            memory_t   *dev_bus_addr);
    6.45 +
    6.46 +int xc_gnttab_unmap_grant_ref(int       xc_handle,
    6.47 +                              memory_t  host_virt_addr,
    6.48 +                              memory_t  dev_bus_addr,
    6.49 +                              u16       handle,
    6.50 +                              s16      *status);
    6.51 +
    6.52 +int xc_gnttab_setup_table(int        xc_handle,
    6.53 +                          u32        dom,
    6.54 +                          u16        nr_frames,
    6.55 +                          s16       *status,
    6.56 +                          memory_t **frame_list);
    6.57 +
    6.58 +/* Grant debug builds only: */
    6.59 +int xc_gnttab_dump_table(int        xc_handle,
    6.60 +                         u32        dom,
    6.61 +                         s16       *status);
    6.62 +
    6.63 +
    6.64  #endif /* __XC_H__ */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/libxc/xc_gnttab.c	Tue Mar 08 17:48:59 2005 +0000
     7.3 @@ -0,0 +1,143 @@
     7.4 +/******************************************************************************
     7.5 + * xc_gnttab.c
     7.6 + * 
     7.7 + * API for manipulating and accessing grant tables
     7.8 + * 
     7.9 + * Copyright (c) 2005 Christopher Clark
    7.10 + * based on xc_evtchn.c Copyright (c) 2004, K A Fraser.
    7.11 + */
    7.12 +
    7.13 +#include "xc_private.h"
    7.14 +#include "xen/grant_table.h"
    7.15 +
    7.16 +static int
    7.17 +do_gnttab_op( int xc_handle,
    7.18 +              unsigned long cmd,
    7.19 +              gnttab_op_t *op,
    7.20 +              unsigned long count )
    7.21 +{
    7.22 +    int ret = -1;
    7.23 +    privcmd_hypercall_t hypercall;
    7.24 +
    7.25 +    hypercall.op     = __HYPERVISOR_grant_table_op;
    7.26 +    hypercall.arg[0] = cmd;
    7.27 +    hypercall.arg[1] = (unsigned long)(op);
    7.28 +    hypercall.arg[2] = count;
    7.29 +
    7.30 +    if ( mlock(op, sizeof(*op)) != 0 )
    7.31 +    {
    7.32 +        PERROR("Could not lock memory for Xen hypercall");
    7.33 +        goto out1;
    7.34 +    }
    7.35 +
    7.36 +    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
    7.37 +    {
    7.38 +        printf("do_gnttab_op: hypercall returned error %d\n", ret);
    7.39 +        goto out2;
    7.40 +    }
    7.41 +
    7.42 + out2: (void)munlock(op, sizeof(*op));
    7.43 + out1: return ret;
    7.44 +}
    7.45 +
    7.46 +
    7.47 +int xc_gnttab_map_grant_ref(int         xc_handle,
    7.48 +                            memory_t    host_virt_addr,
    7.49 +                            u32         dom,
    7.50 +                            u16         ref,
    7.51 +                            u16         flags,
    7.52 +                            s16        *handle,
    7.53 +                            memory_t   *dev_bus_addr)
    7.54 +{
    7.55 +    gnttab_op_t     op;
    7.56 +    int             rc;
    7.57 +
    7.58 +    op.u.map_grant_ref.host_virt_addr = host_virt_addr;
    7.59 +    op.u.map_grant_ref.dom            = (domid_t)dom;
    7.60 +    op.u.map_grant_ref.ref            = ref;
    7.61 +    op.u.map_grant_ref.flags          = flags;
    7.62 + 
    7.63 +    if ( (rc = do_gnttab_op(xc_handle, GNTTABOP_map_grant_ref, &op, 1)) == 0 )
    7.64 +    {
    7.65 +        *handle         = op.u.map_grant_ref.handle;
    7.66 +        *dev_bus_addr   = op.u.map_grant_ref.dev_bus_addr;
    7.67 +    }
    7.68 +
    7.69 +    return rc;
    7.70 +}
    7.71 +
    7.72 +
    7.73 +int xc_gnttab_unmap_grant_ref(int       xc_handle,
    7.74 +                              memory_t  host_virt_addr,
    7.75 +                              memory_t  dev_bus_addr,
    7.76 +                              u16       handle,
    7.77 +                              s16      *status)
    7.78 +{
    7.79 +    gnttab_op_t     op;
    7.80 +    int             rc;
    7.81 +
    7.82 +    op.u.unmap_grant_ref.host_virt_addr = host_virt_addr;
    7.83 +    op.u.unmap_grant_ref.dev_bus_addr   = dev_bus_addr;
    7.84 +    op.u.unmap_grant_ref.handle         = handle;
    7.85 + 
    7.86 +    if ( (rc = do_gnttab_op(xc_handle, GNTTABOP_unmap_grant_ref, &op, 1)) == 0 )
    7.87 +        *status = op.u.unmap_grant_ref.status;
    7.88 +
    7.89 +    return rc;
    7.90 +}
    7.91 +
    7.92 +int xc_gnttab_setup_table(int        xc_handle,
    7.93 +                          u32        dom,
    7.94 +                          u16        nr_frames,
    7.95 +                          s16       *status,
    7.96 +                          memory_t **frame_list)
    7.97 +{
    7.98 +    gnttab_op_t     op;
    7.99 +    int             rc;
   7.100 +    int             i;
   7.101 +
   7.102 +    op.u.setup_table.dom        = (domid_t)dom;
   7.103 +    op.u.setup_table.nr_frames  = nr_frames;
   7.104 + 
   7.105 +    if ( (rc = do_gnttab_op(xc_handle, GNTTABOP_setup_table, &op, 1)) == 0 )
   7.106 +    {
   7.107 +        *status = op.u.setup_table.status;
   7.108 +        for ( i = 0; i < nr_frames; i++ )
   7.109 +        {
   7.110 +            (*frame_list)[i] = op.u.setup_table.frame_list[i];
   7.111 +        }
   7.112 +    }
   7.113 +
   7.114 +    return rc;
   7.115 +}
   7.116 +
   7.117 +int xc_gnttab_dump_table(int        xc_handle,
   7.118 +                         u32        dom,
   7.119 +                         s16       *status)
   7.120 +{
   7.121 +    gnttab_op_t     op;
   7.122 +    int             rc;
   7.123 +
   7.124 +    op.u.dump_table.dom = (domid_t)dom;
   7.125 + 
   7.126 +    printf("xc_gnttab_dump_table: domain %d\n", dom);
   7.127 +
   7.128 +    if ( (rc = do_gnttab_op(xc_handle, GNTTABOP_dump_table, &op, 1)) == 0 )
   7.129 +        *status = op.u.dump_table.status;
   7.130 +
   7.131 +    return rc;
   7.132 +}
   7.133 +
   7.134 +int xc_grant_interface_open(void)
   7.135 +{
   7.136 +    int fd = open("/proc/xen/grant", O_RDWR);
   7.137 +    if ( fd == -1 )
   7.138 +        PERROR("Could not obtain handle on grant command interface");
   7.139 +    return fd;
   7.140 +
   7.141 +}
   7.142 +
   7.143 +int xc_grant_interface_close(int xc_grant_handle)
   7.144 +{
   7.145 +    return close(xc_grant_handle);
   7.146 +}
     8.1 --- a/xen/arch/x86/mm.c	Tue Mar 08 17:12:15 2005 +0000
     8.2 +++ b/xen/arch/x86/mm.c	Tue Mar 08 17:48:59 2005 +0000
     8.3 @@ -1060,14 +1060,14 @@ void free_page_type(struct pfn_info *pag
     8.4  }
     8.5  
     8.6  
     8.7 -void put_page_type(struct pfn_info *page)
     8.8 +void put_page_types(struct pfn_info *page, u32 decrement)
     8.9  {
    8.10      u32 nx, x, y = page->u.inuse.type_info;
    8.11  
    8.12   again:
    8.13      do {
    8.14          x  = y;
    8.15 -        nx = x - 1;
    8.16 +        nx = x - decrement;
    8.17  
    8.18          ASSERT((x & PGT_count_mask) != 0);
    8.19  
    8.20 @@ -1911,16 +1911,124 @@ int do_mmu_update(
    8.21      return rc;
    8.22  }
    8.23  
    8.24 +void update_shadow_va_mapping(unsigned long va,
    8.25 +                              unsigned long val,
    8.26 +                              struct exec_domain *ed,
    8.27 +                              struct domain *d)
    8.28 +{
    8.29 +    /* This function assumes the caller is holding the domain's BIGLOCK
    8.30 +     * and is running in a shadow mode
    8.31 +     */
    8.32 +
    8.33 +    unsigned long   sval = 0;
    8.34 +
    8.35 +    l1pte_propagate_from_guest(d, &val, &sval);
    8.36 +
    8.37 +    if ( unlikely(__put_user(sval, ((unsigned long *)(
    8.38 +        &shadow_linear_pg_table[l1_linear_offset(va)])))) )
    8.39 +    {
    8.40 +        /*
    8.41 +         * Since L2's are guranteed RW, failure indicates either that the
    8.42 +         * page was not shadowed, or that the L2 entry has not yet been
    8.43 +         * updated to reflect the shadow.
    8.44 +         */
    8.45 +        l2_pgentry_t gpde = linear_l2_table[l2_table_offset(va)];
    8.46 +        unsigned long gpfn = l2_pgentry_val(gpde) >> PAGE_SHIFT;
    8.47 +
    8.48 +        if (get_shadow_status(d, gpfn))
    8.49 +        {
    8.50 +            unsigned long gmfn = __gpfn_to_mfn(d, gpfn);
    8.51 +            unsigned long *gl1e = map_domain_mem(gmfn << PAGE_SHIFT);
    8.52 +            unsigned l1_idx = l1_table_offset(va);
    8.53 +            gl1e[l1_idx] = sval;
    8.54 +            unmap_domain_mem(gl1e);
    8.55 +            put_shadow_status(d);
    8.56 +
    8.57 +            perfc_incrc(shadow_update_va_fail1);
    8.58 +        }
    8.59 +        else
    8.60 +            perfc_incrc(shadow_update_va_fail2);
    8.61 +    }
    8.62 +
    8.63 +    /*
    8.64 +     * If we're in log-dirty mode then we need to note that we've updated
    8.65 +     * the PTE in the PT-holding page. We need the machine frame number
    8.66 +     * for this.
    8.67 +     */
    8.68 +    if ( shadow_mode_log_dirty(d) )
    8.69 +        mark_dirty(d, va_to_l1mfn(va));
    8.70 +
    8.71 +    check_pagetable(d, ed->arch.guest_table, "va"); /* debug */
    8.72 +}
    8.73 +
    8.74 +int update_grant_va_mapping(unsigned long va,
    8.75 +                            unsigned long _nl1e, 
    8.76 +                            struct domain *d,
    8.77 +                            struct exec_domain *ed)
    8.78 +{
    8.79 +    /* Caller must:
    8.80 +     * . own d's BIGLOCK 
    8.81 +     * . already have 'get_page' correctly on the to-be-installed nl1e
    8.82 +     * . be responsible for flushing the TLB
    8.83 +     * . check PTE being installed isn't DISALLOWED
    8.84 +     */
    8.85 +
    8.86 +    /* Return value:
    8.87 +     * -ve : error
    8.88 +     * 0   : done
    8.89 +     * GNTUPDVA_prev_ro : done & prior mapping was ro to same frame
    8.90 +     * GNTUPDVA_prev_rw : done & prior mapping was rw to same frame
    8.91 +     */
    8.92 +
    8.93 +    int             rc = 0;
    8.94 +    l1_pgentry_t   *pl1e;
    8.95 +    unsigned long   _ol1e;
    8.96 +
    8.97 +    cleanup_writable_pagetable(d);
    8.98 +
    8.99 +    pl1e = &linear_pg_table[l1_linear_offset(va)];
   8.100 +
   8.101 +    if ( unlikely(__get_user(_ol1e, (unsigned long *)pl1e) != 0) )
   8.102 +        rc = -EINVAL;
   8.103 +    else
   8.104 +    {
   8.105 +        l1_pgentry_t ol1e = mk_l1_pgentry(_ol1e);
   8.106 +
   8.107 +        if ( update_l1e(pl1e, ol1e, mk_l1_pgentry(_nl1e)) )
   8.108 +        {
   8.109 +            /* overwrote different mfn?  */
   8.110 +            if (((_ol1e ^ _nl1e) & (PADDR_MASK & PAGE_MASK)) != 0)
   8.111 +            {
   8.112 +                rc = 0;
   8.113 +                put_page_from_l1e(ol1e, d);
   8.114 +            }
   8.115 +            else
   8.116 +                rc = ((_ol1e & _PAGE_RW) ? GNTUPDVA_prev_rw
   8.117 +                                         : GNTUPDVA_prev_ro );
   8.118 +                /* use return code to avoid nasty grant table
   8.119 +                 * slow path in put_page_from_l1e -- caller
   8.120 +                 * must handle ref count instead. */
   8.121 +        }
   8.122 +        else
   8.123 +            rc = -EINVAL;
   8.124 +    }
   8.125 +
   8.126 +    if ( unlikely(shadow_mode_enabled(d)) )
   8.127 +        update_shadow_va_mapping(va, _nl1e, ed, d);
   8.128 +
   8.129 +    return rc;
   8.130 +}
   8.131 +
   8.132  
   8.133  int do_update_va_mapping(unsigned long va,
   8.134                           unsigned long val, 
   8.135                           unsigned long flags)
   8.136  {
   8.137 -    struct exec_domain *ed = current;
   8.138 -    struct domain *d = ed->domain;
   8.139 -    int err = 0;
   8.140 -    unsigned int cpu = ed->processor;
   8.141 -    unsigned long deferred_ops;
   8.142 +    struct exec_domain      *ed  = current;
   8.143 +    struct domain           *d   = ed->domain;
   8.144 +    unsigned int             cpu = ed->processor;
   8.145 +    unsigned long            deferred_ops;
   8.146 +    int                      rc = 0;
   8.147  
   8.148      perfc_incrc(calls_to_update_va);
   8.149  
   8.150 @@ -1941,52 +2049,14 @@ int do_update_va_mapping(unsigned long v
   8.151  
   8.152      if ( unlikely(!mod_l1_entry(&linear_pg_table[l1_linear_offset(va)],
   8.153                                  mk_l1_pgentry(val))) )
   8.154 -        err = -EINVAL;
   8.155 +        rc = -EINVAL;
   8.156  
   8.157      if ( unlikely(shadow_mode_enabled(d)) )
   8.158      {
   8.159 -        unsigned long sval = 0;
   8.160 -
   8.161 -        l1pte_propagate_from_guest(d, &val, &sval);
   8.162 -
   8.163 -        if ( unlikely(__put_user(sval, ((unsigned long *)(
   8.164 -            &shadow_linear_pg_table[l1_linear_offset(va)])))) )
   8.165 -        {
   8.166 -            /*
   8.167 -             * Since L2's are guranteed RW, failure indicates either that the
   8.168 -             * page was not shadowed, or that the L2 entry has not yet been
   8.169 -             * updated to reflect the shadow.
   8.170 -             */
   8.171 -            if ( shadow_mode_external(current->domain) )
   8.172 -                BUG(); // can't use linear_l2_table with external tables.
   8.173 -
   8.174 -            l2_pgentry_t gpde = linear_l2_table[l2_table_offset(va)];
   8.175 -            unsigned long gpfn = l2_pgentry_val(gpde) >> PAGE_SHIFT;
   8.176 -
   8.177 -            if (get_shadow_status(d, gpfn))
   8.178 -            {
   8.179 -                unsigned long gmfn = __gpfn_to_mfn(d, gpfn);
   8.180 -                unsigned long *gl1e = map_domain_mem(gmfn << PAGE_SHIFT);
   8.181 -                unsigned l1_idx = l1_table_offset(va);
   8.182 -                gl1e[l1_idx] = sval;
   8.183 -                unmap_domain_mem(gl1e);
   8.184 -                put_shadow_status(d);
   8.185 -
   8.186 -                perfc_incrc(shadow_update_va_fail1);
   8.187 -            }
   8.188 -            else
   8.189 -                perfc_incrc(shadow_update_va_fail2);
   8.190 -        }
   8.191 -
   8.192 -        /*
   8.193 -         * If we're in log-dirty mode then we need to note that we've updated
   8.194 -         * the PTE in the PT-holding page. We need the machine frame number
   8.195 -         * for this.
   8.196 -         */
   8.197 -        if ( shadow_mode_log_dirty(d) )
   8.198 -            mark_dirty(d, va_to_l1mfn(va));
   8.199 -  
   8.200 -        check_pagetable(d, ed->arch.guest_table, "va"); /* debug */
   8.201 +        if ( shadow_mode_external(current->domain) )
   8.202 +            BUG(); // can't use linear_l2_table with external tables.
   8.203 +
   8.204 +        update_shadow_va_mapping(va, val, ed, d);
   8.205      }
   8.206  
   8.207      deferred_ops = percpu_info[cpu].deferred_ops;
   8.208 @@ -2003,7 +2073,7 @@ int do_update_va_mapping(unsigned long v
   8.209      
   8.210      UNLOCK_BIGLOCK(d);
   8.211  
   8.212 -    return err;
   8.213 +    return rc;
   8.214  }
   8.215  
   8.216  int do_update_va_mapping_otherdomain(unsigned long va,
     9.1 --- a/xen/common/grant_table.c	Tue Mar 08 17:12:15 2005 +0000
     9.2 +++ b/xen/common/grant_table.c	Tue Mar 08 17:48:59 2005 +0000
     9.3 @@ -4,6 +4,7 @@
     9.4   * Mechanism for granting foreign access to page frames, and receiving
     9.5   * page-ownership transfers.
     9.6   * 
     9.7 + * Copyright (c) 2005 Christopher Clark
     9.8   * Copyright (c) 2004 K A Fraser
     9.9   * 
    9.10   * This program is free software; you can redistribute it and/or modify
    9.11 @@ -21,8 +22,12 @@
    9.12   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.13   */
    9.14  
    9.15 +#define GRANT_DEBUG 1
    9.16 +
    9.17  #include <xen/config.h>
    9.18  #include <xen/sched.h>
    9.19 +#include <asm-x86/mm.h>
    9.20 +#include <asm-x86/shadow.h>
    9.21  
    9.22  #define PIN_FAIL(_rc, _f, _a...)   \
    9.23      do {                           \
    9.24 @@ -50,19 +55,24 @@ put_maptrack_handle(
    9.25      t->maptrack_head = handle;
    9.26  }
    9.27  
    9.28 -static void
    9.29 +static int
    9.30  __gnttab_map_grant_ref(
    9.31 -    gnttab_map_grant_ref_t *uop)
    9.32 +    gnttab_map_grant_ref_t *uop,
    9.33 +    unsigned long *va)
    9.34  {
    9.35 -    domid_t        dom, sdom;
    9.36 -    grant_ref_t    ref;
    9.37 -    struct domain *ld, *rd;
    9.38 -    u16            flags, sflags;
    9.39 -    int            handle;
    9.40 +    domid_t               dom, sdom;
    9.41 +    grant_ref_t           ref;
    9.42 +    struct domain        *ld, *rd;
    9.43 +    struct exec_domain   *led;
    9.44 +    u16                   flags, sflags;
    9.45 +    int                   handle;
    9.46      active_grant_entry_t *act;
    9.47 -    grant_entry_t *sha;
    9.48 -    s16            rc = 0;
    9.49 -    unsigned long  frame;
    9.50 +    grant_entry_t        *sha;
    9.51 +    s16                   rc = 0;
    9.52 +    unsigned long         frame = 0, host_virt_addr;
    9.53 +
    9.54 +    /* Returns 0 if TLB flush / invalidate required by caller.
    9.55 +     * va will indicate the address to be invalidated. */
    9.56  
    9.57      /*
    9.58       * We bound the number of times we retry CMPXCHG on memory locations that
    9.59 @@ -74,23 +84,33 @@ static void
    9.60       */
    9.61      int            retries = 0;
    9.62  
    9.63 -    ld = current->domain;
    9.64 +    led = current;
    9.65 +    ld = led->domain;
    9.66  
    9.67      /* Bitwise-OR avoids short-circuiting which screws control flow. */
    9.68      if ( unlikely(__get_user(dom, &uop->dom) |
    9.69                    __get_user(ref, &uop->ref) |
    9.70 +                  __get_user(host_virt_addr, &uop->host_virt_addr) |
    9.71                    __get_user(flags, &uop->flags)) )
    9.72      {
    9.73          DPRINTK("Fault while reading gnttab_map_grant_ref_t.\n");
    9.74 -        return; /* don't set status */
    9.75 +        return -EFAULT; /* don't set status */
    9.76      }
    9.77  
    9.78 -    if ( unlikely(ref >= NR_GRANT_ENTRIES) || 
    9.79 +    if ( ((host_virt_addr != 0) || (flags & GNTMAP_host_map) ) &&
    9.80 +         unlikely(!__addr_ok(host_virt_addr)))
    9.81 +    {
    9.82 +        DPRINTK("Bad virtual address (%x) or flags (%x).\n", host_virt_addr, flags);
    9.83 +        (void)__put_user(GNTST_bad_virt_addr, &uop->handle);
    9.84 +        return GNTST_bad_gntref;
    9.85 +    }
    9.86 +
    9.87 +    if ( unlikely(ref >= NR_GRANT_ENTRIES) ||
    9.88           unlikely((flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0) )
    9.89      {
    9.90          DPRINTK("Bad ref (%d) or flags (%x).\n", ref, flags);
    9.91          (void)__put_user(GNTST_bad_gntref, &uop->handle);
    9.92 -        return;
    9.93 +        return GNTST_bad_gntref;
    9.94      }
    9.95  
    9.96      if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
    9.97 @@ -100,7 +120,7 @@ static void
    9.98              put_domain(rd);
    9.99          DPRINTK("Could not find domain %d\n", dom);
   9.100          (void)__put_user(GNTST_bad_domain, &uop->handle);
   9.101 -        return;
   9.102 +        return GNTST_bad_domain;
   9.103      }
   9.104  
   9.105      if ( unlikely((handle = get_maptrack_handle(ld->grant_table)) == -1) )
   9.106 @@ -108,14 +128,16 @@ static void
   9.107          put_domain(rd);
   9.108          DPRINTK("No more map handles available\n");
   9.109          (void)__put_user(GNTST_no_device_space, &uop->handle);
   9.110 -        return;
   9.111 +        return GNTST_no_device_space;
   9.112      }
   9.113 +    DPRINTK("Mapping grant ref (%hu) for domain (%hu) with flags (%x)\n",
   9.114 +            ref, dom, flags);
   9.115  
   9.116      act = &rd->grant_table->active[ref];
   9.117      sha = &rd->grant_table->shared[ref];
   9.118  
   9.119      spin_lock(&rd->grant_table->lock);
   9.120 -    
   9.121 +
   9.122      if ( act->pin == 0 )
   9.123      {
   9.124          /* CASE 1: Activating a previously inactive entry. */
   9.125 @@ -148,7 +170,7 @@ static void
   9.126  
   9.127              /* NB. prev_scombo is updated in place to seen value. */
   9.128              if ( unlikely(cmpxchg_user((u32 *)&sha->flags,
   9.129 -                                       prev_scombo, 
   9.130 +                                       prev_scombo,
   9.131                                         new_scombo)) )
   9.132                  PIN_FAIL(GNTST_general_error,
   9.133                           "Fault while modifying shared flags and domid.\n");
   9.134 @@ -168,16 +190,18 @@ static void
   9.135          }
   9.136  
   9.137          /* rmb(); */ /* not on x86 */
   9.138 -        frame = sha->frame;
   9.139 -        if ( unlikely(!pfn_is_ram(frame)) || 
   9.140 -             unlikely(!((flags & GNTMAP_readonly) ? 
   9.141 -                        get_page(&frame_table[frame], rd) : 
   9.142 -                        get_page_and_type(&frame_table[frame], rd, 
   9.143 +
   9.144 +        frame = __translate_gpfn_to_mfn(rd, sha->frame);
   9.145 +
   9.146 +        if ( unlikely(!pfn_is_ram(frame)) ||
   9.147 +             unlikely(!((flags & GNTMAP_readonly) ?
   9.148 +                        get_page(&frame_table[frame], rd) :
   9.149 +                        get_page_and_type(&frame_table[frame], rd,
   9.150                                            PGT_writable_page))) )
   9.151          {
   9.152              clear_bit(_GTF_writing, &sha->flags);
   9.153              clear_bit(_GTF_reading, &sha->flags);
   9.154 -            PIN_FAIL(GNTST_general_error, 
   9.155 +            PIN_FAIL(GNTST_general_error,
   9.156                       "Could not pin the granted frame!\n");
   9.157          }
   9.158  
   9.159 @@ -230,7 +254,9 @@ static void
   9.160                  sflags = prev_sflags;
   9.161              }
   9.162  
   9.163 -            if ( unlikely(!get_page_type(&frame_table[act->frame],
   9.164 +            frame = act->frame;
   9.165 +
   9.166 +            if ( unlikely(!get_page_type(&frame_table[frame],
   9.167                                           PGT_writable_page)) )
   9.168              {
   9.169                  clear_bit(_GTF_writing, &sha->flags);
   9.170 @@ -251,34 +277,91 @@ static void
   9.171      ld->grant_table->maptrack[handle].ref_and_flags =
   9.172          (ref << MAPTRACK_REF_SHIFT) | (flags & MAPTRACK_GNTMAP_MASK);
   9.173  
   9.174 +    if ( (host_virt_addr != 0) && (flags & GNTMAP_host_map) )
   9.175 +    {
   9.176 +        /* Write update into the pagetable
   9.177 +         */
   9.178 +        if ( 0 > (rc = update_grant_va_mapping( host_virt_addr,
   9.179 +                                (frame << PAGE_SHIFT) | _PAGE_PRESENT  |
   9.180 +                                                        _PAGE_ACCESSED |
   9.181 +                                                        _PAGE_DIRTY    |
   9.182 +                       ((flags & GNTMAP_readonly) ? 0 : _PAGE_RW),
   9.183 +                       ld, led )) )
   9.184 +        {
   9.185 +            /* Abort. */
   9.186 +            act->pin -= (flags & GNTMAP_readonly) ?
   9.187 +                GNTPIN_hstr_inc : GNTPIN_hstw_inc;
   9.188 +
   9.189 +            if ( flags & GNTMAP_readonly )
   9.190 +                act->pin -= GNTPIN_hstr_inc;
   9.191 +            else
   9.192 +            {
   9.193 +                act->pin -= GNTPIN_hstw_inc;
   9.194 +                if ( (act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) == 0 )
   9.195 +                    put_page_type(&frame_table[frame]);
   9.196 +
   9.197 +                if ( act->pin == 0 )
   9.198 +                    put_page(&frame_table[frame]);
   9.199 +            }
   9.200 +            goto fail;
   9.201 +        }
   9.202 +
   9.203 +        if ( rc == GNTUPDVA_prev_ro )
   9.204 +            act->pin -= GNTPIN_hstr_inc;
   9.205 +
   9.206 +        if ( rc == GNTUPDVA_prev_rw ) 
   9.207 +        {
   9.208 +            act->pin -= GNTPIN_hstw_inc;
   9.209 +            put_page_type(&frame_table[frame]);
   9.210 +        }
   9.211 +        rc = 0;
   9.212 +        *va = host_virt_addr;
   9.213 +
   9.214 +        /* IMPORTANT: must flush / invalidate entry in TLB.
   9.215 +         * This is done in the outer gnttab_map_grant_ref when return 0.
   9.216 +         */
   9.217 +    }
   9.218 +
   9.219 +    if ( flags & GNTMAP_device_map )
   9.220 +        (void)__put_user(frame,  &uop->dev_bus_addr);
   9.221 +
   9.222      /* Unchecked and unconditional. */
   9.223      (void)__put_user(handle, &uop->handle);
   9.224 -    (void)__put_user(act->frame,  &uop->dev_bus_addr);
   9.225  
   9.226      spin_unlock(&rd->grant_table->lock);
   9.227      put_domain(rd);
   9.228 -    return;
   9.229 +    return 0;
   9.230  
   9.231   fail:
   9.232      (void)__put_user(rc, &uop->handle);
   9.233      spin_unlock(&rd->grant_table->lock);
   9.234      put_domain(rd);
   9.235 -    put_maptrack_handle(ld->grant_table, handle);
   9.236 +    put_maptrack_handle(ld->grant_table, handle); //cwc22: check this
   9.237 +    return rc;
   9.238  }
   9.239  
   9.240  static long
   9.241  gnttab_map_grant_ref(
   9.242      gnttab_map_grant_ref_t *uop, unsigned int count)
   9.243  {
   9.244 -    int i;
   9.245 +    int i, flush = 0;
   9.246 +    unsigned long va;
   9.247 +
   9.248      for ( i = 0; i < count; i++ )
   9.249 -        __gnttab_map_grant_ref(&uop[i]);
   9.250 +        if ( __gnttab_map_grant_ref(&uop[i], &va) == 0)
   9.251 +            flush++;
   9.252 +
   9.253 +    if ( flush == 1 )
   9.254 +        __flush_tlb_one(va);
   9.255 +    else if ( flush )
   9.256 +        local_flush_tlb();
   9.257      return 0;
   9.258  }
   9.259  
   9.260 -static void
   9.261 +static int
   9.262  __gnttab_unmap_grant_ref(
   9.263 -    gnttab_unmap_grant_ref_t *uop)
   9.264 +    gnttab_unmap_grant_ref_t *uop,
   9.265 +    unsigned long *va)
   9.266  {
   9.267      domid_t        dom;
   9.268      grant_ref_t    ref;
   9.269 @@ -288,7 +371,7 @@ static void
   9.270      active_grant_entry_t *act;
   9.271      grant_entry_t *sha;
   9.272      grant_mapping_t *map;
   9.273 -    s16            rc = 0;
   9.274 +    s16            rc = -EFAULT;
   9.275      unsigned long  frame, virt;
   9.276  
   9.277      ld = current->domain;
   9.278 @@ -299,7 +382,7 @@ static void
   9.279                    __get_user(handle, &uop->handle)) )
   9.280      {
   9.281          DPRINTK("Fault while reading gnttab_unmap_grant_ref_t.\n");
   9.282 -        return; /* don't set status */
   9.283 +        return -EFAULT; /* don't set status */
   9.284      }
   9.285  
   9.286      map = &ld->grant_table->maptrack[handle];
   9.287 @@ -309,7 +392,7 @@ static void
   9.288      {
   9.289          DPRINTK("Bad handle (%d).\n", handle);
   9.290          (void)__put_user(GNTST_bad_handle, &uop->status);
   9.291 -        return;
   9.292 +        return GNTST_bad_handle;
   9.293      }
   9.294  
   9.295      dom = map->domid;
   9.296 @@ -322,8 +405,10 @@ static void
   9.297              put_domain(rd);
   9.298          DPRINTK("Could not find domain %d\n", dom);
   9.299          (void)__put_user(GNTST_bad_domain, &uop->status);
   9.300 -        return;
   9.301 +        return GNTST_bad_domain;
   9.302      }
   9.303 +    DPRINTK("Unmapping grant ref (%hu) for domain (%hu) with handle (%hu)\n",
   9.304 +            ref, dom, handle);
   9.305  
   9.306      act = &rd->grant_table->active[ref];
   9.307      sha = &rd->grant_table->shared[ref];
   9.308 @@ -344,12 +429,53 @@ static void
   9.309          frame = act->frame;
   9.310      }
   9.311  
   9.312 -    if ( (virt != 0) && (map->ref_and_flags & GNTMAP_host_map) )
   9.313 +    if ( (virt != 0) &&
   9.314 +         (map->ref_and_flags & GNTMAP_host_map) &&
   9.315 +         ((act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) > 0))
   9.316      {
   9.317 -        act->pin -= (map->ref_and_flags & GNTMAP_readonly) ?
   9.318 -            GNTPIN_hstr_inc : GNTPIN_hstw_inc;
   9.319 +        l1_pgentry_t   *pl1e;
   9.320 +        unsigned long   _ol1e;
   9.321 +
   9.322 +        pl1e = &linear_pg_table[l1_linear_offset(virt)];
   9.323 +                                                                                            
   9.324 +        if ( unlikely(__get_user(_ol1e, (unsigned long *)pl1e) != 0) )
   9.325 +        {
   9.326 +            DPRINTK("Could not find PTE entry for address %x\n", virt);
   9.327 +            rc = -EINVAL;
   9.328 +            goto fail;
   9.329 +        }
   9.330 +
   9.331 +        /* check that the virtual address supplied is actually
   9.332 +         * mapped to act->frame.
   9.333 +         */
   9.334 +        if ( unlikely((_ol1e >> PAGE_SHIFT) != frame ))
   9.335 +        {
   9.336 +            DPRINTK("PTE entry %x for address %x doesn't match frame %x\n",
   9.337 +                    _ol1e, virt, frame);
   9.338 +            rc = -EINVAL;
   9.339 +            goto fail;
   9.340 +        }
   9.341 +
   9.342 +        /* This code _requires_ that the act->pin bits are updated
   9.343 +         * if a mapping is ever switched between RO and RW.
   9.344 +         */
   9.345 +        act->pin -= ( _ol1e & _PAGE_RW ) ? GNTPIN_hstw_inc
   9.346 +                                         : GNTPIN_hstr_inc;
   9.347 +
   9.348 +        /* Delete pagetable entry
   9.349 +         */
   9.350 +        if ( unlikely(__put_user(0, (unsigned long *)pl1e)))
   9.351 +        {
   9.352 +            DPRINTK("Cannot delete PTE entry at %x for virtual address %x\n",
   9.353 +                    pl1e, virt);
   9.354 +            rc = -EINVAL;
   9.355 +            goto fail;
   9.356 +        }
   9.357 +        rc = 0;
   9.358 +        *va = virt;
   9.359      }
   9.360  
   9.361 +    /* If the last writable mapping has been removed, put_page_type */
   9.362      if ( ((act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0) &&
   9.363                !(map->ref_and_flags & GNTMAP_readonly) )
   9.364      {
   9.365 @@ -367,15 +493,24 @@ static void
   9.366      (void)__put_user(rc, &uop->status);
   9.367      spin_unlock(&rd->grant_table->lock);
   9.368      put_domain(rd);
   9.369 +    return rc;
   9.370  }
   9.371  
   9.372  static long
   9.373  gnttab_unmap_grant_ref(
   9.374      gnttab_unmap_grant_ref_t *uop, unsigned int count)
   9.375  {
   9.376 -    int i;
   9.377 +    int i, flush = 0;
   9.378 +    unsigned long va = 0;
   9.379 +
   9.380      for ( i = 0; i < count; i++ )
   9.381 -        __gnttab_unmap_grant_ref(&uop[i]);
   9.382 +        if ( __gnttab_unmap_grant_ref(&uop[i], &va) == 0)
   9.383 +            flush++;
   9.384 +
   9.385 +    if ( flush == 1 )
   9.386 +        __flush_tlb_one(va);
   9.387 +    else if ( flush )
   9.388 +        local_flush_tlb();
   9.389      return 0;
   9.390  }
   9.391  
   9.392 @@ -423,7 +558,7 @@ gnttab_setup_table(
   9.393      {
   9.394          ASSERT(d->grant_table != NULL);
   9.395          (void)put_user(GNTST_okay, &uop->status);
   9.396 -        (void)put_user(virt_to_phys(d->grant_table) >> PAGE_SHIFT,
   9.397 +        (void)put_user(virt_to_phys(d->grant_table->shared) >> PAGE_SHIFT,
   9.398                         &uop->frame_list[0]);
   9.399      }
   9.400  
   9.401 @@ -431,14 +566,99 @@ gnttab_setup_table(
   9.402      return 0;
   9.403  }
   9.404  
   9.405 +#ifdef GRANT_DEBUG
   9.406 +static int
   9.407 +gnttab_dump_table(gnttab_dump_table_t *uop)
   9.408 +{
   9.409 +    grant_table_t        *gt;
   9.410 +    gnttab_dump_table_t   op;
   9.411 +    struct domain        *d;
   9.412 +    u32                   shared_mfn;
   9.413 +    active_grant_entry_t *act;
   9.414 +    grant_entry_t         sha_copy;
   9.415 +    grant_mapping_t      *maptrack;
   9.416 +    int                   i;
   9.417 +
   9.418 +
   9.419 +    if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
   9.420 +    {
   9.421 +        DPRINTK("Fault while reading gnttab_dump_table_t.\n");
   9.422 +        return -EFAULT;
   9.423 +    }
   9.424 +
   9.425 +    if ( op.dom == DOMID_SELF )
   9.426 +    {
   9.427 +        op.dom = current->domain->id;
   9.428 +    }
   9.429 +
   9.430 +    if ( unlikely((d = find_domain_by_id(op.dom)) == NULL) )
   9.431 +    {
   9.432 +        DPRINTK("Bad domid %d.\n", op.dom);
   9.433 +        (void)put_user(GNTST_bad_domain, &uop->status);
   9.434 +        return 0;
   9.435 +    }
   9.436 +
   9.437 +    ASSERT(d->grant_table != NULL);
   9.438 +    gt = d->grant_table;
   9.439 +    (void)put_user(GNTST_okay, &uop->status);
   9.440 +
   9.441 +    shared_mfn = virt_to_phys(d->grant_table->shared);
   9.442 +
   9.443 +    DPRINTK("Grant table for dom (%hu) MFN (%x)\n",
   9.444 +            op.dom, shared_mfn);
   9.445 +
   9.446 +    spin_lock(&gt->lock);
   9.447 +
   9.448 +    ASSERT(d->grant_table->active != NULL);
   9.449 +    ASSERT(d->grant_table->shared != NULL);
   9.450 +
   9.451 +    for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
   9.452 +    {
   9.453 +        act      = &gt->active[i];
   9.454 +        sha_copy =  gt->shared[i];
   9.455 +
   9.456 +        if ( act->pin || act->domid || act->frame ||
   9.457 +             sha_copy.flags || sha_copy.domid || sha_copy.frame )
   9.458 +        {
   9.459 +            DPRINTK("Grant: dom (%hu) ACTIVE (%d) pin:(%x) dom:(%hu) frame:(%u)\n",
   9.460 +                    op.dom, i, act->pin, act->domid, act->frame);
   9.461 +            DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) dom:(%hu) frame:(%u)\n",
   9.462 +                    op.dom, i, sha_copy.flags, sha_copy.domid, sha_copy.frame);
   9.463 +
   9.464 +        }
   9.465 +
   9.466 +    }
   9.467 +
   9.468 +    ASSERT(d->grant_table->maptrack != NULL);
   9.469 +
   9.470 +    for ( i = 0; i < NR_MAPTRACK_ENTRIES; i++ )
   9.471 +    {
   9.472 +        maptrack = &gt->maptrack[i];
   9.473 +
   9.474 +        if ( maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK )
   9.475 +        {
   9.476 +            DPRINTK("Grant: dom (%hu) MAP (%d) ref:(%hu) flags:(%x) dom:(%hu)\n",
   9.477 +                    op.dom, i,
   9.478 +                    maptrack->ref_and_flags >> MAPTRACK_REF_SHIFT,
   9.479 +                    maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK,
   9.480 +                    maptrack->domid);
   9.481 +        }
   9.482 +    }
   9.483 +
   9.484 +    spin_unlock(&gt->lock);
   9.485 +
   9.486 +    put_domain(d);
   9.487 +    return 0;
   9.488 +}
   9.489 +#endif
   9.490 +
   9.491  long 
   9.492  do_grant_table_op(
   9.493      unsigned int cmd, void *uop, unsigned int count)
   9.494  {
   9.495      long rc;
   9.496  
   9.497 -    /* XXX stubbed out XXX */
   9.498 -    return -ENOSYS;
   9.499 +    DPRINTK("Grant: table operation (%u) count: (%u)\n", cmd, count);
   9.500  
   9.501      if ( count > 512 )
   9.502          return -EINVAL;
   9.503 @@ -462,6 +682,11 @@ do_grant_table_op(
   9.504      case GNTTABOP_setup_table:
   9.505          rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count);
   9.506          break;
   9.507 +#ifdef GRANT_DEBUG
   9.508 +    case GNTTABOP_dump_table:
   9.509 +        rc = gnttab_dump_table((gnttab_dump_table_t *)uop);
   9.510 +        break;
   9.511 +#endif
   9.512      default:
   9.513          rc = -ENOSYS;
   9.514          break;
   9.515 @@ -476,6 +701,11 @@ int
   9.516  gnttab_check_unmap(
   9.517      struct domain *rd, struct domain *ld, unsigned long frame, int readonly)
   9.518  {
   9.519 +    /* TODO: beat the caller around the head with a brick.
   9.520 +     *       have to walk the grant tables to find this thing.
   9.521 +     */
   9.522 +    /*DPRINTK("gnttab_check_unmap remote dom(%d) local dom(%d) frame (%x) flags(%x).\n",
   9.523 +            rd->id, ld->id, frame, readonly);*/
   9.524      return 0;
   9.525  }
   9.526  
   9.527 @@ -552,8 +782,17 @@ gnttab_prepare_for_transfer(
   9.528  
   9.529  void 
   9.530  gnttab_notify_transfer(
   9.531 -    struct domain *rd, grant_ref_t ref, unsigned long frame)
   9.532 +    struct domain *rd, grant_ref_t ref, unsigned long sframe)
   9.533  {
   9.534 +    unsigned long frame;
   9.535 +
   9.536 +    /* cwc22
   9.537 +     * TODO: this requires that the machine_to_phys_mapping
   9.538 +     *       has already been updated, so the accept_transfer hypercall
   9.539 +     *       must do this.
   9.540 +     */
   9.541 +    frame = __mfn_to_gpfn(rd, sframe);
   9.542 +
   9.543      wmb(); /* Ensure that the reassignment is globally visible. */
   9.544      rd->grant_table->shared[ref].frame = frame;
   9.545  }
   9.546 @@ -607,6 +846,71 @@ grant_table_create(
   9.547      return -ENOMEM;
   9.548  }
   9.549  
   9.550 +static void
   9.551 +gnttab_release_all_mappings(grant_table_t *gt)
   9.552 +{
   9.553 +    grant_mapping_t        *map;
   9.554 +    domid_t                 dom;
   9.555 +    grant_ref_t             ref;
   9.556 +    u16                     handle;
   9.557 +    u32                     pincount;
   9.558 +    struct domain          *ld, *rd;
   9.559 +    unsigned long           frame;
   9.560 +    active_grant_entry_t   *act;
   9.561 +    grant_entry_t          *sha;
   9.562 +
   9.563 +    ld = current->domain;
   9.564 +
   9.565 +    for ( handle = 0; handle < NR_MAPTRACK_ENTRIES; handle++ )
   9.566 +    {
   9.567 +        map = &gt->maptrack[handle];
   9.568 +                                                                                        
   9.569 +        if ( map->ref_and_flags & MAPTRACK_GNTMAP_MASK )
   9.570 +        {
   9.571 +            dom = map->domid;
   9.572 +            ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
   9.573 +
   9.574 +            DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n",
   9.575 +                    handle, ref,
   9.576 +                    map->ref_and_flags & MAPTRACK_GNTMAP_MASK, dom);
   9.577 +
   9.578 +            if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
   9.579 +                 unlikely(ld == rd) )
   9.580 +            {
   9.581 +                if ( rd != NULL )
   9.582 +                    put_domain(rd);
   9.583 +
   9.584 +                printk(KERN_WARNING "Grant release: Could not find domain %d\n", dom);
   9.585 +                continue;
   9.586 +            }
   9.587 +
   9.588 +            act = &rd->grant_table->active[ref];
   9.589 +            sha = &rd->grant_table->shared[ref];
   9.590 +
   9.591 +            spin_lock(&rd->grant_table->lock);
   9.592 +
   9.593 +            frame = act->frame;
   9.594 +
   9.595 +            pincount = ((act->pin & GNTPIN_hstw_mask) >> GNTPIN_hstw_shift) +
   9.596 +                       ((act->pin & GNTPIN_devw_mask) >> GNTPIN_devw_shift);
   9.597 +
   9.598 +            if ( pincount > 0 )
   9.599 +                put_page_types(&frame_table[frame], pincount);
   9.600 +
   9.601 +            put_page(&frame_table[frame]);
   9.602 +
   9.603 +            act->pin = 0;
   9.604 +
   9.605 +            clear_bit(_GTF_reading, &sha->flags);
   9.606 +            clear_bit(_GTF_writing, &sha->flags);
   9.607 +
   9.608 +            spin_unlock(&rd->grant_table->lock);
   9.609 +
   9.610 +            put_domain(rd);
   9.611 +        }
   9.612 +    }
   9.613 +}
   9.614 +
   9.615  void
   9.616  grant_table_destroy(
   9.617      struct domain *d)
   9.618 @@ -615,6 +919,9 @@ grant_table_destroy(
   9.619  
   9.620      if ( (t = d->grant_table) != NULL )
   9.621      {
   9.622 +        if ( t->maptrack != NULL )
   9.623 +            gnttab_release_all_mappings(t);
   9.624 +
   9.625          /* Free memory relating to this grant table. */
   9.626          d->grant_table = NULL;
   9.627          free_xenheap_page((unsigned long)t->shared);
   9.628 @@ -629,6 +936,7 @@ grant_table_init(
   9.629      void)
   9.630  {
   9.631      /* Nothing. */
   9.632 +    DPRINTK("Grant table init\n");
   9.633  }
   9.634  
   9.635  /*
    10.1 --- a/xen/include/asm-x86/mm.h	Tue Mar 08 17:12:15 2005 +0000
    10.2 +++ b/xen/include/asm-x86/mm.h	Tue Mar 08 17:48:59 2005 +0000
    10.3 @@ -182,9 +182,14 @@ static inline int get_page(struct pfn_in
    10.4      return 1;
    10.5  }
    10.6  
    10.7 -void put_page_type(struct pfn_info *page);
    10.8 +void put_page_types(struct pfn_info *page, u32 decrement);
    10.9  int  get_page_type(struct pfn_info *page, u32 type);
   10.10  
   10.11 +static inline void put_page_type(struct pfn_info *page)
   10.12 +{
   10.13 +    put_page_types(page, 1);
   10.14 +}
   10.15 +
   10.16  static inline void put_page_and_type(struct pfn_info *page)
   10.17  {
   10.18      put_page_type(page);
   10.19 @@ -336,4 +341,14 @@ void audit_domains(void);
   10.20  
   10.21  void propagate_page_fault(unsigned long addr, u16 error_code);
   10.22  
   10.23 +/* update_grant_va_mapping
   10.24 + * Caller must own d's BIGLOCK, is responsible for flushing the TLB,
   10.25 + * and have already get_page'd */
   10.26 +int update_grant_va_mapping(unsigned long va,
   10.27 +                            unsigned long val,
   10.28 +                            struct domain *d,
   10.29 +                            struct exec_domain *ed);
   10.30 +#define GNTUPDVA_prev_ro 1
   10.31 +#define GNTUPDVA_prev_rw 2
   10.32 +
   10.33  #endif /* __ASM_X86_MM_H__ */
    11.1 --- a/xen/include/asm-x86/shadow.h	Tue Mar 08 17:12:15 2005 +0000
    11.2 +++ b/xen/include/asm-x86/shadow.h	Tue Mar 08 17:48:59 2005 +0000
    11.3 @@ -61,6 +61,62 @@ extern void vmx_shadow_clear_state(struc
    11.4        ? phys_to_machine_mapping(gpfn)                  \
    11.5        : (gpfn) )
    11.6  
    11.7 +#define __translate_gpfn_to_mfn(_d, gpfn)              \
    11.8 +    ( (shadow_mode_translate(_d))                      \
    11.9 +      ? translate_gpfn_to_mfn(_d, gpfn)                \
   11.10 +      : (gpfn) )
   11.11 +
   11.12 +static inline unsigned long
   11.13 +translate_gpfn_to_mfn(struct domain *rd, unsigned long gpfn)
   11.14 +{
   11.15 +    unsigned long       ma_of_phys_to_mach;
   11.16 +    l2_pgentry_t       *l2_table;
   11.17 +    l2_pgentry_t        l2_entry;
   11.18 +    unsigned long       ma_of_l1_table;
   11.19 +    l1_pgentry_t       *l1_table;
   11.20 +    l1_pgentry_t        pte;
   11.21 +    unsigned long       mfn = 0;
   11.22 +
   11.23 +    /*
   11.24 +     * translation of: (domain, gpfn) -> mfn
   11.25 +     * where domain != current, and is in translate shadow mode
   11.26 +     */
   11.27 +
   11.28 +    ASSERT( shadow_mode_translate(rd) );
   11.29 +
   11.30 +    shadow_lock(rd);
   11.31 +
   11.32 +    /* TODO: check using shadow_lock is correct
   11.33 +     * TODO: move arch.phys_table from exec_domain to domain
   11.34 +     *       - use of zero index is a hack - FIXME
   11.35 +     */
   11.36 +
   11.37 +    ma_of_phys_to_mach = pagetable_val( (rd->exec_domain[0])->arch.phys_table );
   11.38 +
   11.39 +    l2_table = (l2_pgentry_t *) map_domain_mem( ma_of_phys_to_mach );
   11.40 +    l2_entry = l2_table[ gpfn >> (L2_PAGETABLE_SHIFT - PAGE_SHIFT) ];
   11.41 +
   11.42 +    unmap_domain_mem( l2_table );
   11.43 +
   11.44 +    if ( l2_pgentry_val(l2_entry) == 0 )
   11.45 +        goto unlock_out;
   11.46 +
   11.47 +    ma_of_l1_table = l2_pgentry_to_phys( l2_entry );
   11.48 +
   11.49 +    l1_table = (l1_pgentry_t *) map_domain_mem( ma_of_l1_table );
   11.50 +    pte      = l1_table[ (gpfn >> (L1_PAGETABLE_SHIFT - PAGE_SHIFT)) &
   11.51 +                         (L1_PAGETABLE_ENTRIES - 1 ) ];
   11.52 +
   11.53 +    unmap_domain_mem( l1_table );
   11.54 +
   11.55 +    mfn = l1_pgentry_to_pfn(pte);
   11.56 +
   11.57 +unlock_out:
   11.58 +    shadow_unlock(rd);
   11.59 +
   11.60 +    return mfn;
   11.61 +}
   11.62 +
   11.63  extern void __shadow_mode_disable(struct domain *d);
   11.64  static inline void shadow_mode_disable(struct domain *d)
   11.65  {
    12.1 --- a/xen/include/public/grant_table.h	Tue Mar 08 17:12:15 2005 +0000
    12.2 +++ b/xen/include/public/grant_table.h	Tue Mar 08 17:48:59 2005 +0000
    12.3 @@ -207,6 +207,19 @@ typedef struct {
    12.4  } PACKED gnttab_setup_table_t; /* 16 bytes */
    12.5  
    12.6  /*
    12.7 + * GNTTABOP_dump_table: Dump the contents of the grant table to the
    12.8 + * xen console. Debugging use only.
    12.9 + */
   12.10 +#define GNTTABOP_dump_table           3
   12.11 +typedef struct {
   12.12 +    /* IN parameters. */
   12.13 +    domid_t     dom;                  /*  0 */
   12.14 +    /* OUT parameters. */
   12.15 +    s16         status;               /* 2: GNTST_* */
   12.16 +} PACKED gnttab_dump_table_t; /* 4 bytes */
   12.17 +
   12.18 +
   12.19 +/*
   12.20   * Bitfield values for update_pin_status.flags.
   12.21   */
   12.22   /* Map the grant entry for access by I/O devices. */
   12.23 @@ -233,9 +246,10 @@ typedef struct {
   12.24  #define GNTST_general_error    (-1) /* General undefined error.              */
   12.25  #define GNTST_bad_domain       (-2) /* Unrecognsed domain id.                */
   12.26  #define GNTST_bad_gntref       (-3) /* Unrecognised or inappropriate gntref. */
   12.27 -#define GNTST_bad_handle       (-3) /* Unrecognised or inappropriate handle. */
   12.28 -#define GNTST_no_device_space  (-4) /* Out of space in I/O MMU.              */
   12.29 -#define GNTST_permission_denied (-5) /* Not enough privilege for operation.  */
   12.30 +#define GNTST_bad_handle       (-4) /* Unrecognised or inappropriate handle. */
   12.31 +#define GNTST_bad_virt_addr    (-5) /* Inappropriate virtual address to map. */
   12.32 +#define GNTST_no_device_space  (-6) /* Out of space in I/O MMU.              */
   12.33 +#define GNTST_permission_denied (-7) /* Not enough privilege for operation.  */
   12.34  
   12.35  #define GNTTABOP_error_msgs {                   \
   12.36      "okay",                                     \
   12.37 @@ -243,9 +257,20 @@ typedef struct {
   12.38      "unrecognised domain id",                   \
   12.39      "invalid grant reference",                  \
   12.40      "invalid mapping handle",                   \
   12.41 +    "invalid virtual address",                  \
   12.42      "no spare translation slot in the I/O MMU", \
   12.43      "permission denied"                         \
   12.44  }
   12.45          
   12.46 +                                                                                       
   12.47 +typedef struct {
   12.48 +    union {                           /*  0 */
   12.49 +        gnttab_map_grant_ref_t    map_grant_ref;
   12.50 +        gnttab_unmap_grant_ref_t  unmap_grant_ref;
   12.51 +        gnttab_setup_table_t      setup_table;
   12.52 +        gnttab_dump_table_t       dump_table;
   12.53 +        u8                        __dummy[24];
   12.54 +    } PACKED u;
   12.55 +} PACKED gnttab_op_t; /* 32 bytes */
   12.56  
   12.57  #endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */