From nobody Fri Apr 26 17:26:50 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1557837148; cv=none; d=zoho.com; s=zohoarc; b=SAL+aBKwVKGRsZH4RFbqG/7tOmdH/39vv1qFUEDOm214RMeSfei8fwnmBFqj1E1m7qH6M954Uj78MhBxs9d6l7C7UeHuHNWTUlYihQH6j58dDwq19v/DxF9spqTvz/oRX36RCZf8vuWLH56suMWsblWdX0224xtYlZKjelt02Tg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557837148; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=APJzreMBZxF3B6yZ1frc+3ECyif+0gi/aTIo6kpCy18=; b=JgUO3YYlcyzq28jlDHIoVQQD2AbUjmoiSSb50Ry7U7o9fv9ZwED3sQC4xX2GK+Qt++wuJ27FAh5nUSFLOyRwF6hkYbmLuJvfCP9WA9z8vdgjDp3VJkx8a44eXAVsjohaar6AsMpxZ2fjQXeBcEh0Px7vmgsE7e3ci+khQDIMsak= ARC-Authentication-Results: i=1; mx.zoho.com; spf=none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 155783714872733.880519111271155; Tue, 14 May 2019 05:32:28 -0700 (PDT) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hQWay-0005UG-Nc; Tue, 14 May 2019 12:31:48 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hQWax-0005Sd-CG for xen-devel@lists.xenproject.org; Tue, 14 May 2019 12:31:47 +0000 Received: from foss.arm.com (unknown [217.140.101.70]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTP id 3cc2bb54-7644-11e9-aba7-3fae97ee57bb; Tue, 14 May 2019 12:31:46 +0000 (UTC) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id E121015AB; Tue, 14 May 2019 05:31:45 -0700 (PDT) Received: from e108454-lin.cambridge.arm.com (e108454-lin.cambridge.arm.com [10.1.196.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id ADCC53F71E; Tue, 14 May 2019 05:31:44 -0700 (PDT) X-Inumbo-ID: 3cc2bb54-7644-11e9-aba7-3fae97ee57bb From: Julien Grall To: xen-devel@lists.xenproject.org Date: Tue, 14 May 2019 13:31:23 +0100 Message-Id: <20190514123125.29086-11-julien.grall@arm.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190514123125.29086-1-julien.grall@arm.com> References: <20190514123125.29086-1-julien.grall@arm.com> Subject: [Xen-devel] [PATCH MM-PART3 v2 10/12] xen/arm: mm: Rework Xen page-tables walk during update X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Oleksandr_Tyshchenko@epam.com, Julien Grall , Stefano Stabellini , Andrii Anisov MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Currently, xen_pt_update_entry() is only able to update the region covered by xen_second (i.e 0 to 0x7fffffff). Because of the restriction we end to have multiple functions in mm.c modifying the page-tables differently. Furthermore, we never walked the page-tables fully. This means that any change in the layout may requires major rewrite of the page-tables code. Lastly, we have been quite lucky that no one ever tried to pass an address outside this range because it would have blown-up. xen_pt_update_entry() is reworked to walk over the page-tables every time. The logic has been borrowed from arch/arm/p2m.c and contain some limitations for the time being: - Superpage cannot be shattered - Only level 3 (i.e 4KB) can be done Note that the parameter 'addr' has been renamed to 'virt' to make clear we are dealing with a virtual address. Signed-off-by: Julien Grall Reviewed-by: Andrii Anisov --- Changes in v2: - Add Andrii's reviewed-by --- xen/arch/arm/mm.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++---= ---- 1 file changed, 106 insertions(+), 15 deletions(-) diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index f5979f549b..9a40754f44 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -984,6 +984,53 @@ static void xen_unmap_table(const lpae_t *table) unmap_domain_page(table); } =20 +#define XEN_TABLE_MAP_FAILED 0 +#define XEN_TABLE_SUPER_PAGE 1 +#define XEN_TABLE_NORMAL_PAGE 2 + +/* + * Take the currently mapped table, find the corresponding entry, + * and map the next table, if available. + * + * The read_only parameters indicates whether intermediate tables should + * be allocated when not present. + * + * Return values: + * XEN_TABLE_MAP_FAILED: Either read_only was set and the entry + * was empty, or allocating a new page failed. + * XEN_TABLE_NORMAL_PAGE: next level mapped normally + * XEN_TABLE_SUPER_PAGE: The next entry points to a superpage. + */ +static int xen_pt_next_level(bool read_only, unsigned int level, + lpae_t **table, unsigned int offset) +{ + lpae_t *entry; + int ret; + + entry =3D *table + offset; + + if ( !lpae_is_valid(*entry) ) + { + if ( read_only ) + return XEN_TABLE_MAP_FAILED; + + ret =3D create_xen_table(entry); + if ( ret ) + return XEN_TABLE_MAP_FAILED; + } + + ASSERT(lpae_is_valid(*entry)); + + /* The function xen_pt_next_level is never called at the 3rd level */ + if ( lpae_is_mapping(*entry, level) ) + return XEN_TABLE_SUPER_PAGE; + + xen_unmap_table(*table); + *table =3D xen_map_table(lpae_get_mfn(*entry)); + + return XEN_TABLE_NORMAL_PAGE; +} + /* Sanity check of the entry */ static bool xen_pt_check_entry(lpae_t entry, mfn_t mfn, unsigned int flags) { @@ -1043,30 +1090,65 @@ static bool xen_pt_check_entry(lpae_t entry, mfn_t = mfn, unsigned int flags) return true; } =20 -static int xen_pt_update_entry(unsigned long addr, mfn_t mfn, - unsigned int flags) +static int xen_pt_update_entry(mfn_t root, unsigned long virt, + mfn_t mfn, unsigned int flags) { int rc; + unsigned int level; + /* We only support 4KB mapping (i.e level 3) for now */ + unsigned int target =3D 3; + lpae_t *table; + /* + * The intermediate page tables are read-only when the MFN is not valid + * and we are not populating page table. + * This means we either modify permissions or remove an entry. + */ + bool read_only =3D mfn_eq(mfn, INVALID_MFN) && !(flags & _PAGE_POPULAT= E); lpae_t pte, *entry; - lpae_t *third =3D NULL; + + /* convenience aliases */ + DECLARE_OFFSETS(offsets, (paddr_t)virt); =20 /* _PAGE_POPULATE and _PAGE_PRESENT should never be set together. */ ASSERT((flags & (_PAGE_POPULATE|_PAGE_PRESENT)) !=3D (_PAGE_POPULATE|_= PAGE_PRESENT)); =20 - entry =3D &xen_second[second_linear_offset(addr)]; - if ( !lpae_is_valid(*entry) || !lpae_is_table(*entry, 2) ) + table =3D xen_map_table(root); + for ( level =3D HYP_PT_ROOT_LEVEL; level < target; level++ ) { - int rc =3D create_xen_table(entry); - if ( rc < 0 ) { - printk("%s: L2 failed\n", __func__); - return rc; + rc =3D xen_pt_next_level(read_only, level, &table, offsets[level]); + if ( rc =3D=3D XEN_TABLE_MAP_FAILED ) + { + /* + * We are here because xen_pt_next_level has failed to map + * the intermediate page table (e.g the table does not exist + * and the pt is read-only). It is a valid case when + * removing a mapping as it may not exist in the page table. + * In this case, just ignore it. + */ + if ( flags & (_PAGE_PRESENT|_PAGE_POPULATE) ) + { + mm_printk("%s: Unable to map level %u\n", __func__, level); + rc =3D -ENOENT; + goto out; + } + else + { + rc =3D 0; + goto out; + } } + else if ( rc !=3D XEN_TABLE_NORMAL_PAGE ) + break; } =20 - BUG_ON(!lpae_is_valid(*entry)); + if ( level !=3D target ) + { + mm_printk("%s: Shattering superpage is not supported\n", __func__); + rc =3D -EOPNOTSUPP; + goto out; + } =20 - third =3D xen_map_table(lpae_get_mfn(*entry)); - entry =3D &third[third_table_offset(addr)]; + entry =3D table + offsets[level]; =20 rc =3D -EINVAL; if ( !xen_pt_check_entry(*entry, mfn, flags) ) @@ -1103,7 +1185,7 @@ static int xen_pt_update_entry(unsigned long addr, mf= n_t mfn, rc =3D 0; =20 out: - xen_unmap_table(third); + xen_unmap_table(table); =20 return rc; } @@ -1119,6 +1201,15 @@ static int xen_pt_update(unsigned long virt, unsigned long addr =3D virt, addr_end =3D addr + nr_mfns * PAGE_SIZE; =20 /* + * For arm32, page-tables are different on each CPUs. Yet, they share + * some common mappings. It is assumed that only common mappings + * will be modified with this function. + * + * XXX: Add a check. + */ + const mfn_t root =3D virt_to_mfn(THIS_CPU_PGTABLE); + + /* * The hardware was configured to forbid mapping both writeable and * executable. * When modifying/creating mapping (i.e _PAGE_PRESENT is set), @@ -1139,9 +1230,9 @@ static int xen_pt_update(unsigned long virt, =20 spin_lock(&xen_pt_lock); =20 - for( ; addr < addr_end; addr +=3D PAGE_SIZE ) + for ( ; addr < addr_end; addr +=3D PAGE_SIZE ) { - rc =3D xen_pt_update_entry(addr, mfn, flags); + rc =3D xen_pt_update_entry(root, addr, mfn, flags); if ( rc ) break; =20 --=20 2.11.0 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel