mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.1159.1.104 (412cb2ee26F5kEIHPDh0Kj4pQScH6Q)
Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk into labyrinth.cl.cam.ac.uk:/auto/groups/xeno/users/kaf24/xeno
This commit is contained in:
commit
5c3383ecff
18 files changed
+317
-201
No files matched your search
@@ -10,8 +10,11 @@
|
||||
|
||||
#define DECLARE_TQUEUE(_name, _fn, _arg) \
|
||||
struct tq_struct _name = { LIST_HEAD_INIT((_name).list), 0, _fn, _arg }
|
||||
|
||||
#define DECLARE_WORK(_name, _fn, _arg) DECLARE_TQUEUE(_name, _fn, _arg)
|
||||
|
||||
#define work_struct tq_struct
|
||||
#define INIT_WORK(_work, _fn, _arg) INIT_TQUEUE(_work, _fn, _arg)
|
||||
|
||||
#define schedule_work(_w) schedule_task(_w)
|
||||
|
||||
#endif /* __QUEUES_H__ */
|
||||
@@ -60,19 +60,21 @@ typedef struct blkif_st {
|
||||
struct list_head blkdev_list;
|
||||
spinlock_t blk_ring_lock;
|
||||
atomic_t refcnt;
|
||||
|
||||
struct work_struct work;
|
||||
} blkif_t;
|
||||
|
||||
void blkif_create(blkif_be_create_t *create);
|
||||
void blkif_destroy(blkif_be_destroy_t *destroy);
|
||||
void blkif_connect(blkif_be_connect_t *connect);
|
||||
int blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id);
|
||||
void __blkif_disconnect_complete(blkif_t *blkif);
|
||||
void blkif_disconnect_complete(blkif_t *blkif);
|
||||
blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle);
|
||||
#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
|
||||
#define blkif_put(_b) \
|
||||
do { \
|
||||
if ( atomic_dec_and_test(&(_b)->refcnt) ) \
|
||||
__blkif_disconnect_complete(_b); \
|
||||
blkif_disconnect_complete(_b); \
|
||||
} while (0)
|
||||
|
||||
/* An entry in a list of xen_extents. */
|
||||
|
||||
@@ -27,13 +27,14 @@ blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle)
|
||||
return blkif;
|
||||
}
|
||||
|
||||
void __blkif_disconnect_complete(blkif_t *blkif)
|
||||
static void __blkif_disconnect_complete(void *arg)
|
||||
{
|
||||
blkif_t *blkif = (blkif_t *)arg;
|
||||
ctrl_msg_t cmsg;
|
||||
blkif_be_disconnect_t disc;
|
||||
|
||||
/*
|
||||
* These can't be done in __blkif_disconnect() because at that point there
|
||||
* These can't be done in blkif_disconnect() because at that point there
|
||||
* may be outstanding requests at the disc whose asynchronous responses
|
||||
* must still be notified to the remote driver.
|
||||
*/
|
||||
@@ -67,6 +68,12 @@ void __blkif_disconnect_complete(blkif_t *blkif)
|
||||
ctrl_if_send_response(&cmsg);
|
||||
}
|
||||
|
||||
void blkif_disconnect_complete(blkif_t *blkif)
|
||||
{
|
||||
INIT_WORK(&blkif->work, __blkif_disconnect_complete, (void *)blkif);
|
||||
schedule_work(&blkif->work);
|
||||
}
|
||||
|
||||
void blkif_create(blkif_be_create_t *create)
|
||||
{
|
||||
domid_t domid = create->domid;
|
||||
|
||||
@@ -70,19 +70,21 @@ typedef struct netif_st {
|
||||
spinlock_t rx_lock, tx_lock;
|
||||
struct net_device *dev;
|
||||
struct net_device_stats stats;
|
||||
|
||||
struct work_struct work;
|
||||
} netif_t;
|
||||
|
||||
void netif_create(netif_be_create_t *create);
|
||||
void netif_destroy(netif_be_destroy_t *destroy);
|
||||
void netif_connect(netif_be_connect_t *connect);
|
||||
int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id);
|
||||
void __netif_disconnect_complete(netif_t *netif);
|
||||
void netif_disconnect_complete(netif_t *netif);
|
||||
netif_t *netif_find_by_handle(domid_t domid, unsigned int handle);
|
||||
#define netif_get(_b) (atomic_inc(&(_b)->refcnt))
|
||||
#define netif_put(_b) \
|
||||
do { \
|
||||
if ( atomic_dec_and_test(&(_b)->refcnt) ) \
|
||||
__netif_disconnect_complete(_b); \
|
||||
netif_disconnect_complete(_b); \
|
||||
} while (0)
|
||||
|
||||
void netif_interface_init(void);
|
||||
|
||||
@@ -27,13 +27,14 @@ netif_t *netif_find_by_handle(domid_t domid, unsigned int handle)
|
||||
return netif;
|
||||
}
|
||||
|
||||
void __netif_disconnect_complete(netif_t *netif)
|
||||
static void __netif_disconnect_complete(void *arg)
|
||||
{
|
||||
netif_t *netif = (netif_t *)arg;
|
||||
ctrl_msg_t cmsg;
|
||||
netif_be_disconnect_t disc;
|
||||
|
||||
/*
|
||||
* These can't be done in __netif_disconnect() because at that point there
|
||||
* These can't be done in netif_disconnect() because at that point there
|
||||
* may be outstanding requests at the disc whose asynchronous responses
|
||||
* must still be notified to the remote driver.
|
||||
*/
|
||||
@@ -70,6 +71,12 @@ void __netif_disconnect_complete(netif_t *netif)
|
||||
ctrl_if_send_response(&cmsg);
|
||||
}
|
||||
|
||||
void netif_disconnect_complete(netif_t *netif)
|
||||
{
|
||||
INIT_WORK(&netif->work, __netif_disconnect_complete, (void *)netif);
|
||||
schedule_work(&netif->work);
|
||||
}
|
||||
|
||||
void netif_create(netif_be_create_t *create)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
@@ -668,9 +668,9 @@ int construct_dom0(struct domain *p,
|
||||
mfn++ )
|
||||
{
|
||||
page = &frame_table[mfn];
|
||||
page->u.inuse.domain = p;
|
||||
page->u.inuse.domain = p;
|
||||
page->u.inuse.type_info = 0;
|
||||
page->u.inuse.count_info = PGC_allocated | 1;
|
||||
page->u.inuse.count_info = PGC_always_set | PGC_allocated | 1;
|
||||
list_add_tail(&page->list, &p->page_list);
|
||||
p->tot_pages++; p->max_pages++;
|
||||
}
|
||||
|
||||
+74
-38
@@ -153,6 +153,9 @@ void arch_init_memory(void)
|
||||
vm_assist_info[VMASST_TYPE_writable_pagetables].disable =
|
||||
ptwr_disable;
|
||||
|
||||
for ( mfn = 0; mfn < max_page; mfn++ )
|
||||
frame_table[mfn].u.inuse.count_info |= PGC_always_set;
|
||||
|
||||
/* Initialise to a magic of 0x55555555 so easier to spot bugs later. */
|
||||
memset(machine_to_phys_mapping, 0x55, 4<<20);
|
||||
|
||||
@@ -179,9 +182,9 @@ void arch_init_memory(void)
|
||||
mfn < virt_to_phys(&machine_to_phys_mapping[1<<20])>>PAGE_SHIFT;
|
||||
mfn++ )
|
||||
{
|
||||
frame_table[mfn].u.inuse.count_info = 1 | PGC_allocated;
|
||||
frame_table[mfn].u.inuse.type_info = 1 | PGT_gdt_page; /* non-RW */
|
||||
frame_table[mfn].u.inuse.domain = dom_xen;
|
||||
frame_table[mfn].u.inuse.count_info |= PGC_allocated | 1;
|
||||
frame_table[mfn].u.inuse.type_info = PGT_gdt_page | 1; /* non-RW */
|
||||
frame_table[mfn].u.inuse.domain = dom_xen;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,6 +373,7 @@ get_page_from_l1e(
|
||||
{
|
||||
unsigned long l1v = l1_pgentry_val(l1e);
|
||||
unsigned long pfn = l1_pgentry_to_pagenr(l1e);
|
||||
struct pfn_info *page = &frame_table[pfn];
|
||||
extern int domain_iomem_in_pfn(struct domain *d, unsigned long pfn);
|
||||
|
||||
if ( !(l1v & _PAGE_PRESENT) )
|
||||
@@ -383,6 +387,8 @@ get_page_from_l1e(
|
||||
|
||||
if ( unlikely(!pfn_is_ram(pfn)) )
|
||||
{
|
||||
/* SPECIAL CASE 1. Mapping an I/O page. */
|
||||
|
||||
/* Revert to caller privileges if FD == DOMID_IO. */
|
||||
if ( d == dom_io )
|
||||
d = current;
|
||||
@@ -397,17 +403,41 @@ get_page_from_l1e(
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( l1v & _PAGE_RW )
|
||||
if ( unlikely(!get_page_from_pagenr(pfn, d)) )
|
||||
{
|
||||
if ( unlikely(!get_page_and_type_from_pagenr(
|
||||
pfn, PGT_writable_page, d)) )
|
||||
return 0;
|
||||
set_bit(_PGC_tlb_flush_on_type_change,
|
||||
&frame_table[pfn].u.inuse.count_info);
|
||||
return 1;
|
||||
/* SPECIAL CASE 2. Mapping a foreign page via a grant table. */
|
||||
|
||||
int rc;
|
||||
struct domain *e;
|
||||
u32 count_info;
|
||||
/*
|
||||
* Yuk! Amazingly this is the simplest way to get a guaranteed atomic
|
||||
* snapshot of a 64-bit value on IA32. x86/64 solves this of course!
|
||||
* Basically it's a no-op CMPXCHG, to get us the current contents.
|
||||
* No need for LOCK prefix -- we know that count_info is never zero
|
||||
* because it contains PGC_always_set.
|
||||
*/
|
||||
__asm__ __volatile__(
|
||||
"cmpxchg8b %2"
|
||||
: "=a" (e), "=d" (count_info),
|
||||
"=m" (*(volatile u64 *)(&page->u.inuse.domain))
|
||||
: "0" (0), "1" (0), "b" (0), "c" (0) );
|
||||
if ( unlikely((count_info & PGC_count_mask) == 0) ||
|
||||
unlikely(e == NULL) || unlikely(!get_domain(e)) )
|
||||
return 0;
|
||||
rc = gnttab_try_map(e, d, page, l1v & _PAGE_RW);
|
||||
put_domain(e);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return get_page_from_pagenr(pfn, d);
|
||||
if ( l1v & _PAGE_RW )
|
||||
{
|
||||
if ( unlikely(!get_page_type(page, PGT_writable_page)) )
|
||||
return 0;
|
||||
set_bit(_PGC_tlb_flush_on_type_change, &page->u.inuse.count_info);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -434,14 +464,33 @@ get_page_from_l2e(
|
||||
}
|
||||
|
||||
|
||||
static void put_page_from_l1e(l1_pgentry_t l1e)
|
||||
static void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d)
|
||||
{
|
||||
struct pfn_info *page = &frame_table[l1_pgentry_to_pagenr(l1e)];
|
||||
unsigned long l1v = l1_pgentry_val(l1e);
|
||||
struct domain *e = page->u.inuse.domain;
|
||||
|
||||
if ( !(l1v & _PAGE_PRESENT) || !pfn_is_ram(l1v >> PAGE_SHIFT) )
|
||||
return;
|
||||
|
||||
if ( unlikely(e != d) )
|
||||
{
|
||||
/*
|
||||
* Unmap a foreign page that may have been mapped via a grant table.
|
||||
* Note that this can fail for a privileged domain that can map foreign
|
||||
* pages via MMUEXT_SET_FOREIGNDOM. Such domains can have some mappings
|
||||
* counted via a grant entry and some counted directly in the page
|
||||
* structure's reference count. Note that reference counts won't get
|
||||
* dangerously confused as long as we always try to decrement the
|
||||
* grant entry first. We may end up with a mismatch between which
|
||||
* mappings and which unmappings are counted via the grant entry, but
|
||||
* really it doesn't matter as privileged domains have carte blanche.
|
||||
*/
|
||||
if ( likely(gnttab_try_unmap(e, d, page, l1v & _PAGE_RW)) )
|
||||
return;
|
||||
/* Assume this mapping was made via MMUEXT_SET_FOREIGNDOM... */
|
||||
}
|
||||
|
||||
if ( l1v & _PAGE_RW )
|
||||
{
|
||||
put_page_and_type(page);
|
||||
@@ -452,7 +501,7 @@ static void put_page_from_l1e(l1_pgentry_t l1e)
|
||||
if ( unlikely(((page->u.inuse.type_info & PGT_type_mask) ==
|
||||
PGT_ldt_page)) &&
|
||||
unlikely(((page->u.inuse.type_info & PGT_count_mask) != 0)) )
|
||||
invalidate_shadow_ldt(page->u.inuse.domain);
|
||||
invalidate_shadow_ldt(e);
|
||||
put_page(page);
|
||||
}
|
||||
}
|
||||
@@ -527,7 +576,7 @@ static int alloc_l1_table(struct pfn_info *page)
|
||||
|
||||
fail:
|
||||
while ( i-- > 0 )
|
||||
put_page_from_l1e(pl1e[i]);
|
||||
put_page_from_l1e(pl1e[i], d);
|
||||
|
||||
unmap_domain_mem(pl1e);
|
||||
return 0;
|
||||
@@ -551,6 +600,7 @@ static void free_l2_table(struct pfn_info *page)
|
||||
|
||||
static void free_l1_table(struct pfn_info *page)
|
||||
{
|
||||
struct domain *d = page->u.inuse.domain;
|
||||
unsigned long page_nr = page - frame_table;
|
||||
l1_pgentry_t *pl1e;
|
||||
int i;
|
||||
@@ -558,7 +608,7 @@ static void free_l1_table(struct pfn_info *page)
|
||||
pl1e = map_domain_mem(page_nr << PAGE_SHIFT);
|
||||
|
||||
for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ )
|
||||
put_page_from_l1e(pl1e[i]);
|
||||
put_page_from_l1e(pl1e[i], d);
|
||||
|
||||
unmap_domain_mem(pl1e);
|
||||
}
|
||||
@@ -651,6 +701,7 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e)
|
||||
{
|
||||
l1_pgentry_t ol1e;
|
||||
unsigned long _ol1e;
|
||||
struct domain *d = current;
|
||||
|
||||
if ( unlikely(__get_user(_ol1e, (unsigned long *)pl1e) != 0) )
|
||||
{
|
||||
@@ -671,18 +722,18 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e)
|
||||
|
||||
if ( unlikely(!update_l1e(pl1e, ol1e, nl1e)) )
|
||||
{
|
||||
put_page_from_l1e(nl1e);
|
||||
put_page_from_l1e(nl1e, d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
put_page_from_l1e(ol1e);
|
||||
put_page_from_l1e(ol1e, d);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( unlikely(!update_l1e(pl1e, ol1e, nl1e)) )
|
||||
return 0;
|
||||
|
||||
put_page_from_l1e(ol1e);
|
||||
put_page_from_l1e(ol1e, d);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1289,20 +1340,10 @@ int do_update_va_mapping_otherdomain(unsigned long page_nr,
|
||||
}
|
||||
|
||||
|
||||
static inline int readonly_page_from_l1e(l1_pgentry_t l1e)
|
||||
{
|
||||
struct pfn_info *page = &frame_table[l1_pgentry_to_pagenr(l1e)];
|
||||
unsigned long l1v = l1_pgentry_val(l1e);
|
||||
|
||||
if ( (l1v & _PAGE_RW) || !(l1v & _PAGE_PRESENT) ||
|
||||
!pfn_is_ram(l1v >> PAGE_SHIFT) )
|
||||
return 0;
|
||||
put_page_type(page);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Writable Pagetables */
|
||||
/*************************
|
||||
* Writable Pagetables
|
||||
*/
|
||||
|
||||
ptwr_info_t ptwr_info[NR_CPUS] =
|
||||
{ [ 0 ... NR_CPUS-1 ] =
|
||||
@@ -1365,13 +1406,8 @@ void ptwr_reconnect_disconnected(unsigned long addr)
|
||||
nl1e = pl1e[i];
|
||||
if (likely(l1_pgentry_val(nl1e) == l1_pgentry_val(ol1e)))
|
||||
continue;
|
||||
if (likely((l1_pgentry_val(nl1e) ^ l1_pgentry_val(ol1e)) ==
|
||||
_PAGE_RW)) {
|
||||
if (likely(readonly_page_from_l1e(nl1e)))
|
||||
continue;
|
||||
}
|
||||
if (unlikely(l1_pgentry_val(ol1e) & _PAGE_PRESENT))
|
||||
put_page_from_l1e(ol1e);
|
||||
put_page_from_l1e(ol1e, current);
|
||||
if (unlikely(!get_page_from_l1e(nl1e, current)))
|
||||
BUG();
|
||||
}
|
||||
@@ -1438,7 +1474,7 @@ void ptwr_flush_inactive(void)
|
||||
if (likely(l1_pgentry_val(ol1e) == l1_pgentry_val(nl1e)))
|
||||
continue;
|
||||
if (unlikely(l1_pgentry_val(ol1e) & _PAGE_PRESENT))
|
||||
put_page_from_l1e(ol1e);
|
||||
put_page_from_l1e(ol1e, current);
|
||||
if (unlikely(!get_page_from_l1e(nl1e, current)))
|
||||
BUG();
|
||||
}
|
||||
|
||||
@@ -411,7 +411,7 @@ void __init start_of_day(void)
|
||||
clear_bit(smp_processor_id(), &wait_init_idle);
|
||||
smp_threads_ready = 1;
|
||||
smp_commence(); /* Tell other CPUs that state of the world is stable. */
|
||||
while (wait_init_idle)
|
||||
while ( wait_init_idle != 0 )
|
||||
{
|
||||
cpu_relax();
|
||||
barrier();
|
||||
|
||||
+5
-1
@@ -232,12 +232,16 @@ void domain_destruct(struct domain *d)
|
||||
{
|
||||
struct domain **pd;
|
||||
unsigned long flags;
|
||||
atomic_t old, new;
|
||||
|
||||
if ( !test_bit(DF_DYING, &d->flags) )
|
||||
BUG();
|
||||
|
||||
/* May be already destructed, or get_domain() can race us. */
|
||||
if ( cmpxchg(&d->refcnt.counter, 0, DOMAIN_DESTRUCTED) != 0 )
|
||||
_atomic_set(old, 0);
|
||||
_atomic_set(new, DOMAIN_DESTRUCTED);
|
||||
old = atomic_compareandswap(old, new, &d->refcnt);
|
||||
if ( _atomic_read(old) != 0 )
|
||||
return;
|
||||
|
||||
DPRINTK("Releasing task %u\n", d->domain);
|
||||
|
||||
+69
-38
@@ -24,6 +24,13 @@
|
||||
#include <xen/config.h>
|
||||
#include <xen/sched.h>
|
||||
|
||||
#define PIN_FAIL(_rc, _f, _a...) \
|
||||
do { \
|
||||
DPRINTK( _f, ## _a ); \
|
||||
rc = -(_rc); \
|
||||
goto out; \
|
||||
} while ( 0 )
|
||||
|
||||
static inline void
|
||||
check_tlb_flush(
|
||||
active_grant_entry_t *a)
|
||||
@@ -70,6 +77,7 @@ gnttab_update_pin_status(
|
||||
active_grant_entry_t *act;
|
||||
grant_entry_t *sha;
|
||||
long rc = 0;
|
||||
unsigned long frame;
|
||||
|
||||
ld = current;
|
||||
|
||||
@@ -93,8 +101,11 @@ gnttab_update_pin_status(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ( unlikely((rd = find_domain_by_id(dom)) == NULL) )
|
||||
if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
|
||||
unlikely(ld == rd) )
|
||||
{
|
||||
if ( rd != NULL )
|
||||
put_domain(rd);
|
||||
DPRINTK("Could not find domain %d\n", dom);
|
||||
return -ESRCH;
|
||||
}
|
||||
@@ -102,6 +113,8 @@ gnttab_update_pin_status(
|
||||
act = &rd->grant_table->active[ref];
|
||||
sha = &rd->grant_table->shared[ref];
|
||||
|
||||
spin_lock(&rd->grant_table->lock);
|
||||
|
||||
if ( act->status == 0 )
|
||||
{
|
||||
if ( unlikely(pin_flags == 0) )
|
||||
@@ -118,23 +131,17 @@ gnttab_update_pin_status(
|
||||
|
||||
if ( unlikely((sflags & GTF_type_mask) != GTF_permit_access) ||
|
||||
unlikely(sdom != ld->domain) )
|
||||
{
|
||||
DPRINTK("Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
|
||||
PIN_FAIL(EINVAL,
|
||||
"Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
|
||||
sflags, sdom, ld->domain);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sflags |= GTF_reading;
|
||||
if ( !(pin_flags & GNTPIN_readonly) )
|
||||
{
|
||||
sflags |= GTF_writing;
|
||||
if ( unlikely(sflags & GTF_readonly) )
|
||||
{
|
||||
DPRINTK("Attempt to write-pin a read-only grant entry.\n");
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
PIN_FAIL(EINVAL,
|
||||
"Attempt to write-pin a r/o grant entry.\n");
|
||||
}
|
||||
|
||||
/* Merge two 16-bit values into a 32-bit combined update. */
|
||||
@@ -144,11 +151,8 @@ gnttab_update_pin_status(
|
||||
/* NB. prev_sflags is updated in place to seen value. */
|
||||
if ( unlikely(cmpxchg_user((u32 *)&sha->flags, prev_scombo,
|
||||
prev_scombo | GTF_writing)) )
|
||||
{
|
||||
DPRINTK("Fault while modifying shared flags and domid.\n");
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
PIN_FAIL(EINVAL,
|
||||
"Fault while modifying shared flags and domid.\n");
|
||||
|
||||
/* Did the combined update work (did we see what we expected?). */
|
||||
if ( prev_scombo == scombo )
|
||||
@@ -161,10 +165,22 @@ gnttab_update_pin_status(
|
||||
}
|
||||
|
||||
/* rmb(); */ /* not on x86 */
|
||||
frame = sha->frame;
|
||||
if ( unlikely(!pfn_is_ram(frame)) ||
|
||||
unlikely(!((pin_flags & GNTPIN_readonly) ?
|
||||
get_page(&frame_table[frame], rd) :
|
||||
get_page_and_type(&frame_table[frame], rd,
|
||||
PGT_writable_page))) )
|
||||
{
|
||||
clear_bit(_GTF_writing, &sha->flags);
|
||||
clear_bit(_GTF_reading, &sha->flags);
|
||||
PIN_FAIL(EINVAL,
|
||||
"Could not pin the granted frame!\n");
|
||||
}
|
||||
|
||||
act->status = pin_flags;
|
||||
act->domid = sdom;
|
||||
act->frame = sha->frame;
|
||||
act->frame = frame;
|
||||
|
||||
make_entry_mappable(rd->grant_table, act);
|
||||
}
|
||||
@@ -174,11 +190,13 @@ gnttab_update_pin_status(
|
||||
|
||||
if ( unlikely((act->status &
|
||||
(GNTPIN_wmap_mask|GNTPIN_rmap_mask)) != 0) )
|
||||
{
|
||||
DPRINTK("Attempt to deactivate a mapped g.e. (%x)\n", act->status);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
PIN_FAIL(EINVAL,
|
||||
"Attempt to deactiv a mapped g.e. (%x)\n", act->status);
|
||||
|
||||
frame = act->frame;
|
||||
if ( !(act->status & GNTPIN_readonly) )
|
||||
put_page_type(&frame_table[frame]);
|
||||
put_page(&frame_table[frame]);
|
||||
|
||||
act->status = 0;
|
||||
make_entry_unmappable(rd->grant_table, act);
|
||||
@@ -199,12 +217,9 @@ gnttab_update_pin_status(
|
||||
(unlikely((act->status & GNTPIN_wmap_mask) != 0) ||
|
||||
(((pin_flags & GNTPIN_host_accessible) == 0) &&
|
||||
unlikely((act->status & GNTPIN_rmap_mask) != 0))) )
|
||||
{
|
||||
DPRINTK("Attempt to reduce pinning of a mapped g.e. (%x,%x)\n",
|
||||
PIN_FAIL(EINVAL,
|
||||
"Attempt to reduce pinning of a mapped g.e. (%x,%x)\n",
|
||||
pin_flags, act->status);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check for changes to host accessibility. */
|
||||
if ( pin_flags & GNTPIN_host_accessible )
|
||||
@@ -220,6 +235,7 @@ gnttab_update_pin_status(
|
||||
{
|
||||
if ( !(act->status & GNTPIN_readonly) )
|
||||
{
|
||||
put_page_type(&frame_table[act->frame]);
|
||||
check_tlb_flush(act);
|
||||
clear_bit(_GTF_writing, &sha->flags);
|
||||
}
|
||||
@@ -231,20 +247,19 @@ gnttab_update_pin_status(
|
||||
prev_sflags = sflags;
|
||||
|
||||
if ( unlikely(prev_sflags & GTF_readonly) )
|
||||
{
|
||||
DPRINTK("Attempt to write-pin a read-only grant entry.\n");
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
PIN_FAIL(EINVAL,
|
||||
"Attempt to write-pin a r/o grant entry.\n");
|
||||
|
||||
if ( unlikely(!get_page_type(&frame_table[act->frame],
|
||||
PGT_writable_page)) )
|
||||
PIN_FAIL(EINVAL,
|
||||
"Attempt to write-pin a unwritable page.\n");
|
||||
|
||||
/* NB. prev_sflags is updated in place to seen value. */
|
||||
if ( unlikely(cmpxchg_user(&sha->flags, prev_sflags,
|
||||
prev_sflags | GTF_writing)) )
|
||||
{
|
||||
DPRINTK("Fault while modifying shared flags.\n");
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
PIN_FAIL(EINVAL,
|
||||
"Fault while modifying shared flags.\n");
|
||||
}
|
||||
while ( prev_sflags != sflags );
|
||||
}
|
||||
@@ -261,6 +276,7 @@ gnttab_update_pin_status(
|
||||
(void)__put_user(act->frame, &uop->host_phys_addr);
|
||||
|
||||
out:
|
||||
spin_unlock(&rd->grant_table->lock);
|
||||
put_domain(rd);
|
||||
return rc;
|
||||
}
|
||||
@@ -289,6 +305,20 @@ do_grant_table_op(
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
gnttab_try_map(
|
||||
struct domain *rd, struct domain *ld, struct pfn_info *page, int readonly)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
gnttab_try_unmap(
|
||||
struct domain *rd, struct domain *ld, struct pfn_info *page, int readonly)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
grant_table_create(
|
||||
struct domain *d)
|
||||
@@ -318,6 +348,7 @@ grant_table_create(
|
||||
SHARE_PFN_WITH_DOMAIN(virt_to_page(t->shared), d);
|
||||
|
||||
/* Okay, install the structure. */
|
||||
wmb(); /* avoid races with lock-free access to d->grant_table */
|
||||
d->grant_table = t;
|
||||
return 0;
|
||||
|
||||
|
||||
+11
-1
@@ -296,9 +296,19 @@ void cmain(multiboot_info_t *mbi)
|
||||
xmem_cache_init();
|
||||
xmem_cache_sizes_init(max_page);
|
||||
|
||||
/*
|
||||
* Create a domain-structure allocator. The SLAB_NO_REAP flag is essential!
|
||||
* This is because in some situations a domain's reference count will be
|
||||
* incremented by someone with no other handle on the structure -- this is
|
||||
* inherently racey because the struct could be freed by the time that the
|
||||
* count is incremented. By specifying 'no-reap' we ensure that, worst
|
||||
* case, they increment some other domain's count, rather than corrupting
|
||||
* a random field in a random structure!
|
||||
* See, for example, arch/x86/memory.c:get_page_from_l1e().
|
||||
*/
|
||||
domain_struct_cachep = xmem_cache_create(
|
||||
"domain_cache", sizeof(struct domain),
|
||||
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
|
||||
0, SLAB_HWCACHE_ALIGN | SLAB_NO_REAP, NULL, NULL);
|
||||
if ( domain_struct_cachep == NULL )
|
||||
panic("No slab cache for task structs.");
|
||||
|
||||
|
||||
+25
-13
@@ -300,12 +300,21 @@ void init_xenheap_pages(unsigned long ps, unsigned long pe)
|
||||
unsigned long alloc_xenheap_pages(int order)
|
||||
{
|
||||
struct pfn_info *pg;
|
||||
int attempts = 0;
|
||||
int i, attempts = 0;
|
||||
|
||||
retry:
|
||||
if ( unlikely((pg = alloc_heap_pages(MEMZONE_XEN, order)) == NULL) )
|
||||
goto no_memory;
|
||||
|
||||
memguard_unguard_range(page_to_virt(pg), 1 << (order + PAGE_SHIFT));
|
||||
|
||||
for ( i = 0; i < (1 << order); i++ )
|
||||
{
|
||||
pg[i].u.inuse.count_info = PGC_always_set;
|
||||
pg[i].u.inuse.domain = NULL;
|
||||
pg[i].u.inuse.type_info = 0;
|
||||
}
|
||||
|
||||
return (unsigned long)page_to_virt(pg);
|
||||
|
||||
no_memory:
|
||||
@@ -343,7 +352,7 @@ struct pfn_info *alloc_domheap_pages(struct domain *d, int order)
|
||||
{
|
||||
struct pfn_info *pg;
|
||||
unsigned long mask, flushed_mask, pfn_stamp, cpu_stamp;
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
ASSERT(!in_irq());
|
||||
|
||||
@@ -353,19 +362,16 @@ struct pfn_info *alloc_domheap_pages(struct domain *d, int order)
|
||||
flushed_mask = 0;
|
||||
for ( i = 0; i < (1 << order); i++ )
|
||||
{
|
||||
pg[i].u.inuse.domain = NULL;
|
||||
pg[i].u.inuse.type_info = 0;
|
||||
|
||||
if ( (mask = (pg[i].u.free.cpu_mask & ~flushed_mask)) != 0 )
|
||||
{
|
||||
pfn_stamp = pg[i].tlbflush_timestamp;
|
||||
for ( i = 0; (mask != 0) && (i < smp_num_cpus); i++ )
|
||||
for ( j = 0; (mask != 0) && (j < smp_num_cpus); j++ )
|
||||
{
|
||||
if ( mask & (1<<i) )
|
||||
if ( mask & (1<<j) )
|
||||
{
|
||||
cpu_stamp = tlbflush_time[i];
|
||||
cpu_stamp = tlbflush_time[j];
|
||||
if ( !NEED_FLUSH(cpu_stamp, pfn_stamp) )
|
||||
mask &= ~(1<<i);
|
||||
mask &= ~(1<<j);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,6 +382,10 @@ struct pfn_info *alloc_domheap_pages(struct domain *d, int order)
|
||||
flushed_mask |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
pg[i].u.inuse.count_info = PGC_always_set;
|
||||
pg[i].u.inuse.domain = NULL;
|
||||
pg[i].u.inuse.type_info = 0;
|
||||
}
|
||||
|
||||
if ( d == NULL )
|
||||
@@ -401,7 +411,7 @@ struct pfn_info *alloc_domheap_pages(struct domain *d, int order)
|
||||
{
|
||||
pg[i].u.inuse.domain = d;
|
||||
wmb(); /* Domain pointer must be visible before updating refcnt. */
|
||||
pg[i].u.inuse.count_info = PGC_allocated | 1;
|
||||
pg[i].u.inuse.count_info |= PGC_allocated | 1;
|
||||
list_add_tail(&pg[i].list, &d->page_list);
|
||||
}
|
||||
|
||||
@@ -418,10 +428,13 @@ void free_domheap_pages(struct pfn_info *pg, int order)
|
||||
if ( unlikely(IS_XEN_HEAP_FRAME(pg)) )
|
||||
{
|
||||
spin_lock_recursive(&d->page_alloc_lock);
|
||||
|
||||
for ( i = 0; i < (1 << order); i++ )
|
||||
list_del(&pg[i].list);
|
||||
|
||||
d->xenheap_pages -= 1 << order;
|
||||
drop_dom_ref = (d->xenheap_pages == 0);
|
||||
|
||||
spin_unlock_recursive(&d->page_alloc_lock);
|
||||
}
|
||||
else if ( likely(d != NULL) )
|
||||
@@ -431,9 +444,8 @@ void free_domheap_pages(struct pfn_info *pg, int order)
|
||||
|
||||
for ( i = 0; i < (1 << order); i++ )
|
||||
{
|
||||
pg[i].tlbflush_timestamp = tlbflush_clock;
|
||||
pg[i].u.inuse.count_info = 0;
|
||||
pg[i].u.free.cpu_mask = 1 << d->processor;
|
||||
pg[i].tlbflush_timestamp = tlbflush_clock;
|
||||
pg[i].u.free.cpu_mask = 1 << d->processor;
|
||||
list_del(&pg[i].list);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
#define __ARCH_X86_ATOMIC__
|
||||
|
||||
#include <xen/config.h>
|
||||
|
||||
/*
|
||||
* Atomic operations that C can't guarantee us. Useful for
|
||||
* resource counting etc..
|
||||
*/
|
||||
#include <asm/system.h>
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define LOCK "lock ; "
|
||||
@@ -15,11 +11,11 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Make sure gcc doesn't try to be clever and move things around
|
||||
* on us. We need to use _exactly_ the address the user gave us,
|
||||
* not some alias that contains the same information.
|
||||
* NB. I've pushed the volatile qualifier into the operations. This allows
|
||||
* fast accessors such as _atomic_read() and _atomic_set() which don't give
|
||||
* the compiler a fit.
|
||||
*/
|
||||
typedef struct { volatile int counter; } atomic_t;
|
||||
typedef struct { int counter; } atomic_t;
|
||||
|
||||
#define ATOMIC_INIT(i) { (i) }
|
||||
|
||||
@@ -29,8 +25,9 @@ typedef struct { volatile int counter; } atomic_t;
|
||||
*
|
||||
* Atomically reads the value of @v. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define atomic_read(v) ((v)->counter)
|
||||
*/
|
||||
#define _atomic_read(v) ((v).counter)
|
||||
#define atomic_read(v) (*(volatile int *)&((v)->counter))
|
||||
|
||||
/**
|
||||
* atomic_set - set atomic variable
|
||||
@@ -40,7 +37,8 @@ typedef struct { volatile int counter; } atomic_t;
|
||||
* Atomically sets the value of @v to @i. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define atomic_set(v,i) (((v)->counter) = (i))
|
||||
#define _atomic_set(v,i) (((v).counter) = (i))
|
||||
#define atomic_set(v,i) (*(volatile int *)&((v)->counter) = (i))
|
||||
|
||||
/**
|
||||
* atomic_add - add integer to atomic variable
|
||||
@@ -54,8 +52,8 @@ static __inline__ void atomic_add(int i, atomic_t *v)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
LOCK "addl %1,%0"
|
||||
:"=m" (v->counter)
|
||||
:"ir" (i), "m" (v->counter));
|
||||
:"=m" (*(volatile int *)&v->counter)
|
||||
:"ir" (i), "m" (*(volatile int *)&v->counter));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,8 +68,8 @@ static __inline__ void atomic_sub(int i, atomic_t *v)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
LOCK "subl %1,%0"
|
||||
:"=m" (v->counter)
|
||||
:"ir" (i), "m" (v->counter));
|
||||
:"=m" (*(volatile int *)&v->counter)
|
||||
:"ir" (i), "m" (*(volatile int *)&v->counter));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,8 +88,8 @@ static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
|
||||
|
||||
__asm__ __volatile__(
|
||||
LOCK "subl %2,%0; sete %1"
|
||||
:"=m" (v->counter), "=qm" (c)
|
||||
:"ir" (i), "m" (v->counter) : "memory");
|
||||
:"=m" (*(volatile int *)&v->counter), "=qm" (c)
|
||||
:"ir" (i), "m" (*(volatile int *)&v->counter) : "memory");
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -106,8 +104,8 @@ static __inline__ void atomic_inc(atomic_t *v)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
LOCK "incl %0"
|
||||
:"=m" (v->counter)
|
||||
:"m" (v->counter));
|
||||
:"=m" (*(volatile int *)&v->counter)
|
||||
:"m" (*(volatile int *)&v->counter));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,8 +119,8 @@ static __inline__ void atomic_dec(atomic_t *v)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
LOCK "decl %0"
|
||||
:"=m" (v->counter)
|
||||
:"m" (v->counter));
|
||||
:"=m" (*(volatile int *)&v->counter)
|
||||
:"m" (*(volatile int *)&v->counter));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,8 +138,8 @@ static __inline__ int atomic_dec_and_test(atomic_t *v)
|
||||
|
||||
__asm__ __volatile__(
|
||||
LOCK "decl %0; sete %1"
|
||||
:"=m" (v->counter), "=qm" (c)
|
||||
:"m" (v->counter) : "memory");
|
||||
:"=m" (*(volatile int *)&v->counter), "=qm" (c)
|
||||
:"m" (*(volatile int *)&v->counter) : "memory");
|
||||
return c != 0;
|
||||
}
|
||||
|
||||
@@ -160,8 +158,8 @@ static __inline__ int atomic_inc_and_test(atomic_t *v)
|
||||
|
||||
__asm__ __volatile__(
|
||||
LOCK "incl %0; sete %1"
|
||||
:"=m" (v->counter), "=qm" (c)
|
||||
:"m" (v->counter) : "memory");
|
||||
:"=m" (*(volatile int *)&v->counter), "=qm" (c)
|
||||
:"m" (*(volatile int *)&v->counter) : "memory");
|
||||
return c != 0;
|
||||
}
|
||||
|
||||
@@ -181,11 +179,20 @@ static __inline__ int atomic_add_negative(int i, atomic_t *v)
|
||||
|
||||
__asm__ __volatile__(
|
||||
LOCK "addl %2,%0; sets %1"
|
||||
:"=m" (v->counter), "=qm" (c)
|
||||
:"ir" (i), "m" (v->counter) : "memory");
|
||||
:"=m" (*(volatile int *)&v->counter), "=qm" (c)
|
||||
:"ir" (i), "m" (*(volatile int *)&v->counter) : "memory");
|
||||
return c;
|
||||
}
|
||||
|
||||
static __inline__ atomic_t atomic_compareandswap(
|
||||
atomic_t old, atomic_t new, atomic_t *v)
|
||||
{
|
||||
atomic_t rc;
|
||||
rc.counter =
|
||||
__cmpxchg(&v->counter, old.counter, new.counter, sizeof(int));
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Atomic operations are already serializing on x86 */
|
||||
#define smp_mb__before_atomic_dec() barrier()
|
||||
#define smp_mb__after_atomic_dec() barrier()
|
||||
|
||||
+24
-28
@@ -87,9 +87,11 @@ struct pfn_info
|
||||
/* Cleared when the owning guest 'frees' this page. */
|
||||
#define _PGC_allocated 29
|
||||
#define PGC_allocated (1<<_PGC_allocated)
|
||||
/* 28-bit count of references to this frame. */
|
||||
#define PGC_count_mask ((1<<29)-1)
|
||||
|
||||
/* This bit is always set, guaranteeing that the count word is never zero. */
|
||||
#define _PGC_always_set 28
|
||||
#define PGC_always_set (1<<_PGC_always_set)
|
||||
/* 27-bit count of references to this frame. */
|
||||
#define PGC_count_mask ((1<<28)-1)
|
||||
|
||||
/* We trust the slab allocator in slab.c, and our use of it. */
|
||||
#define PageSlab(page) (1)
|
||||
@@ -106,7 +108,8 @@ struct pfn_info
|
||||
wmb(); /* install valid domain ptr before updating refcnt. */ \
|
||||
spin_lock(&(_dom)->page_alloc_lock); \
|
||||
/* _dom holds an allocation reference */ \
|
||||
(_pfn)->u.inuse.count_info = PGC_allocated | 1; \
|
||||
ASSERT((_pfn)->u.inuse.count_info == PGC_always_set); \
|
||||
(_pfn)->u.inuse.count_info |= PGC_allocated | 1; \
|
||||
if ( unlikely((_dom)->xenheap_pages++ == 0) ) \
|
||||
get_knownalive_domain(_dom); \
|
||||
list_add_tail(&(_pfn)->list, &(_dom)->xenpage_list); \
|
||||
@@ -150,10 +153,8 @@ static inline int get_page(struct pfn_info *page,
|
||||
unlikely((nx & PGC_count_mask) == 0) || /* Count overflow? */
|
||||
unlikely(p != domain) ) /* Wrong owner? */
|
||||
{
|
||||
DPRINTK("Error pfn %08lx: ed=%p(%u), sd=%p(%u),"
|
||||
" caf=%08x, taf=%08x\n",
|
||||
page_to_pfn(page), domain, domain->domain,
|
||||
p, (p && !((x & PGC_count_mask) == 0))?p->domain:999,
|
||||
DPRINTK("Error pfn %08lx: ed=%p, sd=%p, caf=%08x, taf=%08x\n",
|
||||
page_to_pfn(page), domain, p,
|
||||
x, page->u.inuse.type_info);
|
||||
return 0;
|
||||
}
|
||||
@@ -364,26 +365,21 @@ void ptwr_reconnect_disconnected(unsigned long addr);
|
||||
void ptwr_flush_inactive(void);
|
||||
int ptwr_do_page_fault(unsigned long);
|
||||
|
||||
static always_inline void
|
||||
__cleanup_writable_pagetable(
|
||||
const int what)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
#define __cleanup_writable_pagetable(_what) \
|
||||
do { \
|
||||
int cpu = smp_processor_id(); \
|
||||
if ((_what) & PTWR_CLEANUP_ACTIVE) \
|
||||
if (ptwr_info[cpu].disconnected != ENTRIES_PER_L2_PAGETABLE) \
|
||||
ptwr_reconnect_disconnected(0L); \
|
||||
if ((_what) & PTWR_CLEANUP_INACTIVE) \
|
||||
if (ptwr_info[cpu].writable_idx) \
|
||||
ptwr_flush_inactive(); \
|
||||
} while ( 0 )
|
||||
|
||||
if (what & PTWR_CLEANUP_ACTIVE)
|
||||
if (ptwr_info[cpu].disconnected != ENTRIES_PER_L2_PAGETABLE)
|
||||
ptwr_reconnect_disconnected(0L);
|
||||
if (what & PTWR_CLEANUP_INACTIVE)
|
||||
if (ptwr_info[cpu].writable_idx)
|
||||
ptwr_flush_inactive();
|
||||
}
|
||||
|
||||
static always_inline void
|
||||
cleanup_writable_pagetable(
|
||||
struct domain *d, const int what)
|
||||
{
|
||||
if ( unlikely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
|
||||
__cleanup_writable_pagetable(what);
|
||||
}
|
||||
#define cleanup_writable_pagetable(_d, _w) \
|
||||
do { \
|
||||
if ( unlikely(VM_ASSIST((_d), VMASST_TYPE_writable_pagetables)) ) \
|
||||
__cleanup_writable_pagetable(_w); \
|
||||
} while ( 0 )
|
||||
|
||||
#endif /* __ASM_X86_MM_H__ */
|
||||
@@ -1,26 +1,13 @@
|
||||
#ifndef __ASM_SMP_H
|
||||
#define __ASM_SMP_H
|
||||
|
||||
/*
|
||||
* We need the APIC definitions automatically as part of 'smp.h'
|
||||
*/
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <xen/config.h>
|
||||
/*#include <xen/threads.h>*/
|
||||
#include <asm/ptrace.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <asm/fixmap.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <asm/mpspec.h>
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
#include <asm/io_apic.h>
|
||||
#endif
|
||||
#include <asm/apic.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#ifndef __ASSEMBLY__
|
||||
@@ -37,12 +24,6 @@ extern int pic_mode;
|
||||
extern int smp_num_siblings;
|
||||
extern int cpu_sibling_map[];
|
||||
|
||||
extern void smp_flush_tlb(void);
|
||||
extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
|
||||
extern void smp_send_reschedule(int cpu);
|
||||
extern void smp_invalidate_rcv(void); /* Process an NMI */
|
||||
extern void (*mtrr_hook) (void);
|
||||
|
||||
/*
|
||||
* On x86 all CPUs are mapped 1:1 to the APIC space.
|
||||
* This simplifies scheduling and IPI sending and
|
||||
|
||||
@@ -30,33 +30,33 @@ static always_inline unsigned long __xchg(unsigned long x, volatile void * ptr,
|
||||
case 1:
|
||||
__asm__ __volatile__("xchgb %b0,%1"
|
||||
:"=q" (x)
|
||||
:"m" (*__xg(ptr)), "0" (x)
|
||||
:"m" (*__xg((volatile void *)ptr)), "0" (x)
|
||||
:"memory");
|
||||
break;
|
||||
case 2:
|
||||
__asm__ __volatile__("xchgw %w0,%1"
|
||||
:"=r" (x)
|
||||
:"m" (*__xg(ptr)), "0" (x)
|
||||
:"m" (*__xg((volatile void *)ptr)), "0" (x)
|
||||
:"memory");
|
||||
break;
|
||||
#if defined(__i386__)
|
||||
case 4:
|
||||
__asm__ __volatile__("xchgl %0,%1"
|
||||
:"=r" (x)
|
||||
:"m" (*__xg(ptr)), "0" (x)
|
||||
:"m" (*__xg((volatile void *)ptr)), "0" (x)
|
||||
:"memory");
|
||||
break;
|
||||
#elif defined(__x86_64__)
|
||||
case 4:
|
||||
__asm__ __volatile__("xchgl %k0,%1"
|
||||
:"=r" (x)
|
||||
:"m" (*__xg(ptr)), "0" (x)
|
||||
:"m" (*__xg((volatile void *)ptr)), "0" (x)
|
||||
:"memory");
|
||||
break;
|
||||
case 8:
|
||||
__asm__ __volatile__("xchgq %0,%1"
|
||||
:"=r" (x)
|
||||
:"m" (*__xg(ptr)), "0" (x)
|
||||
:"m" (*__xg((volatile void *)ptr)), "0" (x)
|
||||
:"memory");
|
||||
break;
|
||||
#endif
|
||||
@@ -78,33 +78,33 @@ static always_inline unsigned long __cmpxchg(volatile void *ptr, unsigned long o
|
||||
case 1:
|
||||
__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
|
||||
: "=a"(prev)
|
||||
: "q"(new), "m"(*__xg(ptr)), "0"(old)
|
||||
: "q"(new), "m"(*__xg((volatile void *)ptr)), "0"(old)
|
||||
: "memory");
|
||||
return prev;
|
||||
case 2:
|
||||
__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
|
||||
: "=a"(prev)
|
||||
: "q"(new), "m"(*__xg(ptr)), "0"(old)
|
||||
: "r"(new), "m"(*__xg((volatile void *)ptr)), "0"(old)
|
||||
: "memory");
|
||||
return prev;
|
||||
#if defined(__i386__)
|
||||
case 4:
|
||||
__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
|
||||
: "=a"(prev)
|
||||
: "q"(new), "m"(*__xg(ptr)), "0"(old)
|
||||
: "r"(new), "m"(*__xg((volatile void *)ptr)), "0"(old)
|
||||
: "memory");
|
||||
return prev;
|
||||
#elif defined(__x86_64__)
|
||||
case 4:
|
||||
__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %k1,%2"
|
||||
: "=a"(prev)
|
||||
: "q"(new), "m"(*__xg(ptr)), "0"(old)
|
||||
: "r"(new), "m"(*__xg((volatile void *)ptr)), "0"(old)
|
||||
: "memory");
|
||||
return prev;
|
||||
case 8:
|
||||
__asm__ __volatile__(LOCK_PREFIX "cmpxchgq %1,%2"
|
||||
: "=a"(prev)
|
||||
: "q"(new), "m"(*__xg(ptr)), "0"(old)
|
||||
: "r"(new), "m"(*__xg((volatile void *)ptr)), "0"(old)
|
||||
: "memory");
|
||||
return prev;
|
||||
#endif
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#ifndef __XEN_GRANT_H__
|
||||
#define __XEN_GRANT_H__
|
||||
|
||||
#include <xen/config.h>
|
||||
#include <xen/mm.h>
|
||||
#include <hypervisor-ifs/grant_table.h>
|
||||
|
||||
/* Active grant entry - used for shadowing GTF_permit_access grants. */
|
||||
@@ -65,10 +67,19 @@ typedef struct {
|
||||
} grant_table_t;
|
||||
|
||||
/* Start-of-day system initialisation. */
|
||||
void grant_table_init(void);
|
||||
void grant_table_init(
|
||||
void);
|
||||
|
||||
/* Create/destroy per-domain grant table context. */
|
||||
int grant_table_create(struct domain *d);
|
||||
void grant_table_destroy(struct domain *d);
|
||||
int grant_table_create(
|
||||
struct domain *d);
|
||||
void grant_table_destroy(
|
||||
struct domain *d);
|
||||
|
||||
/* Create/destroy host-CPU mappings via a grant-table entry. */
|
||||
int gnttab_try_map(
|
||||
struct domain *rd, struct domain *ld, struct pfn_info *page, int readonly);
|
||||
int gnttab_try_unmap(
|
||||
struct domain *rd, struct domain *ld, struct pfn_info *page, int readonly);
|
||||
|
||||
#endif /* __XEN_GRANT_H__ */
|
||||
+17
-10
@@ -1,6 +1,9 @@
|
||||
#ifndef __SCHED_H__
|
||||
#define __SCHED_H__
|
||||
|
||||
#define STACK_SIZE (2*PAGE_SIZE)
|
||||
#define MAX_DOMAIN_NAME 16
|
||||
|
||||
#include <xen/config.h>
|
||||
#include <xen/types.h>
|
||||
#include <xen/spinlock.h>
|
||||
@@ -10,23 +13,18 @@
|
||||
#include <asm/processor.h>
|
||||
#include <hypervisor-ifs/hypervisor-if.h>
|
||||
#include <hypervisor-ifs/dom0_ops.h>
|
||||
#include <xen/grant_table.h>
|
||||
#include <xen/list.h>
|
||||
#include <xen/time.h>
|
||||
#include <xen/ac_timer.h>
|
||||
#include <xen/delay.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#define STACK_SIZE (2*PAGE_SIZE)
|
||||
#include <asm/current.h>
|
||||
|
||||
#define MAX_DOMAIN_NAME 16
|
||||
#include <xen/spinlock.h>
|
||||
#include <xen/grant_table.h>
|
||||
|
||||
extern unsigned long volatile jiffies;
|
||||
extern rwlock_t tasklist_lock;
|
||||
|
||||
#include <xen/spinlock.h>
|
||||
|
||||
struct domain;
|
||||
|
||||
typedef struct event_channel_st
|
||||
@@ -167,10 +165,19 @@ struct domain *alloc_domain_struct();
|
||||
* Use this when you don't have an existing reference to @d. It returns
|
||||
* FALSE if @d is being destructed.
|
||||
*/
|
||||
static inline int get_domain(struct domain *d)
|
||||
static always_inline int get_domain(struct domain *d)
|
||||
{
|
||||
atomic_inc(&d->refcnt);
|
||||
return !(atomic_read(&d->refcnt) & DOMAIN_DESTRUCTED);
|
||||
atomic_t old, new, seen = d->refcnt;
|
||||
do
|
||||
{
|
||||
old = seen;
|
||||
if ( unlikely(_atomic_read(old) & DOMAIN_DESTRUCTED) )
|
||||
return 0;
|
||||
_atomic_set(new, _atomic_read(old) + 1);
|
||||
seen = atomic_compareandswap(old, new, &d->refcnt);
|
||||
}
|
||||
while ( unlikely(_atomic_read(seen) != _atomic_read(old)) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||