From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id B365AC4167D for ; Tue, 31 Oct 2023 02:26:43 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 368D16B0271; Mon, 30 Oct 2023 22:26:43 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 2F1866B0272; Mon, 30 Oct 2023 22:26:43 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 16B866B027A; Mon, 30 Oct 2023 22:26:43 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 01A726B0271 for ; Mon, 30 Oct 2023 22:26:42 -0400 (EDT) Received: from smtpin22.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id B0127A05FC for ; Tue, 31 Oct 2023 02:26:42 +0000 (UTC) X-FDA: 81404168244.22.82E11A9 Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.126]) by imf06.hostedemail.com (Postfix) with ESMTP id 784DF18000B for ; Tue, 31 Oct 2023 02:26:40 +0000 (UTC) Authentication-Results: imf06.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=lzqfXbea; spf=pass (imf06.hostedemail.com: domain of xiaoyao.li@intel.com designates 134.134.136.126 as permitted sender) smtp.mailfrom=xiaoyao.li@intel.com; dmarc=pass (policy=none) header.from=intel.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1698719200; h=from:from:sender: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:dkim-signature; bh=uE3am6pxwYOa2174bdkg3tyVc2t7zw1RH0xv8EN9IOU=; b=Epfmfu198hhHY1zaNe41RIUU6AdMrwfo3zx8qliZumn5Kyd/vKLSd/Bb/PPJgaza/gcpxF /cQyHVhQKVBf/c2aobfskQP/OgQS+97FwFIj2FlOL3hptmA+K5ckqnQoLmVogx1HoImF5+ WClbYCvajW2h+Yzw9+dxBmY+gZb2Pho= ARC-Authentication-Results: i=1; imf06.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=lzqfXbea; spf=pass (imf06.hostedemail.com: domain of xiaoyao.li@intel.com designates 134.134.136.126 as permitted sender) smtp.mailfrom=xiaoyao.li@intel.com; dmarc=pass (policy=none) header.from=intel.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1698719200; a=rsa-sha256; cv=none; b=r0LyvIAgkvmwQKhhQWLfphgrRs76ZiSPT7WWI9W+wL3QIEySGbsM6RWgvjaoyVJEmgeoD6 5zmwILb3eBlFVQ9k2qLmX1ZHJo0jXFeRc4a/44Hw25Zs92me3fjzxK2eJBo7sODlFAI0lk 14PwzoNpWNt32Oiw+vGiZVqEbW/ZgY8= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1698719200; x=1730255200; h=message-id:date:mime-version:subject:to:cc:references: from:in-reply-to:content-transfer-encoding; bh=1RxaiPSscGnriT5S1YWbGyKo7Yhdv1SBTp2kCHaOJTg=; b=lzqfXbea3Fak2kxKVwVBX2tCid17AqzoBpSJYL6nTbNtA9XBy8tsIntJ WebQmcaai0ZflO+qk66sHPHXUMyUeLkgaUZv56yEXTVhvUMiFm0EN+fe+ HEl1Djoxao8IEVeW7rqCye+fyywJcK1yfKUYpYhqeriqC3TbGYyYhbieT womnNXkO0x+HUjh7V981e1kTukPsBqhOf/cP5kiTwu2dLyLrgHVzrkqxx gSoTVJWnrcvpfzbMOW8BiHfylFcVO+f9OzrOAHVuKCzV+zqlfPBXlVG3O viMYQm7xUMO6tFUjZOgET1NltLDG1IGxGNJsXUga0+WaK+lzJ1ohc0SVb w==; X-IronPort-AV: E=McAfee;i="6600,9927,10879"; a="373249641" X-IronPort-AV: E=Sophos;i="6.03,264,1694761200"; d="scan'208";a="373249641" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Oct 2023 19:26:38 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.03,264,1694761200"; d="scan'208";a="8161358" Received: from xiaoyaol-hp-g830.ccr.corp.intel.com (HELO [10.93.9.145]) ([10.93.9.145]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Oct 2023 19:26:27 -0700 Message-ID: <2edd908a-9699-4d8e-9063-c655f1fc9712@intel.com> Date: Tue, 31 Oct 2023 10:26:22 +0800 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v13 08/35] KVM: Introduce KVM_SET_USER_MEMORY_REGION2 Content-Language: en-US To: Sean Christopherson , Paolo Bonzini , Marc Zyngier , Oliver Upton , Huacai Chen , Michael Ellerman , Anup Patel , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexander Viro , Christian Brauner , "Matthew Wilcox (Oracle)" , Andrew Morton Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-mips@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, kvm-riscv@lists.infradead.org, linux-riscv@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Xu Yilun , Chao Peng , Fuad Tabba , Jarkko Sakkinen , Anish Moorthy , David Matlack , Yu Zhang , Isaku Yamahata , =?UTF-8?B?TWlja2HDq2wgU2FsYcO8?= =?UTF-8?Q?n?= , Vlastimil Babka , Vishal Annapurve , Ackerley Tng , Maciej Szmigiero , David Hildenbrand , Quentin Perret , Michael Roth , Wang , Liam Merwick , Isaku Yamahata , "Kirill A . Shutemov" References: <20231027182217.3615211-1-seanjc@google.com> <20231027182217.3615211-9-seanjc@google.com> From: Xiaoyao Li In-Reply-To: <20231027182217.3615211-9-seanjc@google.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Rspamd-Queue-Id: 784DF18000B X-Rspam-User: X-Stat-Signature: i5kkkakcb7pc1par3ctbimkf37115s3p X-Rspamd-Server: rspam01 X-HE-Tag: 1698719200-272322 X-HE-Meta: U2FsdGVkX1/ljNpH1UXeTojV1XDTdCoqe1/g92i6OnhAYw6af1QcMK750Fa07EPfvBg6H40SnPGHxPt3Iwp8kp6kBMihRiGeoyO61t6AOXQYINKCOdzrengOxETcbkBMeH/8ow7xeJ5NOU50vDW90bLfVGPYZIlWnHRz3vwKDK43GsLEXYVSh/nLzoQFtd0panvcBJEFBnjZfrtRVBaB+zkLeXgBvB4G9dvk1CemkLexQSzt9GwYNMZVrZC/DBKeeZciOHkBYURg8d0TayirAZCKLB06rcSe5icAD53TIeBID/hKrcbTBkLg7FRyUQNY8wMpaU4oRzCCsNrCcVZ+dFvC/cHAldlD02Z38JNrhs9nMlOE/0ZM8ctUUdUSftAt7M3muOS1jjlWpjFcjWeyEww4qBv2pRwT8/FszTiLcc0GIA1uUJoVJD+/PnfiPM8dKnMPPsdp89LWyiqb3rbdoh0EW+0n6NNzUFEGK/ec1RQziTP92Wu6LTOYXd4nsN/t8PPyPDD6pTCV9qZMH2KB5thEXPNBHHt4vKwLrK7PpvcfYset91wYfAP+9m90yHWWzwsswCNI+dkF0hQ0sMkfpxQkh5aTkcJ/iMt1VH3NOudkYWVVXVe1KauBReiNrjb+xZQ4YR9BKpHfMK09f6/BZdGxjEmHH5PWJJE15dOm7qj5uJy82yU4WUeRfa7BPTEzKifd+NhyOgyKkHVivOpwbhYgCvPrp9u5Ixc2nnDtddEJF3q67LUgbCIoG4oJzFlXBt8Ar2X+0eydiVqCbLCRk2si/NMfX6/imn/MMcZvQzWbVf6fjIBzPWMMSTOiu93zq2nl1VtHDdLsq2JzrMdfV6i27xaRkMEoAUrbPKsoWVyt+qqq7Cq5/bbl0KRoiyfIuHn6KNytshxjPGVZlIK9PGBxf0qTef5DNSaJlIidGx01a77bAvqNf++hmhwnP6IH9L30kzFkNRL37ficl9R w6i5KHoI VDaosH0vzj5hKo6ep9+K3L7UyvwY7/2XfF86Ah5e4gtFU6LIGFIhAHlWN+P5H4czpiaW115rXlfPANfLUXx7VkbIyYB0zjvnfahRWqN5lLHPJ+Ai9oLtTFceqFPmxeDe3pF3bAm0nDrr7FdmXOFbKzIEc0v8PuzHcJXJ+OkfmN/7Px5lilE3s5IM+ddLX9RTYajGFvIDhersOn5DFZoWyfgMW3cwjz3XMw+UOpGR+gN9H+aoSQIsJvM7Wq730kv5C32aHGwmG7fSUz1fbly/woAaHZ5YO0g/++vKvr2zWoJx73O3F7g+e3eItiYU9FN9olYyiLHKrDp4MrUhrH14QOaoPHnoR2qmxXIq7VJy7f+/Azvt9Sm6RTLGSPv9TX/4JTbdJcg+3lThWnZlmBOldCICKdVpv0jTLV9OFK1VS0TNanth2DF5z8YW58g== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: On 10/28/2023 2:21 AM, Sean Christopherson wrote: > Introduce a "version 2" of KVM_SET_USER_MEMORY_REGION so that additional > information can be supplied without setting userspace up to fail. The > padding in the new kvm_userspace_memory_region2 structure will be used to > pass a file descriptor in addition to the userspace_addr, i.e. allow > userspace to point at a file descriptor and map memory into a guest that > is NOT mapped into host userspace. > > Alternatively, KVM could simply add "struct kvm_userspace_memory_region2" > without a new ioctl(), but as Paolo pointed out, adding a new ioctl() > makes detection of bad flags a bit more robust, e.g. if the new fd field > is guarded only by a flag and not a new ioctl(), then a userspace bug > (setting a "bad" flag) would generate out-of-bounds access instead of an > -EINVAL error. > > Cc: Jarkko Sakkinen > Reviewed-by: Paolo Bonzini > Reviewed-by: Xiaoyao Li > Signed-off-by: Sean Christopherson > --- > Documentation/virt/kvm/api.rst | 21 +++++++++++++++++++ > arch/x86/kvm/x86.c | 2 +- > include/linux/kvm_host.h | 4 ++-- > include/uapi/linux/kvm.h | 13 ++++++++++++ > virt/kvm/kvm_main.c | 38 +++++++++++++++++++++++++++------- > 5 files changed, 67 insertions(+), 11 deletions(-) > > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst > index 21a7578142a1..ace984acc125 100644 > --- a/Documentation/virt/kvm/api.rst > +++ b/Documentation/virt/kvm/api.rst > @@ -6070,6 +6070,27 @@ writes to the CNTVCT_EL0 and CNTPCT_EL0 registers using the SET_ONE_REG > interface. No error will be returned, but the resulting offset will not be > applied. > > +4.139 KVM_SET_USER_MEMORY_REGION2 > +--------------------------------- > + > +:Capability: KVM_CAP_USER_MEMORY2 > +:Architectures: all > +:Type: vm ioctl > +:Parameters: struct kvm_userspace_memory_region2 (in) > +:Returns: 0 on success, -1 on error > + > +:: > + > + struct kvm_userspace_memory_region2 { > + __u32 slot; > + __u32 flags; > + __u64 guest_phys_addr; > + __u64 memory_size; /* bytes */ > + __u64 userspace_addr; /* start of the userspace allocated memory */ missing __u64 pad[16]; > + }; > + > +See KVM_SET_USER_MEMORY_REGION. > + > 5. The kvm_run structure > ======================== > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 41cce5031126..6409914428ca 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -12455,7 +12455,7 @@ void __user * __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, > } > > for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) { > - struct kvm_userspace_memory_region m; > + struct kvm_userspace_memory_region2 m; > > m.slot = id | (i << 16); > m.flags = 0; > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h > index 5faba69403ac..4e741ff27af3 100644 > --- a/include/linux/kvm_host.h > +++ b/include/linux/kvm_host.h > @@ -1146,9 +1146,9 @@ enum kvm_mr_change { > }; > > int kvm_set_memory_region(struct kvm *kvm, > - const struct kvm_userspace_memory_region *mem); > + const struct kvm_userspace_memory_region2 *mem); > int __kvm_set_memory_region(struct kvm *kvm, > - const struct kvm_userspace_memory_region *mem); > + const struct kvm_userspace_memory_region2 *mem); > void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *slot); > void kvm_arch_memslots_updated(struct kvm *kvm, u64 gen); > int kvm_arch_prepare_memory_region(struct kvm *kvm, > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h > index 13065dd96132..bd1abe067f28 100644 > --- a/include/uapi/linux/kvm.h > +++ b/include/uapi/linux/kvm.h > @@ -95,6 +95,16 @@ struct kvm_userspace_memory_region { > __u64 userspace_addr; /* start of the userspace allocated memory */ > }; > > +/* for KVM_SET_USER_MEMORY_REGION2 */ > +struct kvm_userspace_memory_region2 { > + __u32 slot; > + __u32 flags; > + __u64 guest_phys_addr; > + __u64 memory_size; > + __u64 userspace_addr; > + __u64 pad[16]; > +}; > + > /* > * The bit 0 ~ bit 15 of kvm_userspace_memory_region::flags are visible for > * userspace, other bits are reserved for kvm internal use which are defined > @@ -1192,6 +1202,7 @@ struct kvm_ppc_resize_hpt { > #define KVM_CAP_COUNTER_OFFSET 227 > #define KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE 228 > #define KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES 229 > +#define KVM_CAP_USER_MEMORY2 230 > > #ifdef KVM_CAP_IRQ_ROUTING > > @@ -1473,6 +1484,8 @@ struct kvm_vfio_spapr_tce { > struct kvm_userspace_memory_region) > #define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47) > #define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64) > +#define KVM_SET_USER_MEMORY_REGION2 _IOW(KVMIO, 0x49, \ > + struct kvm_userspace_memory_region2) > > /* enable ucontrol for s390 */ > struct kvm_s390_ucas_mapping { > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > index 6e708017064d..3f5b7c2c5327 100644 > --- a/virt/kvm/kvm_main.c > +++ b/virt/kvm/kvm_main.c > @@ -1578,7 +1578,7 @@ static void kvm_replace_memslot(struct kvm *kvm, > } > } > > -static int check_memory_region_flags(const struct kvm_userspace_memory_region *mem) > +static int check_memory_region_flags(const struct kvm_userspace_memory_region2 *mem) > { > u32 valid_flags = KVM_MEM_LOG_DIRTY_PAGES; > > @@ -1980,7 +1980,7 @@ static bool kvm_check_memslot_overlap(struct kvm_memslots *slots, int id, > * Must be called holding kvm->slots_lock for write. > */ > int __kvm_set_memory_region(struct kvm *kvm, > - const struct kvm_userspace_memory_region *mem) > + const struct kvm_userspace_memory_region2 *mem) > { > struct kvm_memory_slot *old, *new; > struct kvm_memslots *slots; > @@ -2084,7 +2084,7 @@ int __kvm_set_memory_region(struct kvm *kvm, > EXPORT_SYMBOL_GPL(__kvm_set_memory_region); > > int kvm_set_memory_region(struct kvm *kvm, > - const struct kvm_userspace_memory_region *mem) > + const struct kvm_userspace_memory_region2 *mem) > { > int r; > > @@ -2096,7 +2096,7 @@ int kvm_set_memory_region(struct kvm *kvm, > EXPORT_SYMBOL_GPL(kvm_set_memory_region); > > static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm, > - struct kvm_userspace_memory_region *mem) > + struct kvm_userspace_memory_region2 *mem) > { > if ((u16)mem->slot >= KVM_USER_MEM_SLOTS) > return -EINVAL; > @@ -4566,6 +4566,7 @@ static int kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) > { > switch (arg) { > case KVM_CAP_USER_MEMORY: > + case KVM_CAP_USER_MEMORY2: > case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: > case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS: > case KVM_CAP_INTERNAL_ERROR_DATA: > @@ -4821,6 +4822,14 @@ static int kvm_vm_ioctl_get_stats_fd(struct kvm *kvm) > return fd; > } > > +#define SANITY_CHECK_MEM_REGION_FIELD(field) \ > +do { \ > + BUILD_BUG_ON(offsetof(struct kvm_userspace_memory_region, field) != \ > + offsetof(struct kvm_userspace_memory_region2, field)); \ > + BUILD_BUG_ON(sizeof_field(struct kvm_userspace_memory_region, field) != \ > + sizeof_field(struct kvm_userspace_memory_region2, field)); \ > +} while (0) > + > static long kvm_vm_ioctl(struct file *filp, > unsigned int ioctl, unsigned long arg) > { > @@ -4843,15 +4852,28 @@ static long kvm_vm_ioctl(struct file *filp, > r = kvm_vm_ioctl_enable_cap_generic(kvm, &cap); > break; > } > + case KVM_SET_USER_MEMORY_REGION2: > case KVM_SET_USER_MEMORY_REGION: { > - struct kvm_userspace_memory_region kvm_userspace_mem; > + struct kvm_userspace_memory_region2 mem; > + unsigned long size; > + > + if (ioctl == KVM_SET_USER_MEMORY_REGION) > + size = sizeof(struct kvm_userspace_memory_region); > + else > + size = sizeof(struct kvm_userspace_memory_region2); > + > + /* Ensure the common parts of the two structs are identical. */ > + SANITY_CHECK_MEM_REGION_FIELD(slot); > + SANITY_CHECK_MEM_REGION_FIELD(flags); > + SANITY_CHECK_MEM_REGION_FIELD(guest_phys_addr); > + SANITY_CHECK_MEM_REGION_FIELD(memory_size); > + SANITY_CHECK_MEM_REGION_FIELD(userspace_addr); > > r = -EFAULT; > - if (copy_from_user(&kvm_userspace_mem, argp, > - sizeof(kvm_userspace_mem))) > + if (copy_from_user(&mem, argp, size)) > goto out; > > - r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_userspace_mem); > + r = kvm_vm_ioctl_set_memory_region(kvm, &mem); > break; > } > case KVM_GET_DIRTY_LOG: {