Received: by 2002:a6b:fb09:0:0:0:0:0 with SMTP id h9csp458705iog; Fri, 24 Jun 2022 07:20:55 -0700 (PDT) X-Google-Smtp-Source: AGRyM1u2xkqhyvdtE1oMbqSBwNc0cA5HU5iT3P+xofPhlU5fR8YjebC1J1k1xsAmSEz9Ja+LTJan X-Received: by 2002:a17:903:32c4:b0:16a:4201:45e4 with SMTP id i4-20020a17090332c400b0016a420145e4mr15616741plr.108.1656080454995; Fri, 24 Jun 2022 07:20:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1656080454; cv=none; d=google.com; s=arc-20160816; b=BTD60/+VS1uljG1Mh8BkGN6zRb+NytP3k6Fqq7sDeZfabxJLAYoYSwWZ5wdM69MFuh /XQw9zuLcC9osgrqRtzC/7SrC/Cr9ucOlUFApE+9ARyL77FwkaTS74MYlHTQ2Qv0fz6G 6ezQ+BRcg+eJ4ItYZsCxom+99oER7zomrDlhJ1KnfZNKTobpAmrzEJBVjYxyAFl1Ys0n hMTFbmY2FwS1UZHwd76rCUjRrXFyGeZdxjBeS4VkfWIMcsJ0AV4wQCu1khjDQWQiu6xl 26Pa9F6vN/E99PO0C6VJtic9oW62BH+LuwXy5CWnYLn642Y8uiOw0Ckso7hzB0fZNAp6 k/Iw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:cc:to:subject :message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=DX4gKze+gSLugENwiJT/N67T0nY4kiuroWR4tE5f6EI=; b=pqpLOhj7q+ktImdvUmi4LZRWX6r4RvxrXf9hi6XtpQvFKoFmnRZl9zynWzijUkEcS1 c9fTXp3L6fUX+7HJs7SDgNEMmGTDuvIAwmcQ6gKCN+j/c9CIVyMHr8pdXjsPotq3ZNa1 CnbY6r/uJM83IAk11Zt8fTixxJFpyOwyWuAb2Z1KHSUGeeFH12Nz+19+WlfDTDWG4gDR xagih2At3pcNtj1FhhCxlPzYpA+mVTsdqraomv+LKH5MPFVaaYusLyG6IWUz17s07p4Q s4L1Nwk1Rt37qHJ2BwFL0hgyfoqvvaTb+h5bS7/WftUppSweJmo3e9GhzGhAimwhGfyj WfcA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=VfEBDmF+; spf=pass (google.com: domain of linux-crypto-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-crypto-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id pj13-20020a17090b4f4d00b001ec99ac7265si8810790pjb.126.2022.06.24.07.20.32; Fri, 24 Jun 2022 07:20:54 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-crypto-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=VfEBDmF+; spf=pass (google.com: domain of linux-crypto-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-crypto-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232427AbiFXOUK (ORCPT + 99 others); Fri, 24 Jun 2022 10:20:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50098 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232373AbiFXOUI (ORCPT ); Fri, 24 Jun 2022 10:20:08 -0400 Received: from mail-lj1-x22c.google.com (mail-lj1-x22c.google.com [IPv6:2a00:1450:4864:20::22c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D442D54FB7 for ; Fri, 24 Jun 2022 07:20:05 -0700 (PDT) Received: by mail-lj1-x22c.google.com with SMTP id by38so2920769ljb.10 for ; Fri, 24 Jun 2022 07:20:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=DX4gKze+gSLugENwiJT/N67T0nY4kiuroWR4tE5f6EI=; b=VfEBDmF+RRx2AePp1LKNOXvU7WJWT/O2vbwOK6TcFPNB4pQVsyY0RfX4vhJAh+Mbnb CSpLC4DuU04b6TaGJLqjByKLSlK8rMKagv+1X/BnF+DG6FGTeJTqco41IJxg4BBknO2c 9nU6xj5VrURoXdlBlHE2MMDs0tD3YctaUDGt7Tex6JVeCdE7WaXXjW/s4w+mK5j07sok iU8nUCW2GGMNSUiRP8CU+ZLEXk2iKTAe2x+UOMTYWOweClggqSOEWwk7/xetU7NHaeBl PymrdlAltUTGV2UX8jh43nTF58/YGtacCmmHQYeAbukWxoteTQOVOrjG4tdcO81x/oRY ogCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=DX4gKze+gSLugENwiJT/N67T0nY4kiuroWR4tE5f6EI=; b=Fml/7momVYXwMT5Ki9BkL4mPi9VvvJN0jZdxZj1mmJNaVCgVS46CDXSfumgE/dPXj9 nCOm1r4jnuSCjdm9wLInV+AvHe1CW83lrYXyAqk/Wsf/3PwdEug/LIRzKXtH1SeoM200 ht5fRdbBJevaGYOsyuyx42Dti3f5hX0YWtX/EAA9hYAE5L5h0/nT/RVGX5zRrb5WZ6lM C2TRRINv/e+Ywsj/kHmGt7UMlpbShNJ0kUGAms+qb6PV0FHV84/5DmIdE8/Iy2nD8MlQ HSEdoUTFKhLm04ONsx+ef7g8UV82SacUbRC0gsITdVz+QjtsDesyQiiKyg3XJ5wGvD65 eOMg== X-Gm-Message-State: AJIora/8yD1PZxHjVHuTL8IbTYMQmvKEJYzLU4adJ5LF2A1TeE6+DchP TobYXcXtvA0M6eIxpJcH1WGazRKeApLfLBxVYKTOqQ== X-Received: by 2002:a2e:2a43:0:b0:25a:84a9:921c with SMTP id q64-20020a2e2a43000000b0025a84a9921cmr7482170ljq.83.1656080403810; Fri, 24 Jun 2022 07:20:03 -0700 (PDT) MIME-Version: 1.0 References: <3a51840f6a80c87b39632dc728dbd9b5dd444cd7.1655761627.git.ashish.kalra@amd.com> In-Reply-To: From: Peter Gonda Date: Fri, 24 Jun 2022 08:19:52 -0600 Message-ID: Subject: Re: [PATCH Part2 v6 14/49] crypto: ccp: Handle the legacy TMR allocation when SNP is enabled To: "Kalra, Ashish" Cc: "the arch/x86 maintainers" , LKML , kvm list , "linux-coco@lists.linux.dev" , "linux-mm@kvack.org" , Linux Crypto Mailing List , Thomas Gleixner , Ingo Molnar , Joerg Roedel , "Lendacky, Thomas" , "H. Peter Anvin" , Ard Biesheuvel , Paolo Bonzini , Sean Christopherson , Vitaly Kuznetsov , Jim Mattson , Andy Lutomirski , Dave Hansen , Sergio Lopez , Peter Zijlstra , Srinivas Pandruvada , David Rientjes , Dov Murik , Tobin Feldman-Fitzthum , Borislav Petkov , "Roth, Michael" , Vlastimil Babka , "Kirill A . Shutemov" , Andi Kleen , Tony Luck , Marc Orr , Sathyanarayanan Kuppuswamy , Alper Gun , "Dr. David Alan Gilbert" , "jarkko@kernel.org" Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-17.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, ENV_AND_HDR_SPF_MATCH,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,USER_IN_DEF_DKIM_WL,USER_IN_DEF_SPF_WL autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org On Tue, Jun 21, 2022 at 2:17 PM Kalra, Ashish wrote: > > [Public] > > Hello Peter, > > >> +static int snp_reclaim_pages(unsigned long pfn, unsigned int npages, > >> +bool locked) { > >> + struct sev_data_snp_page_reclaim data; > >> + int ret, err, i, n =3D 0; > >> + > >> + for (i =3D 0; i < npages; i++) { > > >What about setting |n| here too, also the other increments. > > >for (i =3D 0, n =3D 0; i < npages; i++, n++, pfn++) > > Yes that is simpler. > > >> + memset(&data, 0, sizeof(data)); > >> + data.paddr =3D pfn << PAGE_SHIFT; > >> + > >> + if (locked) > >> + ret =3D __sev_do_cmd_locked(SEV_CMD_SNP_PAGE_R= ECLAIM, &data, &err); > >> + else > >> + ret =3D sev_do_cmd(SEV_CMD_SNP_PAGE_RECLAIM, > >> + &data, &err); > > > Can we change `sev_cmd_mutex` to some sort of nesting lock type? That c= ould clean up this if (locked) code. > > > +static inline int rmp_make_firmware(unsigned long pfn, int level) { > > + return rmp_make_private(pfn, 0, level, 0, true); } > > + > > +static int snp_set_rmp_state(unsigned long paddr, unsigned int npages,= bool to_fw, bool locked, > > + bool need_reclaim) > > >This function can do a lot and when I read the call sites its hard to se= e what its doing since we have a combination of arguments which tell us wha= t behavior is happening, some of which are not valid (ex: to_fw =3D=3D true= and need_reclaim =3D=3D true is an >invalid argument combination). > > to_fw is used to make a firmware page and need_reclaim is for freeing the= firmware page, so they are going to be mutually exclusive. > > I actually can connect with it quite logically with the callers : > snp_alloc_firmware_pages will call with to_fw =3D true and need_reclaim = =3D false > and snp_free_firmware_pages will do the opposite, to_fw =3D false and nee= d_reclaim =3D true. > > That seems straightforward to look at. This might be a preference thing but I find it not straightforward. When I am reading through unmap_firmware_writeable() and I see /* Transition the pre-allocated buffer to the firmware state. */ if (snp_set_rmp_state(__pa(map->host), npages, true, true, false)) return -EFAULT; I don't actually know what snp_set_rmp_state() is doing unless I go look at the definition and see what all those booleans mean. This is unlike the rmp_make_shared() and rmp_make_private() functions, each of which tells me a lot more about what the function will do just from the name. > > >Also this for loop over |npages| is duplicated from snp_reclaim_pages().= One improvement here is that on the current > >snp_reclaim_pages() if we fail to reclaim a page we assume we cannot rec= laim the next pages, this may cause us to snp_leak_pages() more pages than = we actually need too. > > Yes that is true. > > >What about something like this? > > >static snp_leak_page(u64 pfn, enum pg_level level) { > > memory_failure(pfn, 0); > > dump_rmpentry(pfn); > >} > > >static int snp_reclaim_page(u64 pfn, enum pg_level level) { > > int ret; > > struct sev_data_snp_page_reclaim data; > > > ret =3D sev_do_cmd(SEV_CMD_SNP_PAGE_RECLAIM, &data, &err); > > if (ret) > > goto cleanup; > > > ret =3D rmp_make_shared(pfn, level); > > if (ret) > > goto cleanup; > > > return 0; > > >cleanup: > > snp_leak_page(pfn, level) > >} > > >typedef int (*rmp_state_change_func) (u64 pfn, enum pg_level level); > > >static int snp_set_rmp_state(unsigned long paddr, unsigned int npages, r= mp_state_change_func state_change, rmp_state_change_func cleanup) { > > struct sev_data_snp_page_reclaim data; > > int ret, err, i, n =3D 0; > > > for (i =3D 0, n =3D 0; i < npages; i++, n++, pfn++) { > > ret =3D state_change(pfn, PG_LEVEL_4K) > > if (ret) > > goto cleanup; > > } > > > return 0; > > > cleanup: > > for (; i>=3D 0; i--, n--, pfn--) { > > cleanup(pfn, PG_LEVEL_4K); > > } > > > return ret; > >} > > >Then inside of __snp_alloc_firmware_pages(): > > >snp_set_rmp_state(paddr, npages, rmp_make_firmware, snp_reclaim_page); > > >And inside of __snp_free_firmware_pages(): > > >snp_set_rmp_state(paddr, npages, snp_reclaim_page, snp_leak_page); > > >Just a suggestion feel free to ignore. The readability comment could be = addressed much less invasively by just making separate functions for each v= alid combination of arguments here. Like snp_set_rmp_fw_state(), snp_set_rm= p_shared_state(), > >snp_set_rmp_release_state() or something. > > >> +static struct page *__snp_alloc_firmware_pages(gfp_t gfp_mask, int > >> +order, bool locked) { > >> + unsigned long npages =3D 1ul << order, paddr; > >> + struct sev_device *sev; > >> + struct page *page; > >> + > >> + if (!psp_master || !psp_master->sev_data) > >> + return NULL; > >> + > >> + page =3D alloc_pages(gfp_mask, order); > >> + if (!page) > >> + return NULL; > >> + > >> + /* If SEV-SNP is initialized then add the page in RMP table. *= / > >> + sev =3D psp_master->sev_data; > >> + if (!sev->snp_inited) > >> + return page; > >> + > >> + paddr =3D __pa((unsigned long)page_address(page)); > >> + if (snp_set_rmp_state(paddr, npages, true, locked, false)) > >> + return NULL; > > >So what about the case where snp_set_rmp_state() fails but we were able = to reclaim all the pages? Should we be able to signal that to callers so th= at we could free |page| here? But given this is an error path already maybe= we can optimize this in a >follow up series. > > Yes, we should actually tie in to snp_reclaim_pages() success or failure = here in the case we were able to successfully unroll some or all of the fir= mware state change. > > > + > > + return page; > > +} > > + > > +void *snp_alloc_firmware_page(gfp_t gfp_mask) { > > + struct page *page; > > + > > + page =3D __snp_alloc_firmware_pages(gfp_mask, 0, false); > > + > > + return page ? page_address(page) : NULL; } > > +EXPORT_SYMBOL_GPL(snp_alloc_firmware_page); > > + > > +static void __snp_free_firmware_pages(struct page *page, int order, > > +bool locked) { > > + unsigned long paddr, npages =3D 1ul << order; > > + > > + if (!page) > > + return; > > + > > + paddr =3D __pa((unsigned long)page_address(page)); > > + if (snp_set_rmp_state(paddr, npages, false, locked, true)) > > + return; > > > Here we may be able to free some of |page| depending how where inside o= f snp_set_rmp_state() we failed. But again given this is an error path alre= ady maybe we can optimize this in a follow up series. > > Yes, we probably should be able to free some of the page(s) depending on = how many page(s) got reclaimed in snp_set_rmp_state(). > But these reclamation failures may not be very common, so any failure is = indicative of a bigger issue, it might be the case when there is a single p= age reclamation error it might happen with all the subsequent > pages and so follow a simple recovery procedure, then handling a more com= plex recovery for a chunk of pages being reclaimed and another chunk not. > > Thanks, > Ashish > > >