mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
bitkeeper revision 1.1159.65.1 (4133a979YYvSU8Cjqbo3qyIcdTx6pw)
Grant-issuing side of Linux grant-table code. The grant-receiving side is still to be implemented.
This commit is contained in:
1 parent
302138cd98
commit
6e04b88dcb
4 files changed
+203
-3
No files matched your search
@@ -52,7 +52,7 @@ enum fixed_addresses {
|
||||
FIX_NETRING2_BASE,
|
||||
FIX_NETRING3_BASE,
|
||||
FIX_SHARED_INFO,
|
||||
|
||||
FIX_GNTTAB,
|
||||
#ifdef CONFIG_VGA_CONSOLE
|
||||
#define NR_FIX_BTMAPS 32 /* 128KB For the Dom0 VGA Console A0000-C0000 */
|
||||
#else
|
||||
|
||||
@@ -11,17 +11,112 @@
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/fixmap.h>
|
||||
#include <asm-xen/gnttab.h>
|
||||
|
||||
#ifndef set_fixmap_ma
|
||||
#define set_fixmap_ma set_fixmap
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define ASSERT(_p) \
|
||||
if ( !(_p) ) { printk(KERN_ALERT"Assertion '%s': line %d, file %s\n", \
|
||||
#_p , __LINE__, __FILE__); *(int*)0=0; }
|
||||
#else
|
||||
#define ASSERT(_p) ((void)0)
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(gnttab_grant_foreign_access);
|
||||
EXPORT_SYMBOL(gnttab_end_foreign_access);
|
||||
EXPORT_SYMBOL(gnttab_grant_foreign_transfer);
|
||||
EXPORT_SYMBOL(gnttab_end_foreign_transfer);
|
||||
|
||||
struct gntent_auxinfo {
|
||||
u16 write_pin, read_pin; /* reference counts */
|
||||
u16 inuse;
|
||||
grant_ref_t next; /* hash chain */
|
||||
};
|
||||
|
||||
#define NR_GRANT_REFS 512
|
||||
|
||||
static struct gntent_auxinfo auxtab[NR_GRANT_REFS];
|
||||
static grant_ref_t gnttab_free_head;
|
||||
static spinlock_t gnttab_lock;
|
||||
|
||||
#define HASH_INVALID (0xFFFFU)
|
||||
#define GNTTAB_HASH_SZ 512
|
||||
#define GNTTAB_HASH(_f) ((_f) & (GNTTAB_HASH_SZ-1))
|
||||
static grant_ref_t gnttab_hash[GNTTAB_HASH_SZ];
|
||||
|
||||
static grant_entry_t *shared;
|
||||
|
||||
/*
|
||||
* Lock-free grant-entry allocator
|
||||
*/
|
||||
|
||||
static inline grant_ref_t
|
||||
get_free_entry(
|
||||
void)
|
||||
{
|
||||
grant_ref_t fh, nfh = gnttab_free_head;
|
||||
do { fh = nfh; }
|
||||
while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh,
|
||||
auxtab[fh].next)) != fh) );
|
||||
return fh;
|
||||
}
|
||||
|
||||
static inline void
|
||||
put_free_entry(
|
||||
grant_ref_t ref)
|
||||
{
|
||||
grant_ref_t fh, nfh = gnttab_free_head;
|
||||
do { auxtab[ref].next = fh = nfh; wmb(); }
|
||||
while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh, ref)) != fh) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Public interface functions
|
||||
*/
|
||||
|
||||
grant_ref_t
|
||||
gnttab_grant_foreign_access(
|
||||
domid_t domid, unsigned long frame, int readonly)
|
||||
{
|
||||
unsigned long flags;
|
||||
grant_ref_t ref;
|
||||
|
||||
spin_lock_irqsave(&gnttab_lock, flags);
|
||||
|
||||
for ( ref = gnttab_hash[GNTTAB_HASH(frame)];
|
||||
ref != HASH_INVALID;
|
||||
ref = auxtab[ref].next )
|
||||
{
|
||||
if ( auxtab[ref].inuse && (shared[ref].frame == frame) )
|
||||
{
|
||||
if ( readonly )
|
||||
auxtab[ref].read_pin++;
|
||||
else if ( auxtab[ref].write_pin++ == 0 )
|
||||
clear_bit(_GTF_readonly, (unsigned long *)&shared[ref].flags);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ref = get_free_entry();
|
||||
auxtab[ref].inuse = 1;
|
||||
auxtab[ref].read_pin = !!readonly;
|
||||
auxtab[ref].write_pin = !readonly;
|
||||
auxtab[ref].next = gnttab_hash[GNTTAB_HASH(frame)];
|
||||
gnttab_hash[GNTTAB_HASH(frame)] = ref;
|
||||
|
||||
shared[ref].frame = frame;
|
||||
shared[ref].domid = domid;
|
||||
wmb();
|
||||
shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&gnttab_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -29,18 +124,111 @@ void
|
||||
gnttab_end_foreign_access(
|
||||
grant_ref_t ref, int readonly)
|
||||
{
|
||||
unsigned long flags, frame = shared[ref].frame;
|
||||
grant_ref_t *pref;
|
||||
u16 sflags, nsflags;
|
||||
|
||||
spin_lock_irqsave(&gnttab_lock, flags);
|
||||
|
||||
if ( readonly )
|
||||
{
|
||||
if ( (auxtab[ref].read_pin-- == 0) && (auxtab[ref].write_pin == 0) )
|
||||
goto delete;
|
||||
}
|
||||
else if ( auxtab[ref].write_pin-- == 0 )
|
||||
{
|
||||
if ( auxtab[ref].read_pin == 0 )
|
||||
goto delete;
|
||||
nsflags = shared[ref].flags;
|
||||
do {
|
||||
if ( (sflags = nsflags) & GTF_writing )
|
||||
printk(KERN_ALERT "WARNING: g.e. still in use for writing!\n");
|
||||
}
|
||||
while ( (nsflags = cmpxchg(&shared[ref].flags, sflags,
|
||||
sflags | GTF_readonly)) != sflags );
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
||||
delete:
|
||||
nsflags = shared[ref].flags;
|
||||
do {
|
||||
if ( (sflags = nsflags) & (GTF_reading|GTF_writing) )
|
||||
printk(KERN_ALERT "WARNING: g.e. still in use!\n");
|
||||
}
|
||||
while ( (nsflags = cmpxchg(&shared[ref].flags, sflags, 0)) != sflags );
|
||||
|
||||
pref = &gnttab_hash[GNTTAB_HASH(frame)];
|
||||
while ( *pref != ref )
|
||||
pref = &auxtab[*pref].next;
|
||||
*pref = auxtab[ref].next;
|
||||
|
||||
auxtab[ref].inuse = 0;
|
||||
put_free_entry(ref);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&gnttab_lock, flags);
|
||||
}
|
||||
|
||||
grant_ref_t
|
||||
gnttab_grant_foreign_transfer(
|
||||
domid_t domid)
|
||||
{
|
||||
return 0;
|
||||
grant_ref_t ref = get_free_entry();
|
||||
|
||||
shared[ref].frame = 0;
|
||||
shared[ref].domid = domid;
|
||||
wmb();
|
||||
shared[ref].flags = GTF_accept_transfer;
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
gnttab_end_foreign_transfer(
|
||||
grant_ref_t ref)
|
||||
{
|
||||
return 0;
|
||||
unsigned long frame = 0;
|
||||
u16 flags;
|
||||
|
||||
flags = shared[ref].flags;
|
||||
ASSERT(flags == (GTF_accept_transfer | GTF_transfer_committed));
|
||||
|
||||
/*
|
||||
* If a transfer is committed then wait for the frame address to appear.
|
||||
* Otherwise invalidate the grant entry against future use.
|
||||
*/
|
||||
if ( likely(flags != GTF_accept_transfer) ||
|
||||
(cmpxchg(&shared[ref].flags, flags, 0) != GTF_accept_transfer) )
|
||||
while ( unlikely((frame = shared[ref].frame) == 0) )
|
||||
cpu_relax();
|
||||
|
||||
put_free_entry(ref);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
void __init gnttab_init(void)
|
||||
{
|
||||
int i;
|
||||
gnttab_op_t gntop;
|
||||
unsigned long frame;
|
||||
|
||||
spin_lock_init(&gnttab_lock);
|
||||
|
||||
for ( i = 0; i < GNTTAB_HASH_SZ; i++ )
|
||||
{
|
||||
gnttab_hash[i] = HASH_INVALID;
|
||||
auxtab[i].next = i+1;
|
||||
}
|
||||
|
||||
gntop.cmd = GNTTABOP_setup_table;
|
||||
gntop.u.setup_table.dom = DOMID_SELF;
|
||||
gntop.u.setup_table.nr_frames = 1;
|
||||
gntop.u.setup_table.frame_list = &frame;
|
||||
if ( HYPERVISOR_grant_table_op(&gntop) != 0 )
|
||||
BUG();
|
||||
|
||||
set_fixmap_ma(FIX_GNTTAB, frame << PAGE_SHIFT);
|
||||
shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB);
|
||||
}
|
||||
@@ -75,6 +75,7 @@ enum fixed_addresses {
|
||||
FIX_PCIE_MCFG,
|
||||
#endif
|
||||
FIX_SHARED_INFO,
|
||||
FIX_GNTTAB,
|
||||
#ifdef CONFIG_XEN_PRIVILEGED_GUEST
|
||||
#define NR_FIX_ISAMAPS 256
|
||||
FIX_ISAMAP_END,
|
||||
|
||||
@@ -466,6 +466,17 @@ static inline int HYPERVISOR_physdev_op(void *physdev_op)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_grant_table_op(void *gnttab_op)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_grant_table_op),
|
||||
"b" (gnttab_op) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_update_va_mapping_otherdomain(
|
||||
unsigned long page_nr, pte_t new_val, unsigned long flags, domid_t domid)
|
||||
{
|
||||
|
||||