From: kfraser@localhost.localdomain Date: Mon, 13 Nov 2006 12:01:43 +0000 (+0000) Subject: [XEN] Get rid of many uses of domain_crash_synchronous(). X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15551^2~12 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=7fd08736379e8db5cc440ccf718174d3cc511ce8;p=xen.git [XEN] Get rid of many uses of domain_crash_synchronous(). It is much more dangerous than domain_crash() because it stops execution of teh current context regardless of current state (e.g., IRQs disabled, locks held). The preferred method to crash a domain is domain_crash() and error return to the caller. Signed-off-by: Keir Fraser --- diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 63c1235a39..85775d5ae1 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -517,7 +517,8 @@ int hvm_bringup_ap(int vcpuid, int trampoline_vector) if ( bsp->vcpu_id != 0 ) { gdprintk(XENLOG_ERR, "Not calling hvm_bringup_ap from BSP context.\n"); - domain_crash_synchronous(); + domain_crash(bsp->domain); + return -EINVAL; } if ( (v = d->vcpu[vcpuid]) == NULL ) diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c index a145659f2d..ea93a59f8e 100644 --- a/xen/arch/x86/hvm/intercept.c +++ b/xen/arch/x86/hvm/intercept.c @@ -253,11 +253,7 @@ int register_io_handler( struct hvm_io_handler *handler = &d->arch.hvm_domain.io_handler; int num = handler->num_slot; - if ( num >= MAX_IO_HANDLER ) - { - printk("no extra space, register io interceptor failed!\n"); - domain_crash_synchronous(); - } + BUG_ON(num >= MAX_IO_HANDLER); handler->hdl_list[num].addr = addr; handler->hdl_list[num].size = size; diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 0976183bb7..2006f09cb5 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -81,9 +81,7 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r regs->ebx |= ((value & 0xFF) << 8); break; default: - printk("Error: size:%x, index:%x are invalid!\n", size, index); - domain_crash_synchronous(); - break; + goto crash; } break; case WORD: @@ -121,9 +119,7 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r regs->edi |= (value & 0xFFFF); break; default: - printk("Error: size:%x, index:%x are invalid!\n", size, index); - domain_crash_synchronous(); - break; + goto crash; } break; case LONG: @@ -153,15 +149,13 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r regs->edi = value; break; default: - printk("Error: size:%x, index:%x are invalid!\n", size, index); - domain_crash_synchronous(); - break; + goto crash; } break; default: - printk("Error: size:%x, index:%x are invalid!\n", size, index); + crash: + gdprintk(XENLOG_ERR, "size:%x, index:%x are invalid!\n", size, index); domain_crash_synchronous(); - break; } } #else @@ -184,7 +178,7 @@ static inline void __set_reg_value(unsigned long *reg, int size, long value) *reg = value; break; default: - printk("Error: <__set_reg_value>: size:%x is invalid\n", size); + gdprintk(XENLOG_ERR, "size:%x is invalid\n", size); domain_crash_synchronous(); } } @@ -226,7 +220,8 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r regs->rbx |= ((value & 0xFF) << 8); break; default: - printk("Error: size:%x, index:%x are invalid!\n", size, index); + gdprintk(XENLOG_ERR, "size:%x, index:%x are invalid!\n", + size, index); domain_crash_synchronous(); break; } @@ -283,7 +278,7 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r __set_reg_value(®s->r15, size, value); break; default: - printk("Error: Invalid index\n"); + gdprintk(XENLOG_ERR, "Invalid index\n"); domain_crash_synchronous(); } return; diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index 0afae0e4d6..eb495a1417 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -731,8 +731,7 @@ static void hvm_send_assist_req(struct vcpu *v) { /* This indicates a bug in the device model. Crash the domain. */ gdprintk(XENLOG_ERR, "Device model set bad IO state %d.\n", p->state); - domain_crash(v->domain); - return; + domain_crash_synchronous(); } prepare_wait_on_xen_event_channel(v->arch.hvm_vcpu.xen_port); diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 7b8bf46258..29c0a8d23c 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -326,14 +326,14 @@ static inline int long_mode_do_msr_read(struct cpu_user_regs *regs) static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) { u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32); - struct vcpu *vc = current; - struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb; + struct vcpu *v = current; + struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx " "msr_content %"PRIx64"\n", (unsigned long)regs->ecx, msr_content); - switch (regs->ecx) + switch ( regs->ecx ) { case MSR_EFER: #ifdef __x86_64__ @@ -342,24 +342,24 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) { printk("Trying to set reserved bit in EFER: %"PRIx64"\n", msr_content); - svm_inject_exception(vc, TRAP_gp_fault, 1, 0); + svm_inject_exception(v, TRAP_gp_fault, 1, 0); return 0; } /* LME: 0 -> 1 */ if ( msr_content & EFER_LME && - !test_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state)) + !test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state)) { - if ( svm_paging_enabled(vc) || + if ( svm_paging_enabled(v) || !test_bit(SVM_CPU_STATE_PAE_ENABLED, - &vc->arch.hvm_svm.cpu_state) ) + &v->arch.hvm_svm.cpu_state) ) { printk("Trying to set LME bit when " "in paging mode or PAE bit is not set\n"); - svm_inject_exception(vc, TRAP_gp_fault, 1, 0); + svm_inject_exception(v, TRAP_gp_fault, 1, 0); return 0; } - set_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state); + set_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state); } /* We have already recorded that we want LME, so it will be set @@ -374,13 +374,13 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) case MSR_FS_BASE: case MSR_GS_BASE: - if ( !svm_long_mode_enabled(vc) ) - domain_crash_synchronous(); + if ( !svm_long_mode_enabled(v) ) + goto exit_and_crash; if (!IS_CANO_ADDRESS(msr_content)) { HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n"); - svm_inject_exception(vc, TRAP_gp_fault, 1, 0); + svm_inject_exception(v, TRAP_gp_fault, 1, 0); } if (regs->ecx == MSR_FS_BASE) @@ -412,7 +412,13 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) default: return 0; } + return 1; + + exit_and_crash: + gdprintk(XENLOG_ERR, "Fatal error writing MSR %lx\n", (long)regs->ecx); + domain_crash(v->domain); + return 1; /* handled */ } @@ -421,7 +427,6 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) #define savedebug(_v,_reg) \ __asm__ __volatile__ ("mov %%db" #_reg ",%0" : : "r" ((_v)->debugreg[_reg])) - static inline void svm_save_dr(struct vcpu *v) { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; @@ -938,7 +943,8 @@ static void svm_do_general_protection_fault(struct vcpu *v, svm_dump_vmcb(__func__, vmcb); svm_dump_regs(__func__, regs); svm_dump_inst(vmcb->rip); - __hvm_bug(regs); + domain_crash(v->domain); + return; } HVM_DBG_LOG(DBG_LEVEL_1, @@ -1169,8 +1175,9 @@ static void svm_get_prefix_info( if (inst_copy_from_guest(inst, svm_rip2pointer(vmcb), sizeof(inst)) != MAX_INST_LEN) { - printk("%s: get guest instruction failed\n", __func__); - domain_crash_synchronous(); + gdprintk(XENLOG_ERR, "get guest instruction failed\n"); + domain_crash(current->domain); + return; } for (i = 0; i < MAX_INST_LEN; i++) @@ -1266,9 +1273,7 @@ static inline int svm_get_io_address( isize --; if (isize > 1) - { svm_get_prefix_info(vmcb, dir, &seg, &asize); - } ASSERT(dir == IOREQ_READ || dir == IOREQ_WRITE); @@ -1470,8 +1475,10 @@ static int svm_set_cr0(unsigned long value) mfn = get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT); if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain)) { - printk("Invalid CR3 value = %lx\n", v->arch.hvm_svm.cpu_cr3); - domain_crash_synchronous(); /* need to take a clean path */ + gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx (mfn=%lx)\n", + v->arch.hvm_svm.cpu_cr3, mfn); + domain_crash(v->domain); + return 0; } #if defined(__x86_64__) @@ -1556,7 +1563,7 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs) vmcb = v->arch.hvm_svm.vmcb; ASSERT(vmcb); - switch (cr) + switch ( cr ) { case 0: value = v->arch.hvm_svm.cpu_shadow_cr0; @@ -1582,7 +1589,8 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs) break; default: - __hvm_bug(regs); + domain_crash(v->domain); + return; } set_reg(gp, value, regs, vmcb); @@ -1602,14 +1610,11 @@ static inline int svm_pgbit_test(struct vcpu *v) */ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) { - unsigned long value; - unsigned long old_cr; + unsigned long value, old_cr, old_base_mfn, mfn; struct vcpu *v = current; struct vlapic *vlapic = vcpu_vlapic(v); struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - ASSERT(vmcb); - value = get_reg(gpreg, regs, vmcb); HVM_DBG_LOG(DBG_LEVEL_1, "mov_to_cr: CR%d, value = %lx,", cr, value); @@ -1623,8 +1628,6 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) return svm_set_cr0(value); case 3: - { - unsigned long old_base_mfn, mfn; if (svm_dbg_on) printk("CR3 write =%lx \n", value ); /* If paging is not enabled yet, simply copy the value to CR3. */ @@ -1644,7 +1647,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) */ mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); if (mfn != pagetable_get_pfn(v->arch.guest_table)) - __hvm_bug(regs); + goto bad_cr3; shadow_update_cr3(v); } else @@ -1656,10 +1659,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value); mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain)) - { - printk("Invalid CR3 value=%lx\n", value); - domain_crash_synchronous(); /* need to take a clean path */ - } + goto bad_cr3; old_base_mfn = pagetable_get_pfn(v->arch.guest_table); v->arch.guest_table = pagetable_from_pfn(mfn); @@ -1673,10 +1673,8 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value); } break; - } case 4: /* CR4 */ - { if (svm_dbg_on) printk( "write cr4=%lx, cr0=%lx\n", value, v->arch.hvm_svm.cpu_shadow_cr0 ); @@ -1692,10 +1690,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) mfn = get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT); if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) - { - printk("Invalid CR3 value = %lx", v->arch.hvm_svm.cpu_cr3); - domain_crash_synchronous(); /* need to take a clean path */ - } + goto bad_cr3; /* * Now arch.guest_table points to machine physical. @@ -1741,20 +1736,23 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) shadow_update_paging_modes(v); } break; - } case 8: - { vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4)); break; - } default: - printk("invalid cr: %d\n", cr); - __hvm_bug(regs); + gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr); + domain_crash(v->domain); + return 0; } return 1; + + bad_cr3: + gdprintk(XENLOG_ERR, "Invalid CR3\n"); + domain_crash(v->domain); + return 0; } @@ -1857,8 +1855,7 @@ static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type, break; default: - __hvm_bug(regs); - break; + BUG(); } ASSERT(inst_len); @@ -2037,16 +2034,15 @@ void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs) int inst_len; struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - ASSERT(vmcb); /* * Unknown how many bytes the invlpg instruction will take. Use the * maximum instruction length here */ if (inst_copy_from_guest(opcode, svm_rip2pointer(vmcb), length) < length) { - printk("svm_handle_invlpg (): Error reading memory %d bytes\n", - length); - __hvm_bug(regs); + gdprintk(XENLOG_ERR, "Error reading memory %d bytes\n", length); + domain_crash(v->domain); + return; } if (invlpga) @@ -2510,7 +2506,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) if (exit_reason == VMEXIT_INVALID) { svm_dump_vmcb(__func__, vmcb); - domain_crash_synchronous(); + goto exit_and_crash; } #ifdef SVM_EXTRA_DEBUG @@ -2734,8 +2730,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) break; case VMEXIT_TASK_SWITCH: - __hvm_bug(regs); - break; + goto exit_and_crash; case VMEXIT_CPUID: svm_vmexit_do_cpuid(vmcb, regs->eax, regs); @@ -2811,15 +2806,16 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) break; case VMEXIT_SHUTDOWN: - printk("Guest shutdown exit\n"); - domain_crash_synchronous(); - break; + gdprintk(XENLOG_ERR, "Guest shutdown exit\n"); + goto exit_and_crash; default: - printk("unexpected VMEXIT: exit reason = 0x%x, exitinfo1 = %"PRIx64", " - "exitinfo2 = %"PRIx64"\n", exit_reason, - (u64)vmcb->exitinfo1, (u64)vmcb->exitinfo2); - __hvm_bug(regs); /* should not happen */ + exit_and_crash: + gdprintk(XENLOG_ERR, "unexpected VMEXIT: exit reason = 0x%x, " + "exitinfo1 = %"PRIx64", exitinfo2 = %"PRIx64"\n", + exit_reason, + (u64)vmcb->exitinfo1, (u64)vmcb->exitinfo2); + domain_crash(v->domain); break; } @@ -2840,8 +2836,6 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) printk("svm_vmexit_handler: Returning\n"); } #endif - - return; } asmlinkage void svm_load_cr2(void) diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 91328ecc6d..45878d1c03 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -466,14 +466,14 @@ void vm_launch_fail(unsigned long eflags) { unsigned long error = __vmread(VM_INSTRUCTION_ERROR); printk(" error code %lx\n", error); - __hvm_bug(guest_cpu_user_regs()); + domain_crash_synchronous(); } void vm_resume_fail(unsigned long eflags) { unsigned long error = __vmread(VM_INSTRUCTION_ERROR); printk(" error code %lx\n", error); - __hvm_bug(guest_cpu_user_regs()); + domain_crash_synchronous(); } void arch_vmx_do_resume(struct vcpu *v) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 3cbea986d1..aceaf907e3 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -151,15 +151,14 @@ static inline int long_mode_do_msr_read(struct cpu_user_regs *regs) case MSR_FS_BASE: if ( !(vmx_long_mode_enabled(v)) ) - /* XXX should it be GP fault */ - domain_crash_synchronous(); + goto exit_and_crash; msr_content = __vmread(GUEST_FS_BASE); break; case MSR_GS_BASE: if ( !(vmx_long_mode_enabled(v)) ) - domain_crash_synchronous(); + goto exit_and_crash; msr_content = __vmread(GUEST_GS_BASE); break; @@ -183,6 +182,11 @@ static inline int long_mode_do_msr_read(struct cpu_user_regs *regs) regs->edx = (u32)(msr_content >> 32); return 1; + + exit_and_crash: + gdprintk(XENLOG_ERR, "Fatal error reading MSR %lx\n", (long)regs->ecx); + domain_crash(v->domain); + return 1; /* handled */ } static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) @@ -233,7 +237,7 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) case MSR_FS_BASE: case MSR_GS_BASE: if ( !(vmx_long_mode_enabled(v)) ) - domain_crash_synchronous(); + goto exit_and_crash; if ( !IS_CANO_ADDRESS(msr_content) ) { @@ -251,7 +255,7 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) case MSR_SHADOW_GS_BASE: if ( !(vmx_long_mode_enabled(v)) ) - domain_crash_synchronous(); + goto exit_and_crash; v->arch.hvm_vmx.msr_content.shadow_gs = msr_content; wrmsrl(MSR_SHADOW_GS_BASE, msr_content); @@ -267,6 +271,11 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) } return 1; + + exit_and_crash: + gdprintk(XENLOG_ERR, "Fatal error writing MSR %lx\n", (long)regs->ecx); + domain_crash(v->domain); + return 1; /* handled */ } static void vmx_restore_msrs(struct vcpu *v) @@ -726,8 +735,7 @@ static int __get_instruction_length(void) { int len; len = __vmread(VM_EXIT_INSTRUCTION_LEN); /* Safe: callers audited */ - if ( (len < 1) || (len > 15) ) - __hvm_bug(guest_cpu_user_regs()); + BUG_ON((len < 1) || (len > 15)); return len; } @@ -823,7 +831,10 @@ static void vmx_do_cpuid(struct cpu_user_regs *regs) /* 8-byte aligned valid pseudophys address from vmxassist, please. */ if ( (value & 7) || (mfn == INVALID_MFN) || !v->arch.hvm_vmx.vmxassist_enabled ) - domain_crash_synchronous(); + { + domain_crash(v->domain); + return; + } p = map_domain_page(mfn); value = *((uint64_t *)(p + (value & (PAGE_SIZE - 1)))); @@ -966,8 +977,9 @@ static int check_for_null_selector(unsigned long eip, int inst_len, int dir) memset(inst, 0, MAX_INST_LEN); if ( inst_copy_from_guest(inst, eip, inst_len) != inst_len ) { - printk("check_for_null_selector: get guest instruction failed\n"); - domain_crash_synchronous(); + gdprintk(XENLOG_ERR, "Get guest instruction failed\n"); + domain_crash(current->domain); + return 0; } for ( i = 0; i < inst_len; i++ ) @@ -1169,7 +1181,7 @@ static void vmx_world_save(struct vcpu *v, struct vmx_assist_context *c) c->ldtr_arbytes.bytes = __vmread(GUEST_LDTR_AR_BYTES); } -static void vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c) +static int vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c) { unsigned long mfn, old_base_mfn; @@ -1192,10 +1204,7 @@ static void vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c) */ mfn = get_mfn_from_gpfn(c->cr3 >> PAGE_SHIFT); if ( mfn != pagetable_get_pfn(v->arch.guest_table) ) - { - printk("Invalid CR3 value=%x", c->cr3); - domain_crash_synchronous(); - } + goto bad_cr3; } else { @@ -1205,13 +1214,8 @@ static void vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c) */ HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %x", c->cr3); mfn = get_mfn_from_gpfn(c->cr3 >> PAGE_SHIFT); - if ( !VALID_MFN(mfn) ) - { - printk("Invalid CR3 value=%x", c->cr3); - domain_crash_synchronous(); - } - if ( !get_page(mfn_to_page(mfn), v->domain) ) - domain_crash_synchronous(); + if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) + goto bad_cr3; old_base_mfn = pagetable_get_pfn(v->arch.guest_table); v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) @@ -1280,6 +1284,11 @@ static void vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c) shadow_update_paging_modes(v); __vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3); + return 0; + + bad_cr3: + gdprintk(XENLOG_ERR, "Invalid CR3 value=%x", c->cr3); + return -EINVAL; } enum { VMX_ASSIST_INVOKE = 0, VMX_ASSIST_RESTORE }; @@ -1320,7 +1329,8 @@ static int vmx_assist(struct vcpu *v, int mode) if (cp != 0) { if (hvm_copy_from_guest_phys(&c, cp, sizeof(c))) goto error; - vmx_world_restore(v, &c); + if ( vmx_world_restore(v, &c) != 0 ) + goto error; v->arch.hvm_vmx.vmxassist_enabled = 1; return 1; } @@ -1337,7 +1347,8 @@ static int vmx_assist(struct vcpu *v, int mode) if (cp != 0) { if (hvm_copy_from_guest_phys(&c, cp, sizeof(c))) goto error; - vmx_world_restore(v, &c); + if ( vmx_world_restore(v, &c) != 0 ) + goto error; v->arch.hvm_vmx.vmxassist_enabled = 0; return 1; } @@ -1345,8 +1356,8 @@ static int vmx_assist(struct vcpu *v, int mode) } error: - printk("Failed to transfer to vmxassist\n"); - domain_crash_synchronous(); + gdprintk(XENLOG_ERR, "Failed to transfer to vmxassist\n"); + domain_crash(v->domain); return 0; } @@ -1390,9 +1401,10 @@ static int vmx_set_cr0(unsigned long value) mfn = get_mfn_from_gpfn(v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT); if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) { - printk("Invalid CR3 value = %lx (mfn=%lx)\n", - v->arch.hvm_vmx.cpu_cr3, mfn); - domain_crash_synchronous(); /* need to take a clean path */ + gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx (mfn=%lx)\n", + v->arch.hvm_vmx.cpu_cr3, mfn); + domain_crash(v->domain); + return 0; } #if defined(__x86_64__) @@ -1536,12 +1548,12 @@ static int vmx_set_cr0(unsigned long value) */ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) { - unsigned long value; - unsigned long old_cr; + unsigned long value, old_cr, old_base_mfn, mfn; struct vcpu *v = current; struct vlapic *vlapic = vcpu_vlapic(v); - switch ( gp ) { + switch ( gp ) + { CASE_GET_REG(EAX, eax); CASE_GET_REG(ECX, ecx); CASE_GET_REG(EDX, edx); @@ -1554,8 +1566,8 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) value = __vmread(GUEST_RSP); break; default: - printk("invalid gp: %d\n", gp); - __hvm_bug(regs); + gdprintk(XENLOG_ERR, "invalid gp: %d\n", gp); + goto exit_and_crash; } TRACE_VMEXIT(1, TYPE_MOV_TO_CR); @@ -1564,13 +1576,12 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) HVM_DBG_LOG(DBG_LEVEL_1, "CR%d, value = %lx", cr, value); - switch ( cr ) { + switch ( cr ) + { case 0: return vmx_set_cr0(value); - case 3: - { - unsigned long old_base_mfn, mfn; + case 3: /* * If paging is not enabled yet, simply copy the value to CR3. */ @@ -1590,7 +1601,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) */ mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); if (mfn != pagetable_get_pfn(v->arch.guest_table)) - __hvm_bug(regs); + goto bad_cr3; shadow_update_cr3(v); } else { /* @@ -1600,10 +1611,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value); mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) - { - printk("Invalid CR3 value=%lx\n", value); - domain_crash_synchronous(); /* need to take a clean path */ - } + goto bad_cr3; old_base_mfn = pagetable_get_pfn(v->arch.guest_table); v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) @@ -1618,9 +1626,8 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) __vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3); } break; - } + case 4: /* CR4 */ - { old_cr = v->arch.hvm_vmx.cpu_shadow_cr4; if ( (value & X86_CR4_PAE) && !(old_cr & X86_CR4_PAE) ) @@ -1633,10 +1640,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) mfn = get_mfn_from_gpfn(v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT); if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) - { - printk("Invalid CR3 value = %lx", v->arch.hvm_vmx.cpu_cr3); - domain_crash_synchronous(); /* need to take a clean path */ - } + goto bad_cr3; /* * Now arch.guest_table points to machine physical. @@ -1682,18 +1686,24 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) if ( (old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE) ) shadow_update_paging_modes(v); break; - } + case 8: - { vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4)); break; - } + default: - printk("invalid cr: %d\n", gp); - __hvm_bug(regs); + gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr); + domain_crash(v->domain); + return 0; } return 1; + + bad_cr3: + gdprintk(XENLOG_ERR, "Invalid CR3\n"); + exit_and_crash: + domain_crash(v->domain); + return 0; } /* @@ -1715,7 +1725,9 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs) value = (value & 0xF0) >> 4; break; default: - __hvm_bug(regs); + gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr); + domain_crash(v->domain); + break; } switch ( gp ) { @@ -1733,7 +1745,8 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs) break; default: printk("invalid gp: %d\n", gp); - __hvm_bug(regs); + domain_crash(v->domain); + break; } TRACE_VMEXIT(1, TYPE_MOV_FROM_CR); @@ -1782,9 +1795,9 @@ static int vmx_cr_access(unsigned long exit_qualification, return vmx_set_cr0(value); break; default: - __hvm_bug(regs); - break; + BUG(); } + return 1; } @@ -2072,7 +2085,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs) printk("************* VMCS Area **************\n"); vmcs_dump_vcpu(); printk("**************************************\n"); - domain_crash_synchronous(); + goto exit_and_crash; } TRACE_VMEXIT(0, exit_reason); @@ -2186,8 +2199,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs) vmx_do_extint(regs); break; case EXIT_REASON_TRIPLE_FAULT: - domain_crash_synchronous(); - break; + goto exit_and_crash; case EXIT_REASON_PENDING_INTERRUPT: /* Disable the interrupt window. */ v->arch.hvm_vcpu.u.vmx.exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING; @@ -2195,8 +2207,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs) v->arch.hvm_vcpu.u.vmx.exec_control); break; case EXIT_REASON_TASK_SWITCH: - domain_crash_synchronous(); - break; + goto exit_and_crash; case EXIT_REASON_CPUID: inst_len = __get_instruction_length(); /* Safe: CPUID */ __update_guest_eip(inst_len); @@ -2261,8 +2272,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs) case EXIT_REASON_MWAIT_INSTRUCTION: case EXIT_REASON_MONITOR_INSTRUCTION: case EXIT_REASON_PAUSE_INSTRUCTION: - domain_crash_synchronous(); - break; + goto exit_and_crash; case EXIT_REASON_VMCLEAR: case EXIT_REASON_VMLAUNCH: case EXIT_REASON_VMPTRLD: @@ -2282,7 +2292,10 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs) break; default: - domain_crash_synchronous(); /* should not happen */ + exit_and_crash: + gdprintk(XENLOG_ERR, "Bad vmexit (reason %x)\n", exit_reason); + domain_crash(v->domain); + break; } } diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index d3b4d0287e..8e2ad2c788 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -1717,7 +1717,7 @@ int new_guest_cr3(unsigned long mfn) unsigned long old_base_mfn; if ( is_hvm_domain(d) && !hvm_paging_enabled(v) ) - domain_crash_synchronous(); + return 0; if ( shadow_mode_refcounts(d) ) { diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index f9e92f1b51..6e99417aef 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -1310,8 +1310,10 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) case 3: /* Write CR3 */ LOCK_BIGLOCK(v->domain); - (void)new_guest_cr3(gmfn_to_mfn(v->domain, xen_cr3_to_pfn(*reg))); + rc = new_guest_cr3(gmfn_to_mfn(v->domain, xen_cr3_to_pfn(*reg))); UNLOCK_BIGLOCK(v->domain); + if ( rc == 0 ) /* not okay */ + goto fail; break; case 4: diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index 14a7c30d93..409828bbae 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -179,16 +179,16 @@ unsigned long do_iret(void) /* Check worst-case stack frame for overlap with Xen protected area. */ if ( unlikely(!access_ok(regs->esp, 40)) ) - domain_crash_synchronous(); + goto exit_and_crash; /* Pop and restore EAX (clobbered by hypercall). */ if ( unlikely(__copy_from_user(®s->eax, (void __user *)regs->esp, 4)) ) - domain_crash_synchronous(); + goto exit_and_crash; regs->esp += 4; /* Pop and restore CS and EIP. */ if ( unlikely(__copy_from_user(®s->eip, (void __user *)regs->esp, 8)) ) - domain_crash_synchronous(); + goto exit_and_crash; regs->esp += 8; /* @@ -196,7 +196,7 @@ unsigned long do_iret(void) * to avoid firing the BUG_ON(IOPL) check in arch_getdomaininfo_ctxt. */ if ( unlikely(__copy_from_user(&eflags, (void __user *)regs->esp, 4)) ) - domain_crash_synchronous(); + goto exit_and_crash; regs->esp += 4; regs->eflags = (eflags & ~X86_EFLAGS_IOPL) | X86_EFLAGS_IF; @@ -204,17 +204,17 @@ unsigned long do_iret(void) { /* Return to VM86 mode: pop and restore ESP,SS,ES,DS,FS and GS. */ if ( __copy_from_user(®s->esp, (void __user *)regs->esp, 24) ) - domain_crash_synchronous(); + goto exit_and_crash; } else if ( unlikely(ring_0(regs)) ) { - domain_crash_synchronous(); + goto exit_and_crash; } else if ( !ring_1(regs) ) { /* Return to ring 2/3: pop and restore ESP and SS. */ if ( __copy_from_user(®s->esp, (void __user *)regs->esp, 8) ) - domain_crash_synchronous(); + goto exit_and_crash; } /* No longer in NMI context. */ @@ -228,6 +228,11 @@ unsigned long do_iret(void) * value. */ return regs->eax; + + exit_and_crash: + gdprintk(XENLOG_ERR, "Fatal error\n"); + domain_crash(current->domain); + return 0; } #include diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index a59cdaab70..71a1f0a81f 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -200,7 +200,7 @@ unsigned long do_iret(void) { gdprintk(XENLOG_ERR, "Fault while reading IRET context from " "guest stack\n"); - domain_crash_synchronous(); + goto exit_and_crash; } /* Returning to user mode? */ @@ -210,7 +210,7 @@ unsigned long do_iret(void) { gdprintk(XENLOG_ERR, "Guest switching to user mode with no " "user page tables\n"); - domain_crash_synchronous(); + goto exit_and_crash; } toggle_guest_mode(v); } @@ -236,6 +236,11 @@ unsigned long do_iret(void) /* Saved %rax gets written back to regs->rax in entry.S. */ return iret_saved.rax; + + exit_and_crash: + gdprintk(XENLOG_ERR, "Fatal error\n"); + domain_crash(v->domain); + return 0; } asmlinkage void syscall_enter(void); diff --git a/xen/include/asm-x86/hvm/support.h b/xen/include/asm-x86/hvm/support.h index f9ab090dfe..3f3ff94386 100644 --- a/xen/include/asm-x86/hvm/support.h +++ b/xen/include/asm-x86/hvm/support.h @@ -118,13 +118,6 @@ extern unsigned int opt_hvm_debug_level; #define HVM_DBG_LOG(level, _f, _a...) #endif -#define __hvm_bug(regs) \ - do { \ - printk("__hvm_bug at %s:%d\n", __FILE__, __LINE__); \ - show_execution_state(regs); \ - domain_crash_synchronous(); \ - } while (0) - #define TRACE_VMEXIT(index, value) \ current->arch.hvm_vcpu.hvm_trace_values[index] = (value)