@@ -71,11 +71,12 @@ static void __init early_code_mapping_set_exec(int executable)
71
71
72
72
pgd_t * __init efi_call_phys_prolog (void )
73
73
{
74
- unsigned long vaddress ;
74
+ unsigned long vaddr , left_vaddr ;
75
+ unsigned int num_entries ;
75
76
pgd_t * save_pgd ;
76
-
77
- int pgd ;
77
+ pud_t * pud , * pud_k ;
78
78
int n_pgds ;
79
+ int i ;
79
80
80
81
if (!efi_enabled (EFI_OLD_MEMMAP )) {
81
82
save_pgd = (pgd_t * )read_cr3 ();
@@ -88,10 +89,22 @@ pgd_t * __init efi_call_phys_prolog(void)
88
89
n_pgds = DIV_ROUND_UP ((max_pfn << PAGE_SHIFT ), PGDIR_SIZE );
89
90
save_pgd = kmalloc_array (n_pgds , sizeof (* save_pgd ), GFP_KERNEL );
90
91
91
- for (pgd = 0 ; pgd < n_pgds ; pgd ++ ) {
92
- save_pgd [pgd ] = * pgd_offset_k (pgd * PGDIR_SIZE );
93
- vaddress = (unsigned long )__va (pgd * PGDIR_SIZE );
94
- set_pgd (pgd_offset_k (pgd * PGDIR_SIZE ), * pgd_offset_k (vaddress ));
92
+ for (i = 0 ; i < n_pgds ; i ++ ) {
93
+ save_pgd [i ] = * pgd_offset_k (i * PGDIR_SIZE );
94
+
95
+ vaddr = (unsigned long )__va (i * PGDIR_SIZE );
96
+ pud = pud_alloc_one (NULL , 0 );
97
+
98
+ num_entries = PTRS_PER_PUD - pud_index (vaddr );
99
+ pud_k = pud_offset (pgd_offset_k (vaddr ), vaddr );
100
+ memcpy (pud , pud_k , num_entries );
101
+ if (pud_index (vaddr ) > 0 ) {
102
+ left_vaddr = vaddr + (num_entries * PUD_SIZE );
103
+ pud_k = pud_offset (pgd_offset_k (left_vaddr ),
104
+ left_vaddr );
105
+ memcpy (pud + num_entries , pud_k , pud_index (vaddr ));
106
+ }
107
+ pgd_populate (NULL , pgd_offset_k (i * PGDIR_SIZE ), pud );
95
108
}
96
109
out :
97
110
__flush_tlb_all ();
@@ -106,6 +119,8 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd)
106
119
*/
107
120
int pgd_idx ;
108
121
int nr_pgds ;
122
+ pud_t * pud ;
123
+ pgd_t * pgd ;
109
124
110
125
if (!efi_enabled (EFI_OLD_MEMMAP )) {
111
126
write_cr3 ((unsigned long )save_pgd );
@@ -115,8 +130,12 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd)
115
130
116
131
nr_pgds = DIV_ROUND_UP ((max_pfn << PAGE_SHIFT ) , PGDIR_SIZE );
117
132
118
- for (pgd_idx = 0 ; pgd_idx < nr_pgds ; pgd_idx ++ )
133
+ for (pgd_idx = 0 ; pgd_idx < nr_pgds ; pgd_idx ++ ) {
134
+ pgd = pgd_offset_k (pgd_idx * PGDIR_SIZE );
135
+ pud = (pud_t * )pgd_page_vaddr (* pgd );
136
+ pud_free (NULL , pud );
119
137
set_pgd (pgd_offset_k (pgd_idx * PGDIR_SIZE ), save_pgd [pgd_idx ]);
138
+ }
120
139
121
140
kfree (save_pgd );
122
141
0 commit comments