Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 99577
b: refs/heads/master
c: 400d349
h: refs/heads/master
i:
  99575: 09355ab
v: v3
  • Loading branch information
Jeremy Fitzhardinge authored and Ingo Molnar committed Jun 25, 2008
1 parent 2d5abc4 commit cc9cec9
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e57778a1e30470c9f5b79e370511b9af29b59c48
refs/heads/master: 400d34944c4ad82a817c06e570bc93b1114aa596
55 changes: 35 additions & 20 deletions trunk/arch/x86/xen/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,18 +230,35 @@ static bool page_pinned(void *ptr)
return PagePinned(page);
}

void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val)
static void extend_mmu_update(const struct mmu_update *update)
{
struct multicall_space mcs;
struct mmu_update *u;

preempt_disable();
mcs = xen_mc_extend_args(__HYPERVISOR_mmu_update, sizeof(*u));

if (mcs.mc != NULL)
mcs.mc->args[1]++;
else {
mcs = __xen_mc_entry(sizeof(*u));
MULTI_mmu_update(mcs.mc, mcs.args, 1, NULL, DOMID_SELF);
}

mcs = xen_mc_entry(sizeof(*u));
u = mcs.args;
u->ptr = virt_to_machine(ptr).maddr;
u->val = pmd_val_ma(val);
MULTI_mmu_update(mcs.mc, u, 1, NULL, DOMID_SELF);
*u = *update;
}

void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val)
{
struct mmu_update u;

preempt_disable();

xen_mc_batch();

u.ptr = virt_to_machine(ptr).maddr;
u.val = pmd_val_ma(val);
extend_mmu_update(&u);

xen_mc_issue(PARAVIRT_LAZY_MMU);

Expand Down Expand Up @@ -332,14 +349,13 @@ pte_t xen_ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr, pte_t
void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte)
{
struct multicall_space mcs;
struct mmu_update *u;
struct mmu_update u;

mcs = xen_mc_entry(sizeof(*u));
u = mcs.args;
u->ptr = virt_to_machine(ptep).maddr | MMU_PT_UPDATE_PRESERVE_AD;
u->val = pte_val_ma(pte);
MULTI_mmu_update(mcs.mc, u, 1, NULL, DOMID_SELF);
xen_mc_batch();

u.ptr = virt_to_machine(ptep).maddr | MMU_PT_UPDATE_PRESERVE_AD;
u.val = pte_val_ma(pte);
extend_mmu_update(&u);

xen_mc_issue(PARAVIRT_LAZY_MMU);
}
Expand Down Expand Up @@ -396,16 +412,15 @@ pmdval_t xen_pmd_val(pmd_t pmd)

void xen_set_pud_hyper(pud_t *ptr, pud_t val)
{
struct multicall_space mcs;
struct mmu_update *u;
struct mmu_update u;

preempt_disable();

mcs = xen_mc_entry(sizeof(*u));
u = mcs.args;
u->ptr = virt_to_machine(ptr).maddr;
u->val = pud_val_ma(val);
MULTI_mmu_update(mcs.mc, u, 1, NULL, DOMID_SELF);
xen_mc_batch();

u.ptr = virt_to_machine(ptr).maddr;
u.val = pud_val_ma(val);
extend_mmu_update(&u);

xen_mc_issue(PARAVIRT_LAZY_MMU);

Expand Down
40 changes: 34 additions & 6 deletions trunk/arch/x86/xen/multicalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@
#define MC_DEBUG 1

#define MC_BATCH 32
#define MC_ARGS (MC_BATCH * 16 / sizeof(u64))
#define MC_ARGS (MC_BATCH * 16)

struct mc_buffer {
struct multicall_entry entries[MC_BATCH];
#if MC_DEBUG
struct multicall_entry debug[MC_BATCH];
#endif
u64 args[MC_ARGS];
unsigned char args[MC_ARGS];
struct callback {
void (*fn)(void *);
void *data;
Expand Down Expand Up @@ -107,20 +107,48 @@ struct multicall_space __xen_mc_entry(size_t args)
{
struct mc_buffer *b = &__get_cpu_var(mc_buffer);
struct multicall_space ret;
unsigned argspace = (args + sizeof(u64) - 1) / sizeof(u64);
unsigned argidx = roundup(b->argidx, sizeof(u64));

BUG_ON(preemptible());
BUG_ON(argspace > MC_ARGS);
BUG_ON(b->argidx > MC_ARGS);

if (b->mcidx == MC_BATCH ||
(b->argidx + argspace) > MC_ARGS)
(argidx + args) > MC_ARGS) {
xen_mc_flush();
argidx = roundup(b->argidx, sizeof(u64));
}

ret.mc = &b->entries[b->mcidx];
b->mcidx++;
ret.args = &b->args[argidx];
b->argidx = argidx + args;

BUG_ON(b->argidx > MC_ARGS);
return ret;
}

struct multicall_space xen_mc_extend_args(unsigned long op, size_t size)
{
struct mc_buffer *b = &__get_cpu_var(mc_buffer);
struct multicall_space ret = { NULL, NULL };

BUG_ON(preemptible());
BUG_ON(b->argidx > MC_ARGS);

if (b->mcidx == 0)
return ret;

if (b->entries[b->mcidx - 1].op != op)
return ret;

if ((b->argidx + size) > MC_ARGS)
return ret;

ret.mc = &b->entries[b->mcidx - 1];
ret.args = &b->args[b->argidx];
b->argidx += argspace;
b->argidx += size;

BUG_ON(b->argidx > MC_ARGS);
return ret;
}

Expand Down
12 changes: 12 additions & 0 deletions trunk/arch/x86/xen/multicalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,16 @@ static inline void xen_mc_issue(unsigned mode)
/* Set up a callback to be called when the current batch is flushed */
void xen_mc_callback(void (*fn)(void *), void *data);

/*
* Try to extend the arguments of the previous multicall command. The
* previous command's op must match. If it does, then it attempts to
* extend the argument space allocated to the multicall entry by
* arg_size bytes.
*
* The returned multicall_space will return with mc pointing to the
* command on success, or NULL on failure, and args pointing to the
* newly allocated space.
*/
struct multicall_space xen_mc_extend_args(unsigned long op, size_t arg_size);

#endif /* _XEN_MULTICALLS_H */

0 comments on commit cc9cec9

Please sign in to comment.