Received: by 2002:a05:7208:3188:b0:7e:5202:c8b4 with SMTP id r8csp962018rbd; Fri, 23 Feb 2024 08:46:53 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCVs6vzz0i+lMckDaQzbDG2Rjss1N9W8m94PP90qNn/Z5sP2ZuCUoK8TEir5J/ZGfMPJjzsmImzK5goQZtYJIeK2p18xvM6iKqrLgGtwpA== X-Google-Smtp-Source: AGHT+IEE03wLiYbOuuxYOqU4mqyNqMhiFPbX1uRk1uvzaGoE5v7MYUccPc8CY7vyoHgSTLZ0+C4Z X-Received: by 2002:a05:6214:4413:b0:68f:e432:b208 with SMTP id oj19-20020a056214441300b0068fe432b208mr474551qvb.8.1708706813463; Fri, 23 Feb 2024 08:46:53 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708706813; cv=pass; d=google.com; s=arc-20160816; b=LMfrrnaJVQScYd2pU2JJ3gxT7kh4/65QdlnzZaSjabHABAgne2DDBK1S8JVvjCNZSH U15wqe0X/QF8CKjq03IovyRjqBsUsihfMx3Lwr6WGpiqR2DydKhOMwxPQQfcH1x2aO+P ZDlHoTq4Ltt8NpS8wd0nUY1hGmtohYBiHaHL9JUBKviZA8L0abGt/so8YjWKp+H9BsQL lDiwQmdsdtMOWkbCgbKXwACRKeKXXKwWNDU50lJCXtce3w5mCLRaLsRDUGXCZu7++ZmT 75PqxhozTiE8cVvtyMUzLZh4nvCNK9Llm0wXI4eQPdChVRbmzzwlR7HnlTzcAzNudo06 qvwQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=NDZLY+1R91be6hXCSYVgTQ61KoEqdDMYEkzpyOE6s74=; fh=snuN8lTu7CCcd4L/3/zvkp75hhbwDFXBlKsWrCpSFxM=; b=Jvy7fg3fSMJBSNd+KvnTElAhFT/wkrW/OA+BHLNi2WzfVvu4bD+oOxdvWAnQVMVpju P2RAZe/5soNzdf/rdH2SvxYt+9ASgXElw8YdGLv2sp4sGCmHWM1u5YHUs0bCtE8SZJ+m RVO8TH5zh8QSv8gfMZapMfI+pJ8q4WdzRNEjH0ZJPPQq8GKjeGYQEteHI2G+jZk2iYlj pmnIM/4matYx2C4t6xMAMvC4bcoIUhiNijAKUh57kqX0vOqjtFsbOllnOMPXbHCANMQm Luw7fMWQ9TrxRyugTz26KLFp8Hw2+NeZ5H7Tp6YqJyuj4aVqt/dQNDriDj1KFQTHXNfk Gvhw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=slKyzBlr; arc=pass (i=1 spf=pass spfdomain=flex--seanjc.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-78754-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-78754-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id iu1-20020ad45cc1000000b0068f62ba06dfsi12143839qvb.551.2024.02.23.08.46.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Feb 2024 08:46:53 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-78754-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=slKyzBlr; arc=pass (i=1 spf=pass spfdomain=flex--seanjc.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-78754-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-78754-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.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 ny.mirrors.kernel.org (Postfix) with ESMTPS id 2D6A71C2231C for ; Fri, 23 Feb 2024 16:46:53 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 3A9DE1272D9; Fri, 23 Feb 2024 16:46:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="slKyzBlr" Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.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 EAA9812839B for ; Fri, 23 Feb 2024 16:46:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708706804; cv=none; b=Uv072R9chsI621ciWPrCR/rC3iQPkY3MB8wD1vu5qpWn+A5qyOh6d+mTITtgVZrQk4xnEHYBouLqQlv66HaoaIoZhcwkXBhd4+bRlaqHmn7EI+Prg//4jxI9bJKWVxC7xnlV5Ar7DVE35j9vgdNUTRNGH76hRcG1SfyNtWC9tkE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708706804; c=relaxed/simple; bh=UcvDafUh2QDdP5ODtPAmMXLmepE2Ecno7xfGvkqB9kI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=kWsIdED82vUzm6OEzj4wBJozCRSe7eU46htWb+6n+dvdvffFJeQjNML0P3F8GaMcDqs9mYKR2L3sXnTBNzkOmOQigoW6m1PMageE302cYEfzIF9Wu5jEiecUy4yh3vDh9eKzh3JxJ89RbsBS7nFUlYQVMksomE14H+eSDHs3boI= 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=slKyzBlr; arc=none smtp.client-ip=209.85.128.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 Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-607c9677a91so18057767b3.2 for ; Fri, 23 Feb 2024 08:46:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1708706801; x=1709311601; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=NDZLY+1R91be6hXCSYVgTQ61KoEqdDMYEkzpyOE6s74=; b=slKyzBlr4+v7Ypr9+laD4EzDJngZ9dZhQBwNFeky4GMR/DEtDlrU70l6PSa47/711P wdlxvaym8/hDLM3IlgN10LT3KXRdujTsrgO0bSUuFXjn0KDS+xHGwtBRP3SyqF6sHj+h AA8BhD+JbdHAOd475bskI9ym9/pih6We6Dj8liP/iI2IwT5B3xfkOpF2JZoev4D0Xy+R njlqguZyb9ZH5lhP92DEHdS5vUsAPQbvd5wGpq+DLr1PKjsy3w4Ue8L1jF8srCUB9io3 3J4RqgiVMxYRIf1cvfSSuQDp3KsTu/MwxGEb+/Bw8jA3ttZ6BHzsqA+F0CLQZ71vyUr8 Lmug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708706801; x=1709311601; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=NDZLY+1R91be6hXCSYVgTQ61KoEqdDMYEkzpyOE6s74=; b=EilPp/s9eUfnEP+ckG/46dpLLCmXE7EtUAFVJUAz1Kp96HlR7aRZ1hMerQsiRVEWOr unS8kRnLWhwc4QGGv6f8n1MFCN2jgAa0zo8p39Zj9cP2KGJHwMdWRqQziA0vxlZ1lz1F 04BwwOhcoUUXmSbpqBnWSTqf5xbmOuchkAzjCCCqRGRy6oS2sdGPdGPavNcbF1kJbHDO D93QgBoqy6k5JzpcydqwdJGgB7QLQczAmJc9rHEWl7mAb1Oq7FNHUxvyKAnKA49ZIPtl bG1eaD5okZJP8qnOAG7ltqIBhwi7ZfyDVbq8uMI1X9jk1QlzSsafZsyMvft4DT6Rr74C 7QaA== X-Gm-Message-State: AOJu0YwJRNn2SkjZgoG0cZvqRvN1HtjbjIlKX75cCIRGgN/TSasBzPvY 9SQ/3ChJzAahsIuw6dpc+SyFYhfytMXOr9/5LzpoBgGEoE50cyklDHj1yCYYL4MhDGdAL5+1EqH cdw== X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a0d:d74d:0:b0:608:ba07:3093 with SMTP id z74-20020a0dd74d000000b00608ba073093mr79184ywd.1.1708706800867; Fri, 23 Feb 2024 08:46:40 -0800 (PST) Date: Fri, 23 Feb 2024 08:46:39 -0800 In-Reply-To: <20240223104009.632194-8-pbonzini@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240223104009.632194-1-pbonzini@redhat.com> <20240223104009.632194-8-pbonzini@redhat.com> Message-ID: Subject: Re: [PATCH v2 07/11] KVM: x86: define standard behavior for bits 0/1 of VM type From: Sean Christopherson To: Paolo Bonzini Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, michael.roth@amd.com, aik@amd.com Content-Type: text/plain; charset="us-ascii" On Fri, Feb 23, 2024, Paolo Bonzini wrote: > Some VM types have characteristics in common; in fact, the only use > of VM types right now is kvm_arch_has_private_mem and it assumes that > _all_ VM types have private memory. > > So, let the low bits specify the characteristics of the VM type. As > of we have two special things: whether memory is private, and whether > guest state is protected. The latter is similar to > kvm->arch.guest_state_protected, but the latter is only set on a fully > initialized VM. If both are set, ioctls to set registers will cause > an error---SEV-ES did not do so, which is a problematic API. > > Signed-off-by: Paolo Bonzini > Message-Id: <20240209183743.22030-7-pbonzini@redhat.com> > Signed-off-by: Paolo Bonzini > --- > arch/x86/include/asm/kvm_host.h | 9 +++- > arch/x86/kvm/x86.c | 93 +++++++++++++++++++++++++++------ > 2 files changed, 85 insertions(+), 17 deletions(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index 0bcd9ae16097..15db2697863c 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -2135,8 +2135,15 @@ void kvm_mmu_new_pgd(struct kvm_vcpu *vcpu, gpa_t new_pgd); > void kvm_configure_mmu(bool enable_tdp, int tdp_forced_root_level, > int tdp_max_root_level, int tdp_huge_page_level); > > + > +/* Low bits of VM types provide confidential computing capabilities. */ > +#define __KVM_X86_PRIVATE_MEM_TYPE 1 > +#define __KVM_X86_PROTECTED_STATE_TYPE 2 > +#define __KVM_X86_VM_TYPE_FEATURES 3 > +static_assert((KVM_X86_SW_PROTECTED_VM & __KVM_X86_VM_TYPE_FEATURES) == __KVM_X86_PRIVATE_MEM_TYPE); Aliasing bit 0 to KVM_X86_SW_PROTECTED_VM is gross, e.g. this #define KVM_X86_DEFAULT_VM 0 #define KVM_X86_SW_PROTECTED_VM 1 +#define KVM_X86_SEV_VM 8 +#define KVM_X86_SEV_ES_VM 10 is _super_ confusing and bound to cause problems. Oh, good gravy, you're also aliasing __KVM_X86_PROTECTED_STATE_TYPE into SEV_ES_VM. Curse you and your Rami Code induced decimal-based bitwise shenanigans!!! I don't see any reason to bleed the flags into KVM's ABI. Even shoving the flags into kvm->arch.vm_type is unncessary. Aha! As is storing vm_type as an "unsigned long", since (a) it can't ever be bigger than u32, and (b) in practice a u8 will suffice since as Mike pointed out we're effectively limited to 31 types before kvm_vm_ioctl_check_extension() starts returning error codes. So I vote to skip the aliasing and simply do: diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index ff23712f1f3f..27265ff5fd29 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1279,7 +1279,9 @@ enum kvm_apicv_inhibit { }; struct kvm_arch { - unsigned long vm_type; + u8 vm_type; + bool has_private_memory; + bool has_protected_state; unsigned long n_used_mmu_pages; unsigned long n_requested_mmu_pages; unsigned long n_max_mmu_pages; and then just use straight incrementing values for types, i.e. #define KVM_X86_DEFAULT_VM 0 #define KVM_X86_SW_PROTECTED_VM 1 #define KVM_X86_SEV_VM 2 #define KVM_X86_SEV_ES_VM 3 It'll require a bit of extra work in kvm_arch_init_vm(), but I think the end result will be signifincatly easier to follow. > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 8746530930d5..e634e5b67516 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -5526,21 +5526,30 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu, > return 0; > } > > -static void kvm_vcpu_ioctl_x86_get_debugregs(struct kvm_vcpu *vcpu, > - struct kvm_debugregs *dbgregs) > +static int kvm_vcpu_ioctl_x86_get_debugregs(struct kvm_vcpu *vcpu, > + struct kvm_debugregs *dbgregs) > { > unsigned long val; > > + if ((vcpu->kvm->arch.vm_type & __KVM_X86_PROTECTED_STATE_TYPE) && > + vcpu->arch.guest_state_protected) > + return -EINVAL; > + > memset(dbgregs, 0, sizeof(*dbgregs)); > memcpy(dbgregs->db, vcpu->arch.db, sizeof(vcpu->arch.db)); > kvm_get_dr(vcpu, 6, &val); > dbgregs->dr6 = val; > dbgregs->dr7 = vcpu->arch.dr7; > + return 0; > } > static int kvm_vcpu_ioctl_x86_set_xcrs(struct kvm_vcpu *vcpu, > @@ -5622,6 +5645,10 @@ static int kvm_vcpu_ioctl_x86_set_xcrs(struct kvm_vcpu *vcpu, > { > int i, r = 0; > > + if ((vcpu->kvm->arch.vm_type & __KVM_X86_PROTECTED_STATE_TYPE) && > + vcpu->arch.guest_state_protected) > + return -EINVAL; > + > if (!boot_cpu_has(X86_FEATURE_XSAVE)) > return -EINVAL; > > @@ -6010,7 +6037,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp, > case KVM_GET_DEBUGREGS: { > struct kvm_debugregs dbgregs; > > - kvm_vcpu_ioctl_x86_get_debugregs(vcpu, &dbgregs); > + r = kvm_vcpu_ioctl_x86_get_debugregs(vcpu, &dbgregs); > + if (r < 0) I would strongly prefer to just do if (r) as "r < 0" implies that postive return values are possible/allowed. That said, rather than a mix of open coding checks in kvm_arch_vcpu_ioctl() versus burying checks in helpers, what about adding a dedicated helper to take care of everything in one shot? E.g. diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 3bc69b0c9822..f5ca78e75eec 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5864,6 +5864,16 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, } } +static bool kvm_ioctl_accesses_guest_state(unsigned int ioctl) +{ + switch (ioctl) { + case <...>: + return true; + default: + return false: + } +} + long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -5878,6 +5888,11 @@ long kvm_arch_vcpu_ioctl(struct file *filp, void *buffer; } u; + if (vcpu->kvm->arch.has_protected_state && + vcpu->arch.guest_state_protected && + kvm_ioctl_accesses_guest_state(ioctl)) + return -EINVAL; + vcpu_load(vcpu); u.buffer = NULL; It'll be a much smaller diff, and hopefully easier to audit, too.