direct-io.hg

changeset 4265:3cd8c263b94e

bitkeeper revision 1.1254 (42405db8CeBSiHgkIfnk7WeA9Pvjmw)

HL2's are now filled in on demand, rather than by doing the entire thing
on creation. Also fixed a bug in hl2 ref counting. hl2 entries don't
take a writable ref to the guest pages, as they are xen mappings, not
guest mappings. Also fixed a tlb flushing bug with hl2 entries.

Bug fix for shadow table ref counting. CR3's shadow table could, in theory,
get released while it's still pointing at it. Fixed.

Bug fix for shadow code with tlb flushes from hypervisor calls.

Signed-off-by: michael.fetterman@cl.cam.ac.uk
author mafetter@fleming.research
date Tue Mar 22 18:02:32 2005 +0000 (2005-03-22)
parents c54f46498d74
children 7613b44cc5e6
files xen/arch/x86/audit.c xen/arch/x86/mm.c xen/arch/x86/shadow.c xen/include/asm-x86/domain.h xen/include/asm-x86/shadow.h xen/include/xen/perfc_defn.h
line diff
     1.1 --- a/xen/arch/x86/audit.c	Mon Mar 21 23:42:54 2005 +0000
     1.2 +++ b/xen/arch/x86/audit.c	Tue Mar 22 18:02:32 2005 +0000
     1.3 @@ -411,6 +411,8 @@ int audit_adjust_pgtables(struct domain 
     1.4                      if ( pagetable_val(ed->arch.shadow_table) )
     1.5                          adjust(&frame_table[pagetable_val(ed->arch.shadow_table)
     1.6                                              >> PAGE_SHIFT], 0);
     1.7 +                    if ( ed->arch.monitor_shadow_ref )
     1.8 +                        adjust(&frame_table[ed->arch.monitor_shadow_ref], 0);
     1.9                  }
    1.10              }
    1.11      }
     2.1 --- a/xen/arch/x86/mm.c	Mon Mar 21 23:42:54 2005 +0000
     2.2 +++ b/xen/arch/x86/mm.c	Tue Mar 22 18:02:32 2005 +0000
     2.3 @@ -1271,6 +1271,18 @@ int new_guest_cr3(unsigned long mfn)
     2.4              put_page(&frame_table[old_base_mfn]);
     2.5          else
     2.6              put_page_and_type(&frame_table[old_base_mfn]);
     2.7 +
     2.8 +        // CR3 holds its own ref to its shadow...
     2.9 +        //
    2.10 +        if ( shadow_mode_enabled(d) )
    2.11 +        {
    2.12 +            if ( ed->arch.monitor_shadow_ref )
    2.13 +                put_shadow_ref(ed->arch.monitor_shadow_ref);
    2.14 +            ed->arch.monitor_shadow_ref =
    2.15 +                pagetable_val(ed->arch.monitor_table) >> PAGE_SHIFT;
    2.16 +            ASSERT(page_get_owner(&frame_table[ed->arch.monitor_shadow_ref]) == NULL);
    2.17 +            get_shadow_ref(ed->arch.monitor_shadow_ref);
    2.18 +        }
    2.19      }
    2.20      else
    2.21      {
    2.22 @@ -1386,9 +1398,9 @@ static int do_extended_command(unsigned 
    2.23          break;
    2.24      
    2.25      case MMUEXT_INVLPG:
    2.26 -        __flush_tlb_one(ptr);
    2.27          if ( shadow_mode_enabled(d) )
    2.28              shadow_invlpg(ed, ptr);
    2.29 +        __flush_tlb_one(ptr);
    2.30          break;
    2.31  
    2.32      case MMUEXT_FLUSH_CACHE:
    2.33 @@ -1940,9 +1952,9 @@ int do_mmu_update(
    2.34  
    2.35      if ( deferred_ops & DOP_FLUSH_TLB )
    2.36      {
    2.37 -        local_flush_tlb();
    2.38          if ( shadow_mode_enabled(d) )
    2.39              shadow_sync_all(d);
    2.40 +        local_flush_tlb();
    2.41      }
    2.42          
    2.43      if ( deferred_ops & DOP_RELOAD_LDT )
    2.44 @@ -2072,15 +2084,15 @@ int do_update_va_mapping(unsigned long v
    2.45      if ( unlikely(deferred_ops & DOP_FLUSH_TLB) || 
    2.46           unlikely(flags & UVMF_FLUSH_TLB) )
    2.47      {
    2.48 -        local_flush_tlb();
    2.49          if ( unlikely(shadow_mode_enabled(d)) )
    2.50              shadow_sync_all(d);
    2.51 +        local_flush_tlb();
    2.52      }
    2.53      else if ( unlikely(flags & UVMF_INVLPG) )
    2.54      {
    2.55 -        __flush_tlb_one(va);
    2.56          if ( unlikely(shadow_mode_enabled(d)) )
    2.57              shadow_invlpg(current, va);
    2.58 +        __flush_tlb_one(va);
    2.59      }
    2.60  
    2.61      if ( unlikely(deferred_ops & DOP_RELOAD_LDT) )
     3.1 --- a/xen/arch/x86/shadow.c	Mon Mar 21 23:42:54 2005 +0000
     3.2 +++ b/xen/arch/x86/shadow.c	Tue Mar 22 18:02:32 2005 +0000
     3.3 @@ -62,10 +62,14 @@ shadow_promote(struct domain *d, unsigne
     3.4      if ( unlikely(page_is_page_table(page)) )
     3.5          return 1;
     3.6  
     3.7 -    FSH_LOG("shadow_promote gpfn=%p gmfn=%p nt=%p", gpfn, gmfn, new_type);
     3.8 +    FSH_LOG("%s: gpfn=%p gmfn=%p nt=%p", __func__, gpfn, gmfn, new_type);
     3.9  
    3.10      if ( !shadow_remove_all_write_access(d, gpfn, gmfn) )
    3.11 +    {
    3.12 +        FSH_LOG("%s: couldn't find/remove all write accesses, gpfn=%p gmfn=%p\n",
    3.13 +                __func__, gpfn, gmfn);
    3.14          return 0;
    3.15 +    }
    3.16  
    3.17      // To convert this page to use as a page table, the writable count
    3.18      // should now be zero.  Test this by grabbing the page as an page table,
    3.19 @@ -1236,8 +1240,7 @@ shadow_hl2_table(struct domain *d, unsig
    3.20  {
    3.21      unsigned long hl2mfn;
    3.22      l1_pgentry_t *hl2;
    3.23 -    l2_pgentry_t *gl2;
    3.24 -    int i, limit;
    3.25 +    int limit;
    3.26  
    3.27      ASSERT(PGT_base_page_table == PGT_l2_page_table);
    3.28  
    3.29 @@ -1249,7 +1252,6 @@ shadow_hl2_table(struct domain *d, unsig
    3.30  
    3.31      perfc_incrc(shadow_hl2_table_count);
    3.32  
    3.33 -    gl2 = map_domain_mem(gmfn << PAGE_SHIFT);
    3.34      hl2 = map_domain_mem(hl2mfn << PAGE_SHIFT);
    3.35  
    3.36      if ( shadow_mode_external(d) )
    3.37 @@ -1257,19 +1259,7 @@ shadow_hl2_table(struct domain *d, unsig
    3.38      else
    3.39          limit = DOMAIN_ENTRIES_PER_L2_PAGETABLE;
    3.40  
    3.41 -    for ( i = 0; i < limit; i++ )
    3.42 -    {
    3.43 -        unsigned long gl2e = l2_pgentry_val(gl2[i]);
    3.44 -        unsigned long hl2e;
    3.45 -
    3.46 -        hl2e_propagate_from_guest(d, gl2e, &hl2e);
    3.47 -
    3.48 -        if ( (hl2e & _PAGE_PRESENT) &&
    3.49 -             !get_page(pfn_to_page(hl2e >> PAGE_SHIFT), d) )
    3.50 -            hl2e = 0;
    3.51 -
    3.52 -        hl2[i] = mk_l1_pgentry(hl2e);
    3.53 -    }
    3.54 +    memset(hl2, 0, limit * sizeof(l1_pgentry_t));
    3.55  
    3.56      if ( !shadow_mode_external(d) )
    3.57      {
    3.58 @@ -1287,7 +1277,6 @@ shadow_hl2_table(struct domain *d, unsig
    3.59      }
    3.60  
    3.61      unmap_domain_mem(hl2);
    3.62 -    unmap_domain_mem(gl2);
    3.63  
    3.64      return hl2mfn;
    3.65  }
     4.1 --- a/xen/include/asm-x86/domain.h	Mon Mar 21 23:42:54 2005 +0000
     4.2 +++ b/xen/include/asm-x86/domain.h	Tue Mar 22 18:02:32 2005 +0000
     4.3 @@ -122,6 +122,8 @@ struct arch_exec_domain
     4.4      l2_pgentry_t *monitor_vtable;		/* virtual address of monitor_table */
     4.5      l1_pgentry_t *hl2_vtable;			/* virtual address of hl2_table */
     4.6  
     4.7 +    unsigned long monitor_shadow_ref;
     4.8 +
     4.9      /* Virtual CR2 value. Can be read/written by guest. */
    4.10      unsigned long guest_cr2;
    4.11  
     5.1 --- a/xen/include/asm-x86/shadow.h	Mon Mar 21 23:42:54 2005 +0000
     5.2 +++ b/xen/include/asm-x86/shadow.h	Tue Mar 22 18:02:32 2005 +0000
     5.3 @@ -67,6 +67,7 @@ extern int set_p2m_entry(
     5.4  
     5.5  static inline unsigned long __shadow_status(
     5.6      struct domain *d, unsigned long gpfn, unsigned long stype);
     5.7 +static inline void update_hl2e(struct exec_domain *ed, unsigned long va);
     5.8  
     5.9  extern void vmx_shadow_clear_state(struct domain *);
    5.10  
    5.11 @@ -121,6 +122,11 @@ static void inline
    5.12          //
    5.13          __shadow_sync_all(ed->domain);
    5.14      }
    5.15 +
    5.16 +    // Also make sure the HL2 is up-to-date for this address.
    5.17 +    //
    5.18 +    if ( unlikely(shadow_mode_translate(ed->domain)) )
    5.19 +        update_hl2e(ed, va);
    5.20  }
    5.21  
    5.22  static void inline
    5.23 @@ -314,34 +320,58 @@ static inline void
    5.24  __guest_set_l2e(
    5.25      struct exec_domain *ed, unsigned long va, unsigned long value)
    5.26  {
    5.27 +    ed->arch.guest_vtable[l2_table_offset(va)] = mk_l2_pgentry(value);
    5.28 +
    5.29      if ( unlikely(shadow_mode_translate(ed->domain)) )
    5.30 -    {
    5.31 -        unsigned long mfn = phys_to_machine_mapping(value >> PAGE_SHIFT);
    5.32 -        unsigned long old_hl2e =
    5.33 -            l1_pgentry_val(ed->arch.hl2_vtable[l2_table_offset(va)]);
    5.34 -        unsigned long new_hl2e =
    5.35 -            (VALID_MFN(mfn) ? ((mfn << PAGE_SHIFT) | __PAGE_HYPERVISOR) : 0);
    5.36 +        update_hl2e(ed, va);
    5.37 +}
    5.38 +
    5.39 +static inline void
    5.40 +update_hl2e(struct exec_domain *ed, unsigned long va)
    5.41 +{
    5.42 +    int index = l2_table_offset(va);
    5.43 +    unsigned long gl2e = l2_pgentry_val(ed->arch.guest_vtable[index]);
    5.44 +    unsigned long mfn;
    5.45 +    unsigned long old_hl2e, new_hl2e;
    5.46 +    int need_flush = 0;
    5.47 +
    5.48 +    ASSERT(shadow_mode_translate(ed->domain));
    5.49 +
    5.50 +    old_hl2e = l1_pgentry_val(ed->arch.hl2_vtable[index]);
    5.51  
    5.52 -        // only do the ref counting if something important changed.
    5.53 -        //
    5.54 -        if ( (old_hl2e ^ new_hl2e) & (PAGE_MASK | _PAGE_PRESENT) )
    5.55 +    if ( (gl2e & _PAGE_PRESENT) &&
    5.56 +         VALID_MFN(mfn = phys_to_machine_mapping(gl2e >> PAGE_SHIFT)) )
    5.57 +        new_hl2e = (mfn << PAGE_SHIFT) | __PAGE_HYPERVISOR;
    5.58 +    else
    5.59 +        new_hl2e = 0;
    5.60 +
    5.61 +    // only do the ref counting if something important changed.
    5.62 +    //
    5.63 +    if ( (old_hl2e ^ new_hl2e) & (PAGE_MASK | _PAGE_PRESENT) )
    5.64 +    {
    5.65 +        if ( (new_hl2e & _PAGE_PRESENT) &&
    5.66 +             !get_page(pfn_to_page(new_hl2e >> PAGE_SHIFT), ed->domain) )
    5.67 +            new_hl2e = 0;
    5.68 +        if ( old_hl2e & _PAGE_PRESENT )
    5.69          {
    5.70 -            if ( (new_hl2e & _PAGE_PRESENT) &&
    5.71 -                 !shadow_get_page_from_l1e(mk_l1_pgentry(new_hl2e), ed->domain) )
    5.72 -                new_hl2e = 0;
    5.73 -            if ( old_hl2e & _PAGE_PRESENT )
    5.74 -                put_page_from_l1e(mk_l1_pgentry(old_hl2e), ed->domain);
    5.75 +            put_page(pfn_to_page(old_hl2e >> PAGE_SHIFT));
    5.76 +            need_flush = 1;
    5.77          }
    5.78 -
    5.79 -        ed->arch.hl2_vtable[l2_table_offset(va)] = mk_l1_pgentry(new_hl2e);
    5.80      }
    5.81  
    5.82 -    ed->arch.guest_vtable[l2_table_offset(va)] = mk_l2_pgentry(value);
    5.83 +    ed->arch.hl2_vtable[l2_table_offset(va)] = mk_l1_pgentry(new_hl2e);
    5.84 +
    5.85 +    if ( need_flush )
    5.86 +    {
    5.87 +        perfc_incrc(update_hl2e_invlpg);
    5.88 +        __flush_tlb_one(&linear_pg_table[l1_linear_offset(va)]);
    5.89 +    }
    5.90  }
    5.91  
    5.92 +
    5.93  /************************************************************************/
    5.94  
    5.95 -//#define MFN3_TO_WATCH 0x1ff6e
    5.96 +//#define MFN3_TO_WATCH 0x8575
    5.97  #ifdef MFN3_TO_WATCH
    5.98  #define get_shadow_ref(__s) (                                                 \
    5.99  {                                                                             \
     6.1 --- a/xen/include/xen/perfc_defn.h	Mon Mar 21 23:42:54 2005 +0000
     6.2 +++ b/xen/include/xen/perfc_defn.h	Tue Mar 22 18:02:32 2005 +0000
     6.3 @@ -97,3 +97,4 @@ PERFCOUNTER_CPU(remove_write_predicted, 
     6.4  PERFCOUNTER_CPU(remove_write_bad_prediction,       "remove_write bad prediction")
     6.5  PERFCOUNTER_CPU(write_fault_bail,                  "sf bailed due to write_fault")
     6.6  PERFCOUNTER_CPU(read_fault_bail,                   "sf bailed due to read_fault")
     6.7 +PERFCOUNTER_CPU(update_hl2e_invlpg,                 "update_hl2e calls invlpg")