@@ -228,29 +228,76 @@ void __init sev_setup_arch(void)
228228 swiotlb_adjust_size (size );
229229}
230230
231- static void __init __set_clr_pte_enc ( pte_t * kpte , int level , bool enc )
231+ static unsigned long pg_level_to_pfn ( int level , pte_t * kpte , pgprot_t * ret_prot )
232232{
233- pgprot_t old_prot , new_prot ;
234- unsigned long pfn , pa , size ;
235- pte_t new_pte ;
233+ unsigned long pfn = 0 ;
234+ pgprot_t prot ;
236235
237236 switch (level ) {
238237 case PG_LEVEL_4K :
239238 pfn = pte_pfn (* kpte );
240- old_prot = pte_pgprot (* kpte );
239+ prot = pte_pgprot (* kpte );
241240 break ;
242241 case PG_LEVEL_2M :
243242 pfn = pmd_pfn (* (pmd_t * )kpte );
244- old_prot = pmd_pgprot (* (pmd_t * )kpte );
243+ prot = pmd_pgprot (* (pmd_t * )kpte );
245244 break ;
246245 case PG_LEVEL_1G :
247246 pfn = pud_pfn (* (pud_t * )kpte );
248- old_prot = pud_pgprot (* (pud_t * )kpte );
247+ prot = pud_pgprot (* (pud_t * )kpte );
249248 break ;
250249 default :
251- return ;
250+ WARN_ONCE (1 , "Invalid level for kpte\n" );
251+ return 0 ;
252252 }
253253
254+ if (ret_prot )
255+ * ret_prot = prot ;
256+
257+ return pfn ;
258+ }
259+
260+ void notify_range_enc_status_changed (unsigned long vaddr , int npages , bool enc )
261+ {
262+ #ifdef CONFIG_PARAVIRT
263+ unsigned long sz = npages << PAGE_SHIFT ;
264+ unsigned long vaddr_end = vaddr + sz ;
265+
266+ while (vaddr < vaddr_end ) {
267+ int psize , pmask , level ;
268+ unsigned long pfn ;
269+ pte_t * kpte ;
270+
271+ kpte = lookup_address (vaddr , & level );
272+ if (!kpte || pte_none (* kpte )) {
273+ WARN_ONCE (1 , "kpte lookup for vaddr\n" );
274+ return ;
275+ }
276+
277+ pfn = pg_level_to_pfn (level , kpte , NULL );
278+ if (!pfn )
279+ continue ;
280+
281+ psize = page_level_size (level );
282+ pmask = page_level_mask (level );
283+
284+ notify_page_enc_status_changed (pfn , psize >> PAGE_SHIFT , enc );
285+
286+ vaddr = (vaddr & pmask ) + psize ;
287+ }
288+ #endif
289+ }
290+
291+ static void __init __set_clr_pte_enc (pte_t * kpte , int level , bool enc )
292+ {
293+ pgprot_t old_prot , new_prot ;
294+ unsigned long pfn , pa , size ;
295+ pte_t new_pte ;
296+
297+ pfn = pg_level_to_pfn (level , kpte , & old_prot );
298+ if (!pfn )
299+ return ;
300+
254301 new_prot = old_prot ;
255302 if (enc )
256303 pgprot_val (new_prot ) |= _PAGE_ENC ;
@@ -285,12 +332,13 @@ static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc)
285332static int __init early_set_memory_enc_dec (unsigned long vaddr ,
286333 unsigned long size , bool enc )
287334{
288- unsigned long vaddr_end , vaddr_next ;
335+ unsigned long vaddr_end , vaddr_next , start ;
289336 unsigned long psize , pmask ;
290337 int split_page_size_mask ;
291338 int level , ret ;
292339 pte_t * kpte ;
293340
341+ start = vaddr ;
294342 vaddr_next = vaddr ;
295343 vaddr_end = vaddr + size ;
296344
@@ -345,6 +393,7 @@ static int __init early_set_memory_enc_dec(unsigned long vaddr,
345393
346394 ret = 0 ;
347395
396+ notify_range_enc_status_changed (start , PAGE_ALIGN (size ) >> PAGE_SHIFT , enc );
348397out :
349398 __flush_tlb_all ();
350399 return ret ;
0 commit comments