]> xenbits.xensource.com Git - legacy/linux-2.6.18-xen.git/commitdiff
xen, x86: Allow mprotect() pte updates to be batched using new Xen
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 15 Jan 2008 14:35:41 +0000 (14:35 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 15 Jan 2008 14:35:41 +0000 (14:35 +0000)
batched interface which preserves access/dirty pte flags.
Signed-off-by: Bruce Rogers <brogers@novell.com>
arch/i386/mm/hypervisor.c
include/asm-generic/pgtable.h
include/asm-i386/mach-xen/asm/pgtable.h
include/asm-x86_64/mach-xen/asm/pgtable.h
include/xen/interface/xen.h
mm/mprotect.c

index 83a646a20608d87e64243e1d65a546ba97f61816..1516776eafe2e2f1b3713e3bbdd01dbbb4bff5e1 100644 (file)
@@ -548,3 +548,33 @@ int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b)
                mach_lp, (u64)entry_a | ((u64)entry_b<<32));
 }
 #endif
+
+#define MAX_BATCHED_FULL_PTES 32
+
+int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
+                        unsigned long addr, unsigned long end, pgprot_t newprot)
+{
+       int rc = 0, i = 0;
+       mmu_update_t u[MAX_BATCHED_FULL_PTES];
+       pte_t *pte;
+       spinlock_t *ptl;
+
+       pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+       do {
+               if (pte_present(*pte)) {
+                       u[i].ptr = virt_to_machine(pte) | MMU_PT_UPDATE_PRESERVE_AD;
+                       u[i].val = __pte_val(pte_modify(*pte, newprot));
+                       if (++i == MAX_BATCHED_FULL_PTES) {
+                               if ((rc = HYPERVISOR_mmu_update(
+                                       &u[0], i, NULL, DOMID_SELF)) != 0)
+                                       break;
+                               i = 0;
+                       }
+               }
+       } while (pte++, addr += PAGE_SIZE, addr != end);
+       if (i)
+               rc = HYPERVISOR_mmu_update( &u[0], i, NULL, DOMID_SELF);
+       pte_unmap_unlock(pte - 1, ptl);
+       BUG_ON(rc && rc != -ENOSYS);
+       return !rc;
+}
index c2059a3a06216cb936a163255501e20d464c6b21..cac50cb8eb7d04808b4f5610581ff869eccbec4c 100644 (file)
@@ -188,6 +188,10 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
 })
 #endif
 
+#ifndef arch_change_pte_range
+#define arch_change_pte_range(mm, pmd, addr, end, newprot) 0
+#endif
+
 #ifndef __ASSEMBLY__
 /*
  * When walking page tables, we usually want to skip any p?d_none entries;
index a6defb4d8398aa96249fb433cf3d7e302f02c3c8..28e3885d0cf1c8d70dc2051ab6513e62cb5e1120 100644 (file)
@@ -512,6 +512,12 @@ int touch_pte_range(struct mm_struct *mm,
                     unsigned long address,
                     unsigned long size);
 
+int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
+               unsigned long addr, unsigned long end, pgprot_t newprot);
+
+#define arch_change_pte_range(mm, pmd, addr, end, newprot)     \
+               xen_change_pte_range(mm, pmd, addr, end, newprot)
+
 #define io_remap_pfn_range(vma,from,pfn,size,prot) \
 direct_remap_pfn_range(vma,from,pfn,size,prot,DOMID_IO)
 
index 86b51cb71f9bbfddfc95c5373b2e45a4c5023324..57ab249f1c0c17b35135cb8e2ad3aa2aa700759b 100644 (file)
@@ -541,6 +541,12 @@ int touch_pte_range(struct mm_struct *mm,
                     unsigned long address,
                     unsigned long size);
 
+int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
+               unsigned long addr, unsigned long end, pgprot_t newprot);
+
+#define arch_change_pte_range(mm, pmd, addr, end, newprot)     \
+               xen_change_pte_range(mm, pmd, addr, end, newprot)
+
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
                direct_remap_pfn_range(vma,vaddr,pfn,size,prot,DOMID_IO)
 
index 991128f0ee421afbeddadcf435a5dd7a97f0b700..10f23c7704c0c4212b0f730713de01a455bd180e 100644 (file)
  * ptr[:2]  -- Machine address within the frame whose mapping to modify.
  *             The frame must belong to the FD, if one is specified.
  * val      -- Value to write into the mapping entry.
+ * 
+ * ptr[1:0] == MMU_PT_UPDATE_PRESERVE_AD:
+ * As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed
+ * with those in @val.
  */
-#define MMU_NORMAL_PT_UPDATE     0 /* checked '*ptr = val'. ptr is MA.       */
-#define MMU_MACHPHYS_UPDATE      1 /* ptr = MA of frame to modify entry for  */
+#define MMU_NORMAL_PT_UPDATE      0 /* checked '*ptr = val'. ptr is MA.      */
+#define MMU_MACHPHYS_UPDATE       1 /* ptr = MA of frame to modify entry for */
+#define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */
 
 /*
  * MMU EXTENDED OPERATIONS
@@ -583,10 +588,10 @@ typedef uint8_t xen_domain_handle_t[16];
 #define __mk_unsigned_long(x) x ## UL
 #define mk_unsigned_long(x) __mk_unsigned_long(x)
 
-DEFINE_XEN_GUEST_HANDLE(uint8_t);
-DEFINE_XEN_GUEST_HANDLE(uint16_t);
-DEFINE_XEN_GUEST_HANDLE(uint32_t);
-DEFINE_XEN_GUEST_HANDLE(uint64_t);
+__DEFINE_XEN_GUEST_HANDLE(uint8,  uint8_t);
+__DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t);
+__DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t);
+__DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
 
 #else /* __ASSEMBLY__ */
 
index 638edabaff7118206b379c0436ffd6aa3e2fda40..cb1b15519bd67bf4af8b2baf53da9a41f73d90a2 100644 (file)
@@ -76,6 +76,8 @@ static inline void change_pmd_range(struct mm_struct *mm, pud_t *pud,
                next = pmd_addr_end(addr, end);
                if (pmd_none_or_clear_bad(pmd))
                        continue;
+               if (arch_change_pte_range(mm, pmd, addr, next, newprot))
+                       continue;
                change_pte_range(mm, pmd, addr, next, newprot);
        } while (pmd++, addr = next, addr != end);
 }