From patchwork Wed Oct 28 09:22:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 11862631 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 924CD92C for ; Wed, 28 Oct 2020 09:22:59 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4F08D24680 for ; Wed, 28 Oct 2020 09:22:59 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="q2y7pH7q" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4F08D24680 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from list by lists.xenproject.org with outflank-mailman.13419.34034 (Exim 4.92) (envelope-from ) id 1kXheh-0005BP-CC; Wed, 28 Oct 2020 09:22:07 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 13419.34034; Wed, 28 Oct 2020 09:22:07 +0000 X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1kXheh-0005BI-99; Wed, 28 Oct 2020 09:22:07 +0000 Received: by outflank-mailman (input) for mailman id 13419; Wed, 28 Oct 2020 09:22:05 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1kXhef-0005BD-Qc for xen-devel@lists.xenproject.org; Wed, 28 Oct 2020 09:22:05 +0000 Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id c45dc1a0-7852-4b33-b0f6-489983d15d97; Wed, 28 Oct 2020 09:22:04 +0000 (UTC) Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id EC929AE55; Wed, 28 Oct 2020 09:22:03 +0000 (UTC) Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1kXhef-0005BD-Qc for xen-devel@lists.xenproject.org; Wed, 28 Oct 2020 09:22:05 +0000 X-Inumbo-ID: c45dc1a0-7852-4b33-b0f6-489983d15d97 Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id c45dc1a0-7852-4b33-b0f6-489983d15d97; Wed, 28 Oct 2020 09:22:04 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1603876924; 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=yu6nsT1gjKKWROl7+xNzleE21oVo7PP0tppH9efwgOc=; b=q2y7pH7q4P+xg0XBXJX+RfzzUHGlmVIs65+CrckFJFVZukH7KW5gyhUwq/oK1GKLCYE6p7 +hbU/347P9GfihhNXl3XUT/t9m4ULw0mpRUMao4GmKDnuaP2lNPRusTXJ1ba/r9a8o83PF lw6t+nBhpak8ZNmlxf8ZcefaTPOd93k= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id EC929AE55; Wed, 28 Oct 2020 09:22:03 +0000 (UTC) Subject: [PATCH 1/5] x86/p2m: paging_write_p2m_entry() is a private function From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Wei Liu , =?utf-8?q?Roger_Pau_Monn=C3=A9?= , George Dunlap , Tim Deegan References: <29d30de1-2a8d-aee2-d3c3-331758766fc9@suse.com> Message-ID: <1fab241b-3969-9ce5-2388-bcdbe3be6079@suse.com> Date: Wed, 28 Oct 2020 10:22:04 +0100 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.4.0 MIME-Version: 1.0 In-Reply-To: <29d30de1-2a8d-aee2-d3c3-331758766fc9@suse.com> Content-Language: en-US As it gets installed by p2m_pt_init(), it doesn't need to live in paging.c. The function working in terms of l1_pgentry_t even further indicates its non-paging-generic nature. Move it and drop its paging_ prefix, not adding any new one now that it's static. This then also makes more obvious that in the EPT case we wouldn't risk mistakenly calling through the NULL hook pointer. Signed-off-by: Jan Beulich Acked-by: Roger Pau Monné --- a/xen/arch/x86/mm/p2m-pt.c +++ b/xen/arch/x86/mm/p2m-pt.c @@ -108,6 +108,31 @@ static unsigned long p2m_type_to_flags(c } } +/* + * Atomically write a P2M entry and update the paging-assistance state + * appropriately. + * Arguments: the domain in question, the GFN whose mapping is being updated, + * a pointer to the entry to be written, the MFN in which the entry resides, + * the new contents of the entry, and the level in the p2m tree at which + * we are writing. + */ +static int write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, + l1_pgentry_t *p, l1_pgentry_t new, + unsigned int level) +{ + struct domain *d = p2m->domain; + struct vcpu *v = current; + int rc = 0; + + if ( v->domain != d ) + v = d->vcpu ? d->vcpu[0] : NULL; + if ( likely(v && paging_mode_enabled(d) && paging_get_hostmode(v)) ) + rc = paging_get_hostmode(v)->write_p2m_entry(p2m, gfn, p, new, level); + else + safe_write_pte(p, new); + + return rc; +} // Find the next level's P2M entry, checking for out-of-range gfn's... // Returns NULL on error. @@ -594,7 +619,7 @@ p2m_pt_set_entry(struct p2m_domain *p2m, entry_content.l1 = l3e_content.l3; rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 3); - /* NB: paging_write_p2m_entry() handles tlb flushes properly */ + /* NB: write_p2m_entry() handles tlb flushes properly */ if ( rc ) goto out; } @@ -631,7 +656,7 @@ p2m_pt_set_entry(struct p2m_domain *p2m, /* level 1 entry */ rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 1); - /* NB: paging_write_p2m_entry() handles tlb flushes properly */ + /* NB: write_p2m_entry() handles tlb flushes properly */ if ( rc ) goto out; } @@ -666,7 +691,7 @@ p2m_pt_set_entry(struct p2m_domain *p2m, entry_content.l1 = l2e_content.l2; rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 2); - /* NB: paging_write_p2m_entry() handles tlb flushes properly */ + /* NB: write_p2m_entry() handles tlb flushes properly */ if ( rc ) goto out; } @@ -1107,7 +1132,7 @@ void p2m_pt_init(struct p2m_domain *p2m) p2m->recalc = do_recalc; p2m->change_entry_type_global = p2m_pt_change_entry_type_global; p2m->change_entry_type_range = p2m_pt_change_entry_type_range; - p2m->write_p2m_entry = paging_write_p2m_entry; + p2m->write_p2m_entry = write_p2m_entry; #if P2M_AUDIT p2m->audit_p2m = p2m_pt_audit_p2m; #else --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -941,27 +941,7 @@ void paging_update_nestedmode(struct vcp v->arch.paging.nestedmode = NULL; hvm_asid_flush_vcpu(v); } -#endif -int paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, - l1_pgentry_t *p, l1_pgentry_t new, - unsigned int level) -{ - struct domain *d = p2m->domain; - struct vcpu *v = current; - int rc = 0; - - if ( v->domain != d ) - v = d->vcpu ? d->vcpu[0] : NULL; - if ( likely(v && paging_mode_enabled(d) && paging_get_hostmode(v) != NULL) ) - rc = paging_get_hostmode(v)->write_p2m_entry(p2m, gfn, p, new, level); - else - safe_write_pte(p, new); - - return rc; -} - -#ifdef CONFIG_HVM int __init paging_set_allocation(struct domain *d, unsigned int pages, bool *preempted) { --- a/xen/include/asm-x86/paging.h +++ b/xen/include/asm-x86/paging.h @@ -371,18 +371,6 @@ static inline void safe_write_pte(l1_pge *p = new; } -/* Atomically write a P2M entry and update the paging-assistance state - * appropriately. - * Arguments: the domain in question, the GFN whose mapping is being updated, - * a pointer to the entry to be written, the MFN in which the entry resides, - * the new contents of the entry, and the level in the p2m tree at which - * we are writing. */ -struct p2m_domain; - -int paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, - l1_pgentry_t *p, l1_pgentry_t new, - unsigned int level); - /* * Called from the guest to indicate that the a process is being * torn down and its pagetables will soon be discarded. From patchwork Wed Oct 28 09:22:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 11862633 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D492C6A2 for ; Wed, 28 Oct 2020 09:23:55 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8158C24680 for ; Wed, 28 Oct 2020 09:23:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="bJnA87lK" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8158C24680 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from list by lists.xenproject.org with outflank-mailman.13423.34045 (Exim 4.92) (envelope-from ) id 1kXhfZ-0005KO-OE; Wed, 28 Oct 2020 09:23:01 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 13423.34045; Wed, 28 Oct 2020 09:23:01 +0000 X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1kXhfZ-0005KH-LI; Wed, 28 Oct 2020 09:23:01 +0000 Received: by outflank-mailman (input) for mailman id 13423; Wed, 28 Oct 2020 09:23:00 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1kXhfX-0005K5-V3 for xen-devel@lists.xenproject.org; Wed, 28 Oct 2020 09:22:59 +0000 Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 751d2f3c-6ebd-40cb-87eb-2a65ecf7f8db; Wed, 28 Oct 2020 09:22:58 +0000 (UTC) Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id D7F21AF2D; Wed, 28 Oct 2020 09:22:57 +0000 (UTC) Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1kXhfX-0005K5-V3 for xen-devel@lists.xenproject.org; Wed, 28 Oct 2020 09:22:59 +0000 X-Inumbo-ID: 751d2f3c-6ebd-40cb-87eb-2a65ecf7f8db Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 751d2f3c-6ebd-40cb-87eb-2a65ecf7f8db; Wed, 28 Oct 2020 09:22:58 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1603876977; 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=NCgW+bACNDPGH3cgrnwMxwZu4xm7gdBOFvqRHOsKIW4=; b=bJnA87lKFKTAaHIFeVGKAu6cHQ29VmLbF3rgVk1h6reUbJInqMPWBVEKkPKxc2HHGr4pih 8UZyOR5Td/DsyFgGiIzAf3VH0RmLArqgLQHtF7tcxReUagI1IhdcdldHOMCYlYhwEznxBH B27B690Rej5Ulr5g/yXoHjOMh6Btu5c= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id D7F21AF2D; Wed, 28 Oct 2020 09:22:57 +0000 (UTC) Subject: [PATCH 2/5] x86/p2m: collapse the two ->write_p2m_entry() hooks From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Wei Liu , =?utf-8?q?Roger_Pau_Monn=C3=A9?= , George Dunlap , Tim Deegan References: <29d30de1-2a8d-aee2-d3c3-331758766fc9@suse.com> Message-ID: Date: Wed, 28 Oct 2020 10:22:58 +0100 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.4.0 MIME-Version: 1.0 In-Reply-To: <29d30de1-2a8d-aee2-d3c3-331758766fc9@suse.com> Content-Language: en-US The struct paging_mode instances get set to the same functions regardless of mode by both HAP and shadow code, hence there's no point having this hook there. The hook also doesn't need moving elsewhere - we can directly use struct p2m_domain's. This merely requires (from a strictly formal pov; in practice this may not even be needed) making sure we don't end up using safe_write_pte() for nested P2Ms. Signed-off-by: Jan Beulich Acked-by: Tim Deegan Acked-by: Roger Pau Monné --- Like for the possibly unnecessary p2m_is_nestedp2m() I'm not really sure the paging_get_hostmode() check there is still needed either. But I didn't want to alter more aspects than necessary here. Of course with the p2m_is_nestedp2m() check there and with all three of {hap,nestedp2m,shadow}_write_p2m_entry() now globally accessible, it's certainly an option to do away with the indirect call there altogether. In fact we may even be able to go further and fold the three functions: They're relatively similar, and this would "seamlessly" address the apparent bug of nestedp2m_write_p2m_entry() not making use of p2m_entry_modify(). --- a/xen/arch/x86/mm/hap/hap.c +++ b/xen/arch/x86/mm/hap/hap.c @@ -823,6 +823,11 @@ hap_write_p2m_entry(struct p2m_domain *p return 0; } +void hap_p2m_init(struct p2m_domain *p2m) +{ + p2m->write_p2m_entry = hap_write_p2m_entry; +} + static unsigned long hap_gva_to_gfn_real_mode( struct vcpu *v, struct p2m_domain *p2m, unsigned long gva, uint32_t *pfec) { @@ -846,7 +851,6 @@ static const struct paging_mode hap_pagi .p2m_ga_to_gfn = hap_p2m_ga_to_gfn_real_mode, .update_cr3 = hap_update_cr3, .update_paging_modes = hap_update_paging_modes, - .write_p2m_entry = hap_write_p2m_entry, .flush_tlb = flush_tlb, .guest_levels = 1 }; @@ -858,7 +862,6 @@ static const struct paging_mode hap_pagi .p2m_ga_to_gfn = hap_p2m_ga_to_gfn_2_levels, .update_cr3 = hap_update_cr3, .update_paging_modes = hap_update_paging_modes, - .write_p2m_entry = hap_write_p2m_entry, .flush_tlb = flush_tlb, .guest_levels = 2 }; @@ -870,7 +873,6 @@ static const struct paging_mode hap_pagi .p2m_ga_to_gfn = hap_p2m_ga_to_gfn_3_levels, .update_cr3 = hap_update_cr3, .update_paging_modes = hap_update_paging_modes, - .write_p2m_entry = hap_write_p2m_entry, .flush_tlb = flush_tlb, .guest_levels = 3 }; @@ -882,7 +884,6 @@ static const struct paging_mode hap_pagi .p2m_ga_to_gfn = hap_p2m_ga_to_gfn_4_levels, .update_cr3 = hap_update_cr3, .update_paging_modes = hap_update_paging_modes, - .write_p2m_entry = hap_write_p2m_entry, .flush_tlb = flush_tlb, .guest_levels = 4 }; --- a/xen/arch/x86/mm/p2m-pt.c +++ b/xen/arch/x86/mm/p2m-pt.c @@ -126,8 +126,9 @@ static int write_p2m_entry(struct p2m_do if ( v->domain != d ) v = d->vcpu ? d->vcpu[0] : NULL; - if ( likely(v && paging_mode_enabled(d) && paging_get_hostmode(v)) ) - rc = paging_get_hostmode(v)->write_p2m_entry(p2m, gfn, p, new, level); + if ( likely(v && paging_mode_enabled(d) && paging_get_hostmode(v)) || + p2m_is_nestedp2m(p2m) ) + rc = p2m->write_p2m_entry(p2m, gfn, p, new, level); else safe_write_pte(p, new); @@ -209,7 +210,7 @@ p2m_next_level(struct p2m_domain *p2m, v new_entry = l1e_from_mfn(mfn, P2M_BASE_FLAGS | _PAGE_RW); - rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level + 1); + rc = write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level + 1); if ( rc ) goto error; } @@ -251,7 +252,7 @@ p2m_next_level(struct p2m_domain *p2m, v { new_entry = l1e_from_pfn(pfn | (i << ((level - 1) * PAGETABLE_ORDER)), flags); - rc = p2m->write_p2m_entry(p2m, gfn, l1_entry + i, new_entry, level); + rc = write_p2m_entry(p2m, gfn, l1_entry + i, new_entry, level); if ( rc ) { unmap_domain_page(l1_entry); @@ -262,8 +263,7 @@ p2m_next_level(struct p2m_domain *p2m, v unmap_domain_page(l1_entry); new_entry = l1e_from_mfn(mfn, P2M_BASE_FLAGS | _PAGE_RW); - rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, - level + 1); + rc = write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level + 1); if ( rc ) goto error; } @@ -335,7 +335,7 @@ static int p2m_pt_set_recalc_range(struc if ( (l1e_get_flags(e) & _PAGE_PRESENT) && !needs_recalc(l1, e) ) { set_recalc(l1, e); - err = p2m->write_p2m_entry(p2m, first_gfn, pent, e, level); + err = write_p2m_entry(p2m, first_gfn, pent, e, level); if ( err ) { ASSERT_UNREACHABLE(); @@ -412,8 +412,8 @@ static int do_recalc(struct p2m_domain * !needs_recalc(l1, ent) ) { set_recalc(l1, ent); - err = p2m->write_p2m_entry(p2m, gfn - remainder, &ptab[i], - ent, level); + err = write_p2m_entry(p2m, gfn - remainder, &ptab[i], ent, + level); if ( err ) { ASSERT_UNREACHABLE(); @@ -426,7 +426,7 @@ static int do_recalc(struct p2m_domain * if ( !err ) { clear_recalc(l1, e); - err = p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1); + err = write_p2m_entry(p2m, gfn, pent, e, level + 1); ASSERT(!err); recalc_done = true; @@ -474,7 +474,7 @@ static int do_recalc(struct p2m_domain * } else clear_recalc(l1, e); - err = p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1); + err = write_p2m_entry(p2m, gfn, pent, e, level + 1); ASSERT(!err); recalc_done = true; @@ -618,7 +618,7 @@ p2m_pt_set_entry(struct p2m_domain *p2m, : l3e_empty(); entry_content.l1 = l3e_content.l3; - rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 3); + rc = write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 3); /* NB: write_p2m_entry() handles tlb flushes properly */ if ( rc ) goto out; @@ -655,7 +655,7 @@ p2m_pt_set_entry(struct p2m_domain *p2m, entry_content = l1e_empty(); /* level 1 entry */ - rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 1); + rc = write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 1); /* NB: write_p2m_entry() handles tlb flushes properly */ if ( rc ) goto out; @@ -690,7 +690,7 @@ p2m_pt_set_entry(struct p2m_domain *p2m, : l2e_empty(); entry_content.l1 = l2e_content.l2; - rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 2); + rc = write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 2); /* NB: write_p2m_entry() handles tlb flushes properly */ if ( rc ) goto out; @@ -914,7 +914,7 @@ static void p2m_pt_change_entry_type_glo int rc; set_recalc(l1, e); - rc = p2m->write_p2m_entry(p2m, gfn, &tab[i], e, 4); + rc = write_p2m_entry(p2m, gfn, &tab[i], e, 4); if ( rc ) { ASSERT_UNREACHABLE(); @@ -1132,7 +1132,13 @@ void p2m_pt_init(struct p2m_domain *p2m) p2m->recalc = do_recalc; p2m->change_entry_type_global = p2m_pt_change_entry_type_global; p2m->change_entry_type_range = p2m_pt_change_entry_type_range; - p2m->write_p2m_entry = write_p2m_entry; + + /* Still too early to use paging_mode_hap(). */ + if ( hap_enabled(p2m->domain) ) + hap_p2m_init(p2m); + else if ( IS_ENABLED(CONFIG_SHADOW_PAGING) ) + shadow_p2m_init(p2m); + #if P2M_AUDIT p2m->audit_p2m = p2m_pt_audit_p2m; #else --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -3137,7 +3137,7 @@ static void sh_unshadow_for_p2m_change(s } } -int +static int shadow_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, l1_pgentry_t *p, l1_pgentry_t new, unsigned int level) @@ -3183,6 +3183,11 @@ shadow_write_p2m_entry(struct p2m_domain return 0; } +void shadow_p2m_init(struct p2m_domain *p2m) +{ + p2m->write_p2m_entry = shadow_write_p2m_entry; +} + /**************************************************************************/ /* Log-dirty mode support */ --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -4792,7 +4792,6 @@ const struct paging_mode sh_paging_mode .gva_to_gfn = sh_gva_to_gfn, .update_cr3 = sh_update_cr3, .update_paging_modes = shadow_update_paging_modes, - .write_p2m_entry = shadow_write_p2m_entry, .flush_tlb = shadow_flush_tlb, .guest_levels = GUEST_PAGING_LEVELS, .shadow.detach_old_tables = sh_detach_old_tables, --- a/xen/arch/x86/mm/shadow/none.c +++ b/xen/arch/x86/mm/shadow/none.c @@ -60,21 +60,12 @@ static void _update_paging_modes(struct ASSERT_UNREACHABLE(); } -static int _write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, - l1_pgentry_t *p, l1_pgentry_t new, - unsigned int level) -{ - ASSERT_UNREACHABLE(); - return -EOPNOTSUPP; -} - static const struct paging_mode sh_paging_none = { .page_fault = _page_fault, .invlpg = _invlpg, .gva_to_gfn = _gva_to_gfn, .update_cr3 = _update_cr3, .update_paging_modes = _update_paging_modes, - .write_p2m_entry = _write_p2m_entry, }; void shadow_vcpu_init(struct vcpu *v) --- a/xen/arch/x86/mm/shadow/private.h +++ b/xen/arch/x86/mm/shadow/private.h @@ -390,11 +390,6 @@ static inline int sh_remove_write_access } #endif -/* Functions that atomically write PT/P2M entries and update state */ -int shadow_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, - l1_pgentry_t *p, l1_pgentry_t new, - unsigned int level); - /* Functions that atomically write PV guest PT entries */ void sh_write_guest_entry(struct vcpu *v, intpte_t *p, intpte_t new, mfn_t gmfn); --- a/xen/include/asm-x86/p2m.h +++ b/xen/include/asm-x86/p2m.h @@ -836,6 +836,9 @@ void p2m_flush_nestedp2m(struct domain * /* Flushes the np2m specified by np2m_base (if it exists) */ void np2m_flush_base(struct vcpu *v, unsigned long np2m_base); +void hap_p2m_init(struct p2m_domain *p2m); +void shadow_p2m_init(struct p2m_domain *p2m); + int nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, l1_pgentry_t *p, l1_pgentry_t new, unsigned int level); --- a/xen/include/asm-x86/paging.h +++ b/xen/include/asm-x86/paging.h @@ -141,10 +141,6 @@ struct paging_mode { void (*update_cr3 )(struct vcpu *v, int do_locking, bool noflush); void (*update_paging_modes )(struct vcpu *v); - int (*write_p2m_entry )(struct p2m_domain *p2m, - unsigned long gfn, - l1_pgentry_t *p, l1_pgentry_t new, - unsigned int level); bool (*flush_tlb )(bool (*flush_vcpu)(void *ctxt, struct vcpu *v), void *ctxt); From patchwork Wed Oct 28 09:23:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 11862635 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8346492C for ; Wed, 28 Oct 2020 09:24:38 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4050E24680 for ; Wed, 28 Oct 2020 09:24:38 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="d1ADUAQy" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4050E24680 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from list by lists.xenproject.org with outflank-mailman.13426.34058 (Exim 4.92) (envelope-from ) id 1kXhgI-0005SF-2J; Wed, 28 Oct 2020 09:23:46 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 13426.34058; Wed, 28 Oct 2020 09:23:46 +0000 X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1kXhgH-0005S7-Uo; Wed, 28 Oct 2020 09:23:45 +0000 Received: by outflank-mailman (input) for mailman id 13426; Wed, 28 Oct 2020 09:23:44 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1kXhgG-0005Ry-Jg for xen-devel@lists.xenproject.org; Wed, 28 Oct 2020 09:23:44 +0000 Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 51916575-9bb7-4837-a3e0-4485b7de8df7; Wed, 28 Oct 2020 09:23:42 +0000 (UTC) Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 8D7D9AE55; Wed, 28 Oct 2020 09:23:41 +0000 (UTC) Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1kXhgG-0005Ry-Jg for xen-devel@lists.xenproject.org; Wed, 28 Oct 2020 09:23:44 +0000 X-Inumbo-ID: 51916575-9bb7-4837-a3e0-4485b7de8df7 Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 51916575-9bb7-4837-a3e0-4485b7de8df7; Wed, 28 Oct 2020 09:23:42 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1603877021; 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=Ldwy/42iIo0sCTIc18oLAOIhkEM9oMjLPSiF7ItDO6A=; b=d1ADUAQyyFUI5XPvjZrMvxa7fbW5nx6uYZ2x76+G4OxQVF6a/8D3953Der42YgiufWgwaq pU0gZg+yCkDQoGRT/GV7jDbhARuDfrvBelfA2iO2aEMUrv31G0NowcZvsRrb5+c6yx2bvQ j77ku8ZK5XWVCUFY5OpYz89d0hzj+co= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 8D7D9AE55; Wed, 28 Oct 2020 09:23:41 +0000 (UTC) Subject: [PATCH 3/5] x86/p2m: suppress audit_p2m hook when possible From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Wei Liu , =?utf-8?q?Roger_Pau_Monn=C3=A9?= , George Dunlap References: <29d30de1-2a8d-aee2-d3c3-331758766fc9@suse.com> Message-ID: <722cf75e-da6a-49c5-472a-898796c9030e@suse.com> Date: Wed, 28 Oct 2020 10:23:42 +0100 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.4.0 MIME-Version: 1.0 In-Reply-To: <29d30de1-2a8d-aee2-d3c3-331758766fc9@suse.com> Content-Language: en-US When P2M_AUDIT is false, it's unused, so instead of having a dangling NULL pointer sit there, omit the field altogether. Instead of adding "#if P2M_AUDIT && defined(CONFIG_HVM)" in even more places, fold the latter part right into the definition of P2M_AUDIT. Signed-off-by: Jan Beulich Acked-by: Roger Pau Monné --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -1012,7 +1012,7 @@ long arch_do_domctl( break; #endif -#if P2M_AUDIT && defined(CONFIG_HVM) +#if P2M_AUDIT case XEN_DOMCTL_audit_p2m: if ( d == currd ) ret = -EPERM; --- a/xen/arch/x86/mm/p2m-ept.c +++ b/xen/arch/x86/mm/p2m-ept.c @@ -1260,7 +1260,9 @@ int ept_p2m_init(struct p2m_domain *p2m) p2m->change_entry_type_global = ept_change_entry_type_global; p2m->change_entry_type_range = ept_change_entry_type_range; p2m->memory_type_changed = ept_memory_type_changed; +#if P2M_AUDIT p2m->audit_p2m = NULL; +#endif p2m->tlb_flush = ept_tlb_flush; /* Set the memory type used when accessing EPT paging structures. */ --- a/xen/arch/x86/mm/p2m-pt.c +++ b/xen/arch/x86/mm/p2m-pt.c @@ -971,8 +971,8 @@ static int p2m_pt_change_entry_type_rang return err; } -#if P2M_AUDIT && defined(CONFIG_HVM) -long p2m_pt_audit_p2m(struct p2m_domain *p2m) +#if P2M_AUDIT +static long p2m_pt_audit_p2m(struct p2m_domain *p2m) { unsigned long entry_count = 0, pmbad = 0; unsigned long mfn, gfn, m2pfn; @@ -1120,8 +1120,6 @@ long p2m_pt_audit_p2m(struct p2m_domain return pmbad; } -#else -# define p2m_pt_audit_p2m NULL #endif /* P2M_AUDIT */ /* Set up the p2m function pointers for pagetable format */ @@ -1141,8 +1139,6 @@ void p2m_pt_init(struct p2m_domain *p2m) #if P2M_AUDIT p2m->audit_p2m = p2m_pt_audit_p2m; -#else - p2m->audit_p2m = NULL; #endif } --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -2435,7 +2435,7 @@ int p2m_altp2m_propagate_change(struct d /*** Audit ***/ -#if P2M_AUDIT && defined(CONFIG_HVM) +#if P2M_AUDIT void audit_p2m(struct domain *d, uint64_t *orphans, uint64_t *m2p_bad, --- a/xen/include/asm-x86/p2m.h +++ b/xen/include/asm-x86/p2m.h @@ -31,6 +31,14 @@ #include #include /* for pagetable_t */ +/* Debugging and auditing of the P2M code? */ +#ifndef NDEBUG +#define P2M_AUDIT defined(CONFIG_HVM) +#else +#define P2M_AUDIT 0 +#endif +#define P2M_DEBUGGING 0 + extern bool_t opt_hap_1gb, opt_hap_2mb; /* @@ -268,7 +276,9 @@ struct p2m_domain { int (*write_p2m_entry)(struct p2m_domain *p2m, unsigned long gfn, l1_pgentry_t *p, l1_pgentry_t new, unsigned int level); +#if P2M_AUDIT long (*audit_p2m)(struct p2m_domain *p2m); +#endif /* * P2M updates may require TLBs to be flushed (invalidated). @@ -758,14 +768,6 @@ extern void p2m_pt_init(struct p2m_domai void *map_domain_gfn(struct p2m_domain *p2m, gfn_t gfn, mfn_t *mfn, p2m_query_t q, uint32_t *pfec); -/* Debugging and auditing of the P2M code? */ -#ifndef NDEBUG -#define P2M_AUDIT 1 -#else -#define P2M_AUDIT 0 -#endif -#define P2M_DEBUGGING 0 - #if P2M_AUDIT extern void audit_p2m(struct domain *d, uint64_t *orphans, From patchwork Wed Oct 28 09:24:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 11862639 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EFEEC92C for ; Wed, 28 Oct 2020 09:25:24 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B2F0C24680 for ; Wed, 28 Oct 2020 09:25:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="VJI6vy9R" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B2F0C24680 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from list by lists.xenproject.org with outflank-mailman.13431.34069 (Exim 4.92) (envelope-from ) id 1kXhgk-0005Z6-BI; Wed, 28 Oct 2020 09:24:14 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 13431.34069; Wed, 28 Oct 2020 09:24:14 +0000 X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1kXhgk-0005Yz-8I; Wed, 28 Oct 2020 09:24:14 +0000 Received: by outflank-mailman (input) for mailman id 13431; Wed, 28 Oct 2020 09:24:13 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1kXhgj-0005Yr-IG for xen-devel@lists.xenproject.org; Wed, 28 Oct 2020 09:24:13 +0000 Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id ca21e3f6-7e57-4e2c-be35-2f85bffc0e51; Wed, 28 Oct 2020 09:24:12 +0000 (UTC) Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 14286ACAC; Wed, 28 Oct 2020 09:24:12 +0000 (UTC) Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1kXhgj-0005Yr-IG for xen-devel@lists.xenproject.org; Wed, 28 Oct 2020 09:24:13 +0000 X-Inumbo-ID: ca21e3f6-7e57-4e2c-be35-2f85bffc0e51 Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id ca21e3f6-7e57-4e2c-be35-2f85bffc0e51; Wed, 28 Oct 2020 09:24:12 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1603877052; 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=JtLLY79rVz1/b+gt5Ib9A6igOOIy5NEZdkH5oVbCQnk=; b=VJI6vy9R90Vs2E3wVekuCxGJTGtQbMA4OcA0MkysEL29mIv9ddl22Dg2FTzRuu9F7+yyZf YZXwFWeCwK6agSPEID1Bc/CPdV4b0T3p8fvmZN/JucbKeOGA2IhHk3RlzULuld3IebIm4u DDcocneMpPBPVgjW78gYTUevI12lO4Q= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 14286ACAC; Wed, 28 Oct 2020 09:24:12 +0000 (UTC) Subject: [PATCH 4/5] x86/HAP: move nested-P2M flush calculations out of locked region From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Wei Liu , =?utf-8?q?Roger_Pau_Monn=C3=A9?= , George Dunlap References: <29d30de1-2a8d-aee2-d3c3-331758766fc9@suse.com> Message-ID: <551dc0a2-f5ef-a646-26eb-8a67ae428745@suse.com> Date: Wed, 28 Oct 2020 10:24:12 +0100 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.4.0 MIME-Version: 1.0 In-Reply-To: <29d30de1-2a8d-aee2-d3c3-331758766fc9@suse.com> Content-Language: en-US By latching the old MFN into a local variable, these calculations don't depend on anything but local variables anymore. Hence the point in time when they get performed doesn't matter anymore, so they can be moved past the locked region. Signed-off-by: Jan Beulich Acked-by: Roger Pau Monné --- a/xen/arch/x86/mm/hap/hap.c +++ b/xen/arch/x86/mm/hap/hap.c @@ -780,7 +780,7 @@ hap_write_p2m_entry(struct p2m_domain *p { struct domain *d = p2m->domain; uint32_t old_flags; - bool_t flush_nestedp2m = 0; + mfn_t omfn; int rc; /* We know always use the host p2m here, regardless if the vcpu @@ -790,21 +790,11 @@ hap_write_p2m_entry(struct p2m_domain *p paging_lock(d); old_flags = l1e_get_flags(*p); - - if ( nestedhvm_enabled(d) && (old_flags & _PAGE_PRESENT) - && !p2m_get_hostp2m(d)->defer_nested_flush ) { - /* We are replacing a valid entry so we need to flush nested p2ms, - * unless the only change is an increase in access rights. */ - mfn_t omfn = l1e_get_mfn(*p); - mfn_t nmfn = l1e_get_mfn(new); - - flush_nestedp2m = !(mfn_eq(omfn, nmfn) - && perms_strictly_increased(old_flags, l1e_get_flags(new)) ); - } + omfn = l1e_get_mfn(*p); rc = p2m_entry_modify(p2m, p2m_flags_to_type(l1e_get_flags(new)), p2m_flags_to_type(old_flags), l1e_get_mfn(new), - l1e_get_mfn(*p), level); + omfn, level); if ( rc ) { paging_unlock(d); @@ -817,7 +807,14 @@ hap_write_p2m_entry(struct p2m_domain *p paging_unlock(d); - if ( flush_nestedp2m ) + if ( nestedhvm_enabled(d) && (old_flags & _PAGE_PRESENT) && + !p2m_get_hostp2m(d)->defer_nested_flush && + /* + * We are replacing a valid entry so we need to flush nested p2ms, + * unless the only change is an increase in access rights. + */ + (!mfn_eq(omfn, l1e_get_mfn(new)) || + !perms_strictly_increased(old_flags, l1e_get_flags(new))) ) p2m_flush_nestedp2m(d); return 0; From patchwork Wed Oct 28 09:24:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 11862637 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5FDEF6A2 for ; Wed, 28 Oct 2020 09:25:18 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0E21424680 for ; Wed, 28 Oct 2020 09:25:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="IaRkl9wN" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0E21424680 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from list by lists.xenproject.org with outflank-mailman.13435.34082 (Exim 4.92) (envelope-from ) id 1kXhhQ-0005gz-Mb; Wed, 28 Oct 2020 09:24:56 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 13435.34082; Wed, 28 Oct 2020 09:24:56 +0000 X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1kXhhQ-0005gs-JF; Wed, 28 Oct 2020 09:24:56 +0000 Received: by outflank-mailman (input) for mailman id 13435; Wed, 28 Oct 2020 09:24:56 +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.92) (envelope-from ) id 1kXhhP-0005gl-UQ for xen-devel@lists.xenproject.org; Wed, 28 Oct 2020 09:24:55 +0000 Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 7387b699-f4a1-4898-bf58-bea01d086430; Wed, 28 Oct 2020 09:24:53 +0000 (UTC) Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id D76F5AD1E; Wed, 28 Oct 2020 09:24:52 +0000 (UTC) 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.92) (envelope-from ) id 1kXhhP-0005gl-UQ for xen-devel@lists.xenproject.org; Wed, 28 Oct 2020 09:24:55 +0000 X-Inumbo-ID: 7387b699-f4a1-4898-bf58-bea01d086430 Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 7387b699-f4a1-4898-bf58-bea01d086430; Wed, 28 Oct 2020 09:24:53 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1603877092; 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=BDnAoknm+d841ow9/Slk5qnPpHUKxVRIWzU0TPE9W4Q=; b=IaRkl9wNnRkAYR4tHYkztpaya1S+G4WqI1ofPVXEweLaJHLizWLBP6alUy/hXF9q8YaIW4 1bVoFRXzw9WjWgnDGPmRESha8NKmfKLb/wfvunYDHj5k26YTos9zGLIif3KmGJPbbsBvrr FDqdTRFs5ZRo3AYDeZRPdQbC713JjNQ= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id D76F5AD1E; Wed, 28 Oct 2020 09:24:52 +0000 (UTC) Subject: [PATCH 5/5] x86/p2m: split write_p2m_entry() hook From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Wei Liu , =?utf-8?q?Roger_Pau_Monn=C3=A9?= , George Dunlap , Tim Deegan References: <29d30de1-2a8d-aee2-d3c3-331758766fc9@suse.com> Message-ID: <7b2b7cc9-8828-41bd-7949-764161bbe7ff@suse.com> Date: Wed, 28 Oct 2020 10:24:53 +0100 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.4.0 MIME-Version: 1.0 In-Reply-To: <29d30de1-2a8d-aee2-d3c3-331758766fc9@suse.com> Content-Language: en-US Fair parts of the present handlers are identical; in fact nestedp2m_write_p2m_entry() lacks a call to p2m_entry_modify(). Move common parts right into write_p2m_entry(), splitting the hooks into a "pre" one (needed just by shadow code) and a "post" one. For the common parts moved I think that the p2m_flush_nestedp2m() is, at least from an abstract perspective, also applicable in the shadow case. Hence it doesn't get a 3rd hook put in place. The initial comment that was in hap_write_p2m_entry() gets dropped: Its placement was bogus, and looking back the the commit introducing it (dd6de3ab9985 "Implement Nested-on-Nested") I can't see either what use of a p2m it was meant to be associated with. Signed-off-by: Jan Beulich Acked-by: Tim Deegan Acked-by: Roger Pau Monné --- RFC: This is effectively the alternative to the suggestion in an earlier patch that we might do away with the hook altogether. Of course a hybrid approach would also be possible, by using direct calls here instead of splitting the hook into two. --- I'm unsure whether p2m_init_nestedp2m() zapping the "pre" hook is actually correct, or whether previously the sh_unshadow_for_p2m_change() invocation was wrongly skipped. --- a/xen/arch/x86/mm/hap/hap.c +++ b/xen/arch/x86/mm/hap/hap.c @@ -774,55 +774,18 @@ static void hap_update_paging_modes(stru put_gfn(d, cr3_gfn); } -static int -hap_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, l1_pgentry_t *p, - l1_pgentry_t new, unsigned int level) +static void +hap_write_p2m_entry_post(struct p2m_domain *p2m, unsigned int oflags) { struct domain *d = p2m->domain; - uint32_t old_flags; - mfn_t omfn; - int rc; - /* We know always use the host p2m here, regardless if the vcpu - * is in host or guest mode. The vcpu can be in guest mode by - * a hypercall which passes a domain and chooses mostly the first - * vcpu. */ - - paging_lock(d); - old_flags = l1e_get_flags(*p); - omfn = l1e_get_mfn(*p); - - rc = p2m_entry_modify(p2m, p2m_flags_to_type(l1e_get_flags(new)), - p2m_flags_to_type(old_flags), l1e_get_mfn(new), - omfn, level); - if ( rc ) - { - paging_unlock(d); - return rc; - } - - safe_write_pte(p, new); - if ( old_flags & _PAGE_PRESENT ) + if ( oflags & _PAGE_PRESENT ) guest_flush_tlb_mask(d, d->dirty_cpumask); - - paging_unlock(d); - - if ( nestedhvm_enabled(d) && (old_flags & _PAGE_PRESENT) && - !p2m_get_hostp2m(d)->defer_nested_flush && - /* - * We are replacing a valid entry so we need to flush nested p2ms, - * unless the only change is an increase in access rights. - */ - (!mfn_eq(omfn, l1e_get_mfn(new)) || - !perms_strictly_increased(old_flags, l1e_get_flags(new))) ) - p2m_flush_nestedp2m(d); - - return 0; } void hap_p2m_init(struct p2m_domain *p2m) { - p2m->write_p2m_entry = hap_write_p2m_entry; + p2m->write_p2m_entry_post = hap_write_p2m_entry_post; } static unsigned long hap_gva_to_gfn_real_mode( --- a/xen/arch/x86/mm/hap/nested_hap.c +++ b/xen/arch/x86/mm/hap/nested_hap.c @@ -71,24 +71,11 @@ /* NESTED VIRT P2M FUNCTIONS */ /********************************************/ -int -nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, - l1_pgentry_t *p, l1_pgentry_t new, unsigned int level) +void +nestedp2m_write_p2m_entry_post(struct p2m_domain *p2m, unsigned int oflags) { - struct domain *d = p2m->domain; - uint32_t old_flags; - - paging_lock(d); - - old_flags = l1e_get_flags(*p); - safe_write_pte(p, new); - - if (old_flags & _PAGE_PRESENT) - guest_flush_tlb_mask(d, p2m->dirty_cpumask); - - paging_unlock(d); - - return 0; + if ( oflags & _PAGE_PRESENT ) + guest_flush_tlb_mask(p2m->domain, p2m->dirty_cpumask); } /********************************************/ --- a/xen/arch/x86/mm/p2m-pt.c +++ b/xen/arch/x86/mm/p2m-pt.c @@ -122,17 +122,55 @@ static int write_p2m_entry(struct p2m_do { struct domain *d = p2m->domain; struct vcpu *v = current; - int rc = 0; if ( v->domain != d ) v = d->vcpu ? d->vcpu[0] : NULL; if ( likely(v && paging_mode_enabled(d) && paging_get_hostmode(v)) || p2m_is_nestedp2m(p2m) ) - rc = p2m->write_p2m_entry(p2m, gfn, p, new, level); + { + unsigned int oflags; + mfn_t omfn; + int rc; + + paging_lock(d); + + if ( p2m->write_p2m_entry_pre ) + p2m->write_p2m_entry_pre(d, gfn, p, new, level); + + oflags = l1e_get_flags(*p); + omfn = l1e_get_mfn(*p); + + rc = p2m_entry_modify(p2m, p2m_flags_to_type(l1e_get_flags(new)), + p2m_flags_to_type(oflags), l1e_get_mfn(new), + omfn, level); + if ( rc ) + { + paging_unlock(d); + return rc; + } + + safe_write_pte(p, new); + + if ( p2m->write_p2m_entry_post ) + p2m->write_p2m_entry_post(p2m, oflags); + + paging_unlock(d); + + if ( nestedhvm_enabled(d) && !p2m_is_nestedp2m(p2m) && + (oflags & _PAGE_PRESENT) && + !p2m_get_hostp2m(d)->defer_nested_flush && + /* + * We are replacing a valid entry so we need to flush nested p2ms, + * unless the only change is an increase in access rights. + */ + (!mfn_eq(omfn, l1e_get_mfn(new)) || + !perms_strictly_increased(oflags, l1e_get_flags(new))) ) + p2m_flush_nestedp2m(d); + } else safe_write_pte(p, new); - return rc; + return 0; } // Find the next level's P2M entry, checking for out-of-range gfn's... --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -198,7 +198,8 @@ static int p2m_init_nestedp2m(struct dom return -ENOMEM; } p2m->p2m_class = p2m_nested; - p2m->write_p2m_entry = nestedp2m_write_p2m_entry; + p2m->write_p2m_entry_pre = NULL; + p2m->write_p2m_entry_post = nestedp2m_write_p2m_entry_post; list_add(&p2m->np2m_list, &p2m_get_hostp2m(d)->np2m_list); } --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -3137,34 +3137,22 @@ static void sh_unshadow_for_p2m_change(s } } -static int -shadow_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, - l1_pgentry_t *p, l1_pgentry_t new, - unsigned int level) +static void +sh_write_p2m_entry_pre(struct domain *d, unsigned long gfn, l1_pgentry_t *p, + l1_pgentry_t new, unsigned int level) { - struct domain *d = p2m->domain; - int rc; - - paging_lock(d); - /* If there are any shadows, update them. But if shadow_teardown() * has already been called then it's not safe to try. */ if ( likely(d->arch.paging.shadow.total_pages != 0) ) sh_unshadow_for_p2m_change(d, gfn, p, new, level); - - rc = p2m_entry_modify(p2m, p2m_flags_to_type(l1e_get_flags(new)), - p2m_flags_to_type(l1e_get_flags(*p)), - l1e_get_mfn(new), l1e_get_mfn(*p), level); - if ( rc ) - { - paging_unlock(d); - return rc; - } - - /* Update the entry with new content */ - safe_write_pte(p, new); +} #if (SHADOW_OPTIMIZATIONS & SHOPT_FAST_FAULT_PATH) +static void +sh_write_p2m_entry_post(struct p2m_domain *p2m, unsigned int oflags) +{ + struct domain *d = p2m->domain; + /* If we're doing FAST_FAULT_PATH, then shadow mode may have cached the fact that this is an mmio region in the shadow page tables. Blow the tables away to remove the cache. @@ -3176,16 +3164,15 @@ shadow_write_p2m_entry(struct p2m_domain shadow_blow_tables(d); d->arch.paging.shadow.has_fast_mmio_entries = false; } -#endif - - paging_unlock(d); - - return 0; } +#else +# define sh_write_p2m_entry_post NULL +#endif void shadow_p2m_init(struct p2m_domain *p2m) { - p2m->write_p2m_entry = shadow_write_p2m_entry; + p2m->write_p2m_entry_pre = sh_write_p2m_entry_pre; + p2m->write_p2m_entry_post = sh_write_p2m_entry_post; } /**************************************************************************/ --- a/xen/include/asm-x86/p2m.h +++ b/xen/include/asm-x86/p2m.h @@ -272,10 +272,13 @@ struct p2m_domain { unsigned long first_gfn, unsigned long last_gfn); void (*memory_type_changed)(struct p2m_domain *p2m); - - int (*write_p2m_entry)(struct p2m_domain *p2m, - unsigned long gfn, l1_pgentry_t *p, - l1_pgentry_t new, unsigned int level); + void (*write_p2m_entry_pre)(struct domain *d, + unsigned long gfn, + l1_pgentry_t *p, + l1_pgentry_t new, + unsigned int level); + void (*write_p2m_entry_post)(struct p2m_domain *p2m, + unsigned int oflags); #if P2M_AUDIT long (*audit_p2m)(struct p2m_domain *p2m); #endif @@ -472,7 +475,7 @@ void __put_gfn(struct p2m_domain *p2m, u * * This is also used in the shadow code whenever the paging lock is * held -- in those cases, the caller is protected against concurrent - * p2m updates by the fact that shadow_write_p2m_entry() also takes + * p2m updates by the fact that write_p2m_entry() also takes * the paging lock. * * Note that an unlocked accessor only makes sense for a "query" lookup. @@ -841,8 +844,8 @@ void np2m_flush_base(struct vcpu *v, uns void hap_p2m_init(struct p2m_domain *p2m); void shadow_p2m_init(struct p2m_domain *p2m); -int nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, - l1_pgentry_t *p, l1_pgentry_t new, unsigned int level); +void nestedp2m_write_p2m_entry_post(struct p2m_domain *p2m, + unsigned int oflags); /* * Alternate p2m: shadow p2m tables used for alternate memory views