diff -r c1fafdcdb19a xen/common/grant_table.c --- a/xen/common/grant_table.c Tue May 01 22:24:01 2007 +0100 +++ b/xen/common/grant_table.c Tue Apr 03 15:44:08 2007 +0100 @@ -46,6 +46,13 @@ integer_param("gnttab_max_nr_frames", ma */ #define MAX_MAPTRACK_TO_GRANTS_RATIO 8 +/* The number of reserved grant entries in each domain's grant table, for use + * by the tools. + */ +#ifndef NR_RESERVED_ENTRIES +#define NR_RESERVED_ENTRIES 8 +#endif + /* * The first two members of a grant entry are updated as a combined pair. * The following union allows that to happen in an endian-neutral fashion. @@ -1166,6 +1173,50 @@ gnttab_copy( return 0; } +static void +__gnttab_install_entry( + gnttab_install_entry_t *op) +{ + struct domain *d; + grant_entry_t *target; + s16 rc = GNTST_okay; + + if ( op->handle >= NR_RESERVED_ENTRIES ) + PIN_FAIL(error_out, GNTST_bad_handle, + "handle must be < NR_RESERVED_ENTRIES = %d", + NR_RESERVED_ENTRIES); + + if ( (d = rcu_lock_domain_by_id(op->domid)) == NULL ) + PIN_FAIL(error_out, GNTST_bad_domain, + "couldn't find %d\n", op->domid); + + spin_lock(&d->grant_table->lock); + target = &shared_entry(d->grant_table, op->handle); + *target = op->entry; + spin_unlock(&d->grant_table->lock); +error_out: + if ( d ) + rcu_unlock_domain( d ); +} + +static long +gnttab_install_entry( + XEN_GUEST_HANDLE(gnttab_install_entry_t) uop, unsigned int count) +{ + int i; + gnttab_install_entry_t op; + + for ( i = 0; i < count; i++ ) + { + if ( unlikely(__copy_from_guest_offset(&op, uop, i, 1)) ) + return -EFAULT; + __gnttab_install_entry(&op); + if ( unlikely(__copy_to_guest_offset(uop, i, &op, 1)) ) + return -EFAULT; + } + return 0; +} + long do_grant_table_op( unsigned int cmd, XEN_GUEST_HANDLE(void) uop, unsigned int count) @@ -1177,7 +1228,7 @@ do_grant_table_op( return -EINVAL; LOCK_BIGLOCK(d); - + rc = -EFAULT; switch ( cmd ) { @@ -1236,6 +1287,18 @@ do_grant_table_op( { rc = gnttab_query_size( guest_handle_cast(uop, gnttab_query_size_t), count); + break; + } + case GNTTABOP_install_entry: + { + XEN_GUEST_HANDLE(gnttab_install_entry_t) install = + guest_handle_cast(uop, gnttab_install_entry_t); + if ( unlikely(!guest_handle_okay(install, count)) ) + goto out; + rc = -EPERM; + if ( unlikely(!IS_PRIV(d)) ) + goto out; + rc = gnttab_install_entry(install, count); break; } default: diff -r c1fafdcdb19a xen/include/public/grant_table.h --- a/xen/include/public/grant_table.h Tue May 01 22:24:01 2007 +0100 +++ b/xen/include/public/grant_table.h Fri Mar 30 14:43:53 2007 +0100 @@ -328,6 +328,27 @@ typedef struct gnttab_query_size gnttab_ typedef struct gnttab_query_size gnttab_query_size_t; DEFINE_XEN_GUEST_HANDLE(gnttab_query_size_t); +/* + * GNTTABOP_install_entry: Install a grant entry in (the reserved section of) + * the grant table for the specified domain, with the specified handle. + * NOTES: + * 1. Only a sufficiently-privileged domain may use this hypercall. + * 2. It is the responsibility of the invoker to maintain a count of used + * entries, and to avoid overwriting other entries. + * 3. It is the responsibility of the guest to maintain a reserved section of + * the grant table, covering the first 8 entries. + */ +#define GNTTABOP_install_entry 7 +struct gnttab_install_entry { + /* IN parameters. */ + domid_t domid; + grant_handle_t handle; + grant_entry_t entry; + /* OUT parameters. */ + int16_t status; +}; +typedef struct gnttab_install_entry gnttab_install_entry_t; +DEFINE_XEN_GUEST_HANDLE(gnttab_install_entry_t); /* * Bitfield values for update_pin_status.flags.