#include <asm/current.h>
#include <asm/event.h>
#include <asm/guest_access.h>
+#include <asm/guest_atomics.h>
#include <asm/regs.h>
#include <asm/p2m.h>
#include <asm/irq.h>
void vcpu_mark_events_pending(struct vcpu *v)
{
- int already_pending = test_and_set_bit(
+ bool already_pending = guest_test_and_set_bit(v->domain,
0, (unsigned long *)&vcpu_info(v, evtchn_upcall_pending));
if ( already_pending )
#include <xen/pfn.h>
#include <xen/sizes.h>
#include <xen/libfdt/libfdt.h>
+
+#include <asm/guest_atomics.h>
#include <asm/setup.h>
struct domain *dom_xen, *dom_io, *dom_cow;
return;
}
-void gnttab_clear_flag(unsigned long nr, uint16_t *addr)
+void gnttab_clear_flag(struct domain *d, unsigned long nr, uint16_t *addr)
{
/*
* Note that this cannot be clear_bit(), as the access must be
do {
old = *addr;
- } while (cmpxchg(addr, old, old & mask) != old);
+ } while (guest_cmpxchg(d, addr, old, old & mask) != old);
}
void gnttab_mark_dirty(struct domain *d, unsigned long l)
#include <xen/sched.h>
#include <xen/event.h>
+#include <asm/guest_atomics.h>
+
static void evtchn_2l_set_pending(struct vcpu *v, struct evtchn *evtchn)
{
struct domain *d = v->domain;
* others may require explicit memory barriers.
*/
- if ( test_and_set_bit(port, &shared_info(d, evtchn_pending)) )
+ if ( guest_test_and_set_bit(d, port, &shared_info(d, evtchn_pending)) )
return;
- if ( !test_bit (port, &shared_info(d, evtchn_mask)) &&
- !test_and_set_bit(port / BITS_PER_EVTCHN_WORD(d),
- &vcpu_info(v, evtchn_pending_sel)) )
+ if ( !guest_test_bit(d, port, &shared_info(d, evtchn_mask)) &&
+ !guest_test_and_set_bit(d, port / BITS_PER_EVTCHN_WORD(d),
+ &vcpu_info(v, evtchn_pending_sel)) )
{
vcpu_mark_events_pending(v);
}
static void evtchn_2l_clear_pending(struct domain *d, struct evtchn *evtchn)
{
- clear_bit(evtchn->port, &shared_info(d, evtchn_pending));
+ guest_clear_bit(d, evtchn->port, &shared_info(d, evtchn_pending));
}
static void evtchn_2l_unmask(struct domain *d, struct evtchn *evtchn)
* These operations must happen in strict order. Based on
* evtchn_2l_set_pending() above.
*/
- if ( test_and_clear_bit(port, &shared_info(d, evtchn_mask)) &&
- test_bit (port, &shared_info(d, evtchn_pending)) &&
- !test_and_set_bit (port / BITS_PER_EVTCHN_WORD(d),
- &vcpu_info(v, evtchn_pending_sel)) )
+ if ( guest_test_and_clear_bit(d, port, &shared_info(d, evtchn_mask)) &&
+ guest_test_bit(d, port, &shared_info(d, evtchn_pending)) &&
+ !guest_test_and_set_bit(d, port / BITS_PER_EVTCHN_WORD(d),
+ &vcpu_info(v, evtchn_pending_sel)) )
{
vcpu_mark_events_pending(v);
}
unsigned int max_ports = BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d);
ASSERT(port < max_ports);
- return port < max_ports && test_bit(port, &shared_info(d, evtchn_pending));
+ return (port < max_ports &&
+ guest_test_bit(d, port, &shared_info(d, evtchn_pending)));
}
static bool_t evtchn_2l_is_masked(struct domain *d, evtchn_port_t port)
unsigned int max_ports = BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d);
ASSERT(port < max_ports);
- return port >= max_ports || test_bit(port, &shared_info(d, evtchn_mask));
+ return (port >= max_ports ||
+ guest_test_bit(d, port, &shared_info(d, evtchn_mask)));
}
static void evtchn_2l_print_state(struct domain *d,
#include <xen/mm.h>
#include <xen/domain_page.h>
+#include <asm/guest_atomics.h>
+
#include <public/event_channel.h>
static inline event_word_t *evtchn_fifo_word_from_port(struct domain *d,
* on the wrong VCPU or with an unexpected priority.
*/
word = evtchn_fifo_word_from_port(d, evtchn->port);
- if ( word && test_bit(EVTCHN_FIFO_LINKED, word) )
+ if ( word && guest_test_bit(d, EVTCHN_FIFO_LINKED, word) )
gdprintk(XENLOG_WARNING, "domain %d, port %d already on a queue\n",
d->domain_id, evtchn->port);
}
* We block unmasking by the guest by marking the tail word as BUSY,
* therefore, the cmpxchg() may fail at most 4 times.
*/
-static bool_t evtchn_fifo_set_link(const struct domain *d, event_word_t *word,
+static bool_t evtchn_fifo_set_link(struct domain *d, event_word_t *word,
uint32_t link)
{
event_word_t w;
return ret;
/* Lock the word to prevent guest unmasking. */
- set_bit(EVTCHN_FIFO_BUSY, word);
+ guest_set_bit(d, EVTCHN_FIFO_BUSY, word);
w = read_atomic(word);
if ( ret >= 0 )
{
if ( ret == 0 )
- clear_bit(EVTCHN_FIFO_BUSY, word);
+ guest_clear_bit(d, EVTCHN_FIFO_BUSY, word);
return ret;
}
}
gdprintk(XENLOG_WARNING, "domain %d, port %d not linked\n",
d->domain_id, link);
- clear_bit(EVTCHN_FIFO_BUSY, word);
+ guest_clear_bit(d, EVTCHN_FIFO_BUSY, word);
return 1;
}
return;
}
- was_pending = test_and_set_bit(EVTCHN_FIFO_PENDING, word);
+ was_pending = guest_test_and_set_bit(d, EVTCHN_FIFO_PENDING, word);
/*
* Link the event if it unmasked and not already linked.
*/
- if ( !test_bit(EVTCHN_FIFO_MASKED, word)
- && !test_bit(EVTCHN_FIFO_LINKED, word) )
+ if ( !guest_test_bit(d, EVTCHN_FIFO_MASKED, word) &&
+ !guest_test_bit(d, EVTCHN_FIFO_LINKED, word) )
{
struct evtchn_fifo_queue *q, *old_q;
event_word_t *tail_word;
if ( !old_q )
goto done;
- if ( test_and_set_bit(EVTCHN_FIFO_LINKED, word) )
+ if ( guest_test_and_set_bit(d, EVTCHN_FIFO_LINKED, word) )
{
spin_unlock_irqrestore(&old_q->lock, flags);
goto done;
spin_unlock_irqrestore(&q->lock, flags);
if ( !linked
- && !test_and_set_bit(q->priority,
- &v->evtchn_fifo->control_block->ready) )
+ && !guest_test_and_set_bit(d, q->priority,
+ &v->evtchn_fifo->control_block->ready) )
vcpu_mark_events_pending(v);
}
done:
* No need to unlink as the guest will unlink and ignore
* non-pending events.
*/
- clear_bit(EVTCHN_FIFO_PENDING, word);
+ guest_clear_bit(d, EVTCHN_FIFO_PENDING, word);
}
static void evtchn_fifo_unmask(struct domain *d, struct evtchn *evtchn)
if ( unlikely(!word) )
return;
- clear_bit(EVTCHN_FIFO_MASKED, word);
+ guest_clear_bit(d, EVTCHN_FIFO_MASKED, word);
/* Relink if pending. */
- if ( test_bit(EVTCHN_FIFO_PENDING, word) )
+ if ( guest_test_bit(d, EVTCHN_FIFO_PENDING, word) )
evtchn_fifo_set_pending(v, evtchn);
}
if ( unlikely(!word) )
return 0;
- return test_bit(EVTCHN_FIFO_PENDING, word);
+ return word && guest_test_bit(d, EVTCHN_FIFO_PENDING, word);
}
static bool_t evtchn_fifo_is_masked(struct domain *d, evtchn_port_t port)
if ( unlikely(!word) )
return 1;
- return test_bit(EVTCHN_FIFO_MASKED, word);
+ return !word || guest_test_bit(d, EVTCHN_FIFO_MASKED, word);
}
static bool_t evtchn_fifo_is_busy(struct domain *d, evtchn_port_t port)
if ( unlikely(!word) )
return 0;
- return test_bit(EVTCHN_FIFO_LINKED, word);
+ return word && guest_test_bit(d, EVTCHN_FIFO_LINKED, word);
}
static int evtchn_fifo_set_priority(struct domain *d, struct evtchn *evtchn,
word = evtchn_fifo_word_from_port(d, evtchn->port);
if ( !word )
printk("? ");
- else if ( test_bit(EVTCHN_FIFO_LINKED, word) )
- printk("%c %-4u", test_bit(EVTCHN_FIFO_BUSY, word) ? 'B' : ' ',
+ else if ( guest_test_bit(d, EVTCHN_FIFO_LINKED, word) )
+ printk("%c %-4u", guest_test_bit(d, EVTCHN_FIFO_BUSY, word) ? 'B' : ' ',
*word & EVTCHN_FIFO_LINK_MASK);
else
- printk("%c - ", test_bit(EVTCHN_FIFO_BUSY, word) ? 'B' : ' ');
+ printk("%c - ", guest_test_bit(d, EVTCHN_FIFO_BUSY, word) ? 'B' : ' ');
}
static const struct evtchn_port_ops evtchn_port_ops_fifo =
evtchn = evtchn_from_port(d, port);
- if ( test_bit(port, &shared_info(d, evtchn_pending)) )
+ if ( guest_test_bit(d, port, &shared_info(d, evtchn_pending)) )
evtchn->pending = 1;
evtchn_fifo_set_priority(d, evtchn, EVTCHN_FIFO_PRIORITY_DEFAULT);
#include <xen/vmap.h>
#include <xsm/xsm.h>
#include <asm/flushtlb.h>
+#include <asm/guest_atomics.h>
/*
* This option is deprecated, use gnttab_max_frames and
}
static int _set_status_v1(const grant_entry_header_t *shah,
+ struct domain *rd,
struct active_grant_entry *act,
int readonly,
int mapflag,
"Attempt to write-pin a r/o grant entry.\n");
}
- prev_scombo.word = cmpxchg((u32 *)shah,
- scombo.word, new_scombo.word);
+ prev_scombo.word = guest_cmpxchg(rd, (u32 *)shah,
+ scombo.word, new_scombo.word);
if ( likely(prev_scombo.word == scombo.word) )
break;
static int _set_status_v2(const grant_entry_header_t *shah,
grant_status_t *status,
+ struct domain *rd,
struct active_grant_entry *act,
int readonly,
int mapflag,
(id != ldomid) ||
(!readonly && (flags & GTF_readonly)) )
{
- gnttab_clear_flag(_GTF_writing, status);
- gnttab_clear_flag(_GTF_reading, status);
+ gnttab_clear_flag(rd, _GTF_writing, status);
+ gnttab_clear_flag(rd, _GTF_reading, status);
PIN_FAIL(done, GNTST_general_error,
"Unstable flags (%x) or dom (%d). (expected dom %d) "
"(r/w: %d)\n",
{
if ( unlikely(flags & GTF_readonly) )
{
- gnttab_clear_flag(_GTF_writing, status);
+ gnttab_clear_flag(rd, _GTF_writing, status);
PIN_FAIL(done, GNTST_general_error,
"Unstable grant readonly flag\n");
}
static int _set_status(const grant_entry_header_t *shah,
grant_status_t *status,
+ struct domain *rd,
unsigned rgt_version,
struct active_grant_entry *act,
int readonly,
{
if ( rgt_version == 1 )
- return _set_status_v1(shah, act, readonly, mapflag, ldomid);
+ return _set_status_v1(shah, rd, act, readonly, mapflag, ldomid);
else
- return _set_status_v2(shah, status, act, readonly, mapflag, ldomid);
+ return _set_status_v2(shah, status, rd, act, readonly, mapflag, ldomid);
}
static struct active_grant_entry *grant_map_exists(const struct domain *ld,
(!(op->flags & GNTMAP_readonly) &&
!(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask))) )
{
- if ( (rc = _set_status(shah, status, rgt->gt_version, act,
+ if ( (rc = _set_status(shah, status, rd, rgt->gt_version, act,
op->flags & GNTMAP_readonly, 1,
ld->domain_id) != GNTST_okay) )
goto act_release_out;
unlock_out_clear:
if ( !(op->flags & GNTMAP_readonly) &&
!(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) )
- gnttab_clear_flag(_GTF_writing, status);
+ gnttab_clear_flag(rd, _GTF_writing, status);
if ( !act->pin )
- gnttab_clear_flag(_GTF_reading, status);
+ gnttab_clear_flag(rd, _GTF_reading, status);
act_release_out:
active_entry_release(act);
if ( ((act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0) &&
!(op->done & GNTMAP_readonly) )
- gnttab_clear_flag(_GTF_writing, status);
+ gnttab_clear_flag(rd, _GTF_writing, status);
if ( act->pin == 0 )
- gnttab_clear_flag(_GTF_reading, status);
+ gnttab_clear_flag(rd, _GTF_reading, status);
active_entry_release(act);
grant_read_unlock(rgt);
new_scombo = scombo;
new_scombo.shorts.flags |= GTF_transfer_committed;
- prev_scombo.word = cmpxchg((u32 *)&sha->flags,
- scombo.word, new_scombo.word);
+ prev_scombo.word = guest_cmpxchg(rd, (u32 *)&sha->flags,
+ scombo.word, new_scombo.word);
if ( likely(prev_scombo.word == scombo.word) )
break;
act->pin -= GNTPIN_hstw_inc;
if ( !(act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) )
- gnttab_clear_flag(_GTF_writing, status);
+ gnttab_clear_flag(rd, _GTF_writing, status);
}
if ( !act->pin )
- gnttab_clear_flag(_GTF_reading, status);
+ gnttab_clear_flag(rd, _GTF_reading, status);
active_entry_release(act);
grant_read_unlock(rgt);
under the domain's grant table lock. */
/* Only safe on transitive grants. Even then, note that we don't
attempt to drop any pin on the referent grant. */
-static void __fixup_status_for_copy_pin(const struct active_grant_entry *act,
- uint16_t *status)
+static void __fixup_status_for_copy_pin(struct domain *rd,
+ const struct active_grant_entry *act,
+ uint16_t *status)
{
if ( !(act->pin & (GNTPIN_hstw_mask | GNTPIN_devw_mask)) )
- gnttab_clear_flag(_GTF_writing, status);
+ gnttab_clear_flag(rd, _GTF_writing, status);
if ( !act->pin )
- gnttab_clear_flag(_GTF_reading, status);
+ gnttab_clear_flag(rd, _GTF_reading, status);
}
/* Grab a frame number from a grant entry and update the flags and pin
{
if ( (!old_pin || (!readonly &&
!(old_pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)))) &&
- (rc = _set_status_v2(shah, status, act, readonly, 0,
+ (rc = _set_status_v2(shah, status, rd, act, readonly, 0,
ldom)) != GNTST_okay )
goto unlock_out;
if ( rc != GNTST_okay )
{
- __fixup_status_for_copy_pin(act, status);
+ __fixup_status_for_copy_pin(rd, act, status);
rcu_unlock_domain(td);
active_entry_release(act);
grant_read_unlock(rgt);
!act->is_sub_page)) )
{
__release_grant_for_copy(td, trans_gref, readonly);
- __fixup_status_for_copy_pin(act, status);
+ __fixup_status_for_copy_pin(rd, act, status);
rcu_unlock_domain(td);
active_entry_release(act);
grant_read_unlock(rgt);
else if ( !old_pin ||
(!readonly && !(old_pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask))) )
{
- if ( (rc = _set_status(shah, status, rgt->gt_version, act,
+ if ( (rc = _set_status(shah, status, rd, rgt->gt_version, act,
readonly, 0, ldom)) != GNTST_okay )
goto unlock_out;
unlock_out_clear:
if ( !(readonly) &&
!(act->pin & (GNTPIN_hstw_mask | GNTPIN_devw_mask)) )
- gnttab_clear_flag(_GTF_writing, status);
+ gnttab_clear_flag(rd, _GTF_writing, status);
if ( !act->pin )
- gnttab_clear_flag(_GTF_reading, status);
+ gnttab_clear_flag(rd, _GTF_reading, status);
unlock_out:
active_entry_release(act);
}
if ( (act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0 )
- gnttab_clear_flag(_GTF_writing, status);
+ gnttab_clear_flag(rd, _GTF_writing, status);
}
if ( act->pin == 0 )
- gnttab_clear_flag(_GTF_reading, status);
+ gnttab_clear_flag(rd, _GTF_reading, status);
active_entry_release(act);
grant_read_unlock(rgt);
#define INITIAL_NR_GRANT_FRAMES 4
#define GNTTAB_MAX_VERSION 1
-void gnttab_clear_flag(unsigned long nr, uint16_t *addr);
+void gnttab_clear_flag(struct domain *d, unsigned long nr, uint16_t *addr);
int create_grant_host_mapping(unsigned long gpaddr,
unsigned long mfn, unsigned int flags, unsigned int
cache_flags);
#define gnttab_mark_dirty(d, f) paging_mark_dirty((d), _mfn(f))
-static inline void gnttab_clear_flag(unsigned int nr, uint16_t *st)
+static inline void gnttab_clear_flag(struct domain *d, unsigned int nr,
+ uint16_t *st)
{
/*
* Note that this cannot be clear_bit(), as the access must be