From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A4DE322527 for ; Thu, 28 May 2026 05:30:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779946240; cv=none; b=eTZKbCQLdDSQPdZEGJhCPxlRNeAJ/GCvqVyyowODVQOzNvmGTcQewqjXo3ETYCJtCrPpaed9gdY6oafmsKbtOMHgFN61KrZbsVqPrvt+KyPXyepXrSpgZQPUFfio/JpDUpg89llEUrvcdbcmL1/FPx87VH/11hAnHK5t4MlmwnE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779946240; c=relaxed/simple; bh=DgWGKIje13k1TapEkr+MBgcoQR7z1LfAsyvCQ1fD20E=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=s2o0tV5TMCQw42/acG3gg0CX4nIQ1YSd7fna4VY3WVOgA3ZiCCkKBrUZoMNwUvryyqqR2tixFpdZ2jExXw1Xy4/MIxlu7OgTFKADjACXHsGiC0DDLkNuQmgRjqg6iWe59PunACS8uRh+wK0LCRqln0W9ZOxSts0r7s3HdW5Uqr0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=atGZH5N7; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=g2jY+8dr; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="atGZH5N7"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="g2jY+8dr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1779946237; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=q73WX9HWItM842HL8te6BLbm9UQjrRb26yA0hD3pI7M=; b=atGZH5N7fk/11IV6Oa57C1Zb3DT83Cp7EQbPoFBaTVkY1nB3GDIMwgewpGXD6S9Jg6YPy/ NWcdWpxRW3L0psqAGj1v7D+9YxdJGhPXWVgNhMBTDSCaYCLLAt5i93g3piRHEmB/6rglvR ito1OpqtPAuwUgs/Y9wADhPg7gpuW3M= Received: from mail-pl1-f199.google.com (mail-pl1-f199.google.com [209.85.214.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-621-NFQakHiHP3-4A4zKv64MIQ-1; Thu, 28 May 2026 01:30:36 -0400 X-MC-Unique: NFQakHiHP3-4A4zKv64MIQ-1 X-Mimecast-MFC-AGG-ID: NFQakHiHP3-4A4zKv64MIQ_1779946235 Received: by mail-pl1-f199.google.com with SMTP id d9443c01a7336-2bf0b7425bbso4918955ad.0 for ; Wed, 27 May 2026 22:30:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1779946235; x=1780551035; darn=vger.kernel.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=q73WX9HWItM842HL8te6BLbm9UQjrRb26yA0hD3pI7M=; b=g2jY+8drgWb3EHsNOOq0oBd3be6Pg3MT76gECU1I50ulpVXWrN9AutzKSUKL1Gs43s 87Z9AEzF2Q3XQ6h5lP/qIRwLWLV++mn3M4FmvHkpZZVHcU0cpZhFmIxjgQUO2gQpchLc KxIzS6ULyxGLUv1/3wmRtzUWN26ZCHJYjs/1n6rQ9vH0tSMMA795r8g1A77cQEddlmxH TM/IhsLg6Og0f+LEoBlNi9nO+npA9UQJiL6uLm+ngRbHfXvFUeSoVWlp0otZV3mlIObL gVx073PK09EWjwyvZzQ3k0xssoF6dKDuNEZtnCAlEJZhA0ASXrJHbrhctYGm3vQF1grn lvNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779946235; x=1780551035; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=q73WX9HWItM842HL8te6BLbm9UQjrRb26yA0hD3pI7M=; b=tHLjS+9oZqPLz64ljM4pT6lQaY7XsfmxDC/Lom5zg4uTJPs5f7BrWbHNVOhyAZYB9O dkS7Hiu4Uzgblh0OWBdLIJVpsDmXTe7U+4iW+tqObodWqP7Iv4vbPC8m2oKRme3NvSFk EbnGQIBkxASd5zDsJ4FQE9AMLucHSUWaBO3HrE9VBCVZ8bveRof7pEp7a9mEPTikbo1o Km2yeyd7/t3KQkNcnkjNkOqpeoWTkngilXYQRsWEPu0m+/imcml+E7Q/lLK25+gsj8rP i7kqJ2s2fHcic+KBLgXyZ+SIDaxTIOaZmCVqmKUMBMZxJfCTMrSngAV7jjpEJ9bbUSDa 0Krg== X-Forwarded-Encrypted: i=1; AFNElJ88A3sQPIMbOpDS5+14Jge07tr4F8WDJADgCsZnJeJ8WL08iiKLuChJFUdQNW3rlsaPROkPsBng4Id8k/w=@vger.kernel.org X-Gm-Message-State: AOJu0YyKmNjl95MxVs1b4FgnL7dFuJwjcDiLSrsFqQh5R56B9dZ7MQuL K0QyNMDk+/C8+09eVoprAM3MdvaD0569a1hicHoe24bXVSgge1fzpaNClp/ustWU0kovo4YcTI0 EgBhPEQdjlpofT5qlVVoye+a9eO5dIcLsojjJBtcmXRTS6/9VkEOo7ZVzzlsAixxcMw== X-Gm-Gg: Acq92OF8HKUTv7HWSVjhLTN2rXifeR2CsCGmKzRWnKcFsgcoxayLpHEebpSC+6LvQC4 +HPeYf0fAaR8MG6thz43+SFFCmY+rB2KpNmqyEXbuFsOjl4yJsW+SjO056yoclUsZ9wLMzY09B/ DvobCQ4BuzdTLPmmnpsztzVTIMSWnMsBzEroKDwIxzkvmadHbW7O7baFNK4g5Uz5VPOrOa8dwHx UYreWkX/fu8OwqVP8Qma3ib7hLzh3h+/ATRsMLMdMg8QU2eeWKC6JMLztnsV8CB2DH0DkbocYCn 11SFOIAWER6MlfwEb9QSBWDO/hx79GDSwgmPEfA6REJyXP9aL3ItjuV+M6sS36UPZpYUuah82J2 9+QzrHGNTAv1RSVCqSjSJXlNpOpQ+Xxyjkgo8hMrQAqDfZNp9IU4rNdipE0RRZbebWr9aUFx/dg w= X-Received: by 2002:a17:903:4b07:b0:2bd:5b20:a5b5 with SMTP id d9443c01a7336-2beb066cd73mr260282105ad.37.1779946232107; Wed, 27 May 2026 22:30:32 -0700 (PDT) X-Received: by 2002:a17:903:4b07:b0:2bd:5b20:a5b5 with SMTP id d9443c01a7336-2beb066cd73mr260281545ad.37.1779946231485; Wed, 27 May 2026 22:30:31 -0700 (PDT) Received: from [192.168.68.51] (n175-34-8-244.mrk21.qld.optusnet.com.au. [175.34.8.244]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2beb56d2702sm173761155ad.31.2026.05.27.22.30.22 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 27 May 2026 22:30:30 -0700 (PDT) Message-ID: Date: Thu, 28 May 2026 15:30:19 +1000 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v14 26/44] arm64: RMI: Allow populating initial contents To: Steven Price , kvm@vger.kernel.org, kvmarm@lists.linux.dev Cc: Catalin Marinas , Marc Zyngier , Will Deacon , James Morse , Oliver Upton , Suzuki K Poulose , Zenghui Yu , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Joey Gouly , Alexandru Elisei , Christoffer Dall , Fuad Tabba , linux-coco@lists.linux.dev, Ganapatrao Kulkarni , Shanker Donthineni , Alper Gun , "Aneesh Kumar K . V" , Emi Kisanuki , Vishal Annapurve , WeiLin.Chang@arm.com, Lorenzo.Pieralisi2@arm.com References: <20260513131757.116630-1-steven.price@arm.com> <20260513131757.116630-27-steven.price@arm.com> Content-Language: en-US From: Gavin Shan In-Reply-To: <20260513131757.116630-27-steven.price@arm.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Hi Steve, On 5/13/26 11:17 PM, Steven Price wrote: > The VMM needs to populate the realm with some data before starting (e.g. > a kernel and initrd). This is measured by the RMM and used as part of > the attestation later on. > > Signed-off-by: Steven Price > --- > Changes since v13: > * Rename realm_create_protected_data_page() to realm_data_map_init(). > Changes since v12: > * The ioctl now updates the structure with the amount populated rather > than returning this through the ioctl return code. > * Use the new RMM v2.0 range based RMI calls. > * Adapt to upstream changes in kvm_gmem_populate(). > Changes since v11: > * The multiplex CAP is gone and there's a new ioctl which makes use of > the generic kvm_gmem_populate() functionality. > Changes since v7: > * Improve the error codes. > * Other minor changes from review. > Changes since v6: > * Handle host potentially having a larger page size than the RMM > granule. > * Drop historic "par" (protected address range) from > populate_par_region() - it doesn't exist within the current > architecture. > * Add a cond_resched() call in kvm_populate_realm(). > Changes since v5: > * Refactor to use PFNs rather than tracking struct page in > realm_create_protected_data_page(). > * Pull changes from a later patch (in the v5 series) for accessing > pages from a guest memfd. > * Do the populate in chunks to avoid holding locks for too long and > triggering RCU stall warnings. > --- > arch/arm64/include/asm/kvm_rmi.h | 4 ++ > arch/arm64/kvm/Kconfig | 1 + > arch/arm64/kvm/arm.c | 13 ++++ > arch/arm64/kvm/rmi.c | 106 +++++++++++++++++++++++++++++++ > 4 files changed, 124 insertions(+) > > diff --git a/arch/arm64/include/asm/kvm_rmi.h b/arch/arm64/include/asm/kvm_rmi.h > index 007249a13dbc..a2b6bc412a22 100644 > --- a/arch/arm64/include/asm/kvm_rmi.h > +++ b/arch/arm64/include/asm/kvm_rmi.h > @@ -88,6 +88,10 @@ int kvm_rec_enter(struct kvm_vcpu *vcpu); > int kvm_rec_pre_enter(struct kvm_vcpu *vcpu); > int handle_rec_exit(struct kvm_vcpu *vcpu, int rec_run_status); > > +struct kvm_arm_rmi_populate; > + > +int kvm_arm_rmi_populate(struct kvm *kvm, > + struct kvm_arm_rmi_populate *arg); > void kvm_realm_unmap_range(struct kvm *kvm, > unsigned long ipa, > unsigned long size, > diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig > index 4e16719fda22..d0cd011cf672 100644 > --- a/arch/arm64/kvm/Kconfig > +++ b/arch/arm64/kvm/Kconfig > @@ -38,6 +38,7 @@ menuconfig KVM > select GUEST_PERF_EVENTS if PERF_EVENTS > select KVM_GUEST_MEMFD > select KVM_GENERIC_MEMORY_ATTRIBUTES > + select HAVE_KVM_ARCH_GMEM_POPULATE > help > Support hosting virtualized guest machines. > > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c > index ed88a203b892..073ba9181da9 100644 > --- a/arch/arm64/kvm/arm.c > +++ b/arch/arm64/kvm/arm.c > @@ -2131,6 +2131,19 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) > return -EFAULT; > return kvm_vm_ioctl_get_reg_writable_masks(kvm, &range); > } > + case KVM_ARM_RMI_POPULATE: { > + struct kvm_arm_rmi_populate req; > + int ret; > + > + if (!kvm_is_realm(kvm)) > + return -ENXIO; > + if (copy_from_user(&req, argp, sizeof(req))) > + return -EFAULT; > + ret = kvm_arm_rmi_populate(kvm, &req); > + if (copy_to_user(argp, &req, sizeof(req))) > + return -EFAULT; > + return ret; > + } s/return ret/return 0; The variable 'ret' can be dropped. > default: > return -EINVAL; > } > diff --git a/arch/arm64/kvm/rmi.c b/arch/arm64/kvm/rmi.c > index a89873a5eb77..209087bcf399 100644 > --- a/arch/arm64/kvm/rmi.c > +++ b/arch/arm64/kvm/rmi.c > @@ -486,6 +486,75 @@ void kvm_realm_unmap_range(struct kvm *kvm, unsigned long start, > realm_unmap_private_range(kvm, start, end, may_block); > } > > +static int realm_data_map_init(struct kvm *kvm, unsigned long ipa, > + kvm_pfn_t dst_pfn, kvm_pfn_t src_pfn, > + unsigned long flags) > +{ > + struct realm *realm = &kvm->arch.realm; > + phys_addr_t rd = virt_to_phys(realm->rd); > + phys_addr_t dst_phys, src_phys; > + int ret; > + > + dst_phys = __pfn_to_phys(dst_pfn); > + src_phys = __pfn_to_phys(src_pfn); > + > + if (rmi_delegate_page(dst_phys)) > + return -ENXIO; > + > + ret = rmi_rtt_data_map_init(rd, dst_phys, ipa, src_phys, flags); > + if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) { > + /* Create missing RTTs and retry */ > + int level = RMI_RETURN_INDEX(ret); > + > + KVM_BUG_ON(level == KVM_PGTABLE_LAST_LEVEL, kvm); KVM_BUG_ON(level >= KVM_PGTABLE_LAST_LEVEL, kvm);> + > + ret = realm_create_rtt_levels(realm, ipa, level, > + KVM_PGTABLE_LAST_LEVEL, NULL); > + if (!ret) { > + ret = rmi_rtt_data_map_init(rd, dst_phys, ipa, src_phys, > + flags); > + } > + } > + > + if (ret) { > + if (WARN_ON(rmi_undelegate_page(dst_phys))) { > + /* Undelegate failed, so we leak the page */ > + get_page(pfn_to_page(dst_pfn)); > + } > + } > + if (ret && WARN_ON(rmi_undelegate_page(dst_phys)) { /* Leak the page that fails to be undelegated */ get_page(pfn_to_page(dst_pfn)); } > + return ret; > +} > + > +static int populate_region_cb(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, > + struct page *src_page, void *opaque) > +{ > + unsigned long data_flags = *(unsigned long *)opaque; > + phys_addr_t ipa = gfn_to_gpa(gfn); > + > + if (!src_page) > + return -EOPNOTSUPP; > + > + return realm_data_map_init(kvm, ipa, pfn, page_to_pfn(src_page), > + data_flags); > +} > + > +static long populate_region(struct kvm *kvm, > + gfn_t base_gfn, > + unsigned long pages, > + u64 uaddr, > + unsigned long data_flags) > +{ > + long ret = 0; > + > + mutex_lock(&kvm->slots_lock); > + ret = kvm_gmem_populate(kvm, base_gfn, u64_to_user_ptr(uaddr), pages, > + populate_region_cb, &data_flags); > + mutex_unlock(&kvm->slots_lock); > + > + return ret; > +} > + > enum ripas_action { > RIPAS_INIT, > RIPAS_SET, > @@ -574,6 +643,43 @@ static int realm_ensure_created(struct kvm *kvm) > return -ENXIO; > } > > +int kvm_arm_rmi_populate(struct kvm *kvm, > + struct kvm_arm_rmi_populate *args) > +{ > + unsigned long data_flags = 0; > + unsigned long ipa_start = args->base; > + unsigned long ipa_end = ipa_start + args->size; > + long pages_populated; > + int ret; > + > + if (args->reserved || > + (args->flags & ~KVM_ARM_RMI_POPULATE_FLAGS_MEASURE) || > + !IS_ALIGNED(ipa_start, PAGE_SIZE) || > + !IS_ALIGNED(ipa_end, PAGE_SIZE) || > + !IS_ALIGNED(args->source_uaddr, PAGE_SIZE)) > + return -EINVAL; > + There are more conditions missed here: args->size == 0, return 0; args->base + args->size < args->base, return -EINVAL; // wrapped range > + ret = realm_ensure_created(kvm); > + if (ret) > + return ret; > + > + if (args->flags & KVM_ARM_RMI_POPULATE_FLAGS_MEASURE) > + data_flags |= RMI_MEASURE_CONTENT; > + > + pages_populated = populate_region(kvm, gpa_to_gfn(ipa_start), > + args->size >> PAGE_SHIFT, > + args->source_uaddr, data_flags); > + > + if (pages_populated < 0) > + return pages_populated; pages_populaged is 'unsigned long', this function returns a 'int' value. > + > + args->size -= pages_populated << PAGE_SHIFT; > + args->source_uaddr += pages_populated << PAGE_SHIFT; > + args->base += pages_populated << PAGE_SHIFT; > + > + return 0; > +} > + > static void kvm_complete_ripas_change(struct kvm_vcpu *vcpu) > { > struct kvm *kvm = vcpu->kvm; Thanks, Gavin