ia64/xen-unstable
changeset 9051:5adaa6908727
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@xensource.com>
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@xensource.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Mon Feb 27 17:18:58 2006 +0100 (2006-02-27) |
parents | 38d9f4cbbc1e |
children | 0416b6ba8c37 |
files | xen/arch/x86/mm.c |
line diff
1.1 --- a/xen/arch/x86/mm.c Mon Feb 27 16:29:03 2006 +0100 1.2 +++ b/xen/arch/x86/mm.c Mon Feb 27 17:18:58 2006 +0100 1.3 @@ -1570,42 +1570,68 @@ int new_guest_cr3(unsigned long mfn) 1.4 unsigned long old_base_mfn; 1.5 1.6 if ( shadow_mode_refcounts(d) ) 1.7 + { 1.8 okay = get_page_from_pagenr(mfn, d); 1.9 + if ( unlikely(!okay) ) 1.10 + { 1.11 + MEM_LOG("Error while installing new baseptr %lx", mfn); 1.12 + return 0; 1.13 + } 1.14 + } 1.15 else 1.16 - okay = get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d); 1.17 - 1.18 - if ( likely(okay) ) 1.19 { 1.20 - invalidate_shadow_ldt(v); 1.21 - 1.22 - old_base_mfn = pagetable_get_pfn(v->arch.guest_table); 1.23 - v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT); 1.24 - update_pagetables(v); /* update shadow_table and monitor_table */ 1.25 - 1.26 - write_ptbase(v); 1.27 - 1.28 + okay = get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d); 1.29 + if ( unlikely(!okay) ) 1.30 + { 1.31 + /* Switch to idle pagetable: this VCPU has no active p.t. now. */ 1.32 + old_base_mfn = pagetable_get_pfn(v->arch.guest_table); 1.33 + v->arch.guest_table = mk_pagetable(0); 1.34 + update_pagetables(v); 1.35 + write_cr3(__pa(idle_pg_table)); 1.36 + if ( old_base_mfn != 0 ) 1.37 + put_page_and_type(mfn_to_page(old_base_mfn)); 1.38 + 1.39 + /* Retry the validation with no active p.t. for this VCPU. */ 1.40 + okay = get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d); 1.41 + if ( !okay ) 1.42 + { 1.43 + /* Failure here is unrecoverable: the VCPU has no pagetable! */ 1.44 + MEM_LOG("Fatal error while installing new baseptr %lx", mfn); 1.45 + domain_crash(d); 1.46 + percpu_info[v->processor].deferred_ops = 0; 1.47 + return 0; 1.48 + } 1.49 + } 1.50 + } 1.51 + 1.52 + invalidate_shadow_ldt(v); 1.53 + 1.54 + old_base_mfn = pagetable_get_pfn(v->arch.guest_table); 1.55 + v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT); 1.56 + update_pagetables(v); /* update shadow_table and monitor_table */ 1.57 + 1.58 + write_ptbase(v); 1.59 + 1.60 + if ( likely(old_base_mfn != 0) ) 1.61 + { 1.62 if ( shadow_mode_refcounts(d) ) 1.63 put_page(mfn_to_page(old_base_mfn)); 1.64 else 1.65 put_page_and_type(mfn_to_page(old_base_mfn)); 1.66 - 1.67 - /* CR3 also holds a ref to its shadow... */ 1.68 - if ( shadow_mode_enabled(d) ) 1.69 - { 1.70 - if ( v->arch.monitor_shadow_ref ) 1.71 - put_shadow_ref(v->arch.monitor_shadow_ref); 1.72 - v->arch.monitor_shadow_ref = 1.73 - pagetable_get_pfn(v->arch.monitor_table); 1.74 - ASSERT(!page_get_owner(mfn_to_page(v->arch.monitor_shadow_ref))); 1.75 - get_shadow_ref(v->arch.monitor_shadow_ref); 1.76 - } 1.77 } 1.78 - else 1.79 + 1.80 + /* CR3 also holds a ref to its shadow... */ 1.81 + if ( shadow_mode_enabled(d) ) 1.82 { 1.83 - MEM_LOG("Error while installing new baseptr %lx", mfn); 1.84 + if ( v->arch.monitor_shadow_ref ) 1.85 + put_shadow_ref(v->arch.monitor_shadow_ref); 1.86 + v->arch.monitor_shadow_ref = 1.87 + pagetable_get_pfn(v->arch.monitor_table); 1.88 + ASSERT(!page_get_owner(mfn_to_page(v->arch.monitor_shadow_ref))); 1.89 + get_shadow_ref(v->arch.monitor_shadow_ref); 1.90 } 1.91 1.92 - return okay; 1.93 + return 1; 1.94 } 1.95 1.96 static void process_deferred_ops(unsigned int cpu) 1.97 @@ -1625,7 +1651,7 @@ static void process_deferred_ops(unsigne 1.98 else 1.99 local_flush_tlb(); 1.100 } 1.101 - 1.102 + 1.103 if ( deferred_ops & DOP_RELOAD_LDT ) 1.104 (void)map_ldt_shadow_page(0); 1.105