From patchwork Wed Nov 25 09:35:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Adalbert_Laz=C4=83r?= X-Patchwork-Id: 11930879 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2424AC64E7C for ; Wed, 25 Nov 2020 09:42:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D31DD2083E for ; Wed, 25 Nov 2020 09:42:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728742AbgKYJmq (ORCPT ); Wed, 25 Nov 2020 04:42:46 -0500 Received: from mx01.bbu.dsd.mx.bitdefender.com ([91.199.104.161]:57198 "EHLO mx01.bbu.dsd.mx.bitdefender.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728268AbgKYJmC (ORCPT ); Wed, 25 Nov 2020 04:42:02 -0500 Received: from smtp.bitdefender.com (smtp01.buh.bitdefender.com [10.17.80.75]) by mx01.bbu.dsd.mx.bitdefender.com (Postfix) with ESMTPS id 9774830462D0; Wed, 25 Nov 2020 11:35:53 +0200 (EET) Received: from localhost.localdomain (unknown [91.199.104.27]) by smtp.bitdefender.com (Postfix) with ESMTPSA id 795CA3072784; Wed, 25 Nov 2020 11:35:53 +0200 (EET) From: =?utf-8?q?Adalbert_Laz=C4=83r?= To: kvm@vger.kernel.org Cc: virtualization@lists.linux-foundation.org, Paolo Bonzini , =?utf-8?q?Adalbert_Laz=C4=83r?= Subject: [PATCH v10 66/81] KVM: introspection: add KVMI_VCPU_GET_XCR Date: Wed, 25 Nov 2020 11:35:45 +0200 Message-Id: <20201125093600.2766-67-alazar@bitdefender.com> In-Reply-To: <20201125093600.2766-1-alazar@bitdefender.com> References: <20201125093600.2766-1-alazar@bitdefender.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This can be used by the introspection tool to emulate SSE instructions. Signed-off-by: Adalbert Lazăr Reported-by: kernel test robot --- Documentation/virt/kvm/kvmi.rst | 33 +++++++++++++++++++ arch/x86/include/uapi/asm/kvmi.h | 9 +++++ arch/x86/kvm/kvmi_msg.c | 21 ++++++++++++ include/uapi/linux/kvmi.h | 1 + .../testing/selftests/kvm/x86_64/kvmi_test.c | 33 +++++++++++++++++++ 5 files changed, 97 insertions(+) diff --git a/Documentation/virt/kvm/kvmi.rst b/Documentation/virt/kvm/kvmi.rst index 24dc1867c1f1..008c7c73a46f 100644 --- a/Documentation/virt/kvm/kvmi.rst +++ b/Documentation/virt/kvm/kvmi.rst @@ -797,6 +797,39 @@ Provides the maximum GFN allocated to the VM by walking through all memory slots. Stricly speaking, the returned value refers to the first inaccessible GFN, next to the maximum accessible GFN. +18. KVMI_VCPU_GET_XCR +--------------------- + +:Architectures: x86 +:Versions: >= 1 +:Parameters: + +:: + + struct kvmi_vcpu_hdr; + struct kvmi_vcpu_get_xcr { + __u8 xcr; + __u8 padding[7]; + }; + +:Returns: + +:: + + struct kvmi_error_code; + struct kvmi_vcpu_get_xcr_reply { + u64 value; + }; + +Returns the value of an extended control register XCR. + +:Errors: + +* -KVM_EINVAL - the selected vCPU is invalid +* -KVM_EINVAL - the specified control register is not XCR0 +* -KVM_EINVAL - the padding is not zero +* -KVM_EAGAIN - the selected vCPU can't be introspected yet + Events ====== diff --git a/arch/x86/include/uapi/asm/kvmi.h b/arch/x86/include/uapi/asm/kvmi.h index 604a8b3d4ac2..5ca6190d85ec 100644 --- a/arch/x86/include/uapi/asm/kvmi.h +++ b/arch/x86/include/uapi/asm/kvmi.h @@ -102,4 +102,13 @@ struct kvmi_vcpu_event_xsetbv { __u64 new_value; }; +struct kvmi_vcpu_get_xcr { + __u8 xcr; + __u8 padding[7]; +}; + +struct kvmi_vcpu_get_xcr_reply { + u64 value; +}; + #endif /* _UAPI_ASM_X86_KVMI_H */ diff --git a/arch/x86/kvm/kvmi_msg.c b/arch/x86/kvm/kvmi_msg.c index d0dc917118b5..596f607296b5 100644 --- a/arch/x86/kvm/kvmi_msg.c +++ b/arch/x86/kvm/kvmi_msg.c @@ -174,11 +174,32 @@ static int handle_vcpu_inject_exception(const struct kvmi_vcpu_msg_job *job, return kvmi_msg_vcpu_reply(job, msg, ec, NULL, 0); } +static int handle_vcpu_get_xcr(const struct kvmi_vcpu_msg_job *job, + const struct kvmi_msg_hdr *msg, + const void *_req) +{ + const struct kvmi_vcpu_get_xcr *req = _req; + struct kvmi_vcpu_get_xcr_reply rpl; + int ec = 0; + + memset(&rpl, 0, sizeof(rpl)); + + if (non_zero_padding(req->padding, ARRAY_SIZE(req->padding))) + ec = -KVM_EINVAL; + else if (req->xcr != 0) + ec = -KVM_EINVAL; + else + rpl.value = job->vcpu->arch.xcr0; + + return kvmi_msg_vcpu_reply(job, msg, ec, &rpl, sizeof(rpl)); +} + static kvmi_vcpu_msg_job_fct const msg_vcpu[] = { [KVMI_VCPU_CONTROL_CR] = handle_vcpu_control_cr, [KVMI_VCPU_GET_CPUID] = handle_vcpu_get_cpuid, [KVMI_VCPU_GET_INFO] = handle_vcpu_get_info, [KVMI_VCPU_GET_REGISTERS] = handle_vcpu_get_registers, + [KVMI_VCPU_GET_XCR] = handle_vcpu_get_xcr, [KVMI_VCPU_INJECT_EXCEPTION] = handle_vcpu_inject_exception, [KVMI_VCPU_SET_REGISTERS] = handle_vcpu_set_registers, }; diff --git a/include/uapi/linux/kvmi.h b/include/uapi/linux/kvmi.h index d503e15baf60..07b6d383641a 100644 --- a/include/uapi/linux/kvmi.h +++ b/include/uapi/linux/kvmi.h @@ -44,6 +44,7 @@ enum { KVMI_VCPU_GET_CPUID = KVMI_VCPU_MESSAGE_ID(5), KVMI_VCPU_CONTROL_CR = KVMI_VCPU_MESSAGE_ID(6), KVMI_VCPU_INJECT_EXCEPTION = KVMI_VCPU_MESSAGE_ID(7), + KVMI_VCPU_GET_XCR = KVMI_VCPU_MESSAGE_ID(8), KVMI_NEXT_VCPU_MESSAGE }; diff --git a/tools/testing/selftests/kvm/x86_64/kvmi_test.c b/tools/testing/selftests/kvm/x86_64/kvmi_test.c index f73dbfe1407d..da90c6a8d535 100644 --- a/tools/testing/selftests/kvm/x86_64/kvmi_test.c +++ b/tools/testing/selftests/kvm/x86_64/kvmi_test.c @@ -1416,6 +1416,38 @@ static void test_event_xsetbv(struct kvm_vm *vm) disable_vcpu_event(vm, event_id); } +static void cmd_vcpu_get_xcr(struct kvm_vm *vm, u8 xcr, u64 *value, + int expected_err) +{ + struct { + struct kvmi_msg_hdr hdr; + struct kvmi_vcpu_hdr vcpu_hdr; + struct kvmi_vcpu_get_xcr cmd; + } req = { 0 }; + struct kvmi_vcpu_get_xcr_reply rpl = { 0 }; + int r; + + req.cmd.xcr = xcr; + + r = do_vcpu0_command(vm, KVMI_VCPU_GET_XCR, &req.hdr, sizeof(req), + &rpl, sizeof(rpl)); + TEST_ASSERT(r == expected_err, + "KVMI_VCPU_GET_XCR failed, error %d (%s), expected %d\n", + -r, kvm_strerror(-r), expected_err); + + *value = r == 0 ? rpl.value : 0; +} + +static void test_cmd_vcpu_get_xcr(struct kvm_vm *vm) +{ + u8 xcr0 = 0, xcr1 = 1; + u64 value; + + cmd_vcpu_get_xcr(vm, xcr0, &value, 0); + pr_debug("XCR0 0x%lx\n", value); + cmd_vcpu_get_xcr(vm, xcr1, &value, -KVM_EINVAL); +} + static void test_introspection(struct kvm_vm *vm) { srandom(time(0)); @@ -1443,6 +1475,7 @@ static void test_introspection(struct kvm_vm *vm) test_cmd_vcpu_inject_exception(vm); test_cmd_vm_get_max_gfn(); test_event_xsetbv(vm); + test_cmd_vcpu_get_xcr(vm); unhook_introspection(vm); }