Received: by 2002:ab2:3319:0:b0:1ef:7a0f:c32d with SMTP id i25csp303021lqc; Thu, 7 Mar 2024 19:27:19 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCX8Dk9v6NA2ODNtYT/GjZF9Pyi8fOY6tv6YoAv2qexO6JFipsxtshH9MmXIIej0EzepktrL7EXRirk13Dop0j+JOl3bWnzXZ3ZGVunVTQ== X-Google-Smtp-Source: AGHT+IGW6unCiqjmhfRHiTuKMFJ0sNDbC46pPkV6b84LRt94a/FM7b9npyhSaPb4gksMt7Qx6J6+ X-Received: by 2002:a05:6a20:4982:b0:1a1:4c31:8006 with SMTP id fs2-20020a056a20498200b001a14c318006mr8119463pzb.51.1709868438766; Thu, 07 Mar 2024 19:27:18 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1709868438; cv=pass; d=google.com; s=arc-20160816; b=J2t4N3Pu5EdqdFrjgbR7pB/TM/8cC4LL3aL96+e7ue1am2CXJ4MtJ9UXH2hVO/7uY3 Dm7f5/2tJqSd5QeWLQr65St+wsdRhYyshpP8+fgzD+AWu+W4y9k2qgu+l6X2QRPp+qg7 gfMsaM+1vkHqTzBytDZMhODnCEsbjQx9O68iBy/xBwEARiyLUrHpHHO0qfwfqJdreFVQ HzJEpeITVn7h2u4Jwh/t7O3R9vP7fIpMtCpcmMdAbQE3KXAfeFvJ6PGNgcjM3gxHhPMV Bsi1ba/CScXI6k22I6z7hLpDnAiQWCFZ3HY/rv/0elMZuoICWWS0fYiveEIYU2k8RH8+ IFTA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=IEEd/Jb1rJBC3yBdVesDQB5z+EkpmwWp0yzCJ4w5sp0=; fh=6RQVJhUadVlbCYQO8WbwFdcKs3+SddxIKFPo/gACb1Y=; b=lRI6atM9VcH5JY7UE+UZXJiSFbYRxdEradwidDsMLBG8xgJy467xHzpBYFAuMvkU/Z V4qY08GsyI+A7IYLkuRkP9Dev8hXvqQLta7f9yUxTUbhvfn4c4KMC4H3b7KbwDhmmHhP 3H/HVlu7jAYTLqponIT2PHRCIvfxAy0AChQzoGOyJcCK70hx1YfuEbhbaIkXpZDC29ec ncPja4w4qe2YYGchGfe8ykyj3YXNUUpmmxbM37/3Nq+jMoQJ3wTTjwwDKpHTa51SiZ2K qKEA/fMsIu15p/Rsk/GEHbHrTP8mY7Wg/Q5D8aAC+iWBaILOCknjzh5e0Z6u7Ud9X5+3 ojBw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@broadcom.com header.s=google header.b=bl2u58DR; arc=pass (i=1 dkim=pass dkdomain=broadcom.com dmarc=pass fromdomain=broadcom.com); spf=pass (google.com: domain of linux-kernel+bounces-96253-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-96253-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=broadcom.com Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id fa13-20020a17090af0cd00b002993be51a7dsi2923625pjb.163.2024.03.07.19.27.18 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 19:27:18 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-96253-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@broadcom.com header.s=google header.b=bl2u58DR; arc=pass (i=1 dkim=pass dkdomain=broadcom.com dmarc=pass fromdomain=broadcom.com); spf=pass (google.com: domain of linux-kernel+bounces-96253-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-96253-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=broadcom.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 521A928759B for ; Thu, 7 Mar 2024 21:30:56 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9102414199F; Thu, 7 Mar 2024 21:30:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="bl2u58DR" Received: from mail-pj1-f43.google.com (mail-pj1-f43.google.com [209.85.216.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 09AD813EFF3 for ; Thu, 7 Mar 2024 21:30:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.43 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709847005; cv=none; b=N3Cf0VLnzFucdsgGAyC8Sxl4exHT7m89IDQqfmhPQ/CWNqPkHBV3eB+6mgOzYb39RqoDB2T/br0R3CTeRU4x0cbqnc9W0WGMq2EqeF1dfg79PBO1kuQLl1MSCaAy1o+tX9R96/1XY5v3Rhznx+vH2V1iDn6bOoVFSriT9fDrhYs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709847005; c=relaxed/simple; bh=PKbUxXln9zAxN6d3uAI8zEHba5+3lXSdVO7w4J4rlNA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=irxZOMVQdu4y+YWzJunIjOtSVE9D0p5nkJ2Lm3dfO50PdYs1VQREQ/IFNu9oMnhuTFuwzMif6m1RIhDtxW35fi6v/ViLK0YvzmhijulkXpa5dZwMNur6rAl4jYHZMsxXz2xSqKiKouGIKnlHssjqLjdSeme9+jfw1N+w8KRI/mE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=bl2u58DR; arc=none smtp.client-ip=209.85.216.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Received: by mail-pj1-f43.google.com with SMTP id 98e67ed59e1d1-29bad5f4ae8so137734a91.1 for ; Thu, 07 Mar 2024 13:30:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1709847003; x=1710451803; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IEEd/Jb1rJBC3yBdVesDQB5z+EkpmwWp0yzCJ4w5sp0=; b=bl2u58DRTKgNJaLjZc2dlrakThIOtCZRoczaw95FlMhnNuhZ2AvWF6oMRq2zD1Dafe aTyN5UZz0GNvn2vOzBavAxMdDXQTwxNgRmOShzkGOEInpUK4Yy+IoSa1x0fwzfORfpHd qjHUrrkRQjiLEWJ3RQMfxHXRMlpmo0zv9MQes= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709847003; x=1710451803; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IEEd/Jb1rJBC3yBdVesDQB5z+EkpmwWp0yzCJ4w5sp0=; b=wHvgRue4792cge2KZP7zmKOKKpV6V8fKQEvB+uf3OU3Ro9/VsaiHgC+ZkDl37RfCKE ouzCFztQqCgWQ72EKaN2G3p4z3hnEAVCtvd+2VrRC7BUnJcq7kO/V3J0ST/lcJZXY8Nt wGboA3+Plv14sARBSfWOQWKwZbQayMx9rwXg3TD6UMbwnbOyiV515EJxYhVKneqnKpDu nU5lev+lv6wy5ZXfJyfumfRbzNvb/tnIiZZd7jEXLmCO7tePutu5E/sZDgKpXhJ0IxnP E5Pfmzf59Fr1pcqpsfMya557sQHpujprAGsLnR4SavO/aekd6L/0VycclkpxAyqIwKpW mWag== X-Gm-Message-State: AOJu0YxefZ7647+WfmJ+jKh2r0tSQNujDwQ6qqG8WSbMiCvog2IOMnS6 Vi+lpxXSJ/IKfDP8S7vLFhNTMJHlv+UAcH4MKE7RCBmsa4naNOruGDe1xaNErp37jrQrD2Nix38 UYF7rw+hQoK5l3aOtQ3daBIGlxqVrYcuULuRxaVRxeshhjkO0INfbmY21BuFu52DsFYpIeXkQNe TJmPHvagGFR2Q3KdWqZtuVvFnQ1HooSS5dJl62pZpkN9FkfQNNunh+ X-Received: by 2002:a17:90b:4b4c:b0:299:6e88:7b6a with SMTP id mi12-20020a17090b4b4c00b002996e887b6amr18853916pjb.36.1709847002566; Thu, 07 Mar 2024 13:30:02 -0800 (PST) Received: from amakhalov-build-vm.eng.vmware.com ([64.186.27.43]) by smtp.gmail.com with ESMTPSA id y12-20020a17090abd0c00b00299db19a81asm1991021pjr.56.2024.03.07.13.30.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 13:30:02 -0800 (PST) From: Alexey Makhalov To: linux-kernel@vger.kernel.org, virtualization@lists.linux.dev, bp@alien8.de, hpa@zytor.com, dave.hansen@linux.intel.com, mingo@redhat.com, tglx@linutronix.de Cc: x86@kernel.org, netdev@vger.kernel.org, richardcochran@gmail.com, linux-input@vger.kernel.org, dmitry.torokhov@gmail.com, zackr@vmware.com, linux-graphics-maintainer@vmware.com, pv-drivers@vmware.com, namit@vmware.com, timothym@vmware.com, akaher@vmware.com, jsipek@vmware.com, dri-devel@lists.freedesktop.org, daniel@ffwll.ch, airlied@gmail.com, tzimmermann@suse.de, mripard@kernel.org, maarten.lankhorst@linux.intel.com, horms@kernel.org, kirill.shutemov@linux.intel.com Subject: [PATCH v7 2/7] x86/vmware: Introduce VMware hypercall API Date: Thu, 7 Mar 2024 13:29:44 -0800 Message-Id: <20240307212949.4166120-3-alexey.makhalov@broadcom.com> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20240307212949.4166120-1-alexey.makhalov@broadcom.com> References: <20240307212949.4166120-1-alexey.makhalov@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Alexey Makhalov Introduce vmware_hypercall family of functions. It is a common implementation to be used by the VMware guest code and virtual device drivers in architecture independent manner. The API consists of vmware_hypercallX and vmware_hypercall_hb_{out,in} set of functions by analogy with KVM hypercall API. Architecture specific implementation is hidden inside. It will simplify future enhancements in VMware hypercalls such as SEV-ES and TDX related changes without needs to modify a caller in device drivers code. Current implementation extends an idea from commit bac7b4e84323 ("x86/vmware: Update platform detection code for VMCALL/VMMCALL hypercalls") to have a slow, but safe path in VMWARE_HYPERCALL earlier during the boot when alternatives are not yet applied. This logic was inherited from VMWARE_CMD from the commit mentioned above. Default alternative code was optimized by size to reduce excessive nop alignment once alternatives are applied. Total default code size is 26 bytes, in worse case (3 bytes alternative) remaining 23 bytes will be aligned by only 3 long NOP instructions. Signed-off-by: Alexey Makhalov Reviewed-by: Nadav Amit Reviewed-by: Jeff Sipek --- arch/x86/include/asm/vmware.h | 288 +++++++++++++++++++----- arch/x86/kernel/cpu/vmware.c | 35 ++- drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h | 6 +- drivers/input/mouse/vmmouse.c | 2 + drivers/ptp/ptp_vmw.c | 2 + 5 files changed, 252 insertions(+), 81 deletions(-) diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h index de2533337611..2ac87068184a 100644 --- a/arch/x86/include/asm/vmware.h +++ b/arch/x86/include/asm/vmware.h @@ -7,14 +7,37 @@ #include /* - * The hypercall definitions differ in the low word of the %edx argument + * VMware hypercall ABI. + * + * - Low bandwidth (LB) hypercalls (I/O port based, vmcall and vmmcall) + * have up to 6 input and 6 output arguments passed and returned using + * registers: %eax (arg0), %ebx (arg1), %ecx (arg2), %edx (arg3), + * %esi (arg4), %edi (arg5). + * The following input arguments must be initialized by the caller: + * arg0 - VMWARE_HYPERVISOR_MAGIC + * arg2 - Hypercall command + * arg3 bits [15:0] - Port number, LB and direction flags + * + * - High bandwidth (HB) hypercalls are I/O port based only. They have + * up to 7 input and 7 output arguments passed and returned using + * registers: %eax (arg0), %ebx (arg1), %ecx (arg2), %edx (arg3), + * %esi (arg4), %edi (arg5), %ebp (arg6). + * The following input arguments must be initialized by the caller: + * arg0 - VMWARE_HYPERVISOR_MAGIC + * arg1 - Hypercall command + * arg3 bits [15:0] - Port number, HB and direction flags + * + * For compatibility purposes, x86_64 systems use only lower 32 bits + * for input and output arguments. + * + * The hypercall definitions differ in the low word of the %edx (arg3) * in the following way: the old I/O port based interface uses the port * number to distinguish between high- and low bandwidth versions, and * uses IN/OUT instructions to define transfer direction. * * The new vmcall interface instead uses a set of flags to select * bandwidth mode and transfer direction. The flags should be loaded - * into %dx by any user and are automatically replaced by the port + * into arg3 by any user and are automatically replaced by the port * number if the I/O port method is used. */ @@ -37,69 +60,218 @@ extern u8 vmware_hypercall_mode; -/* The low bandwidth call. The low word of edx is presumed clear. */ -#define VMWARE_HYPERCALL \ - ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT) ", %%dx; " \ - "inl (%%dx), %%eax", \ - "vmcall", X86_FEATURE_VMCALL, \ - "vmmcall", X86_FEATURE_VMW_VMMCALL) - /* - * The high bandwidth out call. The low word of edx is presumed to have the - * HB and OUT bits set. + * The low bandwidth call. The low word of %edx is presumed to have OUT bit + * set. The high word of %edx may contain input data from the caller. */ -#define VMWARE_HYPERCALL_HB_OUT \ - ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT_HB) ", %%dx; " \ - "rep outsb", \ +#define VMWARE_HYPERCALL \ + ALTERNATIVE_3("cmpb $" \ + __stringify(CPUID_VMWARE_FEATURES_ECX_VMMCALL) \ + ", %[mode]\n\t" \ + "jg 2f\n\t" \ + "je 1f\n\t" \ + "movw %[port], %%dx\n\t" \ + "inl (%%dx), %%eax\n\t" \ + "jmp 3f\n\t" \ + "1: vmmcall\n\t" \ + "jmp 3f\n\t" \ + "2: vmcall\n\t" \ + "3:\n\t", \ + "movw %[port], %%dx\n\t" \ + "inl (%%dx), %%eax", X86_FEATURE_HYPERVISOR, \ "vmcall", X86_FEATURE_VMCALL, \ "vmmcall", X86_FEATURE_VMW_VMMCALL) +static inline +unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1) +{ + unsigned long out0; + + asm_inline volatile (VMWARE_HYPERCALL + : "=a" (out0) + : [port] "i" (VMWARE_HYPERVISOR_PORT), + [mode] "m" (vmware_hypercall_mode), + "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (in1), + "c" (cmd), + "d" (0) + : "cc", "memory"); + return out0; +} + +static inline +unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1, + uint32_t *out1, uint32_t *out2) +{ + unsigned long out0; + + asm_inline volatile (VMWARE_HYPERCALL + : "=a" (out0), "=b" (*out1), "=c" (*out2) + : [port] "i" (VMWARE_HYPERVISOR_PORT), + [mode] "m" (vmware_hypercall_mode), + "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (in1), + "c" (cmd), + "d" (0) + : "cc", "memory"); + return out0; +} + +static inline +unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1, + uint32_t *out1, uint32_t *out2, + uint32_t *out3) +{ + unsigned long out0; + + asm_inline volatile (VMWARE_HYPERCALL + : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3) + : [port] "i" (VMWARE_HYPERVISOR_PORT), + [mode] "m" (vmware_hypercall_mode), + "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (in1), + "c" (cmd), + "d" (0) + : "cc", "memory"); + return out0; +} + +static inline +unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1, + unsigned long in3, unsigned long in4, + unsigned long in5, uint32_t *out2) +{ + unsigned long out0; + + asm_inline volatile (VMWARE_HYPERCALL + : "=a" (out0), "=c" (*out2) + : [port] "i" (VMWARE_HYPERVISOR_PORT), + [mode] "m" (vmware_hypercall_mode), + "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (in1), + "c" (cmd), + "d" (in3), + "S" (in4), + "D" (in5) + : "cc", "memory"); + return out0; +} + +static inline +unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1, + unsigned long in3, uint32_t *out2, + uint32_t *out3, uint32_t *out4, + uint32_t *out5) +{ + unsigned long out0; + + asm_inline volatile (VMWARE_HYPERCALL + : "=a" (out0), "=c" (*out2), "=d" (*out3), "=S" (*out4), + "=D" (*out5) + : [port] "i" (VMWARE_HYPERVISOR_PORT), + [mode] "m" (vmware_hypercall_mode), + "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (in1), + "c" (cmd), + "d" (in3) + : "cc", "memory"); + return out0; +} + +static inline +unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1, + unsigned long in3, unsigned long in4, + unsigned long in5, uint32_t *out1, + uint32_t *out2, uint32_t *out3) +{ + unsigned long out0; + + asm_inline volatile (VMWARE_HYPERCALL + : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3) + : [port] "i" (VMWARE_HYPERVISOR_PORT), + [mode] "m" (vmware_hypercall_mode), + "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (in1), + "c" (cmd), + "d" (in3), + "S" (in4), + "D" (in5) + : "cc", "memory"); + return out0; +} + + +#ifdef CONFIG_X86_64 +#define VMW_BP_REG "%%rbp" +#define VMW_BP_CONSTRAINT "r" +#else +#define VMW_BP_REG "%%ebp" +#define VMW_BP_CONSTRAINT "m" +#endif + /* - * The high bandwidth in call. The low word of edx is presumed to have the - * HB bit set. + * High bandwidth calls are not supported on encrypted memory guests. + * The caller should check cc_platform_has(CC_ATTR_MEM_ENCRYPT) and use + * low bandwidth hypercall it memory encryption is set. + * This assumption simplifies HB hypercall impementation to just I/O port + * based approach without alternative patching. */ -#define VMWARE_HYPERCALL_HB_IN \ - ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT_HB) ", %%dx; " \ - "rep insb", \ - "vmcall", X86_FEATURE_VMCALL, \ - "vmmcall", X86_FEATURE_VMW_VMMCALL) +static inline +unsigned long vmware_hypercall_hb_out(unsigned long cmd, unsigned long in2, + unsigned long in3, unsigned long in4, + unsigned long in5, unsigned long in6, + uint32_t *out1) +{ + unsigned long out0; + + asm_inline volatile ( + UNWIND_HINT_SAVE + "push " VMW_BP_REG "\n\t" + UNWIND_HINT_UNDEFINED + "mov %[in6], " VMW_BP_REG "\n\t" + "rep outsb\n\t" + "pop " VMW_BP_REG "\n\t" + UNWIND_HINT_RESTORE + : "=a" (out0), "=b" (*out1) + : "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (cmd), + "c" (in2), + "d" (in3 | VMWARE_HYPERVISOR_PORT_HB), + "S" (in4), + "D" (in5), + [in6] VMW_BP_CONSTRAINT (in6) + : "cc", "memory"); + return out0; +} + +static inline +unsigned long vmware_hypercall_hb_in(unsigned long cmd, unsigned long in2, + unsigned long in3, unsigned long in4, + unsigned long in5, unsigned long in6, + uint32_t *out1) +{ + unsigned long out0; -#define VMWARE_PORT(cmd, eax, ebx, ecx, edx) \ - __asm__("inl (%%dx), %%eax" : \ - "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \ - "a"(VMWARE_HYPERVISOR_MAGIC), \ - "c"(VMWARE_CMD_##cmd), \ - "d"(VMWARE_HYPERVISOR_PORT), "b"(UINT_MAX) : \ - "memory") - -#define VMWARE_VMCALL(cmd, eax, ebx, ecx, edx) \ - __asm__("vmcall" : \ - "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \ - "a"(VMWARE_HYPERVISOR_MAGIC), \ - "c"(VMWARE_CMD_##cmd), \ - "d"(0), "b"(UINT_MAX) : \ - "memory") - -#define VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx) \ - __asm__("vmmcall" : \ - "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \ - "a"(VMWARE_HYPERVISOR_MAGIC), \ - "c"(VMWARE_CMD_##cmd), \ - "d"(0), "b"(UINT_MAX) : \ - "memory") - -#define VMWARE_CMD(cmd, eax, ebx, ecx, edx) do { \ - switch (vmware_hypercall_mode) { \ - case CPUID_VMWARE_FEATURES_ECX_VMCALL: \ - VMWARE_VMCALL(cmd, eax, ebx, ecx, edx); \ - break; \ - case CPUID_VMWARE_FEATURES_ECX_VMMCALL: \ - VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx); \ - break; \ - default: \ - VMWARE_PORT(cmd, eax, ebx, ecx, edx); \ - break; \ - } \ - } while (0) + asm_inline volatile ( + UNWIND_HINT_SAVE + "push " VMW_BP_REG "\n\t" + UNWIND_HINT_UNDEFINED + "mov %[in6], " VMW_BP_REG "\n\t" + "rep insb\n\t" + "pop " VMW_BP_REG "\n\t" + UNWIND_HINT_RESTORE + : "=a" (out0), "=b" (*out1) + : "a" (VMWARE_HYPERVISOR_MAGIC), + "b" (cmd), + "c" (in2), + "d" (in3 | VMWARE_HYPERVISOR_PORT_HB), + "S" (in4), + "D" (in5), + [in6] VMW_BP_CONSTRAINT (in6) + : "cc", "memory"); + return out0; +} +#undef VMW_BP_REG +#undef VMW_BP_CONSTRAINT #endif diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 4db8e1daa4a1..3aa1adaed18f 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -67,9 +67,10 @@ EXPORT_SYMBOL_GPL(vmware_hypercall_mode); static inline int __vmware_platform(void) { - uint32_t eax, ebx, ecx, edx; - VMWARE_CMD(GETVERSION, eax, ebx, ecx, edx); - return eax != (uint32_t)-1 && ebx == VMWARE_HYPERVISOR_MAGIC; + uint32_t eax, ebx, ecx; + + eax = vmware_hypercall3(VMWARE_CMD_GETVERSION, 0, &ebx, &ecx); + return eax != UINT_MAX && ebx == VMWARE_HYPERVISOR_MAGIC; } static unsigned long vmware_get_tsc_khz(void) @@ -121,21 +122,12 @@ static void __init vmware_cyc2ns_setup(void) pr_info("using clock offset of %llu ns\n", d->cyc2ns_offset); } -static int vmware_cmd_stealclock(uint32_t arg1, uint32_t arg2) +static int vmware_cmd_stealclock(uint32_t addr_hi, uint32_t addr_lo) { - uint32_t result, info; - - asm volatile (VMWARE_HYPERCALL : - "=a"(result), - "=c"(info) : - "a"(VMWARE_HYPERVISOR_MAGIC), - "b"(0), - "c"(VMWARE_CMD_STEALCLOCK), - "d"(0), - "S"(arg1), - "D"(arg2) : - "memory"); - return result; + uint32_t info; + + return vmware_hypercall5(VMWARE_CMD_STEALCLOCK, 0, 0, addr_hi, addr_lo, + &info); } static bool stealclock_enable(phys_addr_t pa) @@ -344,10 +336,10 @@ static void __init vmware_set_capabilities(void) static void __init vmware_platform_setup(void) { - uint32_t eax, ebx, ecx, edx; + uint32_t eax, ebx, ecx; uint64_t lpj, tsc_khz; - VMWARE_CMD(GETHZ, eax, ebx, ecx, edx); + eax = vmware_hypercall3(VMWARE_CMD_GETHZ, UINT_MAX, &ebx, &ecx); if (ebx != UINT_MAX) { lpj = tsc_khz = eax | (((uint64_t)ebx) << 32); @@ -429,8 +421,9 @@ static uint32_t __init vmware_platform(void) /* Checks if hypervisor supports x2apic without VT-D interrupt remapping. */ static bool __init vmware_legacy_x2apic_available(void) { - uint32_t eax, ebx, ecx, edx; - VMWARE_CMD(GETVCPU_INFO, eax, ebx, ecx, edx); + uint32_t eax; + + eax = vmware_hypercall1(VMWARE_CMD_GETVCPU_INFO, 0); return !(eax & BIT(VCPU_RESERVED)) && (eax & BIT(VCPU_LEGACY_X2APIC)); } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h index 23899d743a90..e040ee21ea1a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h @@ -68,6 +68,8 @@ "=d"(edx), \ "=S"(si), \ "=D"(di) : \ + [port] "i" (VMWARE_HYPERVISOR_PORT), \ + [mode] "m" (vmware_hypercall_mode), \ "a"(magic), \ "b"(in_ebx), \ "c"(cmd), \ @@ -110,7 +112,7 @@ "push %%rbp;" \ UNWIND_HINT_UNDEFINED \ "mov %12, %%rbp;" \ - VMWARE_HYPERCALL_HB_OUT \ + "rep outsb;" \ "pop %%rbp;" \ UNWIND_HINT_RESTORE : \ "=a"(eax), \ @@ -139,7 +141,7 @@ "push %%rbp;" \ UNWIND_HINT_UNDEFINED \ "mov %12, %%rbp;" \ - VMWARE_HYPERCALL_HB_IN \ + "rep insb;" \ "pop %%rbp;" \ UNWIND_HINT_RESTORE : \ "=a"(eax), \ diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c index ea9eff7c8099..ad94c835ee66 100644 --- a/drivers/input/mouse/vmmouse.c +++ b/drivers/input/mouse/vmmouse.c @@ -91,6 +91,8 @@ struct vmmouse_data { "=d"(out4), \ "=S"(__dummy1), \ "=D"(__dummy2) : \ + [port] "i" (VMWARE_HYPERVISOR_PORT), \ + [mode] "m" (vmware_hypercall_mode), \ "a"(VMMOUSE_PROTO_MAGIC), \ "b"(in1), \ "c"(VMMOUSE_PROTO_CMD_##cmd), \ diff --git a/drivers/ptp/ptp_vmw.c b/drivers/ptp/ptp_vmw.c index 27c5547aa8a9..279d191d2df9 100644 --- a/drivers/ptp/ptp_vmw.c +++ b/drivers/ptp/ptp_vmw.c @@ -29,6 +29,8 @@ static int ptp_vmw_pclk_read(u64 *ns) asm volatile (VMWARE_HYPERCALL : "=a"(ret), "=b"(nsec_hi), "=c"(nsec_lo), "=d"(unused1), "=S"(unused2), "=D"(unused3) : + [port] "i" (VMWARE_HYPERVISOR_PORT), + [mode] "m" (vmware_hypercall_mode), "a"(VMWARE_MAGIC), "b"(0), "c"(VMWARE_CMD_PCLK_GETTIME), "d"(0) : "memory"); -- 2.39.0