From nobody Thu Oct 2 07:48:36 2025 Received: from mail-pg1-f202.google.com (mail-pg1-f202.google.com [209.85.215.202]) (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 608A12E7F1D for ; Fri, 19 Sep 2025 22:33:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758321209; cv=none; b=iwYj36IQ+3hEkgdTpzG5ZaMNGC+utrro7K48D7Q/yd2Uzjqd3iRKgA9SDyVmpyTb+5+ht73z3667smK7m2YXe0TIYkDlZqNuIqkyapG6IyTa8VPuKsEek4C6FDCsvmDmxjwHM39uO+ZRT5TgX+coaM5vHtITvG7P9EeV7eycUjE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758321209; c=relaxed/simple; bh=WAz+OPNGncuQ7MlKExXhXByj1PrQJD9ziBuUEUdKnOQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=nLn/5zlNZ4Y/fN3LurWWsqKoN0B6UHOIzNtYAGnAWZAXWF2b3Eb/eDCU9ec9T93N30F2D8FyyU52mQWPHTJsJ3ywi6+zA22lgbEClNgb0f4YILmYHvjdayiWS8dPZK+2ZVod5/tWPWt1MbNlvauC4LR3HrAQ6OF27jwreZiL+4g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=bHZn7hrp; arc=none smtp.client-ip=209.85.215.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="bHZn7hrp" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-b551ca103d8so756735a12.1 for ; Fri, 19 Sep 2025 15:33:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1758321207; x=1758926007; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date:message-id:reply-to; bh=8opc7S0Texwr1Y0+7J7NcGWGbaq8Y3HSFNECcKZKOxk=; b=bHZn7hrpUtyjr6LgaJ3BWqQFAp3ua3PpKjOGzZ9qGSbFds9z5/rppR55WWFnVwlfYv xwtk8bClciJwUZSZlhynA+lWk6kLIbDpaDMoCo/rGZyjWsGtyJN7NHS3wH7SOpIDM7/7 43GjxVfYgU8U4plHINSi+xXPLDOBGMiqCIkveS76eFlR1Pzk90NcuQvUGGT9N3G6UxUB Xm4pYvK3VzELzSaCyq1LQcDcTYdosjDO7UUgc/00YYbB65HbbaLAWXnuBQabksKRoT/l 1L9Rx0ellRR2unp0BUFQOEVREtfctqf6ZNCZkx+2VvyWxHGAhxWjRHSpNyy3XhMie125 ey5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758321207; x=1758926007; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=8opc7S0Texwr1Y0+7J7NcGWGbaq8Y3HSFNECcKZKOxk=; b=rAeoxT1CK5YbsCLkW4iB03iYuSLZjGoRk14Q76bVPRWUEVcVGbt2GWCj37VYC1vWVF KFS9Lr4x6bPdWUahS5KEIckDIccgP9Ckjv6bSaTcoSqycpLS3qJYftIxEseX3ymlIosn rHFWyhQmA0kzZlQIk9F+vCW1nV7oc3hWWnsKvZMimC55OCuDEx8zUi6rRKXSBS4nno2u Syksf79e0AeKrmx5kTfOzjwFsEnCerhXpBmmPvy34FIcuKtXk/7Ge/nwzp+TCtCQoal7 S/KliPxTURDs+6Bl0ISc887FO8SwUWHV3QAf4k33tQOwTsO5c5f2ay1UxaKlDurjisBu IU2Q== X-Forwarded-Encrypted: i=1; AJvYcCXvI+Up17bDSI40P9yC99Clz071sVnqJKy3LGgcoD5eZlJ/KWfHO2dMWaTOR5jtz3ulmpmO4J7HU7qyE3I=@vger.kernel.org X-Gm-Message-State: AOJu0YydP9V8lCfNdCiLHTgQW4aPZLcHJGRE/s9yDIVdbuCA+S0P99N4 yT87X1B+6Ccpg8uS538gIXMLkla9sXPfPhQzchwPs6d1bISkLnOp00WtH40wbUg0rPgYEZREiqf jIkqI1Q== X-Google-Smtp-Source: AGHT+IGLcHt3zxuicSOW0aEtZIt9C7ht7qM1vM3VeEofwQHXCWu0JrA1UAYPsGfA+0sHn9V626/TGf2DOOw= X-Received: from pgco29.prod.google.com ([2002:a63:731d:0:b0:b54:fe45:6acf]) (user=seanjc job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:728b:b0:244:facc:65ea with SMTP id adf61e73a8af0-2925f57462emr6706732637.18.1758321206706; Fri, 19 Sep 2025 15:33:26 -0700 (PDT) Reply-To: Sean Christopherson Date: Fri, 19 Sep 2025 15:32:20 -0700 In-Reply-To: <20250919223258.1604852-1-seanjc@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250919223258.1604852-1-seanjc@google.com> X-Mailer: git-send-email 2.51.0.470.ga7dc726c21-goog Message-ID: <20250919223258.1604852-14-seanjc@google.com> Subject: [PATCH v16 13/51] KVM: x86: Enable guest SSP read/write interface with new uAPIs From: Sean Christopherson To: Paolo Bonzini , Sean Christopherson Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Tom Lendacky , Mathias Krause , John Allen , Rick Edgecombe , Chao Gao , Binbin Wu , Xiaoyao Li , Maxim Levitsky , Zhang Yi Z , Xin Li Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yang Weijiang Add a KVM-defined ONE_REG register, KVM_REG_GUEST_SSP, to let userspace save and restore the guest's Shadow Stack Pointer (SSP). On both Intel and AMD, SSP is a hardware register that can only be accessed by software via dedicated ISA (e.g. RDSSP) or via VMCS/VMCB fields (used by hardware to context switch SSP at entry/exit). As a result, SSP doesn't fit in any of KVM's existing interfaces for saving/restoring state. Internally, treat SSP as a fake/synthetic MSR, as the semantics of writes to SSP follow that of several other Shadow Stack MSRs, e.g. the PLx_SSP MSRs. Use a translation layer to hide the KVM-internal MSR index so that the arbitrary index doesn't become ABI, e.g. so that KVM can rework its implementation as needed, so long as the ONE_REG ABI is maintained. Explicitly reject accesses to SSP if the vCPU doesn't have Shadow Stack support to avoid running afoul of ignore_msrs, which unfortunately applies to host-initiated accesses (which is a discussion for another day). I.e. ensure consistent behavior for KVM-defined registers irrespective of ignore_msrs. Link: https://lore.kernel.org/all/aca9d389-f11e-4811-90cf-d98e345a5cc2@inte= l.com Suggested-by: Sean Christopherson Signed-off-by: Yang Weijiang Tested-by: Mathias Krause Tested-by: John Allen Tested-by: Rick Edgecombe Signed-off-by: Chao Gao Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Reviewed-by: Binbin Wu Reviewed-by: Xiaoyao Li --- Documentation/virt/kvm/api.rst | 8 +++++++ arch/x86/include/uapi/asm/kvm.h | 3 +++ arch/x86/kvm/x86.c | 37 +++++++++++++++++++++++++++++---- arch/x86/kvm/x86.h | 10 +++++++++ 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index abd02675a24d..6ae24c5ca559 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -2911,6 +2911,14 @@ such as set vcpu counter or reset vcpu, and they hav= e the following id bit patte x86 MSR registers have the following id bit patterns:: 0x2030 0002 =20 +Following are the KVM-defined registers for x86: + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D= =3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D + Encoding Register Description +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D= =3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D + 0x2030 0003 0000 0000 SSP Shadow Stack Pointer +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D= =3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D + 4.69 KVM_GET_ONE_REG -------------------- =20 diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kv= m.h index aae1033c8afa..467116186e71 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -437,6 +437,9 @@ struct kvm_xcrs { #define KVM_X86_REG_KVM(index) \ KVM_X86_REG_ID(KVM_X86_REG_TYPE_KVM, index) =20 +/* KVM-defined registers starting from 0 */ +#define KVM_REG_GUEST_SSP 0 + #define KVM_SYNC_X86_REGS (1UL << 0) #define KVM_SYNC_X86_SREGS (1UL << 1) #define KVM_SYNC_X86_EVENTS (1UL << 2) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 5245b21168cb..720540f102e1 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6016,9 +6016,27 @@ struct kvm_x86_reg_id { __u8 x86; }; =20 -static int kvm_translate_kvm_reg(struct kvm_x86_reg_id *reg) +static int kvm_translate_kvm_reg(struct kvm_vcpu *vcpu, + struct kvm_x86_reg_id *reg) { - return -EINVAL; + switch (reg->index) { + case KVM_REG_GUEST_SSP: + /* + * FIXME: If host-initiated accesses are ever exempted from + * ignore_msrs (in kvm_do_msr_access()), drop this manual check + * and rely on KVM's standard checks to reject accesses to regs + * that don't exist. + */ + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK)) + return -EINVAL; + + reg->type =3D KVM_X86_REG_TYPE_MSR; + reg->index =3D MSR_KVM_INTERNAL_GUEST_SSP; + break; + default: + return -EINVAL; + } + return 0; } =20 static int kvm_get_one_msr(struct kvm_vcpu *vcpu, u32 msr, u64 __user *use= r_val) @@ -6067,7 +6085,7 @@ static int kvm_get_set_one_reg(struct kvm_vcpu *vcpu,= unsigned int ioctl, return -EINVAL; =20 if (reg->type =3D=3D KVM_X86_REG_TYPE_KVM) { - r =3D kvm_translate_kvm_reg(reg); + r =3D kvm_translate_kvm_reg(vcpu, reg); if (r) return r; } @@ -6098,11 +6116,22 @@ static int kvm_get_set_one_reg(struct kvm_vcpu *vcp= u, unsigned int ioctl, static int kvm_get_reg_list(struct kvm_vcpu *vcpu, struct kvm_reg_list __user *user_list) { - u64 nr_regs =3D 0; + u64 nr_regs =3D guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) ? 1 : 0; + u64 user_nr_regs; + + if (get_user(user_nr_regs, &user_list->n)) + return -EFAULT; =20 if (put_user(nr_regs, &user_list->n)) return -EFAULT; =20 + if (user_nr_regs < nr_regs) + return -E2BIG; + + if (nr_regs && + put_user(KVM_X86_REG_KVM(KVM_REG_GUEST_SSP), &user_list->reg[0])) + return -EFAULT; + return 0; } =20 diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 786e36fcd0fb..a7c9c72fca93 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -101,6 +101,16 @@ do { \ #define KVM_SVM_DEFAULT_PLE_WINDOW_MAX USHRT_MAX #define KVM_SVM_DEFAULT_PLE_WINDOW 3000 =20 +/* + * KVM's internal, non-ABI indices for synthetic MSRs. The values themselv= es + * are arbitrary and have no meaning, the only requirement is that they do= n't + * conflict with "real" MSRs that KVM supports. Use values at the upper end + * of KVM's reserved paravirtual MSR range to minimize churn, i.e. these v= alues + * will be usable until KVM exhausts its supply of paravirtual MSR indices. + */ + +#define MSR_KVM_INTERNAL_GUEST_SSP 0x4b564dff + static inline unsigned int __grow_ple_window(unsigned int val, unsigned int base, unsigned int modifier, unsigned int max) { --=20 2.51.0.470.ga7dc726c21-goog