From 1458605d7e67842708a5c2b9a8ab1a613048f8a1 Mon Sep 17 00:00:00 2001 From: Mihai Caraman Date: Tue, 11 Dec 2012 03:38:23 +0000 Subject: [PATCH] --- yaml --- r: 356839 b: refs/heads/master c: 68e2ffed358c92341c126e606b500098fc72f5f7 h: refs/heads/master i: 356837: 149975f86a578dbcfbfb1cad99ae6fecf37fe23e 356835: d6088036b6de1d14577ff0ce4d99c95141d206a9 356831: 27076e9aedd680025d6f24d74a06664bd343f00a v: v3 --- [refs] | 2 +- trunk/Documentation/virtual/kvm/api.txt | 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 +- 8 files changed, 269 insertions(+), 385 deletions(-) diff --git a/[refs] b/[refs] index a834672aea05..0b53d725b6dd 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f79ed82da494bc2ea677c6fc28b5439eacf4f5cc +refs/heads/master: 68e2ffed358c92341c126e606b500098fc72f5f7 diff --git a/trunk/Documentation/virtual/kvm/api.txt b/trunk/Documentation/virtual/kvm/api.txt index f2d6391178b9..4fc2bfcb16d5 100644 --- a/trunk/Documentation/virtual/kvm/api.txt +++ b/trunk/Documentation/virtual/kvm/api.txt @@ -345,7 +345,7 @@ struct kvm_sregs { __u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64]; }; -/* ppc -- see arch/powerpc/include/asm/kvm.h */ +/* ppc -- see arch/powerpc/include/uapi/asm/kvm.h */ interrupt_bitmap is a bitmap of pending external interrupts. At most one bit may be set. This interrupt has been acknowledged by the APIC diff --git a/trunk/arch/x86/kvm/emulate.c b/trunk/arch/x86/kvm/emulate.c index 619a33d0ee0a..53c5ad6851d1 100644 --- a/trunk/arch/x86/kvm/emulate.c +++ b/trunk/arch/x86/kvm/emulate.c @@ -24,7 +24,6 @@ #include "kvm_cache_regs.h" #include #include -#include #include "x86.h" #include "tss.h" @@ -150,8 +149,6 @@ #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 @@ -162,27 +159,6 @@ #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; @@ -192,7 +168,6 @@ 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); }; @@ -441,41 +416,6 @@ 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; \ @@ -1645,9 +1585,6 @@ 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); @@ -2061,8 +1998,17 @@ static int em_grp2(struct x86_emulate_ctxt *ctxt) return X86EMUL_CONTINUE; } -FASTOP1(not); -FASTOP1(neg); +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; +} static int em_mul_ex(struct x86_emulate_ctxt *ctxt) { @@ -3026,15 +2972,63 @@ static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt) return X86EMUL_CONTINUE; } -FASTOP2(add); -FASTOP2(or); -FASTOP2(adc); -FASTOP2(sbb); -FASTOP2(and); -FASTOP2(sub); -FASTOP2(xor); -FASTOP2(cmp); -FASTOP2(test); +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; +} static int em_xchg(struct x86_emulate_ctxt *ctxt) { @@ -3652,7 +3646,6 @@ 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) \ @@ -3663,13 +3656,12 @@ 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 F6ALU(_f, _e) F2bv((_f) | DstMem | SrcReg | ModRM, _e), \ - F2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock, _e), \ - F2bv(((_f) & ~Lock) | DstAcc | SrcImm, _e) +#define I6ALU(_f, _e) I2bv((_f) | DstMem | SrcReg | ModRM, _e), \ + I2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock, _e), \ + I2bv(((_f) & ~Lock) | DstAcc | SrcImm, _e) static const struct opcode group7_rm1[] = { DI(SrcNone | Priv, monitor), @@ -3695,14 +3687,14 @@ static const struct opcode group7_rm7[] = { }; static const struct opcode group1[] = { - 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), + 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), }; static const struct opcode group1A[] = { @@ -3710,10 +3702,10 @@ static const struct opcode group1A[] = { }; static const struct opcode group3[] = { - 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(DstMem | SrcImm, em_test), + I(DstMem | SrcImm, em_test), + I(DstMem | SrcNone | Lock, em_not), + I(DstMem | SrcNone | Lock, em_neg), I(SrcMem, em_mul_ex), I(SrcMem, em_imul_ex), I(SrcMem, em_div_ex), @@ -3853,29 +3845,29 @@ static const struct escape escape_dd = { { static const struct opcode opcode_table[256] = { /* 0x00 - 0x07 */ - F6ALU(Lock, em_add), + I6ALU(Lock, em_add), I(ImplicitOps | Stack | No64 | Src2ES, em_push_sreg), I(ImplicitOps | Stack | No64 | Src2ES, em_pop_sreg), /* 0x08 - 0x0F */ - F6ALU(Lock | PageTable, em_or), + I6ALU(Lock | PageTable, em_or), I(ImplicitOps | Stack | No64 | Src2CS, em_push_sreg), N, /* 0x10 - 0x17 */ - F6ALU(Lock, em_adc), + I6ALU(Lock, em_adc), I(ImplicitOps | Stack | No64 | Src2SS, em_push_sreg), I(ImplicitOps | Stack | No64 | Src2SS, em_pop_sreg), /* 0x18 - 0x1F */ - F6ALU(Lock, em_sbb), + I6ALU(Lock, em_sbb), I(ImplicitOps | Stack | No64 | Src2DS, em_push_sreg), I(ImplicitOps | Stack | No64 | Src2DS, em_pop_sreg), /* 0x20 - 0x27 */ - F6ALU(Lock | PageTable, em_and), N, N, + I6ALU(Lock | PageTable, em_and), N, N, /* 0x28 - 0x2F */ - F6ALU(Lock, em_sub), N, I(ByteOp | DstAcc | No64, em_das), + I6ALU(Lock, em_sub), N, I(ByteOp | DstAcc | No64, em_das), /* 0x30 - 0x37 */ - F6ALU(Lock, em_xor), N, N, + I6ALU(Lock, em_xor), N, N, /* 0x38 - 0x3F */ - F6ALU(NoWrite, em_cmp), N, N, + I6ALU(0, em_cmp), N, N, /* 0x40 - 0x4F */ X16(D(DstReg)), /* 0x50 - 0x57 */ @@ -3901,7 +3893,7 @@ static const struct opcode opcode_table[256] = { G(DstMem | SrcImm, group1), G(ByteOp | DstMem | SrcImm | No64, group1), G(DstMem | SrcImmByte, group1), - F2bv(DstMem | SrcReg | ModRM | NoWrite, em_test), + I2bv(DstMem | SrcReg | ModRM, em_test), I2bv(DstMem | SrcReg | ModRM | Lock | PageTable, em_xchg), /* 0x88 - 0x8F */ I2bv(DstMem | SrcReg | ModRM | Mov | PageTable, em_mov), @@ -3921,12 +3913,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), - F2bv(SrcSI | DstDI | String | NoWrite, em_cmp), + I2bv(SrcSI | DstDI | String, em_cmp), /* 0xA8 - 0xAF */ - F2bv(DstAcc | SrcImm | NoWrite, em_test), + I2bv(DstAcc | SrcImm, em_test), I2bv(SrcAcc | DstDI | Mov | String, em_mov), I2bv(SrcSI | DstAcc | Mov | String, em_mov), - F2bv(SrcAcc | DstDI | String | NoWrite, em_cmp), + I2bv(SrcAcc | DstDI | String, em_cmp), /* 0xB0 - 0xB7 */ X8(I(ByteOp | DstReg | SrcImm | Mov, em_mov)), /* 0xB8 - 0xBF */ @@ -4510,16 +4502,6 @@ 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) { @@ -4649,13 +4631,6 @@ 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 54fc61e4b061..01d7c2ad05f5 100644 --- a/trunk/arch/x86/kvm/mmu.c +++ b/trunk/arch/x86/kvm/mmu.c @@ -2342,7 +2342,8 @@ 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 level, + unsigned pte_access, int user_fault, + int write_fault, int level, gfn_t gfn, pfn_t pfn, bool speculative, bool can_unsync, bool host_writable) { @@ -2377,13 +2378,20 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, spte |= (u64)pfn << PAGE_SHIFT; - if (pte_access & ACC_WRITE_MASK) { + if ((pte_access & ACC_WRITE_MASK) + || (!vcpu->arch.mmu.direct_map && write_fault + && !is_write_protection(vcpu) && !user_fault)) { /* - * 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. + * 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. */ if (level > PT_PAGE_TABLE_LEVEL && has_wrprotected_page(vcpu->kvm, gfn, level)) @@ -2391,6 +2399,19 @@ 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 @@ -2421,15 +2442,18 @@ 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 write_fault, int *emulate, int level, gfn_t gfn, - pfn_t pfn, bool speculative, bool host_writable) + int user_fault, 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 gfn %llx\n", + pgprintk("%s: spte %llx access %x write_fault %d" + " user_fault %d gfn %llx\n", __func__, *sptep, pt_access, - write_fault, gfn); + write_fault, user_fault, gfn); if (is_rmap_spte(*sptep)) { /* @@ -2453,8 +2477,9 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, was_rmapped = 1; } - if (set_spte(vcpu, sptep, pte_access, level, gfn, pfn, speculative, - true, host_writable)) { + if (set_spte(vcpu, sptep, pte_access, user_fault, write_fault, + level, gfn, pfn, speculative, true, + host_writable)) { if (write_fault) *emulate = 1; kvm_mmu_flush_tlb(vcpu); @@ -2546,9 +2571,10 @@ 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, NULL, - sp->role.level, gfn, page_to_pfn(pages[i]), - true, true); + mmu_set_spte(vcpu, start, ACC_ALL, + access, 0, 0, NULL, + sp->role.level, gfn, + page_to_pfn(pages[i]), true, true); return 0; } @@ -2610,8 +2636,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, - write, &emulate, level, gfn, pfn, - prefault, map_writable); + 0, 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 3d1a35237dbf..a7b24cf59a3c 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; + unsigned index, pt_access, pte_access, accessed_dirty, shift; 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, + mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 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 write_fault, int hlevel, + int user_fault, 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, - write_fault, &emulate, it.level, + user_fault, write_fault, &emulate, it.level, gw->gfn, pfn, prefault, map_writable); FNAME(pte_prefetch)(vcpu, gw, it.sptep); @@ -487,38 +487,6 @@ 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 @@ -573,8 +541,7 @@ 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) - || FNAME(is_self_change_mapping)(vcpu, &walker, user_fault); + force_pt_level = mapping_level_dirty_bitmap(vcpu, walker.gfn); else force_pt_level = 1; if (!force_pt_level) { @@ -593,26 +560,6 @@ 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; @@ -621,7 +568,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, write_fault, + r = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault, level, pfn, map_writable, prefault); ++vcpu->stat.pf_fixed; kvm_mmu_audit(vcpu, AUDIT_POST_PAGE_FAULT); @@ -796,7 +743,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, + set_spte(vcpu, &sp->spt[i], pte_access, 0, 0, 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 dd2a85c1c6f0..55dfc375f1ab 100644 --- a/trunk/arch/x86/kvm/vmx.c +++ b/trunk/arch/x86/kvm/vmx.c @@ -1696,6 +1696,7 @@ 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; @@ -3109,6 +3110,7 @@ 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) @@ -3218,10 +3220,8 @@ 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,6 +3229,13 @@ 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. @@ -3239,7 +3246,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_read_guest_seg_selector(vmx, VCPU_SREG_CS) & 3; + vmx->cpl = __vmx_get_cpl(vcpu); } return vmx->cpl; diff --git a/trunk/drivers/s390/kvm/virtio_ccw.c b/trunk/drivers/s390/kvm/virtio_ccw.c index 2edd94af131c..1a5aff31d752 100644 --- a/trunk/drivers/s390/kvm/virtio_ccw.c +++ b/trunk/drivers/s390/kvm/virtio_ccw.c @@ -46,9 +46,11 @@ 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; @@ -125,21 +127,17 @@ static int doing_io(struct virtio_ccw_device *vcdev, __u32 flag) return ret; } -static int ccw_io_helper(struct virtio_ccw_device *vcdev, - struct ccw1 *ccw, __u32 intparm) +static int ccw_io_helper(struct virtio_ccw_device *vcdev, __u32 intparm) { int ret; unsigned long flags; int flag = intparm & VIRTIO_CCW_INTPARM_MASK; - 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); + 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); wait_event(vcdev->wait_q, doing_io(vcdev, flag) == 0); return ret ? ret : vcdev->err; } @@ -169,19 +167,18 @@ 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, - struct ccw1 *ccw, int index) +static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev, int index) { vcdev->config_block->index = index; - 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); + 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); return vcdev->config_block->num; } -static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw) +static void virtio_ccw_del_vq(struct virtqueue *vq) { struct virtio_ccw_device *vcdev = to_vc_device(vq->vdev); struct virtio_ccw_vq_info *info = vq->priv; @@ -200,12 +197,11 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw) info->info_block->align = 0; info->info_block->index = index; info->info_block->num = 0; - 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); + 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); /* * -ENODEV isn't considered an error: The device is gone anyway. * This may happen on device detach. @@ -224,23 +220,14 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw) 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, ccw); - - kfree(ccw); + virtio_ccw_del_vq(vq); } static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev, int i, vq_callback_t *callback, - const char *name, - struct ccw1 *ccw) + const char *name) { struct virtio_ccw_device *vcdev = to_vc_device(vdev); int err; @@ -263,7 +250,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, ccw, i); + info->num = virtio_ccw_read_vq_conf(vcdev, 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) { @@ -290,11 +277,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; - 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); + 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); if (err) { dev_warn(&vcdev->cdev->dev, "SET_VQ failed\n"); free_pages_exact(info->queue, size); @@ -325,15 +312,9 @@ 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], - ccw); + vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i]); if (IS_ERR(vqs[i])) { ret = PTR_ERR(vqs[i]); vqs[i] = NULL; @@ -348,30 +329,28 @@ 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; - 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); + 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); if (ret) goto out; /* Register indicators2 with host for config changes */ *indicatorp = (unsigned long) &vcdev->indicators2; vcdev->indicators2 = 0; - 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); + 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); if (ret) goto out; kfree(indicatorp); - kfree(ccw); return 0; out: kfree(indicatorp); - kfree(ccw); virtio_ccw_del_vqs(vdev); return ret; } @@ -379,95 +358,64 @@ 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. */ - 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); + 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); } 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, rc; - struct ccw1 *ccw; - - ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); - if (!ccw) - return 0; + struct virtio_feature_desc features; + int ret; - 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; - 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); + 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; -out_free: - kfree(features); - kfree(ccw); - return rc; + memcpy(&features, (void *)(unsigned long)vcdev->area, + sizeof(features)); + return le32_to_cpu(features.features); } 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); + features.index = i; + features.features = cpu_to_le32(vdev->features[i / 2] + >> highbits); + memcpy((void *)(unsigned long)vcdev->area, &features, + sizeof(features)); /* Write the feature bits to the host. */ - 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); + 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); } -out_free: - kfree(features); - kfree(ccw); } static void virtio_ccw_get_config(struct virtio_device *vdev, @@ -475,32 +423,19 @@ 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. */ - 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); + 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); if (ret) - goto out_free; + return; - memcpy(vcdev->config, config_area, sizeof(vcdev->config)); + memcpy(vcdev->config, (void *)(unsigned long)vcdev->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, @@ -508,55 +443,37 @@ 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(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); + 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); } 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; - 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); + 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); } static struct virtio_config_ops virtio_ccw_config_ops = { @@ -582,8 +499,9 @@ static void virtio_ccw_release_dev(struct device *_d) dev); struct virtio_ccw_device *vcdev = to_vc_device(dev); - kfree(vcdev->status); + kfree((void *)(unsigned long)vcdev->area); kfree(vcdev->config_block); + kfree(vcdev->ccw); kfree(vcdev); } @@ -739,6 +657,9 @@ 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; @@ -750,14 +671,21 @@ 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->status = kzalloc(sizeof(*vcdev->status), GFP_DMA | GFP_KERNEL); - if (!vcdev->status) { + vcdev->ccw = kzalloc(sizeof(*vcdev->ccw), GFP_DMA | GFP_KERNEL); + if (!vcdev->ccw) { ret = -ENOMEM; goto out_free; } @@ -786,8 +714,9 @@ static int virtio_ccw_online(struct ccw_device *cdev) return ret; out_free: if (vcdev) { - kfree(vcdev->status); + kfree((void *)(unsigned long)vcdev->area); 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 19911dddaeb7..a23f47c884cf 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(WATCHDOG), ERSN(S390_TSCH) + ERSN(S390_UCONTROL), ERSN(S390_TSCH) TRACE_EVENT(kvm_userspace_exit, TP_PROTO(__u32 reason, int errno),