@@ -84,49 +84,45 @@ static void free_page_list(struct page *freelist)
8484 }
8585}
8686
87- static struct page * free_pt_page (unsigned long pt , struct page * freelist )
87+ static struct page * free_pt_page (u64 * pt , struct page * freelist )
8888{
89- struct page * p = virt_to_page (( void * ) pt );
89+ struct page * p = virt_to_page (pt );
9090
9191 p -> freelist = freelist ;
9292
9393 return p ;
9494}
9595
96- #define DEFINE_FREE_PT_FN (LVL , FN ) \
97- static struct page *free_pt_##LVL (unsigned long __pt, struct page *freelist) \
98- { \
99- unsigned long p; \
100- u64 *pt; \
101- int i; \
102- \
103- pt = (u64 *)__pt; \
104- \
105- for (i = 0; i < 512; ++i) { \
106- /* PTE present? */ \
107- if (!IOMMU_PTE_PRESENT (pt [i ])) \
108- continue ; \
109- \
110- /* Large PTE? */ \
111- if (PM_PTE_LEVEL (pt [i ]) == 0 || \
112- PM_PTE_LEVEL (pt [i ]) == 7 ) \
113- continue ; \
114- \
115- p = (unsigned long )IOMMU_PTE_PAGE (pt [i ]); \
116- freelist = FN (p , freelist ); \
117- } \
118- \
119- return free_pt_page ((unsigned long )pt , freelist ); \
120- }
96+ static struct page * free_pt_lvl (u64 * pt , struct page * freelist , int lvl )
97+ {
98+ u64 * p ;
99+ int i ;
100+
101+ for (i = 0 ; i < 512 ; ++ i ) {
102+ /* PTE present? */
103+ if (!IOMMU_PTE_PRESENT (pt [i ]))
104+ continue ;
121105
122- DEFINE_FREE_PT_FN (l2 , free_pt_page )
123- DEFINE_FREE_PT_FN (l3 , free_pt_l2 )
124- DEFINE_FREE_PT_FN (l4 , free_pt_l3 )
125- DEFINE_FREE_PT_FN (l5 , free_pt_l4 )
126- DEFINE_FREE_PT_FN (l6 , free_pt_l5 )
106+ /* Large PTE? */
107+ if (PM_PTE_LEVEL (pt [i ]) == 0 ||
108+ PM_PTE_LEVEL (pt [i ]) == 7 )
109+ continue ;
127110
128- static struct page * free_sub_pt (unsigned long root , int mode ,
129- struct page * freelist )
111+ /*
112+ * Free the next level. No need to look at l1 tables here since
113+ * they can only contain leaf PTEs; just free them directly.
114+ */
115+ p = IOMMU_PTE_PAGE (pt [i ]);
116+ if (lvl > 2 )
117+ freelist = free_pt_lvl (p , freelist , lvl - 1 );
118+ else
119+ freelist = free_pt_page (p , freelist );
120+ }
121+
122+ return free_pt_page (pt , freelist );
123+ }
124+
125+ static struct page * free_sub_pt (u64 * root , int mode , struct page * freelist )
130126{
131127 switch (mode ) {
132128 case PAGE_MODE_NONE :
@@ -136,19 +132,11 @@ static struct page *free_sub_pt(unsigned long root, int mode,
136132 freelist = free_pt_page (root , freelist );
137133 break ;
138134 case PAGE_MODE_2_LEVEL :
139- freelist = free_pt_l2 (root , freelist );
140- break ;
141135 case PAGE_MODE_3_LEVEL :
142- freelist = free_pt_l3 (root , freelist );
143- break ;
144136 case PAGE_MODE_4_LEVEL :
145- freelist = free_pt_l4 (root , freelist );
146- break ;
147137 case PAGE_MODE_5_LEVEL :
148- freelist = free_pt_l5 (root , freelist );
149- break ;
150138 case PAGE_MODE_6_LEVEL :
151- freelist = free_pt_l6 (root , freelist );
139+ free_pt_lvl (root , freelist , mode );
152140 break ;
153141 default :
154142 BUG ();
@@ -364,7 +352,7 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable,
364352
365353static struct page * free_clear_pte (u64 * pte , u64 pteval , struct page * freelist )
366354{
367- unsigned long pt ;
355+ u64 * pt ;
368356 int mode ;
369357
370358 while (cmpxchg64 (pte , pteval , 0 ) != pteval ) {
@@ -375,7 +363,7 @@ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
375363 if (!IOMMU_PTE_PRESENT (pteval ))
376364 return freelist ;
377365
378- pt = ( unsigned long ) IOMMU_PTE_PAGE (pteval );
366+ pt = IOMMU_PTE_PAGE (pteval );
379367 mode = IOMMU_PTE_MODE (pteval );
380368
381369 return free_sub_pt (pt , mode , freelist );
@@ -512,7 +500,6 @@ static void v1_free_pgtable(struct io_pgtable *iop)
512500 struct amd_io_pgtable * pgtable = container_of (iop , struct amd_io_pgtable , iop );
513501 struct protection_domain * dom ;
514502 struct page * freelist = NULL ;
515- unsigned long root ;
516503
517504 if (pgtable -> mode == PAGE_MODE_NONE )
518505 return ;
@@ -529,8 +516,7 @@ static void v1_free_pgtable(struct io_pgtable *iop)
529516 BUG_ON (pgtable -> mode < PAGE_MODE_NONE ||
530517 pgtable -> mode > PAGE_MODE_6_LEVEL );
531518
532- root = (unsigned long )pgtable -> root ;
533- freelist = free_sub_pt (root , pgtable -> mode , freelist );
519+ freelist = free_sub_pt (pgtable -> root , pgtable -> mode , freelist );
534520
535521 free_page_list (freelist );
536522}
0 commit comments