ia64/xen-unstable

changeset 4172:d617bb4a2907

bitkeeper revision 1.1236.32.9 (42378931ytaSYjOpR6-Ss599yO6Zjg)

Added unshadowing of L2s that contain entries which are both
not present and non-zero. This is a hack, but ought to work OK
for linux domains.

Signed-off-by: michael.fetterman@cl.cam.ac.uk
author mafetter@fleming.research
date Wed Mar 16 01:17:37 2005 +0000 (2005-03-16)
parents e40b961673f2
children 8f0c441d9e25 e38db244d654
files xen/arch/x86/shadow.c xen/include/asm-x86/shadow.h xen/include/xen/perfc_defn.h
line diff
     1.1 --- a/xen/arch/x86/shadow.c	Wed Mar 16 01:14:39 2005 +0000
     1.2 +++ b/xen/arch/x86/shadow.c	Wed Mar 16 01:17:37 2005 +0000
     1.3 @@ -299,8 +299,6 @@ free_shadow_hl2_table(struct domain *d, 
     1.4  static void inline
     1.5  free_shadow_l2_table(struct domain *d, unsigned long smfn)
     1.6  {
     1.7 -    printk("free_shadow_l2_table(smfn=%p)\n", smfn);
     1.8 -
     1.9      unsigned long *pl2e = map_domain_mem(smfn << PAGE_SHIFT);
    1.10      int i, external = shadow_mode_external(d);
    1.11  
    1.12 @@ -1666,6 +1664,7 @@ static int resync_all(struct domain *d, 
    1.13      unsigned long smfn;
    1.14      unsigned long *guest, *shadow, *snapshot;
    1.15      int need_flush = 0, external = shadow_mode_external(d);
    1.16 +    int unshadow;
    1.17  
    1.18      ASSERT(spin_is_locked(&d->arch.shadow_lock));
    1.19  
    1.20 @@ -1686,6 +1685,7 @@ static int resync_all(struct domain *d, 
    1.21          guest    = map_domain_mem(entry->gmfn         << PAGE_SHIFT);
    1.22          snapshot = map_domain_mem(entry->snapshot_mfn << PAGE_SHIFT);
    1.23          shadow   = map_domain_mem(smfn                << PAGE_SHIFT);
    1.24 +        unshadow = 0;
    1.25  
    1.26          switch ( stype ) {
    1.27          case PGT_l1_shadow:
    1.28 @@ -1719,6 +1719,16 @@ static int resync_all(struct domain *d, 
    1.29                      //
    1.30                      // snapshot[i] = new_pde;
    1.31                  }
    1.32 +
    1.33 +                // XXX - This hack works for linux guests.
    1.34 +                //       Need a better solution long term.
    1.35 +                if ( !(new_pde & _PAGE_PRESENT) && unlikely(new_pde != 0) &&
    1.36 +                     (frame_table[smfn].u.inuse.type_info & PGT_pinned) &&
    1.37 +                     !unshadow )
    1.38 +                {
    1.39 +                    perfc_incrc(unshadow_l2_count);
    1.40 +                    unshadow = 1;
    1.41 +                }
    1.42              }
    1.43              break;
    1.44          default:
    1.45 @@ -1729,6 +1739,9 @@ static int resync_all(struct domain *d, 
    1.46          unmap_domain_mem(shadow);
    1.47          unmap_domain_mem(snapshot);
    1.48          unmap_domain_mem(guest);
    1.49 +
    1.50 +        if ( unlikely(unshadow) )
    1.51 +            shadow_unpin(smfn);
    1.52      }
    1.53  
    1.54      return need_flush;
    1.55 @@ -1919,7 +1932,7 @@ void __update_pagetables(struct exec_dom
    1.56      struct domain *d = ed->domain;
    1.57      unsigned long gmfn = pagetable_val(ed->arch.guest_table) >> PAGE_SHIFT;
    1.58      unsigned long gpfn = __mfn_to_gpfn(d, gmfn);
    1.59 -    unsigned long smfn, hl2mfn;
    1.60 +    unsigned long smfn, hl2mfn, old_smfn;
    1.61  
    1.62      int max_mode = ( shadow_mode_external(d) ? SHM_external
    1.63                       : shadow_mode_translate(d) ? SHM_translate
    1.64 @@ -1946,9 +1959,10 @@ void __update_pagetables(struct exec_dom
    1.65          smfn = shadow_l2_table(d, gpfn, gmfn);
    1.66      if ( !get_shadow_ref(smfn) )
    1.67          BUG();
    1.68 -    if ( pagetable_val(ed->arch.shadow_table) )
    1.69 -        put_shadow_ref(pagetable_val(ed->arch.shadow_table) >> PAGE_SHIFT);
    1.70 +    old_smfn = pagetable_val(ed->arch.shadow_table) >> PAGE_SHIFT;
    1.71      ed->arch.shadow_table = mk_pagetable(smfn << PAGE_SHIFT);
    1.72 +    if ( old_smfn )
    1.73 +        put_shadow_ref(old_smfn);
    1.74  
    1.75      SH_VVLOG("0: __update_pagetables(gmfn=%p, smfn=%p)", gmfn, smfn);
    1.76  
     2.1 --- a/xen/include/asm-x86/shadow.h	Wed Mar 16 01:14:39 2005 +0000
     2.2 +++ b/xen/include/asm-x86/shadow.h	Wed Mar 16 01:17:37 2005 +0000
     2.3 @@ -651,7 +651,7 @@ validate_pte_change(
     2.4  static int inline
     2.5  validate_pde_change(
     2.6      struct domain *d,
     2.7 -    unsigned long new_pde,
     2.8 +    unsigned long new_gpde,
     2.9      unsigned long *shadow_pde_p)
    2.10  {
    2.11      unsigned long old_spde, new_spde;
    2.12 @@ -659,11 +659,12 @@ validate_pde_change(
    2.13      perfc_incrc(validate_pde_calls);
    2.14  
    2.15      old_spde = *shadow_pde_p;
    2.16 -    l2pde_propagate_from_guest(d, &new_pde, &new_spde);
    2.17 +    l2pde_propagate_from_guest(d, &new_gpde, &new_spde);
    2.18  
    2.19 -    // XXX Shouldn't we supposed to propagate the new_pde to the guest?
    2.20 +    // XXX Shouldn't we propagate the new_gpde to the guest?
    2.21 +    // And then mark the guest's L2 page as dirty?
    2.22  
    2.23 -    // only do the ref counting if something important changed.
    2.24 +    // Only do the ref counting if something important changed.
    2.25      //
    2.26      if ( ((old_spde | new_spde) & _PAGE_PRESENT) &&
    2.27           ((old_spde ^ new_spde) & (PAGE_MASK | _PAGE_PRESENT)) )
     3.1 --- a/xen/include/xen/perfc_defn.h	Wed Mar 16 01:14:39 2005 +0000
     3.2 +++ b/xen/include/xen/perfc_defn.h	Wed Mar 16 01:17:37 2005 +0000
     3.3 @@ -30,6 +30,7 @@ PERFCOUNTER_CPU( shadow_set_l1e_force_ma
     3.4  PERFCOUNTER_CPU( shadow_set_l1e_unlinked,  "shadow_set_l1e found unlinked l1" )
     3.5  PERFCOUNTER_CPU( shadow_set_l1e_fail,      "shadow_set_l1e failed (no sl1)" )
     3.6  PERFCOUNTER_CPU( shadow_invlpg_faults,     "shadow_invlpg's get_user faulted")
     3.7 +PERFCOUNTER_CPU( unshadow_l2_count,        "unpinned L2 count")
     3.8  
     3.9  
    3.10  /* STATUS counters do not reset when 'P' is hit */