|
|
|
|
|
|
|
|
|
|
xen-changelog
[Xen-changelog] Allow a guest to switch pagetables 'atomically'. That is
# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 5adaa690872746d66f8f4c0fdacc81a9117723cb
# Parent 38d9f4cbbc1e4f26bc7d7a839db4852d6db48193
Allow a guest to switch pagetables 'atomically'. That is, the new pagetables
do not need to be read-only in the old pagetables, and the old pagetables do
not need to be read-only in the new pagetables.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r 38d9f4cbbc1e -r 5adaa6908727 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Mon Feb 27 15:29:03 2006
+++ b/xen/arch/x86/mm.c Mon Feb 27 16:18:58 2006
@@ -1570,42 +1570,68 @@
unsigned long old_base_mfn;
if ( shadow_mode_refcounts(d) )
+ {
okay = get_page_from_pagenr(mfn, d);
+ if ( unlikely(!okay) )
+ {
+ MEM_LOG("Error while installing new baseptr %lx", mfn);
+ return 0;
+ }
+ }
else
+ {
okay = get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d);
-
- if ( likely(okay) )
- {
- invalidate_shadow_ldt(v);
-
- old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
- v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
- update_pagetables(v); /* update shadow_table and monitor_table */
-
- write_ptbase(v);
-
+ if ( unlikely(!okay) )
+ {
+ /* Switch to idle pagetable: this VCPU has no active p.t. now. */
+ old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
+ v->arch.guest_table = mk_pagetable(0);
+ update_pagetables(v);
+ write_cr3(__pa(idle_pg_table));
+ if ( old_base_mfn != 0 )
+ put_page_and_type(mfn_to_page(old_base_mfn));
+
+ /* Retry the validation with no active p.t. for this VCPU. */
+ okay = get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d);
+ if ( !okay )
+ {
+ /* Failure here is unrecoverable: the VCPU has no pagetable! */
+ MEM_LOG("Fatal error while installing new baseptr %lx", mfn);
+ domain_crash(d);
+ percpu_info[v->processor].deferred_ops = 0;
+ return 0;
+ }
+ }
+ }
+
+ invalidate_shadow_ldt(v);
+
+ old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
+ v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
+ update_pagetables(v); /* update shadow_table and monitor_table */
+
+ write_ptbase(v);
+
+ if ( likely(old_base_mfn != 0) )
+ {
if ( shadow_mode_refcounts(d) )
put_page(mfn_to_page(old_base_mfn));
else
put_page_and_type(mfn_to_page(old_base_mfn));
-
- /* CR3 also holds a ref to its shadow... */
- if ( shadow_mode_enabled(d) )
- {
- if ( v->arch.monitor_shadow_ref )
- put_shadow_ref(v->arch.monitor_shadow_ref);
- v->arch.monitor_shadow_ref =
- pagetable_get_pfn(v->arch.monitor_table);
- ASSERT(!page_get_owner(mfn_to_page(v->arch.monitor_shadow_ref)));
- get_shadow_ref(v->arch.monitor_shadow_ref);
- }
- }
- else
- {
- MEM_LOG("Error while installing new baseptr %lx", mfn);
- }
-
- return okay;
+ }
+
+ /* CR3 also holds a ref to its shadow... */
+ if ( shadow_mode_enabled(d) )
+ {
+ if ( v->arch.monitor_shadow_ref )
+ put_shadow_ref(v->arch.monitor_shadow_ref);
+ v->arch.monitor_shadow_ref =
+ pagetable_get_pfn(v->arch.monitor_table);
+ ASSERT(!page_get_owner(mfn_to_page(v->arch.monitor_shadow_ref)));
+ get_shadow_ref(v->arch.monitor_shadow_ref);
+ }
+
+ return 1;
}
static void process_deferred_ops(unsigned int cpu)
@@ -1625,7 +1651,7 @@
else
local_flush_tlb();
}
-
+
if ( deferred_ops & DOP_RELOAD_LDT )
(void)map_ldt_shadow_page(0);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|
<Prev in Thread] |
Current Thread |
[Next in Thread> |
- [Xen-changelog] Allow a guest to switch pagetables 'atomically'. That is, the new pagetables,
Xen patchbot -unstable <=
|
|
|
|
|