aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/kvm')
-rw-r--r--drivers/kvm/mmu.c6
-rw-r--r--drivers/kvm/paging_tmpl.h15
2 files changed, 18 insertions, 3 deletions
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index a05d0609d918..22c426cd8cb2 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -143,6 +143,7 @@ static int dbg = 1;
143#define PFERR_PRESENT_MASK (1U << 0) 143#define PFERR_PRESENT_MASK (1U << 0)
144#define PFERR_WRITE_MASK (1U << 1) 144#define PFERR_WRITE_MASK (1U << 1)
145#define PFERR_USER_MASK (1U << 2) 145#define PFERR_USER_MASK (1U << 2)
146#define PFERR_FETCH_MASK (1U << 4)
146 147
147#define PT64_ROOT_LEVEL 4 148#define PT64_ROOT_LEVEL 4
148#define PT32_ROOT_LEVEL 2 149#define PT32_ROOT_LEVEL 2
@@ -168,6 +169,11 @@ static int is_cpuid_PSE36(void)
168 return 1; 169 return 1;
169} 170}
170 171
172static int is_nx(struct kvm_vcpu *vcpu)
173{
174 return vcpu->shadow_efer & EFER_NX;
175}
176
171static int is_present_pte(unsigned long pte) 177static int is_present_pte(unsigned long pte)
172{ 178{
173 return pte & PT_PRESENT_MASK; 179 return pte & PT_PRESENT_MASK;
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index afcd2a8f45bb..149fa45fd9a5 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -71,7 +71,7 @@ struct guest_walker {
71 */ 71 */
72static int FNAME(walk_addr)(struct guest_walker *walker, 72static int FNAME(walk_addr)(struct guest_walker *walker,
73 struct kvm_vcpu *vcpu, gva_t addr, 73 struct kvm_vcpu *vcpu, gva_t addr,
74 int write_fault, int user_fault) 74 int write_fault, int user_fault, int fetch_fault)
75{ 75{
76 hpa_t hpa; 76 hpa_t hpa;
77 struct kvm_memory_slot *slot; 77 struct kvm_memory_slot *slot;
@@ -123,6 +123,11 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
123 if (user_fault && !(*ptep & PT_USER_MASK)) 123 if (user_fault && !(*ptep & PT_USER_MASK))
124 goto access_error; 124 goto access_error;
125 125
126#if PTTYPE == 64
127 if (fetch_fault && is_nx(vcpu) && (*ptep & PT64_NX_MASK))
128 goto access_error;
129#endif
130
126 if (!(*ptep & PT_ACCESSED_MASK)) 131 if (!(*ptep & PT_ACCESSED_MASK))
127 *ptep |= PT_ACCESSED_MASK; /* avoid rmw */ 132 *ptep |= PT_ACCESSED_MASK; /* avoid rmw */
128 133
@@ -169,6 +174,8 @@ err:
169 walker->error_code |= PFERR_WRITE_MASK; 174 walker->error_code |= PFERR_WRITE_MASK;
170 if (user_fault) 175 if (user_fault)
171 walker->error_code |= PFERR_USER_MASK; 176 walker->error_code |= PFERR_USER_MASK;
177 if (fetch_fault)
178 walker->error_code |= PFERR_FETCH_MASK;
172 return 0; 179 return 0;
173} 180}
174 181
@@ -372,6 +379,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
372{ 379{
373 int write_fault = error_code & PFERR_WRITE_MASK; 380 int write_fault = error_code & PFERR_WRITE_MASK;
374 int user_fault = error_code & PFERR_USER_MASK; 381 int user_fault = error_code & PFERR_USER_MASK;
382 int fetch_fault = error_code & PFERR_FETCH_MASK;
375 struct guest_walker walker; 383 struct guest_walker walker;
376 u64 *shadow_pte; 384 u64 *shadow_pte;
377 int fixed; 385 int fixed;
@@ -388,7 +396,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
388 /* 396 /*
389 * Look up the shadow pte for the faulting address. 397 * Look up the shadow pte for the faulting address.
390 */ 398 */
391 r = FNAME(walk_addr)(&walker, vcpu, addr, write_fault, user_fault); 399 r = FNAME(walk_addr)(&walker, vcpu, addr, write_fault, user_fault,
400 fetch_fault);
392 401
393 /* 402 /*
394 * The page is not mapped by the guest. Let the guest handle it. 403 * The page is not mapped by the guest. Let the guest handle it.
@@ -437,7 +446,7 @@ static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
437 pt_element_t guest_pte; 446 pt_element_t guest_pte;
438 gpa_t gpa; 447 gpa_t gpa;
439 448
440 FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0); 449 FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0);
441 guest_pte = *walker.ptep; 450 guest_pte = *walker.ptep;
442 FNAME(release_walker)(&walker); 451 FNAME(release_walker)(&walker);
443 452