From: cdall@cs.columbia.edu (Christoffer Dall)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 1/7] ARM: KVM: simplify HYP mapping population
Date: Wed, 3 Apr 2013 16:13:44 -0700 [thread overview]
Message-ID: <20130403231344.GA29227@gmail.com> (raw)
In-Reply-To: <1364909115-3810-2-git-send-email-marc.zyngier@arm.com>
On Tue, Apr 02, 2013 at 02:25:09PM +0100, Marc Zyngier wrote:
> The way we populate HYP mappings is a bit convoluted, to say the least.
> Passing a pointer around to keep track of the current PFN is quite
> odd, and we end-up having two different PTE accessors for no good
> reason.
>
> Simplify the whole thing by unifying the two PTE accessors, passing
> a pgprot_t around, and moving the various validity checks to the
> upper layers.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
> arch/arm/kvm/mmu.c | 100 ++++++++++++++++++++++-------------------------------
> 1 file changed, 41 insertions(+), 59 deletions(-)
>
> diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
> index 2f12e40..24811d1 100644
> --- a/arch/arm/kvm/mmu.c
> +++ b/arch/arm/kvm/mmu.c
> @@ -125,54 +125,34 @@ void free_hyp_pmds(void)
> }
>
> static void create_hyp_pte_mappings(pmd_t *pmd, unsigned long start,
> - unsigned long end)
> + unsigned long end, unsigned long pfn,
> + pgprot_t prot)
> {
> pte_t *pte;
> unsigned long addr;
> - struct page *page;
>
> - for (addr = start & PAGE_MASK; addr < end; addr += PAGE_SIZE) {
> - unsigned long hyp_addr = KERN_TO_HYP(addr);
> -
> - pte = pte_offset_kernel(pmd, hyp_addr);
> - BUG_ON(!virt_addr_valid(addr));
> - page = virt_to_page(addr);
> - kvm_set_pte(pte, mk_pte(page, PAGE_HYP));
> - }
> -}
> -
> -static void create_hyp_io_pte_mappings(pmd_t *pmd, unsigned long start,
> - unsigned long end,
> - unsigned long *pfn_base)
> -{
> - pte_t *pte;
> - unsigned long addr;
> -
> - for (addr = start & PAGE_MASK; addr < end; addr += PAGE_SIZE) {
> - unsigned long hyp_addr = KERN_TO_HYP(addr);
> -
> - pte = pte_offset_kernel(pmd, hyp_addr);
> - BUG_ON(pfn_valid(*pfn_base));
> - kvm_set_pte(pte, pfn_pte(*pfn_base, PAGE_HYP_DEVICE));
> - (*pfn_base)++;
> + for (addr = start; addr < end; addr += PAGE_SIZE) {
> + pte = pte_offset_kernel(pmd, addr);
> + kvm_set_pte(pte, pfn_pte(pfn, prot));
> + pfn++;
> }
> }
>
> static int create_hyp_pmd_mappings(pud_t *pud, unsigned long start,
> - unsigned long end, unsigned long *pfn_base)
> + unsigned long end, unsigned long pfn,
> + pgprot_t prot)
> {
> pmd_t *pmd;
> pte_t *pte;
> unsigned long addr, next;
>
> for (addr = start; addr < end; addr = next) {
> - unsigned long hyp_addr = KERN_TO_HYP(addr);
> - pmd = pmd_offset(pud, hyp_addr);
> + pmd = pmd_offset(pud, addr);
>
> BUG_ON(pmd_sect(*pmd));
>
> if (pmd_none(*pmd)) {
> - pte = pte_alloc_one_kernel(NULL, hyp_addr);
> + pte = pte_alloc_one_kernel(NULL, addr);
> if (!pte) {
> kvm_err("Cannot allocate Hyp pte\n");
> return -ENOMEM;
> @@ -182,25 +162,17 @@ static int create_hyp_pmd_mappings(pud_t *pud, unsigned long start,
>
> next = pmd_addr_end(addr, end);
>
> - /*
> - * If pfn_base is NULL, we map kernel pages into HYP with the
> - * virtual address. Otherwise, this is considered an I/O
> - * mapping and we map the physical region starting at
> - * *pfn_base to [start, end[.
> - */
> - if (!pfn_base)
> - create_hyp_pte_mappings(pmd, addr, next);
> - else
> - create_hyp_io_pte_mappings(pmd, addr, next, pfn_base);
> + create_hyp_pte_mappings(pmd, addr, next, pfn, prot);
> + pfn += (next - addr) >> PAGE_SHIFT;
so this scheme always assumes a physically contiguous memory reason,
and I wasn't sure if we ever wanted to support mapping vmalloc'ed
regions into Hyp mode, which is why I wrote the code the way it was
(which goes to your "for no good reason" comment above).
I'm fine with assuming that this only works for contiguous regions, but
I think it deserves a line in the comments on the exported functions
(the non-IO one anyway).
> }
>
> return 0;
> }
>
> -static int __create_hyp_mappings(void *from, void *to, unsigned long *pfn_base)
> +static int __create_hyp_mappings(pgd_t *pgdp,
> + unsigned long start, unsigned long end,
> + unsigned long pfn, pgprot_t prot)
> {
> - unsigned long start = (unsigned long)from;
> - unsigned long end = (unsigned long)to;
> pgd_t *pgd;
> pud_t *pud;
> pmd_t *pmd;
> @@ -209,21 +181,14 @@ static int __create_hyp_mappings(void *from, void *to, unsigned long *pfn_base)
>
> if (start >= end)
> return -EINVAL;
> - /* Check for a valid kernel memory mapping */
> - if (!pfn_base && (!virt_addr_valid(from) || !virt_addr_valid(to - 1)))
> - return -EINVAL;
> - /* Check for a valid kernel IO mapping */
> - if (pfn_base && (!is_vmalloc_addr(from) || !is_vmalloc_addr(to - 1)))
> - return -EINVAL;
>
> mutex_lock(&kvm_hyp_pgd_mutex);
> - for (addr = start; addr < end; addr = next) {
> - unsigned long hyp_addr = KERN_TO_HYP(addr);
> - pgd = hyp_pgd + pgd_index(hyp_addr);
> - pud = pud_offset(pgd, hyp_addr);
> + for (addr = start & PAGE_MASK; addr < end; addr = next) {
> + pgd = pgdp + pgd_index(addr);
> + pud = pud_offset(pgd, addr);
>
> if (pud_none_or_clear_bad(pud)) {
> - pmd = pmd_alloc_one(NULL, hyp_addr);
> + pmd = pmd_alloc_one(NULL, addr);
> if (!pmd) {
> kvm_err("Cannot allocate Hyp pmd\n");
> err = -ENOMEM;
> @@ -233,9 +198,10 @@ static int __create_hyp_mappings(void *from, void *to, unsigned long *pfn_base)
> }
>
> next = pgd_addr_end(addr, end);
> - err = create_hyp_pmd_mappings(pud, addr, next, pfn_base);
> + err = create_hyp_pmd_mappings(pud, addr, next, pfn, prot);
> if (err)
> goto out;
> + pfn += (next - addr) >> PAGE_SHIFT;
nit: consider passing a pointer to pfn instead? Not sure if it's nicer.
> }
> out:
> mutex_unlock(&kvm_hyp_pgd_mutex);
> @@ -255,7 +221,16 @@ out:
> */
> int create_hyp_mappings(void *from, void *to)
> {
> - return __create_hyp_mappings(from, to, NULL);
> + unsigned long phys_addr = virt_to_phys(from);
> + unsigned long start = KERN_TO_HYP((unsigned long)from);
> + unsigned long end = KERN_TO_HYP((unsigned long)to);
> +
> + /* Check for a valid kernel memory mapping */
> + if (!virt_addr_valid(from) || !virt_addr_valid(to - 1))
> + return -EINVAL;
> +
> + return __create_hyp_mappings(hyp_pgd, start, end,
> + __phys_to_pfn(phys_addr), PAGE_HYP);
> }
>
> /**
> @@ -267,10 +242,17 @@ int create_hyp_mappings(void *from, void *to)
> * The resulting HYP VA is the same as the kernel VA, modulo
> * HYP_PAGE_OFFSET.
> */
> -int create_hyp_io_mappings(void *from, void *to, phys_addr_t addr)
> +int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr)
nit: change the parameter documentation name as well.
> {
> - unsigned long pfn = __phys_to_pfn(addr);
> - return __create_hyp_mappings(from, to, &pfn);
> + unsigned long start = KERN_TO_HYP((unsigned long)from);
> + unsigned long end = KERN_TO_HYP((unsigned long)to);
> +
> + /* Check for a valid kernel IO mapping */
> + if (!is_vmalloc_addr(from) || !is_vmalloc_addr(to - 1))
> + return -EINVAL;
> +
> + return __create_hyp_mappings(hyp_pgd, start, end,
> + __phys_to_pfn(phys_addr), PAGE_HYP_DEVICE);
> }
>
> /**
> --
> 1.8.1.4
>
If the contigous thing is not a concern, then I'm happy about the
simplification.
-Christoffer
WARNING: multiple messages have this Message-ID (diff)
From: Christoffer Dall <cdall@cs.columbia.edu>
To: Marc Zyngier <marc.zyngier@arm.com>
Cc: linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org,
kvmarm@lists.cs.columbia.edu, catalin.marinas@arm.com,
will.deacon@arm.com
Subject: Re: [PATCH 1/7] ARM: KVM: simplify HYP mapping population
Date: Wed, 3 Apr 2013 16:13:44 -0700 [thread overview]
Message-ID: <20130403231344.GA29227@gmail.com> (raw)
In-Reply-To: <1364909115-3810-2-git-send-email-marc.zyngier@arm.com>
On Tue, Apr 02, 2013 at 02:25:09PM +0100, Marc Zyngier wrote:
> The way we populate HYP mappings is a bit convoluted, to say the least.
> Passing a pointer around to keep track of the current PFN is quite
> odd, and we end-up having two different PTE accessors for no good
> reason.
>
> Simplify the whole thing by unifying the two PTE accessors, passing
> a pgprot_t around, and moving the various validity checks to the
> upper layers.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
> arch/arm/kvm/mmu.c | 100 ++++++++++++++++++++++-------------------------------
> 1 file changed, 41 insertions(+), 59 deletions(-)
>
> diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
> index 2f12e40..24811d1 100644
> --- a/arch/arm/kvm/mmu.c
> +++ b/arch/arm/kvm/mmu.c
> @@ -125,54 +125,34 @@ void free_hyp_pmds(void)
> }
>
> static void create_hyp_pte_mappings(pmd_t *pmd, unsigned long start,
> - unsigned long end)
> + unsigned long end, unsigned long pfn,
> + pgprot_t prot)
> {
> pte_t *pte;
> unsigned long addr;
> - struct page *page;
>
> - for (addr = start & PAGE_MASK; addr < end; addr += PAGE_SIZE) {
> - unsigned long hyp_addr = KERN_TO_HYP(addr);
> -
> - pte = pte_offset_kernel(pmd, hyp_addr);
> - BUG_ON(!virt_addr_valid(addr));
> - page = virt_to_page(addr);
> - kvm_set_pte(pte, mk_pte(page, PAGE_HYP));
> - }
> -}
> -
> -static void create_hyp_io_pte_mappings(pmd_t *pmd, unsigned long start,
> - unsigned long end,
> - unsigned long *pfn_base)
> -{
> - pte_t *pte;
> - unsigned long addr;
> -
> - for (addr = start & PAGE_MASK; addr < end; addr += PAGE_SIZE) {
> - unsigned long hyp_addr = KERN_TO_HYP(addr);
> -
> - pte = pte_offset_kernel(pmd, hyp_addr);
> - BUG_ON(pfn_valid(*pfn_base));
> - kvm_set_pte(pte, pfn_pte(*pfn_base, PAGE_HYP_DEVICE));
> - (*pfn_base)++;
> + for (addr = start; addr < end; addr += PAGE_SIZE) {
> + pte = pte_offset_kernel(pmd, addr);
> + kvm_set_pte(pte, pfn_pte(pfn, prot));
> + pfn++;
> }
> }
>
> static int create_hyp_pmd_mappings(pud_t *pud, unsigned long start,
> - unsigned long end, unsigned long *pfn_base)
> + unsigned long end, unsigned long pfn,
> + pgprot_t prot)
> {
> pmd_t *pmd;
> pte_t *pte;
> unsigned long addr, next;
>
> for (addr = start; addr < end; addr = next) {
> - unsigned long hyp_addr = KERN_TO_HYP(addr);
> - pmd = pmd_offset(pud, hyp_addr);
> + pmd = pmd_offset(pud, addr);
>
> BUG_ON(pmd_sect(*pmd));
>
> if (pmd_none(*pmd)) {
> - pte = pte_alloc_one_kernel(NULL, hyp_addr);
> + pte = pte_alloc_one_kernel(NULL, addr);
> if (!pte) {
> kvm_err("Cannot allocate Hyp pte\n");
> return -ENOMEM;
> @@ -182,25 +162,17 @@ static int create_hyp_pmd_mappings(pud_t *pud, unsigned long start,
>
> next = pmd_addr_end(addr, end);
>
> - /*
> - * If pfn_base is NULL, we map kernel pages into HYP with the
> - * virtual address. Otherwise, this is considered an I/O
> - * mapping and we map the physical region starting at
> - * *pfn_base to [start, end[.
> - */
> - if (!pfn_base)
> - create_hyp_pte_mappings(pmd, addr, next);
> - else
> - create_hyp_io_pte_mappings(pmd, addr, next, pfn_base);
> + create_hyp_pte_mappings(pmd, addr, next, pfn, prot);
> + pfn += (next - addr) >> PAGE_SHIFT;
so this scheme always assumes a physically contiguous memory reason,
and I wasn't sure if we ever wanted to support mapping vmalloc'ed
regions into Hyp mode, which is why I wrote the code the way it was
(which goes to your "for no good reason" comment above).
I'm fine with assuming that this only works for contiguous regions, but
I think it deserves a line in the comments on the exported functions
(the non-IO one anyway).
> }
>
> return 0;
> }
>
> -static int __create_hyp_mappings(void *from, void *to, unsigned long *pfn_base)
> +static int __create_hyp_mappings(pgd_t *pgdp,
> + unsigned long start, unsigned long end,
> + unsigned long pfn, pgprot_t prot)
> {
> - unsigned long start = (unsigned long)from;
> - unsigned long end = (unsigned long)to;
> pgd_t *pgd;
> pud_t *pud;
> pmd_t *pmd;
> @@ -209,21 +181,14 @@ static int __create_hyp_mappings(void *from, void *to, unsigned long *pfn_base)
>
> if (start >= end)
> return -EINVAL;
> - /* Check for a valid kernel memory mapping */
> - if (!pfn_base && (!virt_addr_valid(from) || !virt_addr_valid(to - 1)))
> - return -EINVAL;
> - /* Check for a valid kernel IO mapping */
> - if (pfn_base && (!is_vmalloc_addr(from) || !is_vmalloc_addr(to - 1)))
> - return -EINVAL;
>
> mutex_lock(&kvm_hyp_pgd_mutex);
> - for (addr = start; addr < end; addr = next) {
> - unsigned long hyp_addr = KERN_TO_HYP(addr);
> - pgd = hyp_pgd + pgd_index(hyp_addr);
> - pud = pud_offset(pgd, hyp_addr);
> + for (addr = start & PAGE_MASK; addr < end; addr = next) {
> + pgd = pgdp + pgd_index(addr);
> + pud = pud_offset(pgd, addr);
>
> if (pud_none_or_clear_bad(pud)) {
> - pmd = pmd_alloc_one(NULL, hyp_addr);
> + pmd = pmd_alloc_one(NULL, addr);
> if (!pmd) {
> kvm_err("Cannot allocate Hyp pmd\n");
> err = -ENOMEM;
> @@ -233,9 +198,10 @@ static int __create_hyp_mappings(void *from, void *to, unsigned long *pfn_base)
> }
>
> next = pgd_addr_end(addr, end);
> - err = create_hyp_pmd_mappings(pud, addr, next, pfn_base);
> + err = create_hyp_pmd_mappings(pud, addr, next, pfn, prot);
> if (err)
> goto out;
> + pfn += (next - addr) >> PAGE_SHIFT;
nit: consider passing a pointer to pfn instead? Not sure if it's nicer.
> }
> out:
> mutex_unlock(&kvm_hyp_pgd_mutex);
> @@ -255,7 +221,16 @@ out:
> */
> int create_hyp_mappings(void *from, void *to)
> {
> - return __create_hyp_mappings(from, to, NULL);
> + unsigned long phys_addr = virt_to_phys(from);
> + unsigned long start = KERN_TO_HYP((unsigned long)from);
> + unsigned long end = KERN_TO_HYP((unsigned long)to);
> +
> + /* Check for a valid kernel memory mapping */
> + if (!virt_addr_valid(from) || !virt_addr_valid(to - 1))
> + return -EINVAL;
> +
> + return __create_hyp_mappings(hyp_pgd, start, end,
> + __phys_to_pfn(phys_addr), PAGE_HYP);
> }
>
> /**
> @@ -267,10 +242,17 @@ int create_hyp_mappings(void *from, void *to)
> * The resulting HYP VA is the same as the kernel VA, modulo
> * HYP_PAGE_OFFSET.
> */
> -int create_hyp_io_mappings(void *from, void *to, phys_addr_t addr)
> +int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr)
nit: change the parameter documentation name as well.
> {
> - unsigned long pfn = __phys_to_pfn(addr);
> - return __create_hyp_mappings(from, to, &pfn);
> + unsigned long start = KERN_TO_HYP((unsigned long)from);
> + unsigned long end = KERN_TO_HYP((unsigned long)to);
> +
> + /* Check for a valid kernel IO mapping */
> + if (!is_vmalloc_addr(from) || !is_vmalloc_addr(to - 1))
> + return -EINVAL;
> +
> + return __create_hyp_mappings(hyp_pgd, start, end,
> + __phys_to_pfn(phys_addr), PAGE_HYP_DEVICE);
> }
>
> /**
> --
> 1.8.1.4
>
If the contigous thing is not a concern, then I'm happy about the
simplification.
-Christoffer
next prev parent reply other threads:[~2013-04-03 23:13 UTC|newest]
Thread overview: 70+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-02 13:25 [PATCH 0/7] ARM: KVM: Revamping the HYP init code for fun and profit Marc Zyngier
2013-04-02 13:25 ` Marc Zyngier
2013-04-02 13:25 ` [PATCH 1/7] ARM: KVM: simplify HYP mapping population Marc Zyngier
2013-04-02 13:25 ` Marc Zyngier
2013-04-03 23:13 ` Christoffer Dall [this message]
2013-04-03 23:13 ` Christoffer Dall
2013-04-04 12:35 ` Marc Zyngier
2013-04-04 12:35 ` Marc Zyngier
2013-04-02 13:25 ` [PATCH 2/7] ARM: KVM: fix HYP mapping limitations around zero Marc Zyngier
2013-04-02 13:25 ` Marc Zyngier
2013-04-03 23:14 ` Christoffer Dall
2013-04-03 23:14 ` Christoffer Dall
2013-04-04 12:40 ` Marc Zyngier
2013-04-04 12:40 ` Marc Zyngier
2013-04-02 13:25 ` [PATCH 3/7] ARM: KVM: move to a KVM provided HYP idmap Marc Zyngier
2013-04-02 13:25 ` Marc Zyngier
2013-04-03 9:43 ` Will Deacon
2013-04-03 9:43 ` Will Deacon
2013-04-03 9:46 ` Marc Zyngier
2013-04-03 9:46 ` Marc Zyngier
2013-04-03 23:14 ` Christoffer Dall
2013-04-03 23:14 ` Christoffer Dall
2013-04-02 13:25 ` [PATCH 4/7] ARM: KVM: enforce page alignment for identity mapped code Marc Zyngier
2013-04-02 13:25 ` Marc Zyngier
2013-04-03 9:50 ` Will Deacon
2013-04-03 9:50 ` Will Deacon
2013-04-03 10:00 ` Marc Zyngier
2013-04-03 10:00 ` Marc Zyngier
2013-04-03 23:15 ` Christoffer Dall
2013-04-03 23:15 ` Christoffer Dall
2013-04-04 10:47 ` Marc Zyngier
2013-04-04 10:47 ` Marc Zyngier
2013-04-04 15:32 ` Christoffer Dall
2013-04-04 15:32 ` Christoffer Dall
2013-04-02 13:25 ` [PATCH 5/7] ARM: KVM: parametrize HYP page table freeing Marc Zyngier
2013-04-02 13:25 ` Marc Zyngier
2013-04-03 23:15 ` Christoffer Dall
2013-04-03 23:15 ` Christoffer Dall
2013-04-02 13:25 ` [PATCH 6/7] ARM: KVM: switch to a dual-step HYP init code Marc Zyngier
2013-04-02 13:25 ` Marc Zyngier
2013-04-03 10:07 ` Will Deacon
2013-04-03 10:07 ` Will Deacon
2013-04-03 10:38 ` Marc Zyngier
2013-04-03 10:38 ` Marc Zyngier
2013-04-03 23:15 ` Christoffer Dall
2013-04-03 23:15 ` Christoffer Dall
2013-04-04 11:05 ` Marc Zyngier
2013-04-04 11:05 ` Marc Zyngier
2013-04-03 23:15 ` Christoffer Dall
2013-04-03 23:15 ` Christoffer Dall
2013-04-04 12:52 ` Marc Zyngier
2013-04-04 12:52 ` Marc Zyngier
2013-04-04 22:10 ` Geoff Levand
2013-04-04 22:10 ` Geoff Levand
2013-04-05 9:08 ` Marc Zyngier
2013-04-05 9:08 ` Marc Zyngier
2013-04-05 16:46 ` Geoff Levand
2013-04-05 16:46 ` Geoff Levand
2013-04-05 16:54 ` Marc Zyngier
2013-04-05 16:54 ` Marc Zyngier
2013-04-18 15:54 ` Russell King - ARM Linux
2013-04-18 15:54 ` Russell King - ARM Linux
2013-04-18 16:01 ` Marc Zyngier
2013-04-18 16:01 ` Marc Zyngier
2013-04-02 13:25 ` [PATCH 7/7] ARM: KVM: perform HYP initilization for hotplugged CPUs Marc Zyngier
2013-04-02 13:25 ` Marc Zyngier
2013-04-03 23:16 ` Christoffer Dall
2013-04-03 23:16 ` Christoffer Dall
2013-04-03 23:18 ` [PATCH 0/7] ARM: KVM: Revamping the HYP init code for fun and profit Christoffer Dall
2013-04-03 23:18 ` Christoffer Dall
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130403231344.GA29227@gmail.com \
--to=cdall@cs.columbia.edu \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.