From patchwork Tue Sep 3 09:39:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 11127559 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D3D9C112C for ; Tue, 3 Sep 2019 09:40:42 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B9675206BB for ; Tue, 3 Sep 2019 09:40:42 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B9675206BB Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i55HC-0005qm-ET; Tue, 03 Sep 2019 09:39:02 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i55HB-0005qd-PX for xen-devel@lists.xenproject.org; Tue, 03 Sep 2019 09:39:01 +0000 X-Inumbo-ID: a72d1b5a-ce2e-11e9-ab8c-12813bfff9fa Received: from mx1.suse.de (unknown [195.135.220.15]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id a72d1b5a-ce2e-11e9-ab8c-12813bfff9fa; Tue, 03 Sep 2019 09:38:58 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id BEFEFABED; Tue, 3 Sep 2019 09:38:57 +0000 (UTC) From: Jan Beulich To: "xen-devel@lists.xenproject.org" References: <347e51f2-e80c-992c-6d0b-3b2bfdb75cce@suse.com> Message-ID: <6509fa84-bc33-6de4-5ce8-eb371b782f0a@suse.com> Date: Tue, 3 Sep 2019 11:39:03 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0 MIME-Version: 1.0 In-Reply-To: <347e51f2-e80c-992c-6d0b-3b2bfdb75cce@suse.com> Content-Language: en-US Subject: [Xen-devel] [PATCH v3 3/8] x86emul: generalize invlpg() hook X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Andrew Cooper , Paul Durrant , Wei Liu , Roger Pau Monne Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" The hook is already in use for INVLPGA as well. Rename the hook and add parameters. For the moment INVLPGA with a non-zero ASID remains unsupported, but the TODO item gets pushed into the actual hook handler. Signed-off-by: Jan Beulich Reviewed-by: Paul Durrant Reviewed-by: Andrew Cooper --- v2: New. --- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c +++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c @@ -370,16 +370,23 @@ static int fuzz_cmpxchg( return maybe_fail(ctxt, "cmpxchg", true); } -static int fuzz_invlpg( - enum x86_segment seg, - unsigned long offset, +static int fuzz_tlb_op( + enum x86emul_tlb_op op, + unsigned long addr, + unsigned long aux, struct x86_emulate_ctxt *ctxt) { - /* invlpg(), unlike all other hooks, may be called with x86_seg_none. */ - assert(is_x86_user_segment(seg) || seg == x86_seg_none); - assert(ctxt->addr_size == 64 || !(offset >> 32)); + switch ( op ) + { + case x86emul_invlpg: + assert(is_x86_user_segment(aux)); + /* fall through */ + case x86emul_invlpga: + assert(ctxt->addr_size == 64 || !(addr >> 32)); + break; + } - return maybe_fail(ctxt, "invlpg", false); + return maybe_fail(ctxt, "TLB-management", false); } static int fuzz_cache_op( @@ -624,7 +631,7 @@ static const struct x86_emulate_ops all_ SET(read_msr), SET(write_msr), SET(cache_op), - SET(invlpg), + SET(tlb_op), .get_fpu = emul_test_get_fpu, .put_fpu = emul_test_put_fpu, .cpuid = emul_test_cpuid, @@ -733,12 +740,12 @@ enum { HOOK_read_msr, HOOK_write_msr, HOOK_cache_op, + HOOK_tlb_op, HOOK_cpuid, HOOK_inject_hw_exception, HOOK_inject_sw_interrupt, HOOK_get_fpu, HOOK_put_fpu, - HOOK_invlpg, HOOK_vmfunc, CANONICALIZE_rip, CANONICALIZE_rsp, @@ -777,9 +784,9 @@ static void disable_hooks(struct x86_emu MAYBE_DISABLE_HOOK(read_msr); MAYBE_DISABLE_HOOK(write_msr); MAYBE_DISABLE_HOOK(cache_op); + MAYBE_DISABLE_HOOK(tlb_op); MAYBE_DISABLE_HOOK(cpuid); MAYBE_DISABLE_HOOK(get_fpu); - MAYBE_DISABLE_HOOK(invlpg); } /* --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -2356,36 +2356,52 @@ static void hvmemul_put_fpu( } } -static int hvmemul_invlpg( - enum x86_segment seg, - unsigned long offset, +static int hvmemul_tlb_op( + enum x86emul_tlb_op op, + unsigned long addr, + unsigned long aux, struct x86_emulate_ctxt *ctxt) { struct hvm_emulate_ctxt *hvmemul_ctxt = container_of(ctxt, struct hvm_emulate_ctxt, ctxt); - unsigned long addr; - int rc; - - rc = hvmemul_virtual_to_linear( - seg, offset, 1, NULL, hvm_access_none, hvmemul_ctxt, &addr); + int rc = X86EMUL_OKAY; - if ( rc == X86EMUL_EXCEPTION ) + switch ( op ) { - /* - * `invlpg` takes segment bases into account, but is not subject to - * faults from segment type/limit checks, and is specified as a NOP - * when issued on non-canonical addresses. - * - * hvmemul_virtual_to_linear() raises exceptions for type/limit - * violations, so squash them. - */ - x86_emul_reset_event(ctxt); - rc = X86EMUL_OKAY; + case x86emul_invlpg: + rc = hvmemul_virtual_to_linear(aux, addr, 1, NULL, hvm_access_none, + hvmemul_ctxt, &addr); + + if ( rc == X86EMUL_EXCEPTION ) + { + /* + * `invlpg` takes segment bases into account, but is not subject + * to faults from segment type/limit checks, and is specified as + * a NOP when issued on non-canonical addresses. + * + * hvmemul_virtual_to_linear() raises exceptions for type/limit + * violations, so squash them. + */ + x86_emul_reset_event(ctxt); + rc = X86EMUL_OKAY; + } + + if ( rc == X86EMUL_OKAY ) + paging_invlpg(current, addr); + break; + + case x86emul_invlpga: + /* TODO: Support ASIDs. */ + if ( !aux ) + paging_invlpg(current, addr); + else + { + x86_emul_hw_exception(TRAP_invalid_op, X86_EVENT_NO_EC, ctxt); + rc = X86EMUL_EXCEPTION; + } + break; } - if ( rc == X86EMUL_OKAY ) - paging_invlpg(current, addr); - return rc; } @@ -2425,10 +2441,10 @@ static const struct x86_emulate_ops hvm_ .read_msr = hvmemul_read_msr, .write_msr = hvmemul_write_msr, .cache_op = hvmemul_cache_op, + .tlb_op = hvmemul_tlb_op, .cpuid = x86emul_cpuid, .get_fpu = hvmemul_get_fpu, .put_fpu = hvmemul_put_fpu, - .invlpg = hvmemul_invlpg, .vmfunc = hvmemul_vmfunc, }; @@ -2452,10 +2468,10 @@ static const struct x86_emulate_ops hvm_ .read_msr = hvmemul_read_msr, .write_msr = hvmemul_write_msr_discard, .cache_op = hvmemul_cache_op_discard, + .tlb_op = hvmemul_tlb_op, .cpuid = x86emul_cpuid, .get_fpu = hvmemul_get_fpu, .put_fpu = hvmemul_put_fpu, - .invlpg = hvmemul_invlpg, .vmfunc = hvmemul_vmfunc, }; --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -5590,10 +5590,9 @@ x86_emulate( generate_exception_if(!(msr_val & EFER_SVME) || !in_protmode(ctxt, ops), EXC_UD); generate_exception_if(!mode_ring0(), EXC_GP, 0); - generate_exception_if(_regs.ecx, EXC_UD); /* TODO: Support ASIDs. */ - fail_if(ops->invlpg == NULL); - if ( (rc = ops->invlpg(x86_seg_none, truncate_ea(_regs.r(ax)), - ctxt)) ) + fail_if(!ops->tlb_op); + if ( (rc = ops->tlb_op(x86emul_invlpga, truncate_ea(_regs.r(ax)), + _regs.ecx, ctxt)) != X86EMUL_OKAY ) goto done; break; @@ -5747,8 +5746,9 @@ x86_emulate( case GRP7_MEM(7): /* invlpg */ ASSERT(ea.type == OP_MEM); generate_exception_if(!mode_ring0(), EXC_GP, 0); - fail_if(ops->invlpg == NULL); - if ( (rc = ops->invlpg(ea.mem.seg, ea.mem.off, ctxt)) ) + fail_if(!ops->tlb_op); + if ( (rc = ops->tlb_op(x86emul_invlpg, ea.mem.off, ea.mem.seg, + ctxt)) != X86EMUL_OKAY ) goto done; break; --- a/xen/arch/x86/x86_emulate/x86_emulate.h +++ b/xen/arch/x86/x86_emulate/x86_emulate.h @@ -185,6 +185,11 @@ enum x86emul_cache_op { x86emul_wbnoinvd, }; +enum x86emul_tlb_op { + x86emul_invlpg, + x86emul_invlpga, +}; + struct x86_emulate_state; /* @@ -472,6 +477,19 @@ struct x86_emulate_ops unsigned long offset, struct x86_emulate_ctxt *ctxt); + /* + * tlb_op: Invalidate paging structures which map addressed byte. + * + * @addr and @aux have @op-specific meaning: + * - INVLPG: @aux:@addr represent seg:offset + * - INVLPGA: @addr is the linear address, @aux the ASID + */ + int (*tlb_op)( + enum x86emul_tlb_op op, + unsigned long addr, + unsigned long aux, + struct x86_emulate_ctxt *ctxt); + /* cpuid: Emulate CPUID via given set of EAX-EDX inputs/outputs. */ int (*cpuid)( uint32_t leaf, @@ -499,12 +517,6 @@ struct x86_emulate_ops enum x86_emulate_fpu_type backout, const struct x86_emul_fpu_aux *aux); - /* invlpg: Invalidate paging structures which map addressed byte. */ - int (*invlpg)( - enum x86_segment seg, - unsigned long offset, - struct x86_emulate_ctxt *ctxt); - /* vmfunc: Emulate VMFUNC via given set of EAX ECX inputs */ int (*vmfunc)( struct x86_emulate_ctxt *ctxt);