@@ -171,12 +171,15 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
171
171
gfn_t table_gfn ;
172
172
unsigned index , pt_access , pte_access ;
173
173
gpa_t pte_gpa ;
174
- bool eperm , last_gpte ;
174
+ bool eperm ;
175
175
int offset ;
176
176
const int write_fault = access & PFERR_WRITE_MASK ;
177
177
const int user_fault = access & PFERR_USER_MASK ;
178
178
const int fetch_fault = access & PFERR_FETCH_MASK ;
179
179
u16 errcode = 0 ;
180
+ gpa_t real_gpa ;
181
+ gfn_t gfn ;
182
+ u32 ac ;
180
183
181
184
trace_kvm_mmu_pagetable_walk (addr , access );
182
185
retry_walk :
@@ -197,12 +200,16 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
197
200
ASSERT ((!is_long_mode (vcpu ) && is_pae (vcpu )) ||
198
201
(mmu -> get_cr3 (vcpu ) & CR3_NONPAE_RESERVED_BITS ) == 0 );
199
202
200
- pt_access = ACC_ALL ;
203
+ pt_access = pte_access = ACC_ALL ;
204
+ ++ walker -> level ;
201
205
202
- for (;;) {
206
+ do {
203
207
gfn_t real_gfn ;
204
208
unsigned long host_addr ;
205
209
210
+ pt_access &= pte_access ;
211
+ -- walker -> level ;
212
+
206
213
index = PT_INDEX (addr , walker -> level );
207
214
208
215
table_gfn = gpte_to_gfn (pte );
@@ -239,46 +246,29 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
239
246
240
247
pte_access = pt_access & gpte_access (vcpu , pte );
241
248
242
- last_gpte = FNAME (is_last_gpte )(walker , vcpu , mmu , pte );
243
-
244
249
walker -> ptes [walker -> level - 1 ] = pte ;
245
-
246
- if (last_gpte ) {
247
- int lvl = walker -> level ;
248
- gpa_t real_gpa ;
249
- gfn_t gfn ;
250
- u32 ac ;
251
-
252
- gfn = gpte_to_gfn_lvl (pte , lvl );
253
- gfn += (addr & PT_LVL_OFFSET_MASK (lvl )) >> PAGE_SHIFT ;
254
-
255
- if (PTTYPE == 32 &&
256
- walker -> level == PT_DIRECTORY_LEVEL &&
257
- is_cpuid_PSE36 ())
258
- gfn += pse36_gfn_delta (pte );
259
-
260
- ac = write_fault | fetch_fault | user_fault ;
261
-
262
- real_gpa = mmu -> translate_gpa (vcpu , gfn_to_gpa (gfn ),
263
- ac );
264
- if (real_gpa == UNMAPPED_GVA )
265
- return 0 ;
266
-
267
- walker -> gfn = real_gpa >> PAGE_SHIFT ;
268
-
269
- break ;
270
- }
271
-
272
- pt_access &= pte_access ;
273
- -- walker -> level ;
274
- }
250
+ } while (!FNAME (is_last_gpte )(walker , vcpu , mmu , pte ));
275
251
276
252
eperm |= permission_fault (mmu , pte_access , access );
277
253
if (unlikely (eperm )) {
278
254
errcode |= PFERR_PRESENT_MASK ;
279
255
goto error ;
280
256
}
281
257
258
+ gfn = gpte_to_gfn_lvl (pte , walker -> level );
259
+ gfn += (addr & PT_LVL_OFFSET_MASK (walker -> level )) >> PAGE_SHIFT ;
260
+
261
+ if (PTTYPE == 32 && walker -> level == PT_DIRECTORY_LEVEL && is_cpuid_PSE36 ())
262
+ gfn += pse36_gfn_delta (pte );
263
+
264
+ ac = write_fault | fetch_fault | user_fault ;
265
+
266
+ real_gpa = mmu -> translate_gpa (vcpu , gfn_to_gpa (gfn ), ac );
267
+ if (real_gpa == UNMAPPED_GVA )
268
+ return 0 ;
269
+
270
+ walker -> gfn = real_gpa >> PAGE_SHIFT ;
271
+
282
272
if (!write_fault )
283
273
protect_clean_gpte (& pte_access , pte );
284
274
0 commit comments