ia64/xen-unstable

changeset 1841:88dcad78fd75

bitkeeper revision 1.1111 (40fd082b9NbHJ_AQDN4a4rgH9Uyztg)

cleanup writable pagetable code
author cl349@freefall.cl.cam.ac.uk
date Tue Jul 20 11:55:23 2004 +0000 (2004-07-20)
parents 8dd08ab8931c
children bde2c59c2519
files xen/arch/x86/memory.c xen/arch/x86/traps.c xen/include/asm-x86/mm.h
line diff
     1.1 --- a/xen/arch/x86/memory.c	Mon Jul 19 10:54:16 2004 +0000
     1.2 +++ b/xen/arch/x86/memory.c	Tue Jul 20 11:55:23 2004 +0000
     1.3 @@ -1,7 +1,3 @@
     1.4 -extern unsigned long disconnected;
     1.5 -extern void ptwr_reconnect(unsigned long);
     1.6 -extern int writable_idx;
     1.7 -extern void ptwr_flush(void);
     1.8  /******************************************************************************
     1.9   * arch/x86/memory.c
    1.10   * 
    1.11 @@ -121,7 +117,7 @@ static int get_page_and_type_from_pagenr
    1.12  static void free_l2_table(struct pfn_info *page);
    1.13  static void free_l1_table(struct pfn_info *page);
    1.14  
    1.15 -int mod_l2_entry(l2_pgentry_t *, l2_pgentry_t, unsigned long);
    1.16 +static int mod_l2_entry(l2_pgentry_t *, l2_pgentry_t, unsigned long);
    1.17  static int mod_l1_entry(l1_pgentry_t *, l1_pgentry_t);
    1.18  
    1.19  /* Used to defer flushing of memory structures. */
    1.20 @@ -524,9 +520,8 @@ static inline void set_l1_page_va(unsign
    1.21  }
    1.22  
    1.23  
    1.24 -#define NPRINTK if (0) printk
    1.25  /* Update the L2 entry at pl2e to new value nl2e. pl2e is within frame pfn. */
    1.26 -int mod_l2_entry(l2_pgentry_t *pl2e, 
    1.27 +static int mod_l2_entry(l2_pgentry_t *pl2e, 
    1.28                          l2_pgentry_t nl2e, 
    1.29                          unsigned long pfn)
    1.30  {
    1.31 @@ -544,8 +539,6 @@ int mod_l2_entry(l2_pgentry_t *pl2e,
    1.32          return 0;
    1.33      ol2e = mk_l2_pgentry(_ol2e);
    1.34  
    1.35 -    NPRINTK("mod_l2_entry pl2e %p ol2e %08lx nl2e %08lx pfn %08lx\n",
    1.36 -            pl2e, l2_pgentry_val(ol2e), l2_pgentry_val(nl2e), pfn);
    1.37      if ( l2_pgentry_val(nl2e) & _PAGE_PRESENT )
    1.38      {
    1.39          /* Differ in mapping (bits 12-31) or presence (bit 0)? */
    1.40 @@ -719,10 +712,7 @@ static int do_extended_command(unsigned 
    1.41      u32 x, y;
    1.42      domid_t domid;
    1.43  
    1.44 -    if (disconnected != ENTRIES_PER_L2_PAGETABLE)
    1.45 -        ptwr_reconnect(0L);
    1.46 -    if (writable_idx)
    1.47 -        ptwr_flush();
    1.48 +    cleanup_writable_pagetable(PTRW_CLEANUP_ACTIVE | PTRW_CLEANUP_INACTIVE);
    1.49  
    1.50      switch ( cmd )
    1.51      {
    1.52 @@ -972,10 +962,7 @@ int do_mmu_update(mmu_update_t *ureqs, i
    1.53      perfc_incrc(calls_to_mmu_update); 
    1.54      perfc_addc(num_page_updates, count);
    1.55  
    1.56 -    if (disconnected != ENTRIES_PER_L2_PAGETABLE)
    1.57 -        ptwr_reconnect(0L);
    1.58 -    if (writable_idx)
    1.59 -        ptwr_flush();
    1.60 +    cleanup_writable_pagetable(PTRW_CLEANUP_ACTIVE | PTRW_CLEANUP_INACTIVE);
    1.61  
    1.62      for ( i = 0; i < count; i++ )
    1.63      {
    1.64 @@ -1150,14 +1137,11 @@ int do_update_va_mapping(unsigned long p
    1.65  
    1.66      perfc_incrc(calls_to_update_va);
    1.67  
    1.68 -    if (disconnected != ENTRIES_PER_L2_PAGETABLE)
    1.69 -        ptwr_reconnect(0L);
    1.70 -    if (writable_idx)
    1.71 -        ptwr_flush();
    1.72 -
    1.73      if ( unlikely(page_nr >= (HYPERVISOR_VIRT_START >> PAGE_SHIFT)) )
    1.74          return -EINVAL;
    1.75  
    1.76 +    cleanup_writable_pagetable(PTRW_CLEANUP_ACTIVE | PTRW_CLEANUP_INACTIVE);
    1.77 +
    1.78      /*
    1.79       * XXX When we make this support 4MB superpages we should also deal with 
    1.80       * the case of updating L2 entries.
    1.81 @@ -1221,6 +1205,8 @@ int do_update_va_mapping_otherdomain(uns
    1.82      if ( unlikely(!IS_PRIV(current)) )
    1.83          return -EPERM;
    1.84  
    1.85 +    cleanup_writable_pagetable(PTRW_CLEANUP_ACTIVE | PTRW_CLEANUP_INACTIVE);
    1.86 +
    1.87      percpu_info[cpu].gps = d = find_domain_by_id(domid);
    1.88      if ( unlikely(d == NULL) )
    1.89      {
    1.90 @@ -1235,3 +1221,151 @@ int do_update_va_mapping_otherdomain(uns
    1.91  
    1.92      return rc;
    1.93  }
    1.94 +
    1.95 +
    1.96 +/*  */
    1.97 +unsigned long ptwr_disconnected = ENTRIES_PER_L2_PAGETABLE;
    1.98 +static unsigned long *ptwr_writable_l1;
    1.99 +#define	PTWR_NR_WRITABLES 4
   1.100 +static unsigned long *ptwr_writables[PTWR_NR_WRITABLES];
   1.101 +int ptwr_writable_idx = 0;
   1.102 +#define PTWR_PRINTK if (0) printk
   1.103 +
   1.104 +void ptwr_reconnect_disconnected(unsigned long addr)
   1.105 +{
   1.106 +    unsigned long pte;
   1.107 +    unsigned long pfn;
   1.108 +    struct pfn_info *page;
   1.109 +    l2_pgentry_t *pl2e;
   1.110 +    PTWR_PRINTK("page fault in disconnected space: addr %08lx space %08lx\n",
   1.111 +                addr, ptwr_disconnected << L2_PAGETABLE_SHIFT);
   1.112 +    pl2e = &linear_l2_table[ptwr_disconnected];
   1.113 +
   1.114 +    if (__get_user(pte, ptwr_writable_l1))
   1.115 +        BUG();
   1.116 +    pfn = pte >> PAGE_SHIFT;
   1.117 +    page = &frame_table[pfn];
   1.118 +
   1.119 +    /* reconnect l1 page */
   1.120 +    PTWR_PRINTK("    pl2e %p l2e %08lx pfn %08lx taf %08x/%08x\n", pl2e,
   1.121 +                l2_pgentry_val(*pl2e),
   1.122 +                l1_pgentry_val(linear_pg_table[(unsigned long)pl2e >>
   1.123 +                                               PAGE_SHIFT]) >> PAGE_SHIFT,
   1.124 +                frame_table[l2_pgentry_to_pagenr(*pl2e)].type_and_flags,
   1.125 +                frame_table[pfn].type_and_flags);
   1.126 +    mod_l2_entry(pl2e, mk_l2_pgentry((l2_pgentry_val(*pl2e) & ~0x800) |
   1.127 +                                     _PAGE_PRESENT),
   1.128 +                 l1_pgentry_val(linear_pg_table[(unsigned long)pl2e >>
   1.129 +                                                PAGE_SHIFT]) >> PAGE_SHIFT);
   1.130 +    PTWR_PRINTK("now pl2e %p l2e %08lx              taf %08x/%08x\n", pl2e,
   1.131 +                l2_pgentry_val(*pl2e),
   1.132 +                frame_table[l2_pgentry_to_pagenr(*pl2e)].type_and_flags,
   1.133 +                frame_table[pfn].type_and_flags);
   1.134 +    ptwr_disconnected = ENTRIES_PER_L2_PAGETABLE;
   1.135 +    /* make pt page write protected */
   1.136 +    if (__get_user(pte, ptwr_writable_l1))
   1.137 +        BUG();
   1.138 +    PTWR_PRINTK("writable_l1 at %p is %08lx\n", ptwr_writable_l1, pte);
   1.139 +    pte &= ~_PAGE_RW;
   1.140 +    if (__put_user(pte, ptwr_writable_l1))
   1.141 +        BUG();
   1.142 +    PTWR_PRINTK("writable_l1 at %p now %08lx\n", ptwr_writable_l1, pte);
   1.143 +    /* and try again */
   1.144 +    return;
   1.145 +}
   1.146 +
   1.147 +void ptwr_flush_inactive(void)
   1.148 +{
   1.149 +    unsigned long pte, pfn;
   1.150 +    struct pfn_info *page;
   1.151 +    int i;
   1.152 +
   1.153 +    for (i = 0; i < ptwr_writable_idx; i++) {
   1.154 +        if (__get_user(pte, ptwr_writables[i]))
   1.155 +            BUG();
   1.156 +        pfn = pte >> PAGE_SHIFT;
   1.157 +        page = &frame_table[pfn];
   1.158 +        PTWR_PRINTK("alloc l1 page %p\n", page);
   1.159 +        if (!get_page_type(page, PGT_l1_page_table))
   1.160 +            BUG();
   1.161 +        /* make pt page writable */
   1.162 +        PTWR_PRINTK("writable_l1 at %p is %08lx\n", ptwr_writables[i], pte);
   1.163 +        pte &= ~_PAGE_RW;
   1.164 +        if (__put_user(pte, ptwr_writables[i]))
   1.165 +            BUG();
   1.166 +        PTWR_PRINTK("writable_l1 at %p now %08lx\n", ptwr_writables[i], pte);
   1.167 +    }
   1.168 +    ptwr_writable_idx = 0;
   1.169 +}
   1.170 +
   1.171 +int ptwr_do_page_fault(unsigned long addr)
   1.172 +{
   1.173 +    /* write page fault, check if we're trying to modify an l1
   1.174 +       page table */
   1.175 +    unsigned long pte, pfn;
   1.176 +    struct pfn_info *page;
   1.177 +    l2_pgentry_t *pl2e;
   1.178 +    PTWR_PRINTK("get user %p for va %08lx\n",
   1.179 +                &linear_pg_table[addr>>PAGE_SHIFT], addr);
   1.180 +    if (l2_pgentry_val(linear_l2_table[addr >> L2_PAGETABLE_SHIFT]) &
   1.181 +        _PAGE_PRESENT &&
   1.182 +        __get_user(pte, (unsigned long *)
   1.183 +                   &linear_pg_table[addr >> PAGE_SHIFT]) == 0) {
   1.184 +        pfn = pte >> PAGE_SHIFT;
   1.185 +        PTWR_PRINTK("check pte %08lx = pfn %08lx for va %08lx\n", pte, pfn,
   1.186 +                    addr);
   1.187 +        page = &frame_table[pfn];
   1.188 +        if ((page->type_and_flags & PGT_type_mask) == PGT_l1_page_table) {
   1.189 +            pl2e = &linear_l2_table[(page->type_and_flags &
   1.190 +                                     PGT_va_mask) >> PGT_va_shift];
   1.191 +            PTWR_PRINTK("page_fault on l1 pt at va %08lx, pt for %08x, pfn %08lx\n",
   1.192 +                        addr, ((page->type_and_flags & PGT_va_mask) >>
   1.193 +                               PGT_va_shift) << L2_PAGETABLE_SHIFT, pfn);
   1.194 +            if (l2_pgentry_val(*pl2e) >> PAGE_SHIFT != pfn) {
   1.195 +                PTWR_PRINTK("freeing l1 page %p\n", page);
   1.196 +                if (ptwr_writable_idx == PTWR_NR_WRITABLES)
   1.197 +                    ptwr_flush_inactive();
   1.198 +                ptwr_writables[ptwr_writable_idx++] = (unsigned long *)
   1.199 +                    &linear_pg_table[addr>>PAGE_SHIFT];
   1.200 +                if ((page->type_and_flags & PGT_count_mask) != 1)
   1.201 +                    BUG();
   1.202 +                put_page_type(page);
   1.203 +            } else {
   1.204 +                if (ptwr_disconnected != ENTRIES_PER_L2_PAGETABLE)
   1.205 +                    ptwr_reconnect_disconnected(addr);
   1.206 +                PTWR_PRINTK("    pl2e %p l2e %08lx pfn %08lx taf %08x/%08x\n",
   1.207 +                       pl2e, l2_pgentry_val(*pl2e),
   1.208 +                       l1_pgentry_val(linear_pg_table[(unsigned long)pl2e
   1.209 +                                                      >> PAGE_SHIFT]) >>
   1.210 +                       PAGE_SHIFT,
   1.211 +                       frame_table[l2_pgentry_to_pagenr(*pl2e)].
   1.212 +                       type_and_flags, frame_table[pfn].type_and_flags);
   1.213 +                /* disconnect l1 page */
   1.214 +                mod_l2_entry(pl2e, mk_l2_pgentry((l2_pgentry_val(*pl2e) &
   1.215 +                                                  ~_PAGE_PRESENT) | 0x800),
   1.216 +                             l1_pgentry_val(linear_pg_table
   1.217 +                                            [(unsigned long)pl2e
   1.218 +                                             >> PAGE_SHIFT]) >>
   1.219 +                             PAGE_SHIFT);
   1.220 +                ptwr_disconnected = (page->type_and_flags & PGT_va_mask) >>
   1.221 +                    PGT_va_shift;
   1.222 +                PTWR_PRINTK("now pl2e %p l2e %08lx              taf %08x/%08x\n",
   1.223 +                       pl2e, l2_pgentry_val(*pl2e),
   1.224 +                       frame_table[l2_pgentry_to_pagenr(*pl2e)].
   1.225 +                       type_and_flags,
   1.226 +                       frame_table[pfn].type_and_flags);
   1.227 +                ptwr_writable_l1 = (unsigned long *)
   1.228 +                    &linear_pg_table[addr>>PAGE_SHIFT];
   1.229 +            }
   1.230 +            /* make pt page writable */
   1.231 +            pte |= _PAGE_RW;
   1.232 +            PTWR_PRINTK("update %p pte to %08lx\n",
   1.233 +                   &linear_pg_table[addr>>PAGE_SHIFT], pte);
   1.234 +            if (__put_user(pte, (unsigned long *)
   1.235 +                           &linear_pg_table[addr>>PAGE_SHIFT]))
   1.236 +                BUG();
   1.237 +            return 1;
   1.238 +        }
   1.239 +    }
   1.240 +    return 0;
   1.241 +}
     2.1 --- a/xen/arch/x86/traps.c	Mon Jul 19 10:54:16 2004 +0000
     2.2 +++ b/xen/arch/x86/traps.c	Tue Jul 20 11:55:23 2004 +0000
     2.3 @@ -301,81 +301,6 @@ asmlinkage void do_double_fault(void)
     2.4      for ( ; ; ) ;
     2.5  }
     2.6  
     2.7 -extern int mod_l2_entry(l2_pgentry_t *, l2_pgentry_t, unsigned long);
     2.8 -unsigned long disconnected = ENTRIES_PER_L2_PAGETABLE;
     2.9 -static unsigned long *writable_l1;
    2.10 -#define	NR_WRITABLES 4
    2.11 -static unsigned long *writables[NR_WRITABLES];
    2.12 -int writable_idx = 0;
    2.13 -#define PRINTK if (0) printk
    2.14 -#define NPRINTK if (0) printk
    2.15 -
    2.16 -void ptwr_reconnect(unsigned long addr)
    2.17 -{
    2.18 -    unsigned long pte;
    2.19 -    unsigned long pfn;
    2.20 -    struct pfn_info *page;
    2.21 -    l2_pgentry_t *pl2e;
    2.22 -    PRINTK("page fault in disconnected space: addr %08lx space %08lx\n",
    2.23 -           addr, disconnected << L2_PAGETABLE_SHIFT);
    2.24 -    pl2e = &linear_l2_table[disconnected];
    2.25 -
    2.26 -    if (__get_user(pte, writable_l1))
    2.27 -        BUG();
    2.28 -    pfn = pte >> PAGE_SHIFT;
    2.29 -    page = &frame_table[pfn];
    2.30 -
    2.31 -    /* reconnect l1 page */
    2.32 -    PRINTK("    pl2e %p l2e %08lx pfn %08lx taf %08x/%08x\n", pl2e,
    2.33 -           l2_pgentry_val(*pl2e),
    2.34 -           l1_pgentry_val(linear_pg_table[(unsigned long)pl2e >>
    2.35 -                                          PAGE_SHIFT]) >> PAGE_SHIFT,
    2.36 -           frame_table[l2_pgentry_to_pagenr(*pl2e)].type_and_flags,
    2.37 -           frame_table[pfn].type_and_flags);
    2.38 -    mod_l2_entry(pl2e, mk_l2_pgentry((l2_pgentry_val(*pl2e) & ~0x800) |
    2.39 -                                     _PAGE_PRESENT),
    2.40 -                 l1_pgentry_val(linear_pg_table[(unsigned long)pl2e >>
    2.41 -                                                PAGE_SHIFT]) >> PAGE_SHIFT);
    2.42 -    PRINTK("now pl2e %p l2e %08lx              taf %08x/%08x\n", pl2e,
    2.43 -           l2_pgentry_val(*pl2e),
    2.44 -           frame_table[l2_pgentry_to_pagenr(*pl2e)].type_and_flags,
    2.45 -           frame_table[pfn].type_and_flags);
    2.46 -    disconnected = ENTRIES_PER_L2_PAGETABLE;
    2.47 -    /* make pt page write protected */
    2.48 -    if (__get_user(pte, writable_l1))
    2.49 -        BUG();
    2.50 -    PRINTK("writable_l1 at %p is %08lx\n", writable_l1, pte);
    2.51 -    pte &= ~_PAGE_RW;
    2.52 -    if (__put_user(pte, writable_l1))
    2.53 -        BUG();
    2.54 -    PRINTK("writable_l1 at %p now %08lx\n", writable_l1, pte);
    2.55 -    /* and try again */
    2.56 -    return;
    2.57 -}
    2.58 -
    2.59 -void ptwr_flush(void)
    2.60 -{
    2.61 -    unsigned long pte, pfn;
    2.62 -    struct pfn_info *page;
    2.63 -    int i;
    2.64 -
    2.65 -    for (i = 0; i < writable_idx; i++) {
    2.66 -        if (__get_user(pte, writables[i]))
    2.67 -            BUG();
    2.68 -        pfn = pte >> PAGE_SHIFT;
    2.69 -        page = &frame_table[pfn];
    2.70 -        PRINTK("alloc l1 page %p\n", page);
    2.71 -        if (!get_page_type(page, PGT_l1_page_table))
    2.72 -            BUG();
    2.73 -        /* make pt page writable */
    2.74 -        PRINTK("writable_l1 at %p is %08lx\n", writables[i], pte);
    2.75 -        pte &= ~_PAGE_RW;
    2.76 -        if (__put_user(pte, writables[i]))
    2.77 -            BUG();
    2.78 -        PRINTK("writable_l1 at %p now %08lx\n", writables[i], pte);
    2.79 -    }
    2.80 -    writable_idx = 0;
    2.81 -}
    2.82  
    2.83  asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
    2.84  {
    2.85 @@ -402,79 +327,13 @@ asmlinkage void do_page_fault(struct pt_
    2.86              return; /* successfully copied the mapping */
    2.87      }
    2.88  
    2.89 -    if ((addr >> L2_PAGETABLE_SHIFT) == disconnected) {
    2.90 -        ptwr_reconnect(addr);
    2.91 +    if ((addr >> L2_PAGETABLE_SHIFT) == ptwr_disconnected) {
    2.92 +        ptwr_reconnect_disconnected(addr);
    2.93          return;
    2.94      }
    2.95  
    2.96 -    if (addr < PAGE_OFFSET && error_code & 2) {
    2.97 -        /* write page fault, check if we're trying to modify an l1
    2.98 -           page table */
    2.99 -        unsigned long pte, pfn;
   2.100 -        struct pfn_info *page;
   2.101 -        l2_pgentry_t *pl2e;
   2.102 -        NPRINTK("get user %p for va %08lx\n",
   2.103 -                &linear_pg_table[addr>>PAGE_SHIFT], addr);
   2.104 -        if (l2_pgentry_val(linear_l2_table[addr >> L2_PAGETABLE_SHIFT]) &
   2.105 -            _PAGE_PRESENT &&
   2.106 -            __get_user(pte, (unsigned long *)
   2.107 -                       &linear_pg_table[addr >> PAGE_SHIFT]) == 0) {
   2.108 -            pfn = pte >> PAGE_SHIFT;
   2.109 -            NPRINTK("check pte %08lx = pfn %08lx for va %08lx\n", pte, pfn, addr);
   2.110 -            page = &frame_table[pfn];
   2.111 -            if ((page->type_and_flags & PGT_type_mask) == PGT_l1_page_table) {
   2.112 -                pl2e = &linear_l2_table[(page->type_and_flags &
   2.113 -                                         PGT_va_mask) >> PGT_va_shift];
   2.114 -                PRINTK("page_fault on l1 pt at va %08lx, pt for %08x, pfn %08lx\n",
   2.115 -                       addr, ((page->type_and_flags & PGT_va_mask) >>
   2.116 -                              PGT_va_shift) << L2_PAGETABLE_SHIFT, pfn);
   2.117 -                if (l2_pgentry_val(*pl2e) >> PAGE_SHIFT != pfn) {
   2.118 -                    PRINTK("freeing l1 page %p\n", page);
   2.119 -                    if (writable_idx == NR_WRITABLES)
   2.120 -                        ptwr_flush();
   2.121 -                    writables[writable_idx++] = (unsigned long *)
   2.122 -                        &linear_pg_table[addr>>PAGE_SHIFT];
   2.123 -                    if ((page->type_and_flags & PGT_count_mask) != 1)
   2.124 -                        BUG();
   2.125 -                    put_page_type(page);
   2.126 -                } else {
   2.127 -                    if (disconnected != ENTRIES_PER_L2_PAGETABLE)
   2.128 -                        ptwr_reconnect(addr);
   2.129 -                    PRINTK("    pl2e %p l2e %08lx pfn %08lx taf %08x/%08x\n",
   2.130 -                           pl2e, l2_pgentry_val(*pl2e),
   2.131 -                           l1_pgentry_val(linear_pg_table[(unsigned long)pl2e
   2.132 -                                                          >> PAGE_SHIFT]) >>
   2.133 -                           PAGE_SHIFT,
   2.134 -                           frame_table[l2_pgentry_to_pagenr(*pl2e)].
   2.135 -                           type_and_flags, frame_table[pfn].type_and_flags);
   2.136 -                    /* disconnect l1 page */
   2.137 -                    mod_l2_entry(pl2e, mk_l2_pgentry((l2_pgentry_val(*pl2e) &
   2.138 -                                                      ~_PAGE_PRESENT) | 0x800),
   2.139 -                                 l1_pgentry_val(linear_pg_table
   2.140 -                                                [(unsigned long)pl2e
   2.141 -                                                 >> PAGE_SHIFT]) >>
   2.142 -                                 PAGE_SHIFT);
   2.143 -                    disconnected = (page->type_and_flags & PGT_va_mask) >>
   2.144 -                        PGT_va_shift;
   2.145 -                    PRINTK("now pl2e %p l2e %08lx              taf %08x/%08x\n",
   2.146 -                           pl2e, l2_pgentry_val(*pl2e),
   2.147 -                           frame_table[l2_pgentry_to_pagenr(*pl2e)].
   2.148 -                           type_and_flags,
   2.149 -                           frame_table[pfn].type_and_flags);
   2.150 -                    writable_l1 = (unsigned long *)
   2.151 -                        &linear_pg_table[addr>>PAGE_SHIFT];
   2.152 -                }
   2.153 -                /* make pt page writable */
   2.154 -                pte |= _PAGE_RW;
   2.155 -                PRINTK("update %p pte to %08lx\n",
   2.156 -                        &linear_pg_table[addr>>PAGE_SHIFT], pte);
   2.157 -                if (__put_user(pte, (unsigned long *)
   2.158 -                               &linear_pg_table[addr>>PAGE_SHIFT]))
   2.159 -                    BUG();
   2.160 -                return;
   2.161 -            }
   2.162 -        }
   2.163 -    }
   2.164 +    if (addr < PAGE_OFFSET && error_code & 2 && ptwr_do_page_fault(addr))
   2.165 +        return;
   2.166  
   2.167      if ( unlikely(p->mm.shadow_mode) && 
   2.168           (addr < PAGE_OFFSET) && shadow_fault(addr, error_code) )
     3.1 --- a/xen/include/asm-x86/mm.h	Mon Jul 19 10:54:16 2004 +0000
     3.2 +++ b/xen/include/asm-x86/mm.h	Tue Jul 20 11:55:23 2004 +0000
     3.3 @@ -316,4 +316,24 @@ int memguard_is_guarded(void *p);
     3.4  #define memguard_is_guarded(_p)        (0)
     3.5  #endif
     3.6  
     3.7 +/*  */
     3.8 +extern unsigned long ptwr_disconnected;
     3.9 +extern int ptwr_writable_idx;
    3.10 +void ptwr_reconnect_disconnected(unsigned long addr);
    3.11 +void ptwr_flush_inactive(void);
    3.12 +int ptwr_do_page_fault(unsigned long);
    3.13 +
    3.14 +#define PTRW_CLEANUP_ACTIVE	1
    3.15 +#define PTRW_CLEANUP_INACTIVE	2
    3.16 +
    3.17 +static inline void cleanup_writable_pagetable(const int what)
    3.18 +{
    3.19 +    if (what & PTRW_CLEANUP_ACTIVE)
    3.20 +        if (ptwr_disconnected != ENTRIES_PER_L2_PAGETABLE)
    3.21 +            ptwr_reconnect_disconnected(0L);
    3.22 +    if (what & PTRW_CLEANUP_INACTIVE)
    3.23 +        if (ptwr_writable_idx)
    3.24 +            ptwr_flush_inactive();
    3.25 +}
    3.26 +
    3.27  #endif /* __ASM_X86_MM_H__ */