mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-01 06:33:07 +00:00
KVM: Replace page fault injection by the generalized exception queue
Signed-off-by: Avi Kivity <avi@qumranet.com>
This commit is contained in:
parent
298101da2f
commit
c3c91fee51
5 changed files with 19 additions and 71 deletions
|
@ -1081,7 +1081,7 @@ static void inject_page_fault(struct kvm_vcpu *vcpu,
|
||||||
u64 addr,
|
u64 addr,
|
||||||
u32 err_code)
|
u32 err_code)
|
||||||
{
|
{
|
||||||
kvm_x86_ops->inject_page_fault(vcpu, addr, err_code);
|
kvm_inject_page_fault(vcpu, addr, err_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void paging_free(struct kvm_vcpu *vcpu)
|
static void paging_free(struct kvm_vcpu *vcpu)
|
||||||
|
|
|
@ -225,12 +225,6 @@ static void inject_ud(struct kvm_vcpu *vcpu)
|
||||||
UD_VECTOR;
|
UD_VECTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_page_fault(uint32_t info)
|
|
||||||
{
|
|
||||||
info &= SVM_EVTINJ_VEC_MASK | SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
|
|
||||||
return info == (PF_VECTOR | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_EXEPT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int is_external_interrupt(u32 info)
|
static int is_external_interrupt(u32 info)
|
||||||
{
|
{
|
||||||
info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
|
info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
|
||||||
|
@ -1624,34 +1618,6 @@ static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void svm_inject_page_fault(struct kvm_vcpu *vcpu,
|
|
||||||
unsigned long addr,
|
|
||||||
uint32_t err_code)
|
|
||||||
{
|
|
||||||
struct vcpu_svm *svm = to_svm(vcpu);
|
|
||||||
uint32_t exit_int_info = svm->vmcb->control.exit_int_info;
|
|
||||||
|
|
||||||
++vcpu->stat.pf_guest;
|
|
||||||
|
|
||||||
if (is_page_fault(exit_int_info)) {
|
|
||||||
|
|
||||||
svm->vmcb->control.event_inj_err = 0;
|
|
||||||
svm->vmcb->control.event_inj = SVM_EVTINJ_VALID |
|
|
||||||
SVM_EVTINJ_VALID_ERR |
|
|
||||||
SVM_EVTINJ_TYPE_EXEPT |
|
|
||||||
DF_VECTOR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vcpu->cr2 = addr;
|
|
||||||
svm->vmcb->save.cr2 = addr;
|
|
||||||
svm->vmcb->control.event_inj = SVM_EVTINJ_VALID |
|
|
||||||
SVM_EVTINJ_VALID_ERR |
|
|
||||||
SVM_EVTINJ_TYPE_EXEPT |
|
|
||||||
PF_VECTOR;
|
|
||||||
svm->vmcb->control.event_inj_err = err_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int is_disabled(void)
|
static int is_disabled(void)
|
||||||
{
|
{
|
||||||
u64 vm_cr;
|
u64 vm_cr;
|
||||||
|
@ -1721,7 +1687,6 @@ static struct kvm_x86_ops svm_x86_ops = {
|
||||||
.set_rflags = svm_set_rflags,
|
.set_rflags = svm_set_rflags,
|
||||||
|
|
||||||
.tlb_flush = svm_flush_tlb,
|
.tlb_flush = svm_flush_tlb,
|
||||||
.inject_page_fault = svm_inject_page_fault,
|
|
||||||
|
|
||||||
.inject_gp = svm_inject_gp,
|
.inject_gp = svm_inject_gp,
|
||||||
|
|
||||||
|
|
|
@ -2487,37 +2487,6 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
|
||||||
asm("int $2");
|
asm("int $2");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vmx_inject_page_fault(struct kvm_vcpu *vcpu,
|
|
||||||
unsigned long addr,
|
|
||||||
u32 err_code)
|
|
||||||
{
|
|
||||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
|
||||||
u32 vect_info = vmx->idt_vectoring_info;
|
|
||||||
|
|
||||||
++vcpu->stat.pf_guest;
|
|
||||||
|
|
||||||
if (is_page_fault(vect_info)) {
|
|
||||||
printk(KERN_DEBUG "inject_page_fault: "
|
|
||||||
"double fault 0x%lx @ 0x%lx\n",
|
|
||||||
addr, vmcs_readl(GUEST_RIP));
|
|
||||||
vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, 0);
|
|
||||||
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
|
|
||||||
DF_VECTOR |
|
|
||||||
INTR_TYPE_EXCEPTION |
|
|
||||||
INTR_INFO_DELIEVER_CODE_MASK |
|
|
||||||
INTR_INFO_VALID_MASK);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vcpu->cr2 = addr;
|
|
||||||
vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, err_code);
|
|
||||||
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
|
|
||||||
PF_VECTOR |
|
|
||||||
INTR_TYPE_EXCEPTION |
|
|
||||||
INTR_INFO_DELIEVER_CODE_MASK |
|
|
||||||
INTR_INFO_VALID_MASK);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vmx_free_vmcs(struct kvm_vcpu *vcpu)
|
static void vmx_free_vmcs(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||||
|
@ -2649,7 +2618,6 @@ static struct kvm_x86_ops vmx_x86_ops = {
|
||||||
.set_rflags = vmx_set_rflags,
|
.set_rflags = vmx_set_rflags,
|
||||||
|
|
||||||
.tlb_flush = vmx_flush_tlb,
|
.tlb_flush = vmx_flush_tlb,
|
||||||
.inject_page_fault = vmx_inject_page_fault,
|
|
||||||
|
|
||||||
.inject_gp = vmx_inject_gp,
|
.inject_gp = vmx_inject_gp,
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,21 @@ void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kvm_queue_exception);
|
EXPORT_SYMBOL_GPL(kvm_queue_exception);
|
||||||
|
|
||||||
|
void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long addr,
|
||||||
|
u32 error_code)
|
||||||
|
{
|
||||||
|
++vcpu->stat.pf_guest;
|
||||||
|
if (vcpu->exception.pending && vcpu->exception.nr == PF_VECTOR) {
|
||||||
|
printk(KERN_DEBUG "kvm: inject_page_fault:"
|
||||||
|
" double fault 0x%lx\n", addr);
|
||||||
|
vcpu->exception.nr = DF_VECTOR;
|
||||||
|
vcpu->exception.error_code = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vcpu->cr2 = addr;
|
||||||
|
kvm_queue_exception_e(vcpu, PF_VECTOR, error_code);
|
||||||
|
}
|
||||||
|
|
||||||
void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code)
|
void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code)
|
||||||
{
|
{
|
||||||
WARN_ON(vcpu->exception.pending);
|
WARN_ON(vcpu->exception.pending);
|
||||||
|
@ -1601,7 +1616,7 @@ static int emulator_write_emulated_onepage(unsigned long addr,
|
||||||
gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
|
gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
|
||||||
|
|
||||||
if (gpa == UNMAPPED_GVA) {
|
if (gpa == UNMAPPED_GVA) {
|
||||||
kvm_x86_ops->inject_page_fault(vcpu, addr, 2);
|
kvm_inject_page_fault(vcpu, addr, 2);
|
||||||
return X86EMUL_PROPAGATE_FAULT;
|
return X86EMUL_PROPAGATE_FAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -219,8 +219,6 @@ struct kvm_x86_ops {
|
||||||
void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
|
void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
|
||||||
|
|
||||||
void (*tlb_flush)(struct kvm_vcpu *vcpu);
|
void (*tlb_flush)(struct kvm_vcpu *vcpu);
|
||||||
void (*inject_page_fault)(struct kvm_vcpu *vcpu,
|
|
||||||
unsigned long addr, u32 err_code);
|
|
||||||
|
|
||||||
void (*inject_gp)(struct kvm_vcpu *vcpu, unsigned err_code);
|
void (*inject_gp)(struct kvm_vcpu *vcpu, unsigned err_code);
|
||||||
|
|
||||||
|
@ -306,6 +304,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data);
|
||||||
|
|
||||||
void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr);
|
void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr);
|
||||||
void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
|
void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
|
||||||
|
void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long cr2,
|
||||||
|
u32 error_code);
|
||||||
|
|
||||||
void fx_init(struct kvm_vcpu *vcpu);
|
void fx_init(struct kvm_vcpu *vcpu);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue