From patchwork Tue Jul 12 18:13:18 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tamas Lengyel X-Patchwork-Id: 9225911 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id EA19460868 for ; Tue, 12 Jul 2016 18:16:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DE9E02787D for ; Tue, 12 Jul 2016 18:16:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D14E627C38; Tue, 12 Jul 2016 18:16:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E06372787D for ; Tue, 12 Jul 2016 18:16:01 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bN2BU-00073x-Na; Tue, 12 Jul 2016 18:13:28 +0000 Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bN2BS-00073l-Tl for xen-devel@lists.xenproject.org; Tue, 12 Jul 2016 18:13:27 +0000 Received: from [193.109.254.147] by server-5.bemta-14.messagelabs.com id C5/B3-08132-64335875; Tue, 12 Jul 2016 18:13:26 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupjkeJIrShJLcpLzFFi42K5GHr/sK6rcWu 4weejYhbft0xmcmD0OPzhCksAYxRrZl5SfkUCa8bDBx2sBZNiKg5smM7awLjStYuRi0NIYCaj xMS3y9m7GDk5WATesEj82CAPkpAQeMci0fWmmxUkISEQI3F2yRVmCLtK4u2Si0wgtpCApsTBD WeYISZNZJLo+38TrIhNwEji6tUeNhBbREBJ4t6qyWANzAKHmCS2PuQCsYUFdCVerH/GBrFZVe LB0ieMIDavgJfE0n29jBDL5CQuT3/ANoGRbwEjwypGjeLUorLUIl1DC72kosz0jJLcxMwcXUN DE73c1OLixPTUnMSkYr3k/NxNjMBQqWdgYNzBeGS75yFGSQ4mJVHedq3WcCG+pPyUyozE4oz4 otKc1OJDjDIcHEoSvB8MgXKCRanpqRVpmTnAoIVJS3DwKInwOhoApXmLCxJzizPTIVKnGI05t vy+tpaJY9vUe2uZhFjy8vNSpcR5Z4NMEgApzSjNgxsEi6ZLjLJSwryMDAwMQjwFqUW5mSWo8q 8YxTkYlYR5m0Cm8GTmlcDtewV0ChPQKbUOzSCnlCQipKQaGLuO9q823Hb7vl4X8+MAzoSLTww iG2/84KrN1Tm15F/0hbm/nbpmPJeJyO4zKrirdjd19rWIrIvhXyf1BHo1PPudt/zpC2bVcK1o tlq9L7LJP5f6/5eWuel5j7XBYoHDuhktJd+3fd+6tNrl2yr2AKd5ZidvquvLKBiKHekSn/eXe eOzGu7nd5RYijMSDbWYi4oTAUwPpOChAgAA X-Env-Sender: tamas.lengyel@zentific.com X-Msg-Ref: server-10.tower-27.messagelabs.com!1468347203!53389405!1 X-Originating-IP: [209.85.223.195] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 8.77; banners=-,-,- X-VirusChecked: Checked Received: (qmail 3492 invoked from network); 12 Jul 2016 18:13:25 -0000 Received: from mail-io0-f195.google.com (HELO mail-io0-f195.google.com) (209.85.223.195) by server-10.tower-27.messagelabs.com with AES128-GCM-SHA256 encrypted SMTP; 12 Jul 2016 18:13:25 -0000 Received: by mail-io0-f195.google.com with SMTP id y195so1533663iod.0 for ; Tue, 12 Jul 2016 11:13:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zentific-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=fxHL67a06XEQHsWyPFoy2QdnI/BGGQORv8Elwi0NM7M=; b=W1COmQ1LTH15ceS6CVsj0Zb9nYrQfQ9cCCn4RWS8iU7U5qYE/JUcr2daC7rfvwguXS S5djkn6d6H9HsTS8Pxo/qjctl3BoEcUc7S+nOTc1L1jlXZ4n7kWFTqAjJ9X3NXNSUPJo joEeQ+QXOJ/9z78EJJWaxnB61plgc8MTYE1lrPBu705UdzktoAAQCn9N6xDuEMhjhdEh Lc9c4tuMauBR5kweSfGIMSnWl2pq90xAZiE4oj8rzMWvirIUfhF1Dt9qet4VnzuKH73u 9ApSiA8qJEvEvI5KiM/8QCNmrwPMOhg8AGcHxmxHFo68CDQc8A/L7YhbBtmgdT6k36/x eOXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=fxHL67a06XEQHsWyPFoy2QdnI/BGGQORv8Elwi0NM7M=; b=OfF+vXHg3jYrq5Zkr1VAk1/crfkWfmoxO2J9oD3P+0Wss1tKpbffVmBO5OLTKaGf+5 teP3ri1Dc3Nq3z45jOpR7Jh6IVBGX/K9lSDH0eOOlBQxR3ma5Z6DD3nCge7JLBCeWkfZ qsyTtqOu0nvebslHko9tIoN6bqkC/aQBDAnynUpqbx2dQJDeW0Ex4/3/BAj7xMj4tC3x iHx5+sPKqmAqKTnHS42y7G8ogjPaMOXbxPUp7PNl1xbddrA+4c/ud0Ih18N0E6QqEAjD +yg429GnG2t5HwHGXvuMd+P+RZUUmrLtvbFsbBZJoSJK3oDC3jsT55oCsh0ed4LaxBBi 52vA== X-Gm-Message-State: ALyK8tICLKqhhYhgorzV8pasbUGKmSilOTa8gbY4xsvB6xuvnbQh6qi3wMi20qMKYMM09g== X-Received: by 10.107.134.140 with SMTP id q12mr4430615ioi.25.1468347203385; Tue, 12 Jul 2016 11:13:23 -0700 (PDT) Received: from l1.lan (c-73-14-35-59.hsd1.co.comcast.net. [73.14.35.59]) by smtp.gmail.com with ESMTPSA id e69sm10275200ite.2.2016.07.12.11.13.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 12 Jul 2016 11:13:22 -0700 (PDT) From: Tamas K Lengyel To: xen-devel@lists.xenproject.org Date: Tue, 12 Jul 2016 12:13:18 -0600 Message-Id: <1468347198-29474-1-git-send-email-tamas.lengyel@zentific.com> X-Mailer: git-send-email 2.8.1 Cc: Kevin Tian , Wei Liu , Jun Nakajima , Razvan Cojocaru , Tamas K Lengyel , Ian Jackson , Jan Beulich , Andrew Cooper Subject: [Xen-devel] [PATCH v2] vmx/monitor: CPUID events X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP This patch implements sending notification to a monitor subscriber when an x86/vmx guest executes the CPUID instruction. Signed-off-by: Tamas K Lengyel Acked-by: Razvan Cojocaru Acked-by: Kevin Tian Acked-by: Wei Liu --- Cc: Ian Jackson Cc: Wei Liu Cc: Razvan Cojocaru Cc: Jan Beulich Cc: Andrew Cooper Cc: Jun Nakajima Cc: Kevin Tian v2: add comment describing rc values in vmx fix typo in xen-access --- tools/libxc/include/xenctrl.h | 1 + tools/libxc/xc_monitor.c | 13 +++++++++++++ tools/tests/xen-access/xen-access.c | 33 ++++++++++++++++++++++++++++++++- xen/arch/x86/hvm/monitor.c | 16 ++++++++++++++++ xen/arch/x86/hvm/vmx/vmx.c | 28 ++++++++++++++++++++++++---- xen/arch/x86/monitor.c | 13 +++++++++++++ xen/include/asm-x86/domain.h | 1 + xen/include/asm-x86/hvm/monitor.h | 1 + xen/include/asm-x86/monitor.h | 3 ++- xen/include/public/domctl.h | 1 + xen/include/public/vm_event.h | 8 ++++++++ 11 files changed, 112 insertions(+), 6 deletions(-) diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 4a85b4a..e904bd5 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -2167,6 +2167,7 @@ int xc_monitor_guest_request(xc_interface *xch, domid_t domain_id, bool enable, bool sync); int xc_monitor_debug_exceptions(xc_interface *xch, domid_t domain_id, bool enable, bool sync); +int xc_monitor_cpuid(xc_interface *xch, domid_t domain_id, bool enable); /** * This function enables / disables emulation for each REP for a * REP-compatible instruction. diff --git a/tools/libxc/xc_monitor.c b/tools/libxc/xc_monitor.c index 264992c..4298813 100644 --- a/tools/libxc/xc_monitor.c +++ b/tools/libxc/xc_monitor.c @@ -172,6 +172,19 @@ int xc_monitor_debug_exceptions(xc_interface *xch, domid_t domain_id, return do_domctl(xch, &domctl); } +int xc_monitor_cpuid(xc_interface *xch, domid_t domain_id, bool enable) +{ + DECLARE_DOMCTL; + + domctl.cmd = XEN_DOMCTL_monitor_op; + domctl.domain = domain_id; + domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE + : XEN_DOMCTL_MONITOR_OP_DISABLE; + domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_CPUID; + + return do_domctl(xch, &domctl); +} + /* * Local variables: * mode: C diff --git a/tools/tests/xen-access/xen-access.c b/tools/tests/xen-access/xen-access.c index 02655d5..ebb63b1 100644 --- a/tools/tests/xen-access/xen-access.c +++ b/tools/tests/xen-access/xen-access.c @@ -337,7 +337,7 @@ void usage(char* progname) { fprintf(stderr, "Usage: %s [-m] write|exec", progname); #if defined(__i386__) || defined(__x86_64__) - fprintf(stderr, "|breakpoint|altp2m_write|altp2m_exec|debug"); + fprintf(stderr, "|breakpoint|altp2m_write|altp2m_exec|debug|cpuid"); #endif fprintf(stderr, "\n" @@ -364,6 +364,7 @@ int main(int argc, char *argv[]) int shutting_down = 0; int altp2m = 0; int debug = 0; + int cpuid = 0; uint16_t altp2m_view_id = 0; char* progname = argv[0]; @@ -426,6 +427,10 @@ int main(int argc, char *argv[]) { debug = 1; } + else if ( !strcmp(argv[0], "cpuid") ) + { + cpuid = 1; + } #endif else { @@ -548,6 +553,16 @@ int main(int argc, char *argv[]) } } + if ( cpuid ) + { + rc = xc_monitor_cpuid(xch, domain_id, 1); + if ( rc < 0 ) + { + ERROR("Error %d setting cpuid listener with vm_event\n", rc); + goto exit; + } + } + /* Wait for access */ for (;;) { @@ -560,6 +575,8 @@ int main(int argc, char *argv[]) rc = xc_monitor_software_breakpoint(xch, domain_id, 0); if ( debug ) rc = xc_monitor_debug_exceptions(xch, domain_id, 0, 0); + if ( cpuid ) + rc = xc_monitor_cpuid(xch, domain_id, 0); if ( altp2m ) { @@ -716,6 +733,20 @@ int main(int argc, char *argv[]) } break; + case VM_EVENT_REASON_CPUID: + printf("CPUID executed: rip=%016"PRIx64", vcpu %d. Insn length: %"PRIu32" " \ + "EAX: 0x%"PRIx64" EBX: 0x%"PRIx64" ECX: 0x%"PRIx64" EDX: 0x%"PRIx64"\n", + req.data.regs.x86.rip, + req.vcpu_id, + req.u.cpuid.insn_length, + req.data.regs.x86.rax, + req.data.regs.x86.rbx, + req.data.regs.x86.rcx, + req.data.regs.x86.rdx); + rsp.flags |= VM_EVENT_FLAG_SET_REGISTERS; + rsp.data = req.data; + rsp.data.regs.x86.rip += req.u.cpuid.insn_length; + break; default: fprintf(stderr, "UNKNOWN REASON CODE %d\n", req.reason); } diff --git a/xen/arch/x86/hvm/monitor.c b/xen/arch/x86/hvm/monitor.c index 8488e21..7277c12 100644 --- a/xen/arch/x86/hvm/monitor.c +++ b/xen/arch/x86/hvm/monitor.c @@ -136,6 +136,22 @@ int hvm_monitor_debug(unsigned long rip, enum hvm_monitor_debug_type type, return monitor_traps(curr, sync, &req); } +int hvm_monitor_cpuid(unsigned long insn_length) +{ + struct vcpu *curr = current; + struct arch_domain *ad = &curr->domain->arch; + vm_event_request_t req = {}; + + if ( !ad->monitor.cpuid_enabled ) + return 0; + + req.reason = VM_EVENT_REASON_CPUID; + req.vcpu_id = curr->vcpu_id; + req.u.cpuid.insn_length = insn_length; + + return monitor_traps(curr, 1, &req); +} + /* * Local variables: * mode: C diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 0776d12..ce47714 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -2396,7 +2396,7 @@ static void vmx_cpuid_intercept( HVMTRACE_5D (CPUID, input, *eax, *ebx, *ecx, *edx); } -static void vmx_do_cpuid(struct cpu_user_regs *regs) +static int vmx_do_cpuid(struct cpu_user_regs *regs) { unsigned int eax, ebx, ecx, edx; @@ -2411,6 +2411,8 @@ static void vmx_do_cpuid(struct cpu_user_regs *regs) regs->ebx = ebx; regs->ecx = ecx; regs->edx = edx; + + return hvm_monitor_cpuid(get_instruction_length()); } static void vmx_dr_access(unsigned long exit_qualification, @@ -3524,10 +3526,28 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) hvm_task_switch((uint16_t)exit_qualification, reasons[source], ecode); break; } - case EXIT_REASON_CPUID: - is_pvh_vcpu(v) ? pv_cpuid(regs) : vmx_do_cpuid(regs); - update_guest_eip(); /* Safe: CPUID */ + case EXIT_REASON_CPUID: { + int rc; + + if ( is_pvh_vcpu(v) ) + { + pv_cpuid(regs); + rc = 0; + } + else + rc = vmx_do_cpuid(regs); + + /* + * rc < 0 error in monitor/vm_event, crash + * !rc continue normally + * rc > 0 paused waiting for response, work here is done + */ + if ( rc < 0 ) + goto exit_and_crash; + if ( !rc ) + update_guest_eip(); /* Safe: CPUID */ break; + } case EXIT_REASON_HLT: update_guest_eip(); /* Safe: HLT */ hvm_hlt(regs->eflags); diff --git a/xen/arch/x86/monitor.c b/xen/arch/x86/monitor.c index 205df41..5f60743 100644 --- a/xen/arch/x86/monitor.c +++ b/xen/arch/x86/monitor.c @@ -240,6 +240,19 @@ int arch_monitor_domctl_event(struct domain *d, break; } + case XEN_DOMCTL_MONITOR_EVENT_CPUID: + { + bool_t old_status = ad->monitor.cpuid_enabled; + + if ( unlikely(old_status == requested_status) ) + return -EEXIST; + + domain_pause(d); + ad->monitor.cpuid_enabled = requested_status; + domain_unpause(d); + break; + } + default: /* * Should not be reached unless arch_monitor_get_capabilities() is diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 8f64ae9..5807a1f 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -405,6 +405,7 @@ struct arch_domain unsigned int software_breakpoint_enabled : 1; unsigned int debug_exception_enabled : 1; unsigned int debug_exception_sync : 1; + unsigned int cpuid_enabled : 1; struct monitor_msr_bitmap *msr_bitmap; } monitor; diff --git a/xen/include/asm-x86/hvm/monitor.h b/xen/include/asm-x86/hvm/monitor.h index 1c8ec6c..a92f3fc 100644 --- a/xen/include/asm-x86/hvm/monitor.h +++ b/xen/include/asm-x86/hvm/monitor.h @@ -40,6 +40,7 @@ bool_t hvm_monitor_cr(unsigned int index, unsigned long value, void hvm_monitor_msr(unsigned int msr, uint64_t value); int hvm_monitor_debug(unsigned long rip, enum hvm_monitor_debug_type type, unsigned long trap_type, unsigned long insn_length); +int hvm_monitor_cpuid(unsigned long insn_length); #endif /* __ASM_X86_HVM_MONITOR_H__ */ diff --git a/xen/include/asm-x86/monitor.h b/xen/include/asm-x86/monitor.h index 0501ca2..63a994b 100644 --- a/xen/include/asm-x86/monitor.h +++ b/xen/include/asm-x86/monitor.h @@ -75,7 +75,8 @@ static inline uint32_t arch_monitor_get_capabilities(struct domain *d) (1U << XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR) | (1U << XEN_DOMCTL_MONITOR_EVENT_SOFTWARE_BREAKPOINT) | (1U << XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST) | - (1U << XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION); + (1U << XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION) | + (1U << XEN_DOMCTL_MONITOR_EVENT_CPUID); /* Since we know this is on VMX, we can just call the hvm func */ if ( hvm_is_singlestep_supported() ) diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 30020ba..d6d2319 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -1081,6 +1081,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cmt_op_t); #define XEN_DOMCTL_MONITOR_EVENT_SOFTWARE_BREAKPOINT 3 #define XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST 4 #define XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION 5 +#define XEN_DOMCTL_MONITOR_EVENT_CPUID 6 struct xen_domctl_monitor_op { uint32_t op; /* XEN_DOMCTL_MONITOR_OP_* */ diff --git a/xen/include/public/vm_event.h b/xen/include/public/vm_event.h index 8c29968..64e6857 100644 --- a/xen/include/public/vm_event.h +++ b/xen/include/public/vm_event.h @@ -122,6 +122,8 @@ #define VM_EVENT_REASON_GUEST_REQUEST 8 /* A debug exception was caught */ #define VM_EVENT_REASON_DEBUG_EXCEPTION 9 +/* CPUID executed */ +#define VM_EVENT_REASON_CPUID 10 /* Supported values for the vm_event_write_ctrlreg index. */ #define VM_EVENT_X86_CR0 0 @@ -222,6 +224,11 @@ struct vm_event_mov_to_msr { uint64_t value; }; +struct vm_event_cpuid { + uint32_t insn_length; + uint32_t _pad; +}; + #define MEM_PAGING_DROP_PAGE (1 << 0) #define MEM_PAGING_EVICT_FAIL (1 << 1) @@ -260,6 +267,7 @@ typedef struct vm_event_st { struct vm_event_singlestep singlestep; struct vm_event_debug software_breakpoint; struct vm_event_debug debug_exception; + struct vm_event_cpuid cpuid; } u; union {