From: jbeulich@xxxxxxxxxx Subject: properly mark mapped grant pages as special for get_user_pages_fast() Patch-mainline: obsolete Should be merged into the 2.6.27 patch. Index: head-2008-10-29/drivers/xen/core/gnttab.c =================================================================== --- head-2008-10-29.orig/drivers/xen/core/gnttab.c 2008-11-03 11:49:51.000000000 +0100 +++ head-2008-10-29/drivers/xen/core/gnttab.c 2008-11-03 15:18:39.000000000 +0100 @@ -630,6 +630,76 @@ void __gnttab_dma_map_page(struct page * } while (unlikely(read_seqretry(&gnttab_dma_lock, seq))); } +#ifdef __HAVE_ARCH_PTE_SPECIAL + +static unsigned int GNTMAP_pte_special; + +bool gnttab_pre_map_adjust(unsigned int cmd, struct gnttab_map_grant_ref *map, + unsigned int count) +{ + unsigned int i; + bool fixup; + + if (unlikely(cmd != GNTTABOP_map_grant_ref)) + count = 0; + + for (i = 0, fixup = false; i < count; ++i, ++map) { + if (!(map->flags & GNTMAP_host_map) + || !(map->flags & GNTMAP_application_map)) + continue; + if (GNTMAP_pte_special) + map->flags |= GNTMAP_pte_special; + else + fixup = true; + } + + BUG_ON(fixup && xen_feature(XENFEAT_auto_translated_physmap)); + + return fixup; +} +EXPORT_SYMBOL(gnttab_pre_map_adjust); + +#if CONFIG_XEN_COMPAT < 0x030400 +int gnttab_post_map_adjust(const struct gnttab_map_grant_ref *map, unsigned int count) +{ + unsigned int i; + int rc = 0; + + for (i = 0; i < count && rc == 0; ++i, ++map) { + pte_t pte; + + if (!(map->flags & GNTMAP_host_map) + || !(map->flags & GNTMAP_application_map)) + continue; + +#ifdef CONFIG_X86 + pte = __pte_ma((map->dev_bus_addr | _PAGE_PRESENT | _PAGE_USER + | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_NX + | _PAGE_SPECIAL) + & __supported_pte_mask); +#else +#error Architecture not yet supported. +#endif + if (!(map->flags & GNTMAP_readonly)) + pte = pte_mkwrite(pte); + + if (map->flags & GNTMAP_contains_pte) { + mmu_update_t u; + + u.ptr = map->host_addr; + u.val = __pte_val(pte); + rc = HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF); + } else + rc = HYPERVISOR_update_va_mapping(map->host_addr, pte, 0); + } + + return rc; +} +EXPORT_SYMBOL(gnttab_post_map_adjust); +#endif + +#endif /* __HAVE_ARCH_PTE_SPECIAL */ + static int gnttab_resume(struct sys_device *dev) { if (max_nr_grant_frames() < nr_grant_frames) @@ -781,6 +851,18 @@ int __devinit gnttab_init(void) gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES; gnttab_free_head = NR_RESERVED_ENTRIES; +#ifdef __HAVE_ARCH_PTE_SPECIAL + if (!xen_feature(XENFEAT_auto_translated_physmap) + && xen_feature(XENFEAT_gnttab_map_avail_bits)) { +#ifdef CONFIG_X86 + GNTMAP_pte_special = (__pte_val(pte_mkspecial(__pte_ma(0))) + >> _PAGE_BIT_UNUSED1) << _GNTMAP_guest_avail0; +#else +#error Architecture not yet supported. +#endif + } +#endif + return 0; ini_nomem: Index: head-2008-10-29/include/asm-x86/mach-xen/asm/hypercall_32.h =================================================================== --- head-2008-10-29.orig/include/asm-x86/mach-xen/asm/hypercall_32.h 2008-11-03 11:49:51.000000000 +0100 +++ head-2008-10-29/include/asm-x86/mach-xen/asm/hypercall_32.h 2008-11-03 13:26:27.000000000 +0100 @@ -332,9 +332,19 @@ static inline int __must_check HYPERVISOR_grant_table_op( unsigned int cmd, void *uop, unsigned int count) { + bool fixup = false; + int rc; + if (arch_use_lazy_mmu_mode()) xen_multicall_flush(false); - return _hypercall3(int, grant_table_op, cmd, uop, count); +#ifdef GNTTABOP_map_grant_ref + if (cmd == GNTTABOP_map_grant_ref) +#endif + fixup = gnttab_pre_map_adjust(cmd, uop, count); + rc = _hypercall3(int, grant_table_op, cmd, uop, count); + if (rc == 0 && fixup) + rc = gnttab_post_map_adjust(uop, count); + return rc; } static inline int __must_check Index: head-2008-10-29/include/asm-x86/mach-xen/asm/hypercall_64.h =================================================================== --- head-2008-10-29.orig/include/asm-x86/mach-xen/asm/hypercall_64.h 2008-11-03 11:49:51.000000000 +0100 +++ head-2008-10-29/include/asm-x86/mach-xen/asm/hypercall_64.h 2008-11-03 13:26:20.000000000 +0100 @@ -324,9 +324,19 @@ static inline int __must_check HYPERVISOR_grant_table_op( unsigned int cmd, void *uop, unsigned int count) { + bool fixup = false; + int rc; + if (arch_use_lazy_mmu_mode()) xen_multicall_flush(false); - return _hypercall3(int, grant_table_op, cmd, uop, count); +#ifdef GNTTABOP_map_grant_ref + if (cmd == GNTTABOP_map_grant_ref) +#endif + fixup = gnttab_pre_map_adjust(cmd, uop, count); + rc = _hypercall3(int, grant_table_op, cmd, uop, count); + if (rc == 0 && fixup) + rc = gnttab_post_map_adjust(uop, count); + return rc; } static inline int __must_check Index: head-2008-10-29/include/asm-x86/mach-xen/asm/hypervisor.h =================================================================== --- head-2008-10-29.orig/include/asm-x86/mach-xen/asm/hypervisor.h 2008-11-03 11:49:51.000000000 +0100 +++ head-2008-10-29/include/asm-x86/mach-xen/asm/hypervisor.h 2008-11-03 15:18:37.000000000 +0100 @@ -166,6 +166,20 @@ static inline bool arch_use_lazy_mmu_mod && xen_use_lazy_mmu_mode(); } +struct gnttab_map_grant_ref; +bool gnttab_pre_map_adjust(unsigned int cmd, struct gnttab_map_grant_ref *, + unsigned int count); +#if CONFIG_XEN_COMPAT < 0x030400 +int gnttab_post_map_adjust(const struct gnttab_map_grant_ref *, unsigned int); +#else +static inline int gnttab_post_map_adjust(const struct gnttab_map_grant_ref *m, + unsigned int count) +{ + BUG(); + return -ENOSYS; +} +#endif + #else /* CONFIG_XEN */ static inline void xen_multicall_flush(bool ignore) {} @@ -174,6 +188,9 @@ static inline bool arch_use_lazy_mmu_mod #define xen_multi_mmu_update(...) ({ BUG(); -ENOSYS; }) #define xen_multi_mmuext_op(...) ({ BUG(); -ENOSYS; }) +#define gnttab_pre_map_adjust(...) false +#define gnttab_post_map_adjust(...) ({ BUG(); -ENOSYS; }) + #endif /* CONFIG_XEN */ #include Index: head-2008-10-29/include/xen/interface/features.h =================================================================== --- head-2008-10-29.orig/include/xen/interface/features.h 2008-10-29 09:55:56.000000000 +0100 +++ head-2008-10-29/include/xen/interface/features.h 2008-10-31 17:03:12.000000000 +0100 @@ -62,6 +62,12 @@ /* x86: Does this Xen host support the MMU_{CLEAR,COPY}_PAGE hypercall? */ #define XENFEAT_highmem_assist 6 +/* + * If set, GNTTABOP_map_grant_ref honors flags to be placed into guest kernel + * available pte bits. + */ +#define XENFEAT_gnttab_map_avail_bits 7 + #define XENFEAT_NR_SUBMAPS 1 #endif /* __XEN_PUBLIC_FEATURES_H__ */ Index: head-2008-10-29/include/xen/interface/grant_table.h =================================================================== --- head-2008-10-29.orig/include/xen/interface/grant_table.h 2008-10-29 11:25:35.000000000 +0100 +++ head-2008-10-29/include/xen/interface/grant_table.h 2008-10-31 17:10:21.000000000 +0100 @@ -367,7 +367,7 @@ DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_and /* - * Bitfield values for update_pin_status.flags. + * Bitfield values for gnttab_map_grant_ref.flags. */ /* Map the grant entry for access by I/O devices. */ #define _GNTMAP_device_map (0) @@ -395,6 +395,13 @@ DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_and #define GNTMAP_contains_pte (1<<_GNTMAP_contains_pte) /* + * Bits to be placed in guest kernel available PTE bits (architecture + * dependent; only supported when XENFEAT_gnttab_map_avail_bits is set). + */ +#define _GNTMAP_guest_avail0 (16) +#define GNTMAP_guest_avail_mask ((uint32_t)~0 << _GNTMAP_guest_avail0) + +/* * Values for error status returns. All errors are -ve. */ #define GNTST_okay (0) /* Normal return. */