Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp705367imm; Wed, 11 Jul 2018 09:33:47 -0700 (PDT) X-Google-Smtp-Source: AAOMgpe2RcsadT/5g7lUIZzvyCeWfceonlxYEKOAZW0UtlYzfcPmbdVOOvvMXffTRc4ueCZikGsN X-Received: by 2002:a17:902:ab90:: with SMTP id f16-v6mr24339565plr.182.1531326827280; Wed, 11 Jul 2018 09:33:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531326827; cv=none; d=google.com; s=arc-20160816; b=MJvnWj+KC9K2PbHKIXae4hqBepencDKUqklea7X1RbdFrwlZPOTbYM2eJ+Ni/AbukM 6VbO+uoYC5bLeNtCpvM/nElPmdZqDDw/1OwDNKHk9i63Tp1Zs7008Rju67VRFVHOl+wX PdsauVJ2koA/vS3Jniy7yDk+ZD7EvGySebOV+IHvcl4a7igdl2i22rU7I5p7TO1Ryq40 ikUedbnCTAkpF8t07EFOHAyzgsq7la5UPGhfk4ukSPvkWAFDSX6v1GpZNSAfMoZEEVJ9 a8LMZLFObYeqd7zgtavsTBqxXXG6b0gBppsO9WXpgbHmpkruuXCVAH/j4vZbM2pcXuhl A3Rw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:arc-authentication-results; bh=MLqn60BTf+TWpaq5rur76nH3f3K+CIGaf0xOm7+7PDg=; b=nUlwerF0nBp14sfNwBRjJoIQdnrdWAEODxcFabWuYyomlEaRRx6S7vtk12aNaWa6jw p76jdwWNf5a+DhKhl84mznn2AdA/FH/GoTTXdhsZ+UhgSIv5bPVUruzA5HAUr/YBgf8b JNnxHhCOoDUY4Xi6bj6EyivHeTcrUmCwmgBe+kp5MSP+BGbXzSGN4d3SK10+Zbvcf9aU CO7rEW46PErrF5zX7x6/smZI83fF9nmjtJsip+sHO8vrW4wVI1TAZUnRXZeUED0z1Ji2 ofJD88mqtWPa5pEYYbAxZpe6qsOjowfEgpyy5PMtMYZpFwxvOv/XmekCTt7lR4zIUESH RbpQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t19-v6si19641124pgb.196.2018.07.11.09.33.32; Wed, 11 Jul 2018 09:33:47 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388018AbeGKNnH (ORCPT + 99 others); Wed, 11 Jul 2018 09:43:07 -0400 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70]:36040 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387837AbeGKNnH (ORCPT ); Wed, 11 Jul 2018 09:43:07 -0400 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 021D27A9; Wed, 11 Jul 2018 06:38:43 -0700 (PDT) Received: from [10.1.206.73] (en101.cambridge.arm.com [10.1.206.73]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 405A63F5AD; Wed, 11 Jul 2018 06:38:41 -0700 (PDT) Subject: Re: [PATCH v5 7/7] KVM: arm64: Add support for creating PUD hugepages at stage 2 To: Punit Agrawal , kvmarm@lists.cs.columbia.edu Cc: linux-arm-kernel@lists.infradead.org, marc.zyngier@arm.com, christoffer.dall@arm.com, linux-kernel@vger.kernel.org, will.deacon@arm.com, Russell King , Catalin Marinas References: <20180709143835.28971-1-punit.agrawal@arm.com> <20180709144124.29164-1-punit.agrawal@arm.com> <20180709144124.29164-7-punit.agrawal@arm.com> From: Suzuki K Poulose Message-ID: Date: Wed, 11 Jul 2018 14:38:38 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 MIME-Version: 1.0 In-Reply-To: <20180709144124.29164-7-punit.agrawal@arm.com> Content-Type: text/plain; charset=us-ascii; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 09/07/18 15:41, Punit Agrawal wrote: > KVM only supports PMD hugepages at stage 2. Now that the various page > handling routines are updated, extend the stage 2 fault handling to > map in PUD hugepages. > > Addition of PUD hugepage support enables additional page sizes (e.g., > 1G with 4K granule) which can be useful on cores that support mapping > larger block sizes in the TLB entries. > > Signed-off-by: Punit Agrawal > Cc: Christoffer Dall > Cc: Marc Zyngier > Cc: Russell King > Cc: Catalin Marinas > Cc: Will Deacon > --- > arch/arm/include/asm/kvm_mmu.h | 19 +++++++ > arch/arm64/include/asm/kvm_mmu.h | 15 +++++ > arch/arm64/include/asm/pgtable-hwdef.h | 2 + > arch/arm64/include/asm/pgtable.h | 2 + > virt/kvm/arm/mmu.c | 78 ++++++++++++++++++++++++-- > 5 files changed, 112 insertions(+), 4 deletions(-) > > diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h > index 8e1e8aee229e..787baf9ec994 100644 > --- a/arch/arm/include/asm/kvm_mmu.h > +++ b/arch/arm/include/asm/kvm_mmu.h > @@ -77,10 +77,13 @@ void kvm_clear_hyp_idmap(void); > > #define kvm_pfn_pte(pfn, prot) pfn_pte(pfn, prot) > #define kvm_pfn_pmd(pfn, prot) pfn_pmd(pfn, prot) > +#define kvm_pfn_pud(pfn, prot) (__pud(0)) > > #define kvm_pud_pfn(pud) (((pud_val(pud) & PUD_MASK) & PHYS_MASK) >> PAGE_SHIFT) > > #define kvm_pmd_mkhuge(pmd) pmd_mkhuge(pmd) > +/* No support for pud hugepages */ > +#define kvm_pud_mkhuge(pud) (pud) > > /* > * The following kvm_*pud*() functionas are provided strictly to allow > @@ -97,6 +100,22 @@ static inline bool kvm_s2pud_readonly(pud_t *pud) > return false; > } > > +static inline void kvm_set_pud(pud_t *pud, pud_t new_pud) > +{ > + BUG(); > +} > + > +static inline pud_t kvm_s2pud_mkwrite(pud_t pud) > +{ > + BUG(); > + return pud; > +} > + > +static inline pud_t kvm_s2pud_mkexec(pud_t pud) > +{ > + BUG(); > + return pud; > +} > > static inline bool kvm_s2pud_exec(pud_t *pud) > { > diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h > index c542052fb199..dd8a23159463 100644 > --- a/arch/arm64/include/asm/kvm_mmu.h > +++ b/arch/arm64/include/asm/kvm_mmu.h > @@ -171,13 +171,16 @@ void kvm_clear_hyp_idmap(void); > > #define kvm_set_pte(ptep, pte) set_pte(ptep, pte) > #define kvm_set_pmd(pmdp, pmd) set_pmd(pmdp, pmd) > +#define kvm_set_pud(pudp, pud) set_pud(pudp, pud) > > #define kvm_pfn_pte(pfn, prot) pfn_pte(pfn, prot) > #define kvm_pfn_pmd(pfn, prot) pfn_pmd(pfn, prot) > +#define kvm_pfn_pud(pfn, prot) pfn_pud(pfn, prot) > > #define kvm_pud_pfn(pud) pud_pfn(pud) > > #define kvm_pmd_mkhuge(pmd) pmd_mkhuge(pmd) > +#define kvm_pud_mkhuge(pud) pud_mkhuge(pud) > > static inline pte_t kvm_s2pte_mkwrite(pte_t pte) > { > @@ -191,6 +194,12 @@ static inline pmd_t kvm_s2pmd_mkwrite(pmd_t pmd) > return pmd; > } > > +static inline pud_t kvm_s2pud_mkwrite(pud_t pud) > +{ > + pud_val(pud) |= PUD_S2_RDWR; > + return pud; > +} > + > static inline pte_t kvm_s2pte_mkexec(pte_t pte) > { > pte_val(pte) &= ~PTE_S2_XN; > @@ -203,6 +212,12 @@ static inline pmd_t kvm_s2pmd_mkexec(pmd_t pmd) > return pmd; > } > > +static inline pud_t kvm_s2pud_mkexec(pud_t pud) > +{ > + pud_val(pud) &= ~PUD_S2_XN; > + return pud; > +} > + > static inline void kvm_set_s2pte_readonly(pte_t *ptep) > { > pteval_t old_pteval, pteval; > diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h > index 10ae592b78b8..e327665e94d1 100644 > --- a/arch/arm64/include/asm/pgtable-hwdef.h > +++ b/arch/arm64/include/asm/pgtable-hwdef.h > @@ -193,6 +193,8 @@ > #define PMD_S2_RDWR (_AT(pmdval_t, 3) << 6) /* HAP[2:1] */ > #define PMD_S2_XN (_AT(pmdval_t, 2) << 53) /* XN[1:0] */ > > +#define PUD_S2_RDONLY (_AT(pudval_t, 1) << 6) /* HAP[2:1] */ > +#define PUD_S2_RDWR (_AT(pudval_t, 3) << 6) /* HAP[2:1] */ > #define PUD_S2_XN (_AT(pudval_t, 2) << 53) /* XN[1:0] */ > > /* > diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h > index 4d9476e420d9..0afc34f94ff5 100644 > --- a/arch/arm64/include/asm/pgtable.h > +++ b/arch/arm64/include/asm/pgtable.h > @@ -389,6 +389,8 @@ static inline int pmd_protnone(pmd_t pmd) > #define pud_mkyoung(pud) pte_pud(pte_mkyoung(pud_pte(pud))) > #define pud_write(pud) pte_write(pud_pte(pud)) > > +#define pud_mkhuge(pud) (__pud(pud_val(pud) & ~PUD_TABLE_BIT)) > + > #define __pud_to_phys(pud) __pte_to_phys(pud_pte(pud)) > #define __phys_to_pud_val(phys) __phys_to_pte_val(phys) > #define pud_pfn(pud) ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT) > diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c > index a6d3ac9d7c7a..d8e2497e5353 100644 > --- a/virt/kvm/arm/mmu.c > +++ b/virt/kvm/arm/mmu.c > @@ -116,6 +116,25 @@ static void stage2_dissolve_pmd(struct kvm *kvm, phys_addr_t addr, pmd_t *pmd) > put_page(virt_to_page(pmd)); > } > > +/** > + * stage2_dissolve_pud() - clear and flush huge PUD entry > + * @kvm: pointer to kvm structure. > + * @addr: IPA > + * @pud: pud pointer for IPA > + * > + * Function clears a PUD entry, flushes addr 1st and 2nd stage TLBs. Marks all > + * pages in the range dirty. > + */ > +static void stage2_dissolve_pud(struct kvm *kvm, phys_addr_t addr, pud_t *pudp) > +{ > + if (!stage2_pud_huge(*pudp)) > + return; > + > + stage2_pud_clear(pudp); > + kvm_tlb_flush_vmid_ipa(kvm, addr); > + put_page(virt_to_page(pudp)); > +} > + > static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache, > int min, int max) > { > @@ -993,7 +1012,7 @@ static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache > pmd_t *pmd; > > pud = stage2_get_pud(kvm, cache, addr); > - if (!pud) > + if (!pud || stage2_pud_huge(*pud)) > return NULL; > > if (stage2_pud_none(*pud)) { > @@ -1038,6 +1057,26 @@ static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache > return 0; > } > > +static int stage2_set_pud_huge(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, > + phys_addr_t addr, const pud_t *new_pudp) > +{ > + pud_t *pudp, old_pud; > + > + pudp = stage2_get_pud(kvm, cache, addr); > + VM_BUG_ON(!pudp); > + > + old_pud = *pudp; > + if (stage2_pud_present(old_pud)) { > + stage2_pud_clear(pudp); > + kvm_tlb_flush_vmid_ipa(kvm, addr); > + } else { > + get_page(virt_to_page(pudp)); > + } > + > + kvm_set_pud(pudp, *new_pudp); > + return 0; > +} > + > /* > * stage2_get_leaf_entry - walk the stage2 VM page tables and return > * true if a valid and present leaf-entry is found. A pointer to the > @@ -1100,6 +1139,7 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, > phys_addr_t addr, const pte_t *new_pte, > unsigned long flags) > { > + pud_t *pud; > pmd_t *pmd; > pte_t *pte, old_pte; > bool iomap = flags & KVM_S2PTE_FLAG_IS_IOMAP; > @@ -1108,6 +1148,22 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, > VM_BUG_ON(logging_active && !cache); > > /* Create stage-2 page table mapping - Levels 0 and 1 */ > + pud = stage2_get_pud(kvm, cache, addr); > + if (!pud) { > + /* > + * Ignore calls from kvm_set_spte_hva for unallocated > + * address ranges. > + */ > + return 0; > + } > + > + /* > + * While dirty page logging - dissolve huge PUD, then continue > + * on to allocate page. Punit, We don't seem to allocate a page here for the PUD entry, in case if it is dissolved or empty (i.e, stage2_pud_none(*pud) is true.). > + */ > + if (logging_active) > + stage2_dissolve_pud(kvm, addr, pud); > + > pmd = stage2_get_pmd(kvm, cache, addr); > if (!pmd) { And once you add an entry, pmd is just the matter of getting stage2_pmd_offset() from your pud. No need to start again from the top-level with stage2_get_pmd(). Cheers Suzuki