Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 70929
b: refs/heads/master
c: 9f79991
h: refs/heads/master
i:
  70927: 16f0bf9
v: v3
  • Loading branch information
Jeremy Fitzhardinge authored and Jeremy Fitzhardinge committed Oct 16, 2007
1 parent 1993502 commit f665324
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 21 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: 91e0c5f3dad47838cb2ecc1865ce789a0b7182b1
refs/heads/master: 9f79991d4186089e228274196413572cc000143b
55 changes: 38 additions & 17 deletions trunk/arch/x86/xen/enlighten.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,23 @@ EXPORT_SYMBOL_GPL(hypercall_page);

DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
DEFINE_PER_CPU(unsigned long, xen_cr3);

/*
* Note about cr3 (pagetable base) values:
*
* xen_cr3 contains the current logical cr3 value; it contains the
* last set cr3. This may not be the current effective cr3, because
* its update may be being lazily deferred. However, a vcpu looking
* at its own cr3 can use this value knowing that it everything will
* be self-consistent.
*
* xen_current_cr3 contains the actual vcpu cr3; it is set once the
* hypercall to set the vcpu cr3 is complete (so it may be a little
* out of date, but it will never be set early). If one vcpu is
* looking at another vcpu's cr3 value, it should use this variable.
*/
DEFINE_PER_CPU(unsigned long, xen_cr3); /* cr3 stored as physaddr */
DEFINE_PER_CPU(unsigned long, xen_current_cr3); /* actual vcpu cr3 */

struct start_info *xen_start_info;
EXPORT_SYMBOL_GPL(xen_start_info);
Expand Down Expand Up @@ -610,32 +626,36 @@ static unsigned long xen_read_cr3(void)
return x86_read_percpu(xen_cr3);
}

static void set_current_cr3(void *v)
{
x86_write_percpu(xen_current_cr3, (unsigned long)v);
}

static void xen_write_cr3(unsigned long cr3)
{
struct mmuext_op *op;
struct multicall_space mcs;
unsigned long mfn = pfn_to_mfn(PFN_DOWN(cr3));

BUG_ON(preemptible());

if (cr3 == x86_read_percpu(xen_cr3)) {
/* just a simple tlb flush */
xen_flush_tlb();
return;
}
mcs = xen_mc_entry(sizeof(*op)); /* disables interrupts */

/* Update while interrupts are disabled, so its atomic with
respect to ipis */
x86_write_percpu(xen_cr3, cr3);

op = mcs.args;
op->cmd = MMUEXT_NEW_BASEPTR;
op->arg1.mfn = mfn;

{
struct mmuext_op *op;
struct multicall_space mcs = xen_mc_entry(sizeof(*op));
unsigned long mfn = pfn_to_mfn(PFN_DOWN(cr3));

op = mcs.args;
op->cmd = MMUEXT_NEW_BASEPTR;
op->arg1.mfn = mfn;
MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);

MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
/* Update xen_update_cr3 once the batch has actually
been submitted. */
xen_mc_callback(set_current_cr3, (void *)cr3);

xen_mc_issue(PARAVIRT_LAZY_CPU);
}
xen_mc_issue(PARAVIRT_LAZY_CPU); /* interrupts restored */
}

/* Early in boot, while setting up the initial pagetable, assume
Expand Down Expand Up @@ -1120,6 +1140,7 @@ asmlinkage void __init xen_start_kernel(void)
/* keep using Xen gdt for now; no urgent need to change it */

x86_write_percpu(xen_cr3, __pa(pgd));
x86_write_percpu(xen_current_cr3, __pa(pgd));

#ifdef CONFIG_SMP
/* Don't do the full vcpu_info placement stuff until we have a
Expand Down
29 changes: 26 additions & 3 deletions trunk/arch/x86/xen/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -514,20 +514,43 @@ static void drop_other_mm_ref(void *info)

if (__get_cpu_var(cpu_tlbstate).active_mm == mm)
leave_mm(smp_processor_id());

/* If this cpu still has a stale cr3 reference, then make sure
it has been flushed. */
if (x86_read_percpu(xen_current_cr3) == __pa(mm->pgd)) {
load_cr3(swapper_pg_dir);
arch_flush_lazy_cpu_mode();
}
}

static void drop_mm_ref(struct mm_struct *mm)
{
cpumask_t mask;
unsigned cpu;

if (current->active_mm == mm) {
if (current->mm == mm)
load_cr3(swapper_pg_dir);
else
leave_mm(smp_processor_id());
arch_flush_lazy_cpu_mode();
}

/* Get the "official" set of cpus referring to our pagetable. */
mask = mm->cpu_vm_mask;

/* It's possible that a vcpu may have a stale reference to our
cr3, because its in lazy mode, and it hasn't yet flushed
its set of pending hypercalls yet. In this case, we can
look at its actual current cr3 value, and force it to flush
if needed. */
for_each_online_cpu(cpu) {
if (per_cpu(xen_current_cr3, cpu) == __pa(mm->pgd))
cpu_set(cpu, mask);
}

if (!cpus_empty(mm->cpu_vm_mask))
xen_smp_call_function_mask(mm->cpu_vm_mask, drop_other_mm_ref,
mm, 1);
if (!cpus_empty(mask))
xen_smp_call_function_mask(mask, drop_other_mm_ref, mm, 1);
}
#else
static void drop_mm_ref(struct mm_struct *mm)
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/x86/xen/xen-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ void xen_copy_trap_info(struct trap_info *traps);

DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
DECLARE_PER_CPU(unsigned long, xen_cr3);
DECLARE_PER_CPU(unsigned long, xen_current_cr3);

extern struct start_info *xen_start_info;
extern struct shared_info *HYPERVISOR_shared_info;
Expand Down

0 comments on commit f665324

Please sign in to comment.