aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2010-09-10 11:30:46 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:52:33 -0400
commit8df25a328a6ca3bd0f048278f4d5ae0a1f6fadc1 (patch)
tree613b4e3c09fa90a7a52b4283cc0687ce547bd5c7 /arch/x86
parent3241f22da85d26505b39f525a88f52ebd1235975 (diff)
KVM: MMU: Track page fault data in struct vcpu
This patch introduces a struct with two new fields in vcpu_arch for x86: * fault.address * fault.error_code This will be used to correctly propagate page faults back into the guest when we could have either an ordinary page fault or a nested page fault. In the case of a nested page fault the fault-address is different from the original address that should be walked. So we need to keep track about the real fault-address. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/include/asm/kvm_emulate.h1
-rw-r--r--arch/x86/include/asm/kvm_host.h17
-rw-r--r--arch/x86/kvm/emulate.c30
-rw-r--r--arch/x86/kvm/mmu.c6
-rw-r--r--arch/x86/kvm/paging_tmpl.h6
-rw-r--r--arch/x86/kvm/x86.c9
6 files changed, 38 insertions, 31 deletions
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 1bf11400ae9..5187dd88019 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -229,7 +229,6 @@ struct x86_emulate_ctxt {
229 int exception; /* exception that happens during emulation or -1 */ 229 int exception; /* exception that happens during emulation or -1 */
230 u32 error_code; /* error code for exception */ 230 u32 error_code; /* error code for exception */
231 bool error_code_valid; 231 bool error_code_valid;
232 unsigned long cr2; /* faulted address in case of #PF */
233 232
234 /* decode cache */ 233 /* decode cache */
235 struct decode_cache decode; 234 struct decode_cache decode;
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 009a4a1b370..3fde5b32253 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -239,9 +239,7 @@ struct kvm_mmu {
239 void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long root); 239 void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long root);
240 unsigned long (*get_cr3)(struct kvm_vcpu *vcpu); 240 unsigned long (*get_cr3)(struct kvm_vcpu *vcpu);
241 int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err); 241 int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err);
242 void (*inject_page_fault)(struct kvm_vcpu *vcpu, 242 void (*inject_page_fault)(struct kvm_vcpu *vcpu);
243 unsigned long addr,
244 u32 error_code);
245 void (*free)(struct kvm_vcpu *vcpu); 243 void (*free)(struct kvm_vcpu *vcpu);
246 gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access, 244 gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access,
247 u32 *error); 245 u32 *error);
@@ -288,6 +286,16 @@ struct kvm_vcpu_arch {
288 bool tpr_access_reporting; 286 bool tpr_access_reporting;
289 287
290 struct kvm_mmu mmu; 288 struct kvm_mmu mmu;
289
290 /*
291 * This struct is filled with the necessary information to propagate a
292 * page fault into the guest
293 */
294 struct {
295 u64 address;
296 unsigned error_code;
297 } fault;
298
291 /* only needed in kvm_pv_mmu_op() path, but it's hot so 299 /* only needed in kvm_pv_mmu_op() path, but it's hot so
292 * put it here to avoid allocation */ 300 * put it here to avoid allocation */
293 struct kvm_pv_mmu_op_buffer mmu_op_buffer; 301 struct kvm_pv_mmu_op_buffer mmu_op_buffer;
@@ -624,8 +632,7 @@ void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr);
624void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code); 632void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
625void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsigned nr); 633void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsigned nr);
626void kvm_requeue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code); 634void kvm_requeue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
627void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long cr2, 635void kvm_inject_page_fault(struct kvm_vcpu *vcpu);
628 u32 error_code);
629bool kvm_require_cpl(struct kvm_vcpu *vcpu, int required_cpl); 636bool kvm_require_cpl(struct kvm_vcpu *vcpu, int required_cpl);
630 637
631int kvm_pic_set_irq(void *opaque, int irq, int level); 638int kvm_pic_set_irq(void *opaque, int irq, int level);
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 27d2c22b114..2b08b78b6ca 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -487,11 +487,9 @@ static void emulate_gp(struct x86_emulate_ctxt *ctxt, int err)
487 emulate_exception(ctxt, GP_VECTOR, err, true); 487 emulate_exception(ctxt, GP_VECTOR, err, true);
488} 488}
489 489
490static void emulate_pf(struct x86_emulate_ctxt *ctxt, unsigned long addr, 490static void emulate_pf(struct x86_emulate_ctxt *ctxt)
491 int err)
492{ 491{
493 ctxt->cr2 = addr; 492 emulate_exception(ctxt, PF_VECTOR, 0, true);
494 emulate_exception(ctxt, PF_VECTOR, err, true);
495} 493}
496 494
497static void emulate_ud(struct x86_emulate_ctxt *ctxt) 495static void emulate_ud(struct x86_emulate_ctxt *ctxt)
@@ -834,7 +832,7 @@ static int read_emulated(struct x86_emulate_ctxt *ctxt,
834 rc = ops->read_emulated(addr, mc->data + mc->end, n, &err, 832 rc = ops->read_emulated(addr, mc->data + mc->end, n, &err,
835 ctxt->vcpu); 833 ctxt->vcpu);
836 if (rc == X86EMUL_PROPAGATE_FAULT) 834 if (rc == X86EMUL_PROPAGATE_FAULT)
837 emulate_pf(ctxt, addr, err); 835 emulate_pf(ctxt);
838 if (rc != X86EMUL_CONTINUE) 836 if (rc != X86EMUL_CONTINUE)
839 return rc; 837 return rc;
840 mc->end += n; 838 mc->end += n;
@@ -921,7 +919,7 @@ static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt,
921 addr = dt.address + index * 8; 919 addr = dt.address + index * 8;
922 ret = ops->read_std(addr, desc, sizeof *desc, ctxt->vcpu, &err); 920 ret = ops->read_std(addr, desc, sizeof *desc, ctxt->vcpu, &err);
923 if (ret == X86EMUL_PROPAGATE_FAULT) 921 if (ret == X86EMUL_PROPAGATE_FAULT)
924 emulate_pf(ctxt, addr, err); 922 emulate_pf(ctxt);
925 923
926 return ret; 924 return ret;
927} 925}
@@ -947,7 +945,7 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
947 addr = dt.address + index * 8; 945 addr = dt.address + index * 8;
948 ret = ops->write_std(addr, desc, sizeof *desc, ctxt->vcpu, &err); 946 ret = ops->write_std(addr, desc, sizeof *desc, ctxt->vcpu, &err);
949 if (ret == X86EMUL_PROPAGATE_FAULT) 947 if (ret == X86EMUL_PROPAGATE_FAULT)
950 emulate_pf(ctxt, addr, err); 948 emulate_pf(ctxt);
951 949
952 return ret; 950 return ret;
953} 951}
@@ -1117,7 +1115,7 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt,
1117 &err, 1115 &err,
1118 ctxt->vcpu); 1116 ctxt->vcpu);
1119 if (rc == X86EMUL_PROPAGATE_FAULT) 1117 if (rc == X86EMUL_PROPAGATE_FAULT)
1120 emulate_pf(ctxt, c->dst.addr.mem, err); 1118 emulate_pf(ctxt);
1121 if (rc != X86EMUL_CONTINUE) 1119 if (rc != X86EMUL_CONTINUE)
1122 return rc; 1120 return rc;
1123 break; 1121 break;
@@ -1939,7 +1937,7 @@ static int task_switch_16(struct x86_emulate_ctxt *ctxt,
1939 &err); 1937 &err);
1940 if (ret == X86EMUL_PROPAGATE_FAULT) { 1938 if (ret == X86EMUL_PROPAGATE_FAULT) {
1941 /* FIXME: need to provide precise fault address */ 1939 /* FIXME: need to provide precise fault address */
1942 emulate_pf(ctxt, old_tss_base, err); 1940 emulate_pf(ctxt);
1943 return ret; 1941 return ret;
1944 } 1942 }
1945 1943
@@ -1949,7 +1947,7 @@ static int task_switch_16(struct x86_emulate_ctxt *ctxt,
1949 &err); 1947 &err);
1950 if (ret == X86EMUL_PROPAGATE_FAULT) { 1948 if (ret == X86EMUL_PROPAGATE_FAULT) {
1951 /* FIXME: need to provide precise fault address */ 1949 /* FIXME: need to provide precise fault address */
1952 emulate_pf(ctxt, old_tss_base, err); 1950 emulate_pf(ctxt);
1953 return ret; 1951 return ret;
1954 } 1952 }
1955 1953
@@ -1957,7 +1955,7 @@ static int task_switch_16(struct x86_emulate_ctxt *ctxt,
1957 &err); 1955 &err);
1958 if (ret == X86EMUL_PROPAGATE_FAULT) { 1956 if (ret == X86EMUL_PROPAGATE_FAULT) {
1959 /* FIXME: need to provide precise fault address */ 1957 /* FIXME: need to provide precise fault address */
1960 emulate_pf(ctxt, new_tss_base, err); 1958 emulate_pf(ctxt);
1961 return ret; 1959 return ret;
1962 } 1960 }
1963 1961
@@ -1970,7 +1968,7 @@ static int task_switch_16(struct x86_emulate_ctxt *ctxt,
1970 ctxt->vcpu, &err); 1968 ctxt->vcpu, &err);
1971 if (ret == X86EMUL_PROPAGATE_FAULT) { 1969 if (ret == X86EMUL_PROPAGATE_FAULT) {
1972 /* FIXME: need to provide precise fault address */ 1970 /* FIXME: need to provide precise fault address */
1973 emulate_pf(ctxt, new_tss_base, err); 1971 emulate_pf(ctxt);
1974 return ret; 1972 return ret;
1975 } 1973 }
1976 } 1974 }
@@ -2081,7 +2079,7 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
2081 &err); 2079 &err);
2082 if (ret == X86EMUL_PROPAGATE_FAULT) { 2080 if (ret == X86EMUL_PROPAGATE_FAULT) {
2083 /* FIXME: need to provide precise fault address */ 2081 /* FIXME: need to provide precise fault address */
2084 emulate_pf(ctxt, old_tss_base, err); 2082 emulate_pf(ctxt);
2085 return ret; 2083 return ret;
2086 } 2084 }
2087 2085
@@ -2091,7 +2089,7 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
2091 &err); 2089 &err);
2092 if (ret == X86EMUL_PROPAGATE_FAULT) { 2090 if (ret == X86EMUL_PROPAGATE_FAULT) {
2093 /* FIXME: need to provide precise fault address */ 2091 /* FIXME: need to provide precise fault address */
2094 emulate_pf(ctxt, old_tss_base, err); 2092 emulate_pf(ctxt);
2095 return ret; 2093 return ret;
2096 } 2094 }
2097 2095
@@ -2099,7 +2097,7 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
2099 &err); 2097 &err);
2100 if (ret == X86EMUL_PROPAGATE_FAULT) { 2098 if (ret == X86EMUL_PROPAGATE_FAULT) {
2101 /* FIXME: need to provide precise fault address */ 2099 /* FIXME: need to provide precise fault address */
2102 emulate_pf(ctxt, new_tss_base, err); 2100 emulate_pf(ctxt);
2103 return ret; 2101 return ret;
2104 } 2102 }
2105 2103
@@ -2112,7 +2110,7 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
2112 ctxt->vcpu, &err); 2110 ctxt->vcpu, &err);
2113 if (ret == X86EMUL_PROPAGATE_FAULT) { 2111 if (ret == X86EMUL_PROPAGATE_FAULT) {
2114 /* FIXME: need to provide precise fault address */ 2112 /* FIXME: need to provide precise fault address */
2115 emulate_pf(ctxt, new_tss_base, err); 2113 emulate_pf(ctxt);
2116 return ret; 2114 return ret;
2117 } 2115 }
2118 } 2116 }
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 86f7557cf3f..99367274b97 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2566,11 +2566,9 @@ static unsigned long get_cr3(struct kvm_vcpu *vcpu)
2566 return vcpu->arch.cr3; 2566 return vcpu->arch.cr3;
2567} 2567}
2568 2568
2569static void inject_page_fault(struct kvm_vcpu *vcpu, 2569static void inject_page_fault(struct kvm_vcpu *vcpu)
2570 u64 addr,
2571 u32 err_code)
2572{ 2570{
2573 vcpu->arch.mmu.inject_page_fault(vcpu, addr, err_code); 2571 vcpu->arch.mmu.inject_page_fault(vcpu);
2574} 2572}
2575 2573
2576static void paging_free(struct kvm_vcpu *vcpu) 2574static void paging_free(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 68ee1b7fa89..d07f48a06f0 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -258,6 +258,10 @@ error:
258 walker->error_code |= PFERR_FETCH_MASK; 258 walker->error_code |= PFERR_FETCH_MASK;
259 if (rsvd_fault) 259 if (rsvd_fault)
260 walker->error_code |= PFERR_RSVD_MASK; 260 walker->error_code |= PFERR_RSVD_MASK;
261
262 vcpu->arch.fault.address = addr;
263 vcpu->arch.fault.error_code = walker->error_code;
264
261 trace_kvm_mmu_walker_error(walker->error_code); 265 trace_kvm_mmu_walker_error(walker->error_code);
262 return 0; 266 return 0;
263} 267}
@@ -521,7 +525,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
521 */ 525 */
522 if (!r) { 526 if (!r) {
523 pgprintk("%s: guest page fault\n", __func__); 527 pgprintk("%s: guest page fault\n", __func__);
524 inject_page_fault(vcpu, addr, walker.error_code); 528 inject_page_fault(vcpu);
525 vcpu->arch.last_pt_write_count = 0; /* reset fork detector */ 529 vcpu->arch.last_pt_write_count = 0; /* reset fork detector */
526 return 0; 530 return 0;
527 } 531 }
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 9d434777154..48b74d2fbfb 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -329,11 +329,12 @@ void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsigned nr)
329} 329}
330EXPORT_SYMBOL_GPL(kvm_requeue_exception); 330EXPORT_SYMBOL_GPL(kvm_requeue_exception);
331 331
332void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long addr, 332void kvm_inject_page_fault(struct kvm_vcpu *vcpu)
333 u32 error_code)
334{ 333{
334 unsigned error_code = vcpu->arch.fault.error_code;
335
335 ++vcpu->stat.pf_guest; 336 ++vcpu->stat.pf_guest;
336 vcpu->arch.cr2 = addr; 337 vcpu->arch.cr2 = vcpu->arch.fault.address;
337 kvm_queue_exception_e(vcpu, PF_VECTOR, error_code); 338 kvm_queue_exception_e(vcpu, PF_VECTOR, error_code);
338} 339}
339 340
@@ -4080,7 +4081,7 @@ static void inject_emulated_exception(struct kvm_vcpu *vcpu)
4080{ 4081{
4081 struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt; 4082 struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
4082 if (ctxt->exception == PF_VECTOR) 4083 if (ctxt->exception == PF_VECTOR)
4083 kvm_inject_page_fault(vcpu, ctxt->cr2, ctxt->error_code); 4084 kvm_inject_page_fault(vcpu);
4084 else if (ctxt->error_code_valid) 4085 else if (ctxt->error_code_valid)
4085 kvm_queue_exception_e(vcpu, ctxt->exception, ctxt->error_code); 4086 kvm_queue_exception_e(vcpu, ctxt->exception, ctxt->error_code);
4086 else 4087 else