@@ -2221,6 +2221,131 @@ void ptep_notify(struct mm_struct *mm, unsigned long vmaddr,
22212221}
22222222EXPORT_SYMBOL_GPL (ptep_notify );
22232223
2224+ static void pmdp_notify_gmap (struct gmap * gmap , pmd_t * pmdp ,
2225+ unsigned long gaddr )
2226+ {
2227+ pmd_val (* pmdp ) &= ~_SEGMENT_ENTRY_GMAP_IN ;
2228+ gmap_call_notifier (gmap , gaddr , gaddr + HPAGE_SIZE - 1 );
2229+ }
2230+
2231+ static void gmap_pmdp_clear (struct mm_struct * mm , unsigned long vmaddr ,
2232+ int purge )
2233+ {
2234+ pmd_t * pmdp ;
2235+ struct gmap * gmap ;
2236+ unsigned long gaddr ;
2237+
2238+ rcu_read_lock ();
2239+ list_for_each_entry_rcu (gmap , & mm -> context .gmap_list , list ) {
2240+ spin_lock (& gmap -> guest_table_lock );
2241+ pmdp = (pmd_t * )radix_tree_delete (& gmap -> host_to_guest ,
2242+ vmaddr >> PMD_SHIFT );
2243+ if (pmdp ) {
2244+ gaddr = __gmap_segment_gaddr ((unsigned long * )pmdp );
2245+ pmdp_notify_gmap (gmap , pmdp , gaddr );
2246+ WARN_ON (pmd_val (* pmdp ) & ~_SEGMENT_ENTRY_HARDWARE_BITS_LARGE );
2247+ if (purge )
2248+ __pmdp_csp (pmdp );
2249+ pmd_val (* pmdp ) = _SEGMENT_ENTRY_EMPTY ;
2250+ }
2251+ spin_unlock (& gmap -> guest_table_lock );
2252+ }
2253+ rcu_read_unlock ();
2254+ }
2255+
2256+ /**
2257+ * gmap_pmdp_invalidate - invalidate all affected guest pmd entries without
2258+ * flushing
2259+ * @mm: pointer to the process mm_struct
2260+ * @vmaddr: virtual address in the process address space
2261+ */
2262+ void gmap_pmdp_invalidate (struct mm_struct * mm , unsigned long vmaddr )
2263+ {
2264+ gmap_pmdp_clear (mm , vmaddr , 0 );
2265+ }
2266+ EXPORT_SYMBOL_GPL (gmap_pmdp_invalidate );
2267+
2268+ /**
2269+ * gmap_pmdp_csp - csp all affected guest pmd entries
2270+ * @mm: pointer to the process mm_struct
2271+ * @vmaddr: virtual address in the process address space
2272+ */
2273+ void gmap_pmdp_csp (struct mm_struct * mm , unsigned long vmaddr )
2274+ {
2275+ gmap_pmdp_clear (mm , vmaddr , 1 );
2276+ }
2277+ EXPORT_SYMBOL_GPL (gmap_pmdp_csp );
2278+
2279+ /**
2280+ * gmap_pmdp_idte_local - invalidate and clear a guest pmd entry
2281+ * @mm: pointer to the process mm_struct
2282+ * @vmaddr: virtual address in the process address space
2283+ */
2284+ void gmap_pmdp_idte_local (struct mm_struct * mm , unsigned long vmaddr )
2285+ {
2286+ unsigned long * entry , gaddr ;
2287+ struct gmap * gmap ;
2288+ pmd_t * pmdp ;
2289+
2290+ rcu_read_lock ();
2291+ list_for_each_entry_rcu (gmap , & mm -> context .gmap_list , list ) {
2292+ spin_lock (& gmap -> guest_table_lock );
2293+ entry = radix_tree_delete (& gmap -> host_to_guest ,
2294+ vmaddr >> PMD_SHIFT );
2295+ if (entry ) {
2296+ pmdp = (pmd_t * )entry ;
2297+ gaddr = __gmap_segment_gaddr (entry );
2298+ pmdp_notify_gmap (gmap , pmdp , gaddr );
2299+ WARN_ON (* entry & ~_SEGMENT_ENTRY_HARDWARE_BITS_LARGE );
2300+ if (MACHINE_HAS_TLB_GUEST )
2301+ __pmdp_idte (gaddr , pmdp , IDTE_GUEST_ASCE ,
2302+ gmap -> asce , IDTE_LOCAL );
2303+ else if (MACHINE_HAS_IDTE )
2304+ __pmdp_idte (gaddr , pmdp , 0 , 0 , IDTE_LOCAL );
2305+ * entry = _SEGMENT_ENTRY_EMPTY ;
2306+ }
2307+ spin_unlock (& gmap -> guest_table_lock );
2308+ }
2309+ rcu_read_unlock ();
2310+ }
2311+ EXPORT_SYMBOL_GPL (gmap_pmdp_idte_local );
2312+
2313+ /**
2314+ * gmap_pmdp_idte_global - invalidate and clear a guest pmd entry
2315+ * @mm: pointer to the process mm_struct
2316+ * @vmaddr: virtual address in the process address space
2317+ */
2318+ void gmap_pmdp_idte_global (struct mm_struct * mm , unsigned long vmaddr )
2319+ {
2320+ unsigned long * entry , gaddr ;
2321+ struct gmap * gmap ;
2322+ pmd_t * pmdp ;
2323+
2324+ rcu_read_lock ();
2325+ list_for_each_entry_rcu (gmap , & mm -> context .gmap_list , list ) {
2326+ spin_lock (& gmap -> guest_table_lock );
2327+ entry = radix_tree_delete (& gmap -> host_to_guest ,
2328+ vmaddr >> PMD_SHIFT );
2329+ if (entry ) {
2330+ pmdp = (pmd_t * )entry ;
2331+ gaddr = __gmap_segment_gaddr (entry );
2332+ pmdp_notify_gmap (gmap , pmdp , gaddr );
2333+ WARN_ON (* entry & ~_SEGMENT_ENTRY_HARDWARE_BITS_LARGE );
2334+ if (MACHINE_HAS_TLB_GUEST )
2335+ __pmdp_idte (gaddr , pmdp , IDTE_GUEST_ASCE ,
2336+ gmap -> asce , IDTE_GLOBAL );
2337+ else if (MACHINE_HAS_IDTE )
2338+ __pmdp_idte (gaddr , pmdp , 0 , 0 , IDTE_GLOBAL );
2339+ else
2340+ __pmdp_csp (pmdp );
2341+ * entry = _SEGMENT_ENTRY_EMPTY ;
2342+ }
2343+ spin_unlock (& gmap -> guest_table_lock );
2344+ }
2345+ rcu_read_unlock ();
2346+ }
2347+ EXPORT_SYMBOL_GPL (gmap_pmdp_idte_global );
2348+
22242349static inline void thp_split_mm (struct mm_struct * mm )
22252350{
22262351#ifdef CONFIG_TRANSPARENT_HUGEPAGE
0 commit comments