11b09c13cSSteffen Eiden /* SPDX-License-Identifier: GPL-2.0 */ 21b09c13cSSteffen Eiden /* 31b09c13cSSteffen Eiden * KVM guest address space mapping code 41b09c13cSSteffen Eiden * 51b09c13cSSteffen Eiden * Copyright IBM Corp. 2007, 2016, 2025 61b09c13cSSteffen Eiden * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> 71b09c13cSSteffen Eiden * Claudio Imbrenda <imbrenda@linux.ibm.com> 81b09c13cSSteffen Eiden */ 91b09c13cSSteffen Eiden 101b09c13cSSteffen Eiden #ifndef ARCH_KVM_GMAP_GMAP_H 111b09c13cSSteffen Eiden #define ARCH_KVM_GMAP_GMAP_H 121b09c13cSSteffen Eiden 13a07276d5SSteffen Eiden #include <linux/kvm_host.h> 14a07276d5SSteffen Eiden 151b09c13cSSteffen Eiden #include "dat.h" 161b09c13cSSteffen Eiden 171b09c13cSSteffen Eiden /** 181b09c13cSSteffen Eiden * enum gmap_flags - Flags of a gmap. 191b09c13cSSteffen Eiden * 201b09c13cSSteffen Eiden * @GMAP_FLAG_SHADOW: The gmap is a vsie shadow gmap. 211b09c13cSSteffen Eiden * @GMAP_FLAG_OWNS_PAGETABLES: The gmap owns all dat levels; normally 1, is 0 221b09c13cSSteffen Eiden * only for ucontrol per-cpu gmaps, since they 231b09c13cSSteffen Eiden * share the page tables with the main gmap. 241b09c13cSSteffen Eiden * @GMAP_FLAG_IS_UCONTROL: The gmap is ucontrol (main gmap or per-cpu gmap). 251b09c13cSSteffen Eiden * @GMAP_FLAG_ALLOW_HPAGE_1M: 1M hugepages are allowed for this gmap, 261b09c13cSSteffen Eiden * independently of the page size used by userspace. 271b09c13cSSteffen Eiden * @GMAP_FLAG_ALLOW_HPAGE_2G: 2G hugepages are allowed for this gmap, 281b09c13cSSteffen Eiden * independently of the page size used by userspace. 291b09c13cSSteffen Eiden * @GMAP_FLAG_PFAULT_ENABLED: Pfault is enabled for the gmap. 301b09c13cSSteffen Eiden * @GMAP_FLAG_USES_SKEYS: If the guest uses storage keys. 311b09c13cSSteffen Eiden * @GMAP_FLAG_USES_CMM: Whether the guest uses CMMA. 321b09c13cSSteffen Eiden * @GMAP_FLAG_EXPORT_ON_UNMAP: Whether to export guest pages when unmapping. 331b09c13cSSteffen Eiden */ 341b09c13cSSteffen Eiden enum gmap_flags { 351b09c13cSSteffen Eiden GMAP_FLAG_SHADOW = 0, 361b09c13cSSteffen Eiden GMAP_FLAG_OWNS_PAGETABLES, 371b09c13cSSteffen Eiden GMAP_FLAG_IS_UCONTROL, 381b09c13cSSteffen Eiden GMAP_FLAG_ALLOW_HPAGE_1M, 391b09c13cSSteffen Eiden GMAP_FLAG_ALLOW_HPAGE_2G, 401b09c13cSSteffen Eiden GMAP_FLAG_PFAULT_ENABLED, 411b09c13cSSteffen Eiden GMAP_FLAG_USES_SKEYS, 421b09c13cSSteffen Eiden GMAP_FLAG_USES_CMM, 431b09c13cSSteffen Eiden GMAP_FLAG_EXPORT_ON_UNMAP, 441b09c13cSSteffen Eiden }; 451b09c13cSSteffen Eiden 461b09c13cSSteffen Eiden /** 471b09c13cSSteffen Eiden * struct gmap_struct - Guest address space. 481b09c13cSSteffen Eiden * 491b09c13cSSteffen Eiden * @flags: GMAP_FLAG_* flags. 501b09c13cSSteffen Eiden * @edat_level: The edat level of this shadow gmap. 511b09c13cSSteffen Eiden * @kvm: The vm. 521b09c13cSSteffen Eiden * @asce: The ASCE used by this gmap. 531b09c13cSSteffen Eiden * @list: List head used in children gmaps for the children gmap list. 541b09c13cSSteffen Eiden * @children_lock: Protects children and scb_users. 551b09c13cSSteffen Eiden * @children: List of child gmaps of this gmap. 561b09c13cSSteffen Eiden * @scb_users: List of vsie_scb that use this shadow gmap. 571b09c13cSSteffen Eiden * @parent: Parent gmap of a child gmap. 581b09c13cSSteffen Eiden * @guest_asce: Original ASCE of this shadow gmap. 591b09c13cSSteffen Eiden * @host_to_rmap_lock: Protects host_to_rmap. 601b09c13cSSteffen Eiden * @host_to_rmap: Radix tree mapping host addresses to guest addresses. 611b09c13cSSteffen Eiden */ 621b09c13cSSteffen Eiden struct gmap { 631b09c13cSSteffen Eiden unsigned long flags; 641b09c13cSSteffen Eiden unsigned char edat_level; 651b09c13cSSteffen Eiden bool invalidated; 661b09c13cSSteffen Eiden struct kvm *kvm; 671b09c13cSSteffen Eiden union asce asce; 681b09c13cSSteffen Eiden struct list_head list; 691b09c13cSSteffen Eiden spinlock_t children_lock; /* Protects: children, scb_users */ 701b09c13cSSteffen Eiden struct list_head children; 711b09c13cSSteffen Eiden struct list_head scb_users; 721b09c13cSSteffen Eiden struct gmap *parent; 731b09c13cSSteffen Eiden union asce guest_asce; 741b09c13cSSteffen Eiden spinlock_t host_to_rmap_lock; /* Protects host_to_rmap */ 751b09c13cSSteffen Eiden struct radix_tree_root host_to_rmap; 761b09c13cSSteffen Eiden refcount_t refcount; 771b09c13cSSteffen Eiden }; 781b09c13cSSteffen Eiden 791b09c13cSSteffen Eiden struct gmap_cache { 801b09c13cSSteffen Eiden struct list_head list; 811b09c13cSSteffen Eiden struct gmap *gmap; 821b09c13cSSteffen Eiden }; 831b09c13cSSteffen Eiden 841b09c13cSSteffen Eiden #define gmap_for_each_rmap_safe(pos, n, head) \ 851b09c13cSSteffen Eiden for (pos = (head); n = pos ? pos->next : NULL, pos; pos = n) 861b09c13cSSteffen Eiden 871b09c13cSSteffen Eiden int s390_replace_asce(struct gmap *gmap); 881b09c13cSSteffen Eiden bool gmap_age_gfn(struct gmap *gmap, gfn_t start, gfn_t end); 891b09c13cSSteffen Eiden bool gmap_unmap_gfn_range(struct gmap *gmap, struct kvm_memory_slot *slot, gfn_t start, gfn_t end); 901b09c13cSSteffen Eiden int gmap_try_fixup_minor(struct gmap *gmap, struct guest_fault *fault); 911b09c13cSSteffen Eiden struct gmap *gmap_new(struct kvm *kvm, gfn_t limit); 921b09c13cSSteffen Eiden struct gmap *gmap_new_child(struct gmap *parent, gfn_t limit); 931b09c13cSSteffen Eiden void gmap_remove_child(struct gmap *child); 941b09c13cSSteffen Eiden void gmap_dispose(struct gmap *gmap); 951b09c13cSSteffen Eiden int gmap_link(struct kvm_s390_mmu_cache *mc, struct gmap *gmap, struct guest_fault *fault, 961b09c13cSSteffen Eiden struct kvm_memory_slot *slot); 971b09c13cSSteffen Eiden void gmap_sync_dirty_log(struct gmap *gmap, gfn_t start, gfn_t end); 981b09c13cSSteffen Eiden int gmap_set_limit(struct gmap *gmap, gfn_t limit); 991b09c13cSSteffen Eiden int gmap_ucas_translate(struct kvm_s390_mmu_cache *mc, struct gmap *gmap, gpa_t *gaddr); 1001b09c13cSSteffen Eiden int gmap_ucas_map(struct gmap *gmap, gfn_t p_gfn, gfn_t c_gfn, unsigned long count); 1011b09c13cSSteffen Eiden void gmap_ucas_unmap(struct gmap *gmap, gfn_t c_gfn, unsigned long count); 102a07276d5SSteffen Eiden 103a07276d5SSteffen Eiden #if KVM_S390_MANAGES_S390_GUEST 1041b09c13cSSteffen Eiden int gmap_enable_skeys(struct gmap *gmap); 105a07276d5SSteffen Eiden #endif /* KVM_S390_MANAGES_S390_GUEST */ 106a07276d5SSteffen Eiden 1071b09c13cSSteffen Eiden int gmap_pv_destroy_range(struct gmap *gmap, gfn_t start, gfn_t end, bool interruptible); 1081b09c13cSSteffen Eiden int gmap_insert_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn, 1091b09c13cSSteffen Eiden gfn_t r_gfn, int level); 1101b09c13cSSteffen Eiden int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn, 1111b09c13cSSteffen Eiden kvm_pfn_t pfn, int level, bool wr); 1121b09c13cSSteffen Eiden void _gmap_handle_vsie_unshadow_event(struct gmap *parent, gfn_t gfn); 1131b09c13cSSteffen Eiden struct gmap *gmap_create_shadow(struct kvm_s390_mmu_cache *mc, struct gmap *gmap, 1141b09c13cSSteffen Eiden union asce asce, int edat_level); 1151b09c13cSSteffen Eiden void gmap_split_huge_pages(struct gmap *gmap); 1161b09c13cSSteffen Eiden 1171b09c13cSSteffen Eiden static inline bool uses_skeys(struct gmap *gmap) 1181b09c13cSSteffen Eiden { 1191b09c13cSSteffen Eiden return test_bit(GMAP_FLAG_USES_SKEYS, &gmap->flags); 1201b09c13cSSteffen Eiden } 1211b09c13cSSteffen Eiden 1221b09c13cSSteffen Eiden static inline bool uses_cmm(struct gmap *gmap) 1231b09c13cSSteffen Eiden { 1241b09c13cSSteffen Eiden return test_bit(GMAP_FLAG_USES_CMM, &gmap->flags); 1251b09c13cSSteffen Eiden } 1261b09c13cSSteffen Eiden 1271b09c13cSSteffen Eiden static inline bool pfault_enabled(struct gmap *gmap) 1281b09c13cSSteffen Eiden { 1291b09c13cSSteffen Eiden return test_bit(GMAP_FLAG_PFAULT_ENABLED, &gmap->flags); 1301b09c13cSSteffen Eiden } 1311b09c13cSSteffen Eiden 1321b09c13cSSteffen Eiden static inline bool is_ucontrol(struct gmap *gmap) 1331b09c13cSSteffen Eiden { 1341b09c13cSSteffen Eiden return test_bit(GMAP_FLAG_IS_UCONTROL, &gmap->flags); 1351b09c13cSSteffen Eiden } 1361b09c13cSSteffen Eiden 1371b09c13cSSteffen Eiden static inline bool is_shadow(struct gmap *gmap) 1381b09c13cSSteffen Eiden { 1391b09c13cSSteffen Eiden return test_bit(GMAP_FLAG_SHADOW, &gmap->flags); 1401b09c13cSSteffen Eiden } 1411b09c13cSSteffen Eiden 1421b09c13cSSteffen Eiden static inline bool owns_page_tables(struct gmap *gmap) 1431b09c13cSSteffen Eiden { 1441b09c13cSSteffen Eiden return test_bit(GMAP_FLAG_OWNS_PAGETABLES, &gmap->flags); 1451b09c13cSSteffen Eiden } 1461b09c13cSSteffen Eiden 1471b09c13cSSteffen Eiden static inline struct gmap *gmap_put(struct gmap *gmap) 1481b09c13cSSteffen Eiden { 1491b09c13cSSteffen Eiden if (refcount_dec_and_test(&gmap->refcount)) 1501b09c13cSSteffen Eiden gmap_dispose(gmap); 1511b09c13cSSteffen Eiden return NULL; 1521b09c13cSSteffen Eiden } 1531b09c13cSSteffen Eiden 1541b09c13cSSteffen Eiden static inline void gmap_get(struct gmap *gmap) 1551b09c13cSSteffen Eiden { 1561b09c13cSSteffen Eiden WARN_ON_ONCE(unlikely(!refcount_inc_not_zero(&gmap->refcount))); 1571b09c13cSSteffen Eiden } 1581b09c13cSSteffen Eiden 1591b09c13cSSteffen Eiden static inline void gmap_handle_vsie_unshadow_event(struct gmap *parent, gfn_t gfn) 1601b09c13cSSteffen Eiden { 1611b09c13cSSteffen Eiden scoped_guard(spinlock, &parent->children_lock) 1621b09c13cSSteffen Eiden _gmap_handle_vsie_unshadow_event(parent, gfn); 1631b09c13cSSteffen Eiden } 1641b09c13cSSteffen Eiden 165*188a15ccSSteffen Eiden #if KVM_S390_MANAGES_S390_GUEST 166*188a15ccSSteffen Eiden bool _gmap_unmap_prefix(struct gmap *gmap, gfn_t gfn, gfn_t end, bool hint); 167*188a15ccSSteffen Eiden #else 168*188a15ccSSteffen Eiden static inline bool _gmap_unmap_prefix(struct gmap *gmap, gfn_t gfn, gfn_t end, bool hint) 169*188a15ccSSteffen Eiden { 170*188a15ccSSteffen Eiden return true; 171*188a15ccSSteffen Eiden } 172*188a15ccSSteffen Eiden #endif /* KVM_S390_MANAGES_S390_GUEST */ 1731b09c13cSSteffen Eiden static inline bool gmap_mkold_prefix(struct gmap *gmap, gfn_t gfn, gfn_t end) 1741b09c13cSSteffen Eiden { 1751b09c13cSSteffen Eiden return _gmap_unmap_prefix(gmap, gfn, end, true); 1761b09c13cSSteffen Eiden } 1771b09c13cSSteffen Eiden 1781b09c13cSSteffen Eiden static inline bool gmap_unmap_prefix(struct gmap *gmap, gfn_t gfn, gfn_t end) 1791b09c13cSSteffen Eiden { 1801b09c13cSSteffen Eiden return _gmap_unmap_prefix(gmap, gfn, end, false); 1811b09c13cSSteffen Eiden } 1821b09c13cSSteffen Eiden 1831b09c13cSSteffen Eiden /** 1841b09c13cSSteffen Eiden * pte_needs_unshadow() -- Check if the pte operations triggers unshadowing. 1851b09c13cSSteffen Eiden * @oldpte: the previous value for the guest pte. 1861b09c13cSSteffen Eiden * @newpte: the new pte being set. 1871b09c13cSSteffen Eiden * @pgste: the pgste for the pte entry. 1881b09c13cSSteffen Eiden * 1891b09c13cSSteffen Eiden * If the pgste.vsie_notif bit is not set, return false: the page is not 1901b09c13cSSteffen Eiden * involved in vsie and thus should not trigger an unshadow operation. 1911b09c13cSSteffen Eiden * 1921b09c13cSSteffen Eiden * If the pgste.vsie_gmem bit is set, this pte represents shadowed guest 1931b09c13cSSteffen Eiden * memory. The access rights on g3's memory should be synchronized with g1's 1941b09c13cSSteffen Eiden * and g2's. Therefore unshadowing is triggered if the new and old pte 1951b09c13cSSteffen Eiden * differ in protection, or if the new pte is invalid. 1961b09c13cSSteffen Eiden * 1971b09c13cSSteffen Eiden * If the pgste.vsie_gmem bit is not set, this pte maps the g2 dat tables 1981b09c13cSSteffen Eiden * for g3. If the entry becomes writable or absent, it becomes impossible to 1991b09c13cSSteffen Eiden * guarantee that the shadow mapping will match g2's mapping. In that case, 2001b09c13cSSteffen Eiden * trigger an unshadow event. 2011b09c13cSSteffen Eiden * 2021b09c13cSSteffen Eiden * Return: true if an unshadow event should be triggered, otherwise false. 2031b09c13cSSteffen Eiden */ 2041b09c13cSSteffen Eiden static inline bool pte_needs_unshadow(union pte oldpte, union pte newpte, union pgste pgste) 2051b09c13cSSteffen Eiden { 2061b09c13cSSteffen Eiden if (!pgste.vsie_notif) 2071b09c13cSSteffen Eiden return false; 2081b09c13cSSteffen Eiden if (pgste.vsie_gmem) 2091b09c13cSSteffen Eiden return (oldpte.h.p != newpte.h.p) || newpte.h.i; 2101b09c13cSSteffen Eiden return !newpte.h.p || !newpte.s.pr; 2111b09c13cSSteffen Eiden } 2121b09c13cSSteffen Eiden 213ce4bee6aSSteffen Eiden #if KVM_S390_MANAGES_S390_GUEST 214ce4bee6aSSteffen Eiden void _gmap_set_cmma_all(struct gmap *gmap, bool dirty); 2151b09c13cSSteffen Eiden static inline void gmap_set_cmma_all_dirty(struct gmap *gmap) 2161b09c13cSSteffen Eiden { 2171b09c13cSSteffen Eiden _gmap_set_cmma_all(gmap, true); 2181b09c13cSSteffen Eiden } 2191b09c13cSSteffen Eiden 2201b09c13cSSteffen Eiden static inline void gmap_set_cmma_all_clean(struct gmap *gmap) 2211b09c13cSSteffen Eiden { 2221b09c13cSSteffen Eiden _gmap_set_cmma_all(gmap, false); 2231b09c13cSSteffen Eiden } 224ce4bee6aSSteffen Eiden #endif /* KVM_S390_MANAGES_S390_GUEST */ 2251b09c13cSSteffen Eiden 2261b09c13cSSteffen Eiden static inline union pgste _gmap_ptep_xchg(struct gmap *gmap, union pte *ptep, union pte newpte, 2271b09c13cSSteffen Eiden union pgste pgste, gfn_t gfn, bool needs_lock) 2281b09c13cSSteffen Eiden { 2291b09c13cSSteffen Eiden lockdep_assert_held(&gmap->kvm->mmu_lock); 2301b09c13cSSteffen Eiden if (!needs_lock) 2311b09c13cSSteffen Eiden lockdep_assert_held(&gmap->children_lock); 2321b09c13cSSteffen Eiden else 2331b09c13cSSteffen Eiden lockdep_assert_not_held(&gmap->children_lock); 2341b09c13cSSteffen Eiden 2351b09c13cSSteffen Eiden if (pgste.prefix_notif && (newpte.h.p || newpte.h.i)) { 2361b09c13cSSteffen Eiden pgste.prefix_notif = 0; 2371b09c13cSSteffen Eiden gmap_unmap_prefix(gmap, gfn, gfn + 1); 2381b09c13cSSteffen Eiden } 2391b09c13cSSteffen Eiden if (pte_needs_unshadow(*ptep, newpte, pgste)) { 2401b09c13cSSteffen Eiden pgste.vsie_notif = 0; 2411b09c13cSSteffen Eiden pgste.vsie_gmem = 0; 2421b09c13cSSteffen Eiden if (needs_lock) 2431b09c13cSSteffen Eiden gmap_handle_vsie_unshadow_event(gmap, gfn); 2441b09c13cSSteffen Eiden else 2451b09c13cSSteffen Eiden _gmap_handle_vsie_unshadow_event(gmap, gfn); 2461b09c13cSSteffen Eiden } 2471b09c13cSSteffen Eiden if (!ptep->s.d && newpte.s.d && !newpte.s.s) 2481b09c13cSSteffen Eiden SetPageDirty(pfn_to_page(newpte.h.pfra)); 2491b09c13cSSteffen Eiden pgste.zero = 0; 2501b09c13cSSteffen Eiden return __dat_ptep_xchg(ptep, pgste, newpte, gfn, gmap->asce, uses_skeys(gmap)); 2511b09c13cSSteffen Eiden } 2521b09c13cSSteffen Eiden 2531b09c13cSSteffen Eiden static inline union pgste gmap_ptep_xchg(struct gmap *gmap, union pte *ptep, union pte newpte, 2541b09c13cSSteffen Eiden union pgste pgste, gfn_t gfn) 2551b09c13cSSteffen Eiden { 2561b09c13cSSteffen Eiden return _gmap_ptep_xchg(gmap, ptep, newpte, pgste, gfn, true); 2571b09c13cSSteffen Eiden } 2581b09c13cSSteffen Eiden 2591b09c13cSSteffen Eiden /** 2601b09c13cSSteffen Eiden * crste_needs_unshadow() -- Check if the crste operations triggers unshadowing. 2611b09c13cSSteffen Eiden * @oldcrste: the previous value for the crste. 2621b09c13cSSteffen Eiden * @newcrste: the new value for the crste. 2631b09c13cSSteffen Eiden * 2641b09c13cSSteffen Eiden * If the old crste did not have the vsie_notif bit set, return false: the 2651b09c13cSSteffen Eiden * page is not involved in vsie and thus should not trigger an unshadow 2661b09c13cSSteffen Eiden * operation. Conversely, if the bit is set, it can only be g3 memory, since 2671b09c13cSSteffen Eiden * dat tables are never mapped using large pages. 2681b09c13cSSteffen Eiden * 2691b09c13cSSteffen Eiden * Similar to the pgste.vsie_gmem case of pte_needs_unshadow(), if the 2701b09c13cSSteffen Eiden * protection bit is changing or the new page is invalid, trigger an 2711b09c13cSSteffen Eiden * unshadow event. Also trigger an unshadow event if the new crste does not 2721b09c13cSSteffen Eiden * have the vsie_notif bit set. 2731b09c13cSSteffen Eiden * 2741b09c13cSSteffen Eiden * Return: true if an unshadow event should be triggered, otherwise false. 2751b09c13cSSteffen Eiden */ 2761b09c13cSSteffen Eiden static inline bool crste_needs_unshadow(union crste oldcrste, union crste newcrste) 2771b09c13cSSteffen Eiden { 2781b09c13cSSteffen Eiden if (!oldcrste.s.fc1.vsie_notif) 2791b09c13cSSteffen Eiden return false; 2801b09c13cSSteffen Eiden return (newcrste.h.p != oldcrste.h.p) || newcrste.h.i || !newcrste.s.fc1.vsie_notif; 2811b09c13cSSteffen Eiden } 2821b09c13cSSteffen Eiden 2831b09c13cSSteffen Eiden static inline bool __must_check _gmap_crstep_xchg_atomic(struct gmap *gmap, union crste *crstep, 2841b09c13cSSteffen Eiden union crste oldcrste, union crste newcrste, 2851b09c13cSSteffen Eiden gfn_t gfn, bool needs_lock) 2861b09c13cSSteffen Eiden { 2871b09c13cSSteffen Eiden unsigned long align = is_pmd(newcrste) ? _PAGE_ENTRIES : _PAGE_ENTRIES * _CRST_ENTRIES; 2881b09c13cSSteffen Eiden 2891b09c13cSSteffen Eiden if (KVM_BUG_ON(crstep->h.tt != oldcrste.h.tt || newcrste.h.tt != oldcrste.h.tt, gmap->kvm)) 2901b09c13cSSteffen Eiden return true; 2911b09c13cSSteffen Eiden 2921b09c13cSSteffen Eiden lockdep_assert_held(&gmap->kvm->mmu_lock); 2931b09c13cSSteffen Eiden if (!needs_lock) 2941b09c13cSSteffen Eiden lockdep_assert_held(&gmap->children_lock); 2951b09c13cSSteffen Eiden 2961b09c13cSSteffen Eiden gfn = ALIGN_DOWN(gfn, align); 2971b09c13cSSteffen Eiden if (crste_prefix(oldcrste) && (newcrste.h.p || newcrste.h.i || !crste_prefix(newcrste))) { 2981b09c13cSSteffen Eiden newcrste.s.fc1.prefix_notif = 0; 2991b09c13cSSteffen Eiden gmap_unmap_prefix(gmap, gfn, gfn + align); 3001b09c13cSSteffen Eiden } 3011b09c13cSSteffen Eiden if (crste_leaf(oldcrste) && crste_needs_unshadow(oldcrste, newcrste)) { 3021b09c13cSSteffen Eiden newcrste = oldcrste; 3031b09c13cSSteffen Eiden newcrste.s.fc1.vsie_notif = 0; 3041b09c13cSSteffen Eiden if (needs_lock) 3051b09c13cSSteffen Eiden gmap_handle_vsie_unshadow_event(gmap, gfn); 3061b09c13cSSteffen Eiden else 3071b09c13cSSteffen Eiden _gmap_handle_vsie_unshadow_event(gmap, gfn); 3081b09c13cSSteffen Eiden if (!dat_crstep_xchg_atomic(crstep, oldcrste, newcrste, gfn, gmap->asce)) 3091b09c13cSSteffen Eiden return false; 3101b09c13cSSteffen Eiden /* 3111b09c13cSSteffen Eiden * Return false even if the swap was successful, as it only 3121b09c13cSSteffen Eiden * indicates that the best effort clearing of the vsie_notif 3131b09c13cSSteffen Eiden * bit was successful. The caller will have to try again 3141b09c13cSSteffen Eiden * regardless, since the desired value has not been set. 3151b09c13cSSteffen Eiden * This pointless check is needed to silence a potential 3161b09c13cSSteffen Eiden * __must_check warning. 3171b09c13cSSteffen Eiden */ 3181b09c13cSSteffen Eiden return false; 3191b09c13cSSteffen Eiden } 3201b09c13cSSteffen Eiden if (!oldcrste.s.fc1.d && newcrste.s.fc1.d && !newcrste.s.fc1.s) 3211b09c13cSSteffen Eiden SetPageDirty(phys_to_page(crste_origin_large(newcrste))); 3221b09c13cSSteffen Eiden return dat_crstep_xchg_atomic(crstep, oldcrste, newcrste, gfn, gmap->asce); 3231b09c13cSSteffen Eiden } 3241b09c13cSSteffen Eiden 3251b09c13cSSteffen Eiden static inline bool __must_check gmap_crstep_xchg_atomic(struct gmap *gmap, union crste *crstep, 3261b09c13cSSteffen Eiden union crste oldcrste, union crste newcrste, 3271b09c13cSSteffen Eiden gfn_t gfn) 3281b09c13cSSteffen Eiden { 3291b09c13cSSteffen Eiden return _gmap_crstep_xchg_atomic(gmap, crstep, oldcrste, newcrste, gfn, true); 3301b09c13cSSteffen Eiden } 3311b09c13cSSteffen Eiden 3321b09c13cSSteffen Eiden /** 3331b09c13cSSteffen Eiden * gmap_is_shadow_valid() - check if a shadow guest address space matches the 3341b09c13cSSteffen Eiden * given properties and is still valid. 3351b09c13cSSteffen Eiden * @sg: Pointer to the shadow guest address space structure. 3361b09c13cSSteffen Eiden * @asce: ASCE for which the shadow table is requested. 3371b09c13cSSteffen Eiden * @edat_level: Edat level to be used for the shadow translation. 3381b09c13cSSteffen Eiden * 3391b09c13cSSteffen Eiden * Return: true if the gmap shadow is still valid and matches the given 3401b09c13cSSteffen Eiden * properties and the caller can continue using it; false otherwise, the 3411b09c13cSSteffen Eiden * caller has to request a new shadow gmap in this case. 3421b09c13cSSteffen Eiden */ 3431b09c13cSSteffen Eiden static inline bool gmap_is_shadow_valid(struct gmap *sg, union asce asce, int edat_level) 3441b09c13cSSteffen Eiden { 3451b09c13cSSteffen Eiden return sg->guest_asce.val == asce.val && sg->edat_level == edat_level; 3461b09c13cSSteffen Eiden } 3471b09c13cSSteffen Eiden 3481b09c13cSSteffen Eiden #endif /* ARCH_KVM_GMAP_GMAP_H */ 349