From patchwork Thu Jun 23 09:51:06 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Vrabel X-Patchwork-Id: 9194799 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 389466077D for ; Thu, 23 Jun 2016 09:53:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 24FDB283DF for ; Thu, 23 Jun 2016 09:53:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 19C2328442; Thu, 23 Jun 2016 09:53:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 6669B283DF for ; Thu, 23 Jun 2016 09:53:16 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bG1IE-0001NZ-DZ; Thu, 23 Jun 2016 09:51:26 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bG1ID-0001NM-4W for xen-devel@lists.xenproject.org; Thu, 23 Jun 2016 09:51:25 +0000 Received: from [85.158.139.211] by server-7.bemta-5.messagelabs.com id CC/94-10476-C11BB675; Thu, 23 Jun 2016 09:51:24 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrKLMWRWlGSWpSXmKPExsXitHRDpK70xux wgynrrC2+b5nM5MDocfjDFZYAxijWzLyk/IoE1oxvm4+xFExRqbizpLSBcZlcFyMnh4SAv8Ti 1YuYQGw2AR2Jx0tmsHcxcnCICKhI3N5rABJmFpjPKHH8hD+ILSwQJDFj01c2EJtFQFXi0JztY DavgJvE8b4mRoiRchLnj/9kBrGFgMZ8XLuKFaJGUOLkzCcsEDMlJA6+eMEMskpCgFvib7f9BE aeWUiqZiGpWsDItIpRvTi1qCy1SNdUL6koMz2jJDcxM0fX0MBULze1uDgxPTUnMalYLzk/dxM jMDgYgGAH45d+50OMkhxMSqK8bKuzw4X4kvJTKjMSizPii0pzUosPMcpwcChJ8P5dD5QTLEpN T61Iy8wBhilMWoKDR0mEN3gdUJq3uCAxtzgzHSJ1ilFRSpz3JEifAEgiozQPrg0WG5cYZaWEe RmBDhHiKUgtys0sQZV/xSjOwagkzHsPZApPZl4J3PRXQIuZgBbf7QdbXJKIkJJqYOSdEJzlsV ZJMTQ/cf62thmlxtbaLzOjlnVv3nls12eDqfOVT2oWV39xfhbcJt7wfV5XxnTeH0+0TOS2Wi7 YYmAc9zvU++APlc4LzP8+2XCkPO07fHU/u6lyYkUbzyavjRVK0xXkJa8u9a37smXavJmbfwoc 5lDLSlw4YWG13O3E337qs46ozlViKc5INNRiLipOBABJ2IfFiAIAAA== X-Env-Sender: prvs=97543d868=david.vrabel@citrix.com X-Msg-Ref: server-13.tower-206.messagelabs.com!1466675482!37159965!1 X-Originating-IP: [66.165.176.89] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 8.46; banners=-,-,- X-VirusChecked: Checked Received: (qmail 43505 invoked from network); 23 Jun 2016 09:51:23 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP; 23 Jun 2016 09:51:23 -0000 X-IronPort-AV: E=Sophos;i="5.26,515,1459814400"; d="scan'208";a="362286952" From: David Vrabel To: Date: Thu, 23 Jun 2016 10:51:06 +0100 Message-ID: <1466675466-7392-1-git-send-email-david.vrabel@citrix.com> X-Mailer: git-send-email 2.1.4 MIME-Version: 1.0 X-DLP: MIA1 Cc: Juergen Gross , Kevin Moraga , Boris Ostrovsky , David Vrabel Subject: [Xen-devel] [PATCHv3] x86/xen: avoid m2p lookup when setting early page table entries X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP When page tables entries are set using xen_set_pte_init() during early boot there is no page fault handler that could handle a fault when performing an M2P lookup. In 64 bit guests (usually dom0) early_ioremap() would fault in xen_set_pte_init() because an M2P lookup faults because the MFN is in MMIO space and not mapped in the M2P. This lookup is done to see if the PFN in in the range used for the initial page table pages, so that the PTE may be set as read-only. The M2P lookup can be avoided by moving the check (and clear of RW) earlier when the PFN is still available. Signed-off-by: David Vrabel Reviewed-by: Boris Ostrovsky --- Cc: Kevin Moraga v3: - fold mask_rw_pte()/mask_rw_pteval() into their callers. v2: - Remove __init annotation from xen_make_pte_init() since PV_CALLEE_SAVE_REGS_THUNK always puts the thunk in .text. - mask_rw_pte() -> mask_rw_pteval() for x86-64. --- arch/x86/xen/mmu.c | 76 +++++++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 41 deletions(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 478a2de..64d8f0b 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1551,41 +1551,6 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd) #endif } -#ifdef CONFIG_X86_32 -static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte) -{ - /* If there's an existing pte, then don't allow _PAGE_RW to be set */ - if (pte_val_ma(*ptep) & _PAGE_PRESENT) - pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) & - pte_val_ma(pte)); - - return pte; -} -#else /* CONFIG_X86_64 */ -static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte) -{ - unsigned long pfn; - - if (xen_feature(XENFEAT_writable_page_tables) || - xen_feature(XENFEAT_auto_translated_physmap) || - xen_start_info->mfn_list >= __START_KERNEL_map) - return pte; - - /* - * Pages belonging to the initial p2m list mapped outside the default - * address range must be mapped read-only. This region contains the - * page tables for mapping the p2m list, too, and page tables MUST be - * mapped read-only. - */ - pfn = pte_pfn(pte); - if (pfn >= xen_start_info->first_p2m_pfn && - pfn < xen_start_info->first_p2m_pfn + xen_start_info->nr_p2m_frames) - pte = __pte_ma(pte_val_ma(pte) & ~_PAGE_RW); - - return pte; -} -#endif /* CONFIG_X86_64 */ - /* * Init-time set_pte while constructing initial pagetables, which * doesn't allow RO page table pages to be remapped RW. @@ -1600,13 +1565,41 @@ static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte) * so always write the PTE directly and rely on Xen trapping and * emulating any updates as necessary. */ -static void __init xen_set_pte_init(pte_t *ptep, pte_t pte) +__visible pte_t xen_make_pte_init(pteval_t pte) { - if (pte_mfn(pte) != INVALID_P2M_ENTRY) - pte = mask_rw_pte(ptep, pte); - else - pte = __pte_ma(0); +#ifdef CONFIG_X86_64 + unsigned long pfn; + + /* + * Pages belonging to the initial p2m list mapped outside the default + * address range must be mapped read-only. This region contains the + * page tables for mapping the p2m list, too, and page tables MUST be + * mapped read-only. + */ + pfn = (pte & PTE_PFN_MASK) >> PAGE_SHIFT; + if (xen_start_info->mfn_list < __START_KERNEL_map && + pfn >= xen_start_info->first_p2m_pfn && + pfn < xen_start_info->first_p2m_pfn + xen_start_info->nr_p2m_frames) + pte &= ~_PAGE_RW; +#endif + pte = pte_pfn_to_mfn(pte); + if ((pte & PTE_PFN_MASK) >> PAGE_SHIFT == INVALID_P2M_ENTRY) + pte = 0; + + return native_make_pte(pte); +} +PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_init); + +static void __init xen_set_pte_init(pte_t *ptep, pte_t pte) +{ +#ifdef CONFIG_X86_32 + /* If there's an existing pte, then don't allow _PAGE_RW to be set */ + if (pte_mfn(pte) != INVALID_P2M_ENTRY + && pte_val_ma(*ptep) & _PAGE_PRESENT) + pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) & + pte_val_ma(pte)); +#endif native_set_pte(ptep, pte); } @@ -2407,6 +2400,7 @@ static void __init xen_post_allocator_init(void) pv_mmu_ops.alloc_pud = xen_alloc_pud; pv_mmu_ops.release_pud = xen_release_pud; #endif + pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte); #ifdef CONFIG_X86_64 pv_mmu_ops.write_cr3 = &xen_write_cr3; @@ -2455,7 +2449,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = { .pte_val = PV_CALLEE_SAVE(xen_pte_val), .pgd_val = PV_CALLEE_SAVE(xen_pgd_val), - .make_pte = PV_CALLEE_SAVE(xen_make_pte), + .make_pte = PV_CALLEE_SAVE(xen_make_pte_init), .make_pgd = PV_CALLEE_SAVE(xen_make_pgd), #ifdef CONFIG_X86_PAE