From 790bd0f2ed9823be72ca523867527cf20c578787 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 14 Jan 2013 11:01:26 +0200 Subject: [PATCH] --- yaml --- r: 356847 b: refs/heads/master c: aa11e3a8a6d9f92c3fe4b91a9aca5d8c23d55d4d h: refs/heads/master i: 356845: 2d039e3e93d8fc65faf3cdea09972c0c5b701fac 356843: 12f23af72483fe8119259a680e7cbba455d39113 356839: 1458605d7e67842708a5c2b9a8ab1a613048f8a1 356831: 27076e9aedd680025d6f24d74a06664bd343f00a v: v3 --- [refs] | 2 +- trunk/arch/x86/kvm/emulate.c | 215 +++++++++++--------- trunk/arch/x86/kvm/mmu.c | 60 ++---- trunk/arch/x86/kvm/paging_tmpl.h | 67 ++++++- trunk/arch/x86/kvm/vmx.c | 15 +- trunk/drivers/s390/kvm/virtio_ccw.c | 291 +++++++++++++++++----------- trunk/include/trace/events/kvm.h | 2 +- 7 files changed, 384 insertions(+), 268 deletions(-) diff --git a/[refs] b/[refs] index b48e6eb0588c..c8e671b4066e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 324b3e63167bce69e6622c2be182595790bf7e38 +refs/heads/master: aa11e3a8a6d9f92c3fe4b91a9aca5d8c23d55d4d diff --git a/trunk/arch/x86/kvm/emulate.c b/trunk/arch/x86/kvm/emulate.c index 53c5ad6851d1..619a33d0ee0a 100644 --- a/trunk/arch/x86/kvm/emulate.c +++ b/trunk/arch/x86/kvm/emulate.c @@ -24,6 +24,7 @@ #include "kvm_cache_regs.h" #include #include +#include #include "x86.h" #include "tss.h" @@ -149,6 +150,8 @@ #define Aligned ((u64)1 << 41) /* Explicitly aligned (e.g. MOVDQA) */ #define Unaligned ((u64)1 << 42) /* Explicitly unaligned (e.g. MOVDQU) */ #define Avx ((u64)1 << 43) /* Advanced Vector Extensions */ +#define Fastop ((u64)1 << 44) /* Use opcode::u.fastop */ +#define NoWrite ((u64)1 << 45) /* No writeback */ #define X2(x...) x, x #define X3(x...) X2(x), x @@ -159,6 +162,27 @@ #define X8(x...) X4(x), X4(x) #define X16(x...) X8(x), X8(x) +#define NR_FASTOP (ilog2(sizeof(ulong)) + 1) +#define FASTOP_SIZE 8 + +/* + * fastop functions have a special calling convention: + * + * dst: [rdx]:rax (in/out) + * src: rbx (in/out) + * src2: rcx (in) + * flags: rflags (in/out) + * + * Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for + * different operand sizes can be reached by calculation, rather than a jump + * table (which would be bigger than the code). + * + * fastop functions are declared as taking a never-defined fastop parameter, + * so they can't be called from C directly. + */ + +struct fastop; + struct opcode { u64 flags : 56; u64 intercept : 8; @@ -168,6 +192,7 @@ struct opcode { const struct group_dual *gdual; const struct gprefix *gprefix; const struct escape *esc; + void (*fastop)(struct fastop *fake); } u; int (*check_perm)(struct x86_emulate_ctxt *ctxt); }; @@ -416,6 +441,41 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt) } \ } while (0) +#define FOP_ALIGN ".align " __stringify(FASTOP_SIZE) " \n\t" +#define FOP_RET "ret \n\t" + +#define FOP_START(op) \ + extern void em_##op(struct fastop *fake); \ + asm(".pushsection .text, \"ax\" \n\t" \ + ".global em_" #op " \n\t" \ + FOP_ALIGN \ + "em_" #op ": \n\t" + +#define FOP_END \ + ".popsection") + +#define FOP1E(op, dst) \ + FOP_ALIGN #op " %" #dst " \n\t" FOP_RET + +#define FASTOP1(op) \ + FOP_START(op) \ + FOP1E(op##b, al) \ + FOP1E(op##w, ax) \ + FOP1E(op##l, eax) \ + ON64(FOP1E(op##q, rax)) \ + FOP_END + +#define FOP2E(op, dst, src) \ + FOP_ALIGN #op " %" #src ", %" #dst " \n\t" FOP_RET + +#define FASTOP2(op) \ + FOP_START(op) \ + FOP2E(op##b, al, bl) \ + FOP2E(op##w, ax, bx) \ + FOP2E(op##l, eax, ebx) \ + ON64(FOP2E(op##q, rax, rbx)) \ + FOP_END + #define __emulate_1op_rax_rdx(ctxt, _op, _suffix, _ex) \ do { \ unsigned long _tmp; \ @@ -1585,6 +1645,9 @@ static int writeback(struct x86_emulate_ctxt *ctxt) { int rc; + if (ctxt->d & NoWrite) + return X86EMUL_CONTINUE; + switch (ctxt->dst.type) { case OP_REG: write_register_operand(&ctxt->dst); @@ -1998,17 +2061,8 @@ static int em_grp2(struct x86_emulate_ctxt *ctxt) return X86EMUL_CONTINUE; } -static int em_not(struct x86_emulate_ctxt *ctxt) -{ - ctxt->dst.val = ~ctxt->dst.val; - return X86EMUL_CONTINUE; -} - -static int em_neg(struct x86_emulate_ctxt *ctxt) -{ - emulate_1op(ctxt, "neg"); - return X86EMUL_CONTINUE; -} +FASTOP1(not); +FASTOP1(neg); static int em_mul_ex(struct x86_emulate_ctxt *ctxt) { @@ -2972,63 +3026,15 @@ static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt) return X86EMUL_CONTINUE; } -static int em_add(struct x86_emulate_ctxt *ctxt) -{ - emulate_2op_SrcV(ctxt, "add"); - return X86EMUL_CONTINUE; -} - -static int em_or(struct x86_emulate_ctxt *ctxt) -{ - emulate_2op_SrcV(ctxt, "or"); - return X86EMUL_CONTINUE; -} - -static int em_adc(struct x86_emulate_ctxt *ctxt) -{ - emulate_2op_SrcV(ctxt, "adc"); - return X86EMUL_CONTINUE; -} - -static int em_sbb(struct x86_emulate_ctxt *ctxt) -{ - emulate_2op_SrcV(ctxt, "sbb"); - return X86EMUL_CONTINUE; -} - -static int em_and(struct x86_emulate_ctxt *ctxt) -{ - emulate_2op_SrcV(ctxt, "and"); - return X86EMUL_CONTINUE; -} - -static int em_sub(struct x86_emulate_ctxt *ctxt) -{ - emulate_2op_SrcV(ctxt, "sub"); - return X86EMUL_CONTINUE; -} - -static int em_xor(struct x86_emulate_ctxt *ctxt) -{ - emulate_2op_SrcV(ctxt, "xor"); - return X86EMUL_CONTINUE; -} - -static int em_cmp(struct x86_emulate_ctxt *ctxt) -{ - emulate_2op_SrcV(ctxt, "cmp"); - /* Disable writeback. */ - ctxt->dst.type = OP_NONE; - return X86EMUL_CONTINUE; -} - -static int em_test(struct x86_emulate_ctxt *ctxt) -{ - emulate_2op_SrcV(ctxt, "test"); - /* Disable writeback. */ - ctxt->dst.type = OP_NONE; - return X86EMUL_CONTINUE; -} +FASTOP2(add); +FASTOP2(or); +FASTOP2(adc); +FASTOP2(sbb); +FASTOP2(and); +FASTOP2(sub); +FASTOP2(xor); +FASTOP2(cmp); +FASTOP2(test); static int em_xchg(struct x86_emulate_ctxt *ctxt) { @@ -3646,6 +3652,7 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt) #define GD(_f, _g) { .flags = ((_f) | GroupDual | ModRM), .u.gdual = (_g) } #define E(_f, _e) { .flags = ((_f) | Escape | ModRM), .u.esc = (_e) } #define I(_f, _e) { .flags = (_f), .u.execute = (_e) } +#define F(_f, _e) { .flags = (_f) | Fastop, .u.fastop = (_e) } #define II(_f, _e, _i) \ { .flags = (_f), .u.execute = (_e), .intercept = x86_intercept_##_i } #define IIP(_f, _e, _i, _p) \ @@ -3656,12 +3663,13 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt) #define D2bv(_f) D((_f) | ByteOp), D(_f) #define D2bvIP(_f, _i, _p) DIP((_f) | ByteOp, _i, _p), DIP(_f, _i, _p) #define I2bv(_f, _e) I((_f) | ByteOp, _e), I(_f, _e) +#define F2bv(_f, _e) F((_f) | ByteOp, _e), F(_f, _e) #define I2bvIP(_f, _e, _i, _p) \ IIP((_f) | ByteOp, _e, _i, _p), IIP(_f, _e, _i, _p) -#define I6ALU(_f, _e) I2bv((_f) | DstMem | SrcReg | ModRM, _e), \ - I2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock, _e), \ - I2bv(((_f) & ~Lock) | DstAcc | SrcImm, _e) +#define F6ALU(_f, _e) F2bv((_f) | DstMem | SrcReg | ModRM, _e), \ + F2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock, _e), \ + F2bv(((_f) & ~Lock) | DstAcc | SrcImm, _e) static const struct opcode group7_rm1[] = { DI(SrcNone | Priv, monitor), @@ -3687,14 +3695,14 @@ static const struct opcode group7_rm7[] = { }; static const struct opcode group1[] = { - I(Lock, em_add), - I(Lock | PageTable, em_or), - I(Lock, em_adc), - I(Lock, em_sbb), - I(Lock | PageTable, em_and), - I(Lock, em_sub), - I(Lock, em_xor), - I(0, em_cmp), + F(Lock, em_add), + F(Lock | PageTable, em_or), + F(Lock, em_adc), + F(Lock, em_sbb), + F(Lock | PageTable, em_and), + F(Lock, em_sub), + F(Lock, em_xor), + F(NoWrite, em_cmp), }; static const struct opcode group1A[] = { @@ -3702,10 +3710,10 @@ static const struct opcode group1A[] = { }; static const struct opcode group3[] = { - I(DstMem | SrcImm, em_test), - I(DstMem | SrcImm, em_test), - I(DstMem | SrcNone | Lock, em_not), - I(DstMem | SrcNone | Lock, em_neg), + F(DstMem | SrcImm | NoWrite, em_test), + F(DstMem | SrcImm | NoWrite, em_test), + F(DstMem | SrcNone | Lock, em_not), + F(DstMem | SrcNone | Lock, em_neg), I(SrcMem, em_mul_ex), I(SrcMem, em_imul_ex), I(SrcMem, em_div_ex), @@ -3845,29 +3853,29 @@ static const struct escape escape_dd = { { static const struct opcode opcode_table[256] = { /* 0x00 - 0x07 */ - I6ALU(Lock, em_add), + F6ALU(Lock, em_add), I(ImplicitOps | Stack | No64 | Src2ES, em_push_sreg), I(ImplicitOps | Stack | No64 | Src2ES, em_pop_sreg), /* 0x08 - 0x0F */ - I6ALU(Lock | PageTable, em_or), + F6ALU(Lock | PageTable, em_or), I(ImplicitOps | Stack | No64 | Src2CS, em_push_sreg), N, /* 0x10 - 0x17 */ - I6ALU(Lock, em_adc), + F6ALU(Lock, em_adc), I(ImplicitOps | Stack | No64 | Src2SS, em_push_sreg), I(ImplicitOps | Stack | No64 | Src2SS, em_pop_sreg), /* 0x18 - 0x1F */ - I6ALU(Lock, em_sbb), + F6ALU(Lock, em_sbb), I(ImplicitOps | Stack | No64 | Src2DS, em_push_sreg), I(ImplicitOps | Stack | No64 | Src2DS, em_pop_sreg), /* 0x20 - 0x27 */ - I6ALU(Lock | PageTable, em_and), N, N, + F6ALU(Lock | PageTable, em_and), N, N, /* 0x28 - 0x2F */ - I6ALU(Lock, em_sub), N, I(ByteOp | DstAcc | No64, em_das), + F6ALU(Lock, em_sub), N, I(ByteOp | DstAcc | No64, em_das), /* 0x30 - 0x37 */ - I6ALU(Lock, em_xor), N, N, + F6ALU(Lock, em_xor), N, N, /* 0x38 - 0x3F */ - I6ALU(0, em_cmp), N, N, + F6ALU(NoWrite, em_cmp), N, N, /* 0x40 - 0x4F */ X16(D(DstReg)), /* 0x50 - 0x57 */ @@ -3893,7 +3901,7 @@ static const struct opcode opcode_table[256] = { G(DstMem | SrcImm, group1), G(ByteOp | DstMem | SrcImm | No64, group1), G(DstMem | SrcImmByte, group1), - I2bv(DstMem | SrcReg | ModRM, em_test), + F2bv(DstMem | SrcReg | ModRM | NoWrite, em_test), I2bv(DstMem | SrcReg | ModRM | Lock | PageTable, em_xchg), /* 0x88 - 0x8F */ I2bv(DstMem | SrcReg | ModRM | Mov | PageTable, em_mov), @@ -3913,12 +3921,12 @@ static const struct opcode opcode_table[256] = { I2bv(DstAcc | SrcMem | Mov | MemAbs, em_mov), I2bv(DstMem | SrcAcc | Mov | MemAbs | PageTable, em_mov), I2bv(SrcSI | DstDI | Mov | String, em_mov), - I2bv(SrcSI | DstDI | String, em_cmp), + F2bv(SrcSI | DstDI | String | NoWrite, em_cmp), /* 0xA8 - 0xAF */ - I2bv(DstAcc | SrcImm, em_test), + F2bv(DstAcc | SrcImm | NoWrite, em_test), I2bv(SrcAcc | DstDI | Mov | String, em_mov), I2bv(SrcSI | DstAcc | Mov | String, em_mov), - I2bv(SrcAcc | DstDI | String, em_cmp), + F2bv(SrcAcc | DstDI | String | NoWrite, em_cmp), /* 0xB0 - 0xB7 */ X8(I(ByteOp | DstReg | SrcImm | Mov, em_mov)), /* 0xB8 - 0xBF */ @@ -4502,6 +4510,16 @@ static void fetch_possible_mmx_operand(struct x86_emulate_ctxt *ctxt, read_mmx_reg(ctxt, &op->mm_val, op->addr.mm); } +static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *)) +{ + ulong flags = (ctxt->eflags & EFLAGS_MASK) | X86_EFLAGS_IF; + fop += __ffs(ctxt->dst.bytes) * FASTOP_SIZE; + asm("push %[flags]; popf; call *%[fastop]; pushf; pop %[flags]\n" + : "+a"(ctxt->dst.val), "+b"(ctxt->src.val), [flags]"+D"(flags) + : "c"(ctxt->src2.val), [fastop]"S"(fop)); + ctxt->eflags = (ctxt->eflags & ~EFLAGS_MASK) | (flags & EFLAGS_MASK); + return X86EMUL_CONTINUE; +} int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) { @@ -4631,6 +4649,13 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) } if (ctxt->execute) { + if (ctxt->d & Fastop) { + void (*fop)(struct fastop *) = (void *)ctxt->execute; + rc = fastop(ctxt, fop); + if (rc != X86EMUL_CONTINUE) + goto done; + goto writeback; + } rc = ctxt->execute(ctxt); if (rc != X86EMUL_CONTINUE) goto done; diff --git a/trunk/arch/x86/kvm/mmu.c b/trunk/arch/x86/kvm/mmu.c index 01d7c2ad05f5..54fc61e4b061 100644 --- a/trunk/arch/x86/kvm/mmu.c +++ b/trunk/arch/x86/kvm/mmu.c @@ -2342,8 +2342,7 @@ static int mmu_need_write_protect(struct kvm_vcpu *vcpu, gfn_t gfn, } static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, - unsigned pte_access, int user_fault, - int write_fault, int level, + unsigned pte_access, int level, gfn_t gfn, pfn_t pfn, bool speculative, bool can_unsync, bool host_writable) { @@ -2378,20 +2377,13 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, spte |= (u64)pfn << PAGE_SHIFT; - if ((pte_access & ACC_WRITE_MASK) - || (!vcpu->arch.mmu.direct_map && write_fault - && !is_write_protection(vcpu) && !user_fault)) { + if (pte_access & ACC_WRITE_MASK) { /* - * There are two cases: - * - the one is other vcpu creates new sp in the window - * between mapping_level() and acquiring mmu-lock. - * - the another case is the new sp is created by itself - * (page-fault path) when guest uses the target gfn as - * its page table. - * Both of these cases can be fixed by allowing guest to - * retry the access, it will refault, then we can establish - * the mapping by using small page. + * Other vcpu creates new sp in the window between + * mapping_level() and acquiring mmu-lock. We can + * allow guest to retry the access, the mapping can + * be fixed if guest refault. */ if (level > PT_PAGE_TABLE_LEVEL && has_wrprotected_page(vcpu->kvm, gfn, level)) @@ -2399,19 +2391,6 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, spte |= PT_WRITABLE_MASK | SPTE_MMU_WRITEABLE; - if (!vcpu->arch.mmu.direct_map - && !(pte_access & ACC_WRITE_MASK)) { - spte &= ~PT_USER_MASK; - /* - * If we converted a user page to a kernel page, - * so that the kernel can write to it when cr0.wp=0, - * then we should prevent the kernel from executing it - * if SMEP is enabled. - */ - if (kvm_read_cr4_bits(vcpu, X86_CR4_SMEP)) - spte |= PT64_NX_MASK; - } - /* * Optimization: for pte sync, if spte was writable the hash * lookup is unnecessary (and expensive). Write protection @@ -2442,18 +2421,15 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, unsigned pt_access, unsigned pte_access, - int user_fault, int write_fault, - int *emulate, int level, gfn_t gfn, - pfn_t pfn, bool speculative, - bool host_writable) + int write_fault, int *emulate, int level, gfn_t gfn, + pfn_t pfn, bool speculative, bool host_writable) { int was_rmapped = 0; int rmap_count; - pgprintk("%s: spte %llx access %x write_fault %d" - " user_fault %d gfn %llx\n", + pgprintk("%s: spte %llx access %x write_fault %d gfn %llx\n", __func__, *sptep, pt_access, - write_fault, user_fault, gfn); + write_fault, gfn); if (is_rmap_spte(*sptep)) { /* @@ -2477,9 +2453,8 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, was_rmapped = 1; } - if (set_spte(vcpu, sptep, pte_access, user_fault, write_fault, - level, gfn, pfn, speculative, true, - host_writable)) { + if (set_spte(vcpu, sptep, pte_access, level, gfn, pfn, speculative, + true, host_writable)) { if (write_fault) *emulate = 1; kvm_mmu_flush_tlb(vcpu); @@ -2571,10 +2546,9 @@ static int direct_pte_prefetch_many(struct kvm_vcpu *vcpu, return -1; for (i = 0; i < ret; i++, gfn++, start++) - mmu_set_spte(vcpu, start, ACC_ALL, - access, 0, 0, NULL, - sp->role.level, gfn, - page_to_pfn(pages[i]), true, true); + mmu_set_spte(vcpu, start, ACC_ALL, access, 0, NULL, + sp->role.level, gfn, page_to_pfn(pages[i]), + true, true); return 0; } @@ -2636,8 +2610,8 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write, unsigned pte_access = ACC_ALL; mmu_set_spte(vcpu, iterator.sptep, ACC_ALL, pte_access, - 0, write, &emulate, - level, gfn, pfn, prefault, map_writable); + write, &emulate, level, gfn, pfn, + prefault, map_writable); direct_pte_prefetch(vcpu, iterator.sptep); ++vcpu->stat.pf_fixed; break; diff --git a/trunk/arch/x86/kvm/paging_tmpl.h b/trunk/arch/x86/kvm/paging_tmpl.h index a7b24cf59a3c..3d1a35237dbf 100644 --- a/trunk/arch/x86/kvm/paging_tmpl.h +++ b/trunk/arch/x86/kvm/paging_tmpl.h @@ -151,7 +151,7 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker, pt_element_t pte; pt_element_t __user *uninitialized_var(ptep_user); gfn_t table_gfn; - unsigned index, pt_access, pte_access, accessed_dirty, shift; + unsigned index, pt_access, pte_access, accessed_dirty; gpa_t pte_gpa; int offset; const int write_fault = access & PFERR_WRITE_MASK; @@ -326,7 +326,7 @@ FNAME(prefetch_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, * we call mmu_set_spte() with host_writable = true because * pte_prefetch_gfn_to_pfn always gets a writable pfn. */ - mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 0, + mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, NULL, PT_PAGE_TABLE_LEVEL, gfn, pfn, true, true); return true; @@ -401,7 +401,7 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw, */ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, struct guest_walker *gw, - int user_fault, int write_fault, int hlevel, + int write_fault, int hlevel, pfn_t pfn, bool map_writable, bool prefault) { struct kvm_mmu_page *sp = NULL; @@ -474,7 +474,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, clear_sp_write_flooding_count(it.sptep); mmu_set_spte(vcpu, it.sptep, access, gw->pte_access, - user_fault, write_fault, &emulate, it.level, + write_fault, &emulate, it.level, gw->gfn, pfn, prefault, map_writable); FNAME(pte_prefetch)(vcpu, gw, it.sptep); @@ -487,6 +487,38 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, return 0; } + /* + * To see whether the mapped gfn can write its page table in the current + * mapping. + * + * It is the helper function of FNAME(page_fault). When guest uses large page + * size to map the writable gfn which is used as current page table, we should + * force kvm to use small page size to map it because new shadow page will be + * created when kvm establishes shadow page table that stop kvm using large + * page size. Do it early can avoid unnecessary #PF and emulation. + * + * Note: the PDPT page table is not checked for PAE-32 bit guest. It is ok + * since the PDPT is always shadowed, that means, we can not use large page + * size to map the gfn which is used as PDPT. + */ +static bool +FNAME(is_self_change_mapping)(struct kvm_vcpu *vcpu, + struct guest_walker *walker, int user_fault) +{ + int level; + gfn_t mask = ~(KVM_PAGES_PER_HPAGE(walker->level) - 1); + + if (!(walker->pte_access & ACC_WRITE_MASK || + (!is_write_protection(vcpu) && !user_fault))) + return false; + + for (level = walker->level; level <= walker->max_level; level++) + if (!((walker->gfn ^ walker->table_gfn[level - 1]) & mask)) + return true; + + return false; +} + /* * Page fault handler. There are several causes for a page fault: * - there is no shadow pte for the guest pte @@ -541,7 +573,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code, } if (walker.level >= PT_DIRECTORY_LEVEL) - force_pt_level = mapping_level_dirty_bitmap(vcpu, walker.gfn); + force_pt_level = mapping_level_dirty_bitmap(vcpu, walker.gfn) + || FNAME(is_self_change_mapping)(vcpu, &walker, user_fault); else force_pt_level = 1; if (!force_pt_level) { @@ -560,6 +593,26 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code, walker.gfn, pfn, walker.pte_access, &r)) return r; + /* + * Do not change pte_access if the pfn is a mmio page, otherwise + * we will cache the incorrect access into mmio spte. + */ + if (write_fault && !(walker.pte_access & ACC_WRITE_MASK) && + !is_write_protection(vcpu) && !user_fault && + !is_noslot_pfn(pfn)) { + walker.pte_access |= ACC_WRITE_MASK; + walker.pte_access &= ~ACC_USER_MASK; + + /* + * If we converted a user page to a kernel page, + * so that the kernel can write to it when cr0.wp=0, + * then we should prevent the kernel from executing it + * if SMEP is enabled. + */ + if (kvm_read_cr4_bits(vcpu, X86_CR4_SMEP)) + walker.pte_access &= ~ACC_EXEC_MASK; + } + spin_lock(&vcpu->kvm->mmu_lock); if (mmu_notifier_retry(vcpu->kvm, mmu_seq)) goto out_unlock; @@ -568,7 +621,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code, kvm_mmu_free_some_pages(vcpu); if (!force_pt_level) transparent_hugepage_adjust(vcpu, &walker.gfn, &pfn, &level); - r = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault, + r = FNAME(fetch)(vcpu, addr, &walker, write_fault, level, pfn, map_writable, prefault); ++vcpu->stat.pf_fixed; kvm_mmu_audit(vcpu, AUDIT_POST_PAGE_FAULT); @@ -743,7 +796,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) host_writable = sp->spt[i] & SPTE_HOST_WRITEABLE; - set_spte(vcpu, &sp->spt[i], pte_access, 0, 0, + set_spte(vcpu, &sp->spt[i], pte_access, PT_PAGE_TABLE_LEVEL, gfn, spte_to_pfn(sp->spt[i]), true, false, host_writable); diff --git a/trunk/arch/x86/kvm/vmx.c b/trunk/arch/x86/kvm/vmx.c index 55dfc375f1ab..dd2a85c1c6f0 100644 --- a/trunk/arch/x86/kvm/vmx.c +++ b/trunk/arch/x86/kvm/vmx.c @@ -1696,7 +1696,6 @@ static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu) static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) { __set_bit(VCPU_EXREG_RFLAGS, (ulong *)&vcpu->arch.regs_avail); - __clear_bit(VCPU_EXREG_CPL, (ulong *)&vcpu->arch.regs_avail); to_vmx(vcpu)->rflags = rflags; if (to_vmx(vcpu)->rmode.vm86_active) { to_vmx(vcpu)->rmode.save_rflags = rflags; @@ -3110,7 +3109,6 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) vmcs_writel(CR0_READ_SHADOW, cr0); vmcs_writel(GUEST_CR0, hw_cr0); vcpu->arch.cr0 = cr0; - __clear_bit(VCPU_EXREG_CPL, (ulong *)&vcpu->arch.regs_avail); } static u64 construct_eptp(unsigned long root_hpa) @@ -3220,8 +3218,10 @@ static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg) return vmx_read_guest_seg_base(to_vmx(vcpu), seg); } -static int __vmx_get_cpl(struct kvm_vcpu *vcpu) +static int vmx_get_cpl(struct kvm_vcpu *vcpu) { + struct vcpu_vmx *vmx = to_vmx(vcpu); + if (!is_protmode(vcpu)) return 0; @@ -3229,13 +3229,6 @@ static int __vmx_get_cpl(struct kvm_vcpu *vcpu) && (kvm_get_rflags(vcpu) & X86_EFLAGS_VM)) /* if virtual 8086 */ return 3; - return vmx_read_guest_seg_selector(to_vmx(vcpu), VCPU_SREG_CS) & 3; -} - -static int vmx_get_cpl(struct kvm_vcpu *vcpu) -{ - struct vcpu_vmx *vmx = to_vmx(vcpu); - /* * If we enter real mode with cs.sel & 3 != 0, the normal CPL calculations * fail; use the cache instead. @@ -3246,7 +3239,7 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu) if (!test_bit(VCPU_EXREG_CPL, (ulong *)&vcpu->arch.regs_avail)) { __set_bit(VCPU_EXREG_CPL, (ulong *)&vcpu->arch.regs_avail); - vmx->cpl = __vmx_get_cpl(vcpu); + vmx->cpl = vmx_read_guest_seg_selector(vmx, VCPU_SREG_CS) & 3; } return vmx->cpl; diff --git a/trunk/drivers/s390/kvm/virtio_ccw.c b/trunk/drivers/s390/kvm/virtio_ccw.c index 1a5aff31d752..2edd94af131c 100644 --- a/trunk/drivers/s390/kvm/virtio_ccw.c +++ b/trunk/drivers/s390/kvm/virtio_ccw.c @@ -46,11 +46,9 @@ struct vq_config_block { struct virtio_ccw_device { struct virtio_device vdev; - __u8 status; + __u8 *status; __u8 config[VIRTIO_CCW_CONFIG_SIZE]; struct ccw_device *cdev; - struct ccw1 *ccw; - __u32 area; __u32 curr_io; int err; wait_queue_head_t wait_q; @@ -127,17 +125,21 @@ static int doing_io(struct virtio_ccw_device *vcdev, __u32 flag) return ret; } -static int ccw_io_helper(struct virtio_ccw_device *vcdev, __u32 intparm) +static int ccw_io_helper(struct virtio_ccw_device *vcdev, + struct ccw1 *ccw, __u32 intparm) { int ret; unsigned long flags; int flag = intparm & VIRTIO_CCW_INTPARM_MASK; - spin_lock_irqsave(get_ccwdev_lock(vcdev->cdev), flags); - ret = ccw_device_start(vcdev->cdev, vcdev->ccw, intparm, 0, 0); - if (!ret) - vcdev->curr_io |= flag; - spin_unlock_irqrestore(get_ccwdev_lock(vcdev->cdev), flags); + do { + spin_lock_irqsave(get_ccwdev_lock(vcdev->cdev), flags); + ret = ccw_device_start(vcdev->cdev, ccw, intparm, 0, 0); + if (!ret) + vcdev->curr_io |= flag; + spin_unlock_irqrestore(get_ccwdev_lock(vcdev->cdev), flags); + cpu_relax(); + } while (ret == -EBUSY); wait_event(vcdev->wait_q, doing_io(vcdev, flag) == 0); return ret ? ret : vcdev->err; } @@ -167,18 +169,19 @@ static void virtio_ccw_kvm_notify(struct virtqueue *vq) do_kvm_notify(schid, virtqueue_get_queue_index(vq)); } -static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev, int index) +static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev, + struct ccw1 *ccw, int index) { vcdev->config_block->index = index; - vcdev->ccw->cmd_code = CCW_CMD_READ_VQ_CONF; - vcdev->ccw->flags = 0; - vcdev->ccw->count = sizeof(struct vq_config_block); - vcdev->ccw->cda = (__u32)(unsigned long)(vcdev->config_block); - ccw_io_helper(vcdev, VIRTIO_CCW_DOING_READ_VQ_CONF); + ccw->cmd_code = CCW_CMD_READ_VQ_CONF; + ccw->flags = 0; + ccw->count = sizeof(struct vq_config_block); + ccw->cda = (__u32)(unsigned long)(vcdev->config_block); + ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_VQ_CONF); return vcdev->config_block->num; } -static void virtio_ccw_del_vq(struct virtqueue *vq) +static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw) { struct virtio_ccw_device *vcdev = to_vc_device(vq->vdev); struct virtio_ccw_vq_info *info = vq->priv; @@ -197,11 +200,12 @@ static void virtio_ccw_del_vq(struct virtqueue *vq) info->info_block->align = 0; info->info_block->index = index; info->info_block->num = 0; - vcdev->ccw->cmd_code = CCW_CMD_SET_VQ; - vcdev->ccw->flags = 0; - vcdev->ccw->count = sizeof(*info->info_block); - vcdev->ccw->cda = (__u32)(unsigned long)(info->info_block); - ret = ccw_io_helper(vcdev, VIRTIO_CCW_DOING_SET_VQ | index); + ccw->cmd_code = CCW_CMD_SET_VQ; + ccw->flags = 0; + ccw->count = sizeof(*info->info_block); + ccw->cda = (__u32)(unsigned long)(info->info_block); + ret = ccw_io_helper(vcdev, ccw, + VIRTIO_CCW_DOING_SET_VQ | index); /* * -ENODEV isn't considered an error: The device is gone anyway. * This may happen on device detach. @@ -220,14 +224,23 @@ static void virtio_ccw_del_vq(struct virtqueue *vq) static void virtio_ccw_del_vqs(struct virtio_device *vdev) { struct virtqueue *vq, *n; + struct ccw1 *ccw; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return; + list_for_each_entry_safe(vq, n, &vdev->vqs, list) - virtio_ccw_del_vq(vq); + virtio_ccw_del_vq(vq, ccw); + + kfree(ccw); } static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev, int i, vq_callback_t *callback, - const char *name) + const char *name, + struct ccw1 *ccw) { struct virtio_ccw_device *vcdev = to_vc_device(vdev); int err; @@ -250,7 +263,7 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev, err = -ENOMEM; goto out_err; } - info->num = virtio_ccw_read_vq_conf(vcdev, i); + info->num = virtio_ccw_read_vq_conf(vcdev, ccw, i); size = PAGE_ALIGN(vring_size(info->num, KVM_VIRTIO_CCW_RING_ALIGN)); info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO); if (info->queue == NULL) { @@ -277,11 +290,11 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev, info->info_block->align = KVM_VIRTIO_CCW_RING_ALIGN; info->info_block->index = i; info->info_block->num = info->num; - vcdev->ccw->cmd_code = CCW_CMD_SET_VQ; - vcdev->ccw->flags = 0; - vcdev->ccw->count = sizeof(*info->info_block); - vcdev->ccw->cda = (__u32)(unsigned long)(info->info_block); - err = ccw_io_helper(vcdev, VIRTIO_CCW_DOING_SET_VQ | i); + ccw->cmd_code = CCW_CMD_SET_VQ; + ccw->flags = 0; + ccw->count = sizeof(*info->info_block); + ccw->cda = (__u32)(unsigned long)(info->info_block); + err = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_VQ | i); if (err) { dev_warn(&vcdev->cdev->dev, "SET_VQ failed\n"); free_pages_exact(info->queue, size); @@ -312,9 +325,15 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, struct virtio_ccw_device *vcdev = to_vc_device(vdev); unsigned long *indicatorp = NULL; int ret, i; + struct ccw1 *ccw; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return -ENOMEM; for (i = 0; i < nvqs; ++i) { - vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i]); + vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i], + ccw); if (IS_ERR(vqs[i])) { ret = PTR_ERR(vqs[i]); vqs[i] = NULL; @@ -329,28 +348,30 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, *indicatorp = (unsigned long) &vcdev->indicators; /* Register queue indicators with host. */ vcdev->indicators = 0; - vcdev->ccw->cmd_code = CCW_CMD_SET_IND; - vcdev->ccw->flags = 0; - vcdev->ccw->count = sizeof(vcdev->indicators); - vcdev->ccw->cda = (__u32)(unsigned long) indicatorp; - ret = ccw_io_helper(vcdev, VIRTIO_CCW_DOING_SET_IND); + ccw->cmd_code = CCW_CMD_SET_IND; + ccw->flags = 0; + ccw->count = sizeof(vcdev->indicators); + ccw->cda = (__u32)(unsigned long) indicatorp; + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND); if (ret) goto out; /* Register indicators2 with host for config changes */ *indicatorp = (unsigned long) &vcdev->indicators2; vcdev->indicators2 = 0; - vcdev->ccw->cmd_code = CCW_CMD_SET_CONF_IND; - vcdev->ccw->flags = 0; - vcdev->ccw->count = sizeof(vcdev->indicators2); - vcdev->ccw->cda = (__u32)(unsigned long) indicatorp; - ret = ccw_io_helper(vcdev, VIRTIO_CCW_DOING_SET_CONF_IND); + ccw->cmd_code = CCW_CMD_SET_CONF_IND; + ccw->flags = 0; + ccw->count = sizeof(vcdev->indicators2); + ccw->cda = (__u32)(unsigned long) indicatorp; + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_CONF_IND); if (ret) goto out; kfree(indicatorp); + kfree(ccw); return 0; out: kfree(indicatorp); + kfree(ccw); virtio_ccw_del_vqs(vdev); return ret; } @@ -358,64 +379,95 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, static void virtio_ccw_reset(struct virtio_device *vdev) { struct virtio_ccw_device *vcdev = to_vc_device(vdev); + struct ccw1 *ccw; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return; /* Zero status bits. */ - vcdev->status = 0; + *vcdev->status = 0; /* Send a reset ccw on device. */ - vcdev->ccw->cmd_code = CCW_CMD_VDEV_RESET; - vcdev->ccw->flags = 0; - vcdev->ccw->count = 0; - vcdev->ccw->cda = 0; - ccw_io_helper(vcdev, VIRTIO_CCW_DOING_RESET); + ccw->cmd_code = CCW_CMD_VDEV_RESET; + ccw->flags = 0; + ccw->count = 0; + ccw->cda = 0; + ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_RESET); + kfree(ccw); } static u32 virtio_ccw_get_features(struct virtio_device *vdev) { struct virtio_ccw_device *vcdev = to_vc_device(vdev); - struct virtio_feature_desc features; - int ret; + struct virtio_feature_desc *features; + int ret, rc; + struct ccw1 *ccw; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return 0; + features = kzalloc(sizeof(*features), GFP_DMA | GFP_KERNEL); + if (!features) { + rc = 0; + goto out_free; + } /* Read the feature bits from the host. */ /* TODO: Features > 32 bits */ - features.index = 0; - vcdev->ccw->cmd_code = CCW_CMD_READ_FEAT; - vcdev->ccw->flags = 0; - vcdev->ccw->count = sizeof(features); - vcdev->ccw->cda = vcdev->area; - ret = ccw_io_helper(vcdev, VIRTIO_CCW_DOING_READ_FEAT); - if (ret) - return 0; + features->index = 0; + ccw->cmd_code = CCW_CMD_READ_FEAT; + ccw->flags = 0; + ccw->count = sizeof(*features); + ccw->cda = (__u32)(unsigned long)features; + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT); + if (ret) { + rc = 0; + goto out_free; + } + + rc = le32_to_cpu(features->features); - memcpy(&features, (void *)(unsigned long)vcdev->area, - sizeof(features)); - return le32_to_cpu(features.features); +out_free: + kfree(features); + kfree(ccw); + return rc; } static void virtio_ccw_finalize_features(struct virtio_device *vdev) { struct virtio_ccw_device *vcdev = to_vc_device(vdev); - struct virtio_feature_desc features; + struct virtio_feature_desc *features; int i; + struct ccw1 *ccw; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return; + + features = kzalloc(sizeof(*features), GFP_DMA | GFP_KERNEL); + if (!features) + goto out_free; /* Give virtio_ring a chance to accept features. */ vring_transport_features(vdev); - for (i = 0; i < sizeof(*vdev->features) / sizeof(features.features); + for (i = 0; i < sizeof(*vdev->features) / sizeof(features->features); i++) { int highbits = i % 2 ? 32 : 0; - features.index = i; - features.features = cpu_to_le32(vdev->features[i / 2] - >> highbits); - memcpy((void *)(unsigned long)vcdev->area, &features, - sizeof(features)); + features->index = i; + features->features = cpu_to_le32(vdev->features[i / 2] + >> highbits); /* Write the feature bits to the host. */ - vcdev->ccw->cmd_code = CCW_CMD_WRITE_FEAT; - vcdev->ccw->flags = 0; - vcdev->ccw->count = sizeof(features); - vcdev->ccw->cda = vcdev->area; - ccw_io_helper(vcdev, VIRTIO_CCW_DOING_WRITE_FEAT); + ccw->cmd_code = CCW_CMD_WRITE_FEAT; + ccw->flags = 0; + ccw->count = sizeof(*features); + ccw->cda = (__u32)(unsigned long)features; + ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT); } +out_free: + kfree(features); + kfree(ccw); } static void virtio_ccw_get_config(struct virtio_device *vdev, @@ -423,19 +475,32 @@ static void virtio_ccw_get_config(struct virtio_device *vdev, { struct virtio_ccw_device *vcdev = to_vc_device(vdev); int ret; + struct ccw1 *ccw; + void *config_area; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return; + + config_area = kzalloc(VIRTIO_CCW_CONFIG_SIZE, GFP_DMA | GFP_KERNEL); + if (!config_area) + goto out_free; /* Read the config area from the host. */ - vcdev->ccw->cmd_code = CCW_CMD_READ_CONF; - vcdev->ccw->flags = 0; - vcdev->ccw->count = offset + len; - vcdev->ccw->cda = vcdev->area; - ret = ccw_io_helper(vcdev, VIRTIO_CCW_DOING_READ_CONFIG); + ccw->cmd_code = CCW_CMD_READ_CONF; + ccw->flags = 0; + ccw->count = offset + len; + ccw->cda = (__u32)(unsigned long)config_area; + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_CONFIG); if (ret) - return; + goto out_free; - memcpy(vcdev->config, (void *)(unsigned long)vcdev->area, - sizeof(vcdev->config)); + memcpy(vcdev->config, config_area, sizeof(vcdev->config)); memcpy(buf, &vcdev->config[offset], len); + +out_free: + kfree(config_area); + kfree(ccw); } static void virtio_ccw_set_config(struct virtio_device *vdev, @@ -443,37 +508,55 @@ static void virtio_ccw_set_config(struct virtio_device *vdev, unsigned len) { struct virtio_ccw_device *vcdev = to_vc_device(vdev); + struct ccw1 *ccw; + void *config_area; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return; + + config_area = kzalloc(VIRTIO_CCW_CONFIG_SIZE, GFP_DMA | GFP_KERNEL); + if (!config_area) + goto out_free; memcpy(&vcdev->config[offset], buf, len); /* Write the config area to the host. */ - memcpy((void *)(unsigned long)vcdev->area, vcdev->config, - sizeof(vcdev->config)); - vcdev->ccw->cmd_code = CCW_CMD_WRITE_CONF; - vcdev->ccw->flags = 0; - vcdev->ccw->count = offset + len; - vcdev->ccw->cda = vcdev->area; - ccw_io_helper(vcdev, VIRTIO_CCW_DOING_WRITE_CONFIG); + memcpy(config_area, vcdev->config, sizeof(vcdev->config)); + ccw->cmd_code = CCW_CMD_WRITE_CONF; + ccw->flags = 0; + ccw->count = offset + len; + ccw->cda = (__u32)(unsigned long)config_area; + ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_CONFIG); + +out_free: + kfree(config_area); + kfree(ccw); } static u8 virtio_ccw_get_status(struct virtio_device *vdev) { struct virtio_ccw_device *vcdev = to_vc_device(vdev); - return vcdev->status; + return *vcdev->status; } static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status) { struct virtio_ccw_device *vcdev = to_vc_device(vdev); + struct ccw1 *ccw; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return; /* Write the status to the host. */ - vcdev->status = status; - memcpy((void *)(unsigned long)vcdev->area, &status, sizeof(status)); - vcdev->ccw->cmd_code = CCW_CMD_WRITE_STATUS; - vcdev->ccw->flags = 0; - vcdev->ccw->count = sizeof(status); - vcdev->ccw->cda = vcdev->area; - ccw_io_helper(vcdev, VIRTIO_CCW_DOING_WRITE_STATUS); + *vcdev->status = status; + ccw->cmd_code = CCW_CMD_WRITE_STATUS; + ccw->flags = 0; + ccw->count = sizeof(status); + ccw->cda = (__u32)(unsigned long)vcdev->status; + ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_STATUS); + kfree(ccw); } static struct virtio_config_ops virtio_ccw_config_ops = { @@ -499,9 +582,8 @@ static void virtio_ccw_release_dev(struct device *_d) dev); struct virtio_ccw_device *vcdev = to_vc_device(dev); - kfree((void *)(unsigned long)vcdev->area); + kfree(vcdev->status); kfree(vcdev->config_block); - kfree(vcdev->ccw); kfree(vcdev); } @@ -657,9 +739,6 @@ static int virtio_ccw_offline(struct ccw_device *cdev) } -/* Area needs to be big enough to fit status, features or configuration. */ -#define VIRTIO_AREA_SIZE VIRTIO_CCW_CONFIG_SIZE /* biggest possible use */ - static int virtio_ccw_online(struct ccw_device *cdev) { int ret; @@ -671,21 +750,14 @@ static int virtio_ccw_online(struct ccw_device *cdev) ret = -ENOMEM; goto out_free; } - vcdev->area = (__u32)(unsigned long)kzalloc(VIRTIO_AREA_SIZE, - GFP_DMA | GFP_KERNEL); - if (!vcdev->area) { - dev_warn(&cdev->dev, "Cound not get memory for virtio\n"); - ret = -ENOMEM; - goto out_free; - } vcdev->config_block = kzalloc(sizeof(*vcdev->config_block), GFP_DMA | GFP_KERNEL); if (!vcdev->config_block) { ret = -ENOMEM; goto out_free; } - vcdev->ccw = kzalloc(sizeof(*vcdev->ccw), GFP_DMA | GFP_KERNEL); - if (!vcdev->ccw) { + vcdev->status = kzalloc(sizeof(*vcdev->status), GFP_DMA | GFP_KERNEL); + if (!vcdev->status) { ret = -ENOMEM; goto out_free; } @@ -714,9 +786,8 @@ static int virtio_ccw_online(struct ccw_device *cdev) return ret; out_free: if (vcdev) { - kfree((void *)(unsigned long)vcdev->area); + kfree(vcdev->status); kfree(vcdev->config_block); - kfree(vcdev->ccw); } kfree(vcdev); return ret; diff --git a/trunk/include/trace/events/kvm.h b/trunk/include/trace/events/kvm.h index a23f47c884cf..19911dddaeb7 100644 --- a/trunk/include/trace/events/kvm.h +++ b/trunk/include/trace/events/kvm.h @@ -14,7 +14,7 @@ ERSN(SHUTDOWN), ERSN(FAIL_ENTRY), ERSN(INTR), ERSN(SET_TPR), \ ERSN(TPR_ACCESS), ERSN(S390_SIEIC), ERSN(S390_RESET), ERSN(DCR),\ ERSN(NMI), ERSN(INTERNAL_ERROR), ERSN(OSI), ERSN(PAPR_HCALL), \ - ERSN(S390_UCONTROL), ERSN(S390_TSCH) + ERSN(S390_UCONTROL), ERSN(WATCHDOG), ERSN(S390_TSCH) TRACE_EVENT(kvm_userspace_exit, TP_PROTO(__u32 reason, int errno),