[PATCH 09/17] powerpc: make __ioremap_caller() common to PPC32 and PPC64
Christophe LEROY
christophe.leroy at c-s.fr
Wed May 16 19:58:05 AEST 2018
Le 08/05/2018 à 11:56, Aneesh Kumar K.V a écrit :
> Christophe Leroy <christophe.leroy at c-s.fr> writes:
>
>> Signed-off-by: Christophe Leroy <christophe.leroy at c-s.fr>
>> ---
>> arch/powerpc/include/asm/book3s/64/pgtable.h | 1 +
>> arch/powerpc/mm/ioremap.c | 126 +++++++--------------------
>> 2 files changed, 34 insertions(+), 93 deletions(-)
>>
>> diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
>> index c5c6ead06bfb..2bebdd8302cb 100644
>> --- a/arch/powerpc/include/asm/book3s/64/pgtable.h
>> +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
>> @@ -18,6 +18,7 @@
>> #define _PAGE_RO 0
>> #define _PAGE_USER 0
>> #define _PAGE_HWWRITE 0
>> +#define _PAGE_COHERENT 0
>
> This is something I was trying to avoid when I split the headers. We do
> support _PAGE_USER it is !_PAGE_PRIVILEGED. It gets really confusing
> when we have these conflicting names because we are trying to make code
> common across platforms.
Euh ... Here patch adds _PAGE_COHERENT
_PAGE_USER was added some time ago.
Well, we have three cases:
BOOK3S64 and NOHASH32/8xx has _PAGE_PRIVILEGED and no _PAGE_USER
BOOKE has both _PAGE_PRIVILEGED and _PAGE_USER
Others have _PAGE_USER and no _PAGE_PRIVILEGED
So when giving user rights to a page, some will set _PAGE_USER, some
will unset _PAGE_PRIVILEGED and some will do both.
_PAGE_USER and _PAGE_PRIVILEGED being used outside of the subarch headers,
- either we have to add uggly ifdefs
- or we can just make sure unused flags are set as 0, then (x | 0) and
(x & ~0) will do nothing and will be eliminated by the compiler.
Today, this is done in asm/pte-common.h. Unfortunately, all headers
except book3s64 do include pte-common.
Another solution would be to make sure _PAGE_xxx flags are not used
outside of subarch specific headers. That would mean having specific
helpers defined in each subarch header, but is it really worth it ?
Lets take the exemple of an even more tricky one :
- Some subarchs have _PAGE_RW, others have _PAGE_RO instead. In
addition, the 8xx has _PAGE_NA
- Book3s64 has _PAGE_READ and _PAGE_WRITE.
- In some places, _PAGE_RW has been redefined has _PAGE_READ | _PAGE_WRITE
It has really become pretty complex. Why having defined new flags
instead of using _PAGE_RO for _PAGE_READ and _PAGE_RW for _PAGE_READ |
_PAGE_WRITE ? Does it make any sense to have the possibility to set
_PAGE_WRITE without _PAGE_READ ?
I feel like having simple generic code like:
flags = (flags & ~_PAGE_PRIVILEGED) | _PAGE_USER;
is better than having almost same code duplicated in several places or
ugly ifdefs like:
#if defined(CONFIG_BOOK3S64) || defined(CONFIG_PPC_8xx) || defined
(CONFIG_BOOKE)
flags &= ~_PAGE_PRIVILEGED;
#endif
#if !defined(CONFIG_BOOK3S64) && !defined(CONFIG_PPC_8xx)
flags |= _PAGE_USER;
#endif
It looks to me that patch
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=812fadcb941a81d1f3948b10a95a4dce663da3e4
allowed a nice code simplification, don't you feel the same ?
Christophe
>
>
>>
>> #define _PAGE_EXEC 0x00001 /* execute permission */
>> #define _PAGE_WRITE 0x00002 /* write access allowed */
>> diff --git a/arch/powerpc/mm/ioremap.c b/arch/powerpc/mm/ioremap.c
>> index 65d611d44d38..59be5dfcb3e9 100644
>> --- a/arch/powerpc/mm/ioremap.c
>> +++ b/arch/powerpc/mm/ioremap.c
>> @@ -33,95 +33,6 @@ unsigned long ioremap_bot;
>> unsigned long ioremap_bot = IOREMAP_BASE;
>> #endif
>>
>> -#ifdef CONFIG_PPC32
>> -
>> -void __iomem *
>> -__ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
>> - void *caller)
>> -{
>> - unsigned long v, i;
>> - phys_addr_t p;
>> - int err;
>> -
>> - /* Make sure we have the base flags */
>> - if ((flags & _PAGE_PRESENT) == 0)
>> - flags |= pgprot_val(PAGE_KERNEL);
>> -
>> - /* Non-cacheable page cannot be coherent */
>> - if (flags & _PAGE_NO_CACHE)
>> - flags &= ~_PAGE_COHERENT;
>> -
>> - /*
>> - * Choose an address to map it to.
>> - * Once the vmalloc system is running, we use it.
>> - * Before then, we use space going up from IOREMAP_BASE
>> - * (ioremap_bot records where we're up to).
>> - */
>> - p = addr & PAGE_MASK;
>> - size = PAGE_ALIGN(addr + size) - p;
>> -
>> - /*
>> - * If the address lies within the first 16 MB, assume it's in ISA
>> - * memory space
>> - */
>> - if (p < 16*1024*1024)
>> - p += _ISA_MEM_BASE;
>> -
>> -#ifndef CONFIG_CRASH_DUMP
>> - /*
>> - * Don't allow anybody to remap normal RAM that we're using.
>> - * mem_init() sets high_memory so only do the check after that.
>> - */
>> - if (slab_is_available() && (p < virt_to_phys(high_memory)) &&
>> - page_is_ram(__phys_to_pfn(p))) {
>> - printk("__ioremap(): phys addr 0x%llx is RAM lr %ps\n",
>> - (unsigned long long)p, __builtin_return_address(0));
>> - return NULL;
>> - }
>> -#endif
>> -
>> - if (size == 0)
>> - return NULL;
>> -
>> - /*
>> - * Is it already mapped? Perhaps overlapped by a previous
>> - * mapping.
>> - */
>> - v = p_block_mapped(p);
>> - if (v)
>> - goto out;
>> -
>> - if (slab_is_available()) {
>> - struct vm_struct *area;
>> - area = get_vm_area_caller(size, VM_IOREMAP, caller);
>> - if (area == 0)
>> - return NULL;
>> - area->phys_addr = p;
>> - v = (unsigned long) area->addr;
>> - } else {
>> - v = ioremap_bot;
>> - ioremap_bot += size;
>> - }
>> -
>> - /*
>> - * Should check if it is a candidate for a BAT mapping
>> - */
>> -
>> - err = 0;
>> - for (i = 0; i < size && err == 0; i += PAGE_SIZE)
>> - err = map_kernel_page(v+i, p+i, flags);
>> - if (err) {
>> - if (slab_is_available())
>> - vunmap((void *)v);
>> - return NULL;
>> - }
>> -
>> -out:
>> - return (void __iomem *) (v + ((unsigned long)addr & ~PAGE_MASK));
>> -}
>> -
>> -#else
>> -
>> /**
>> * __ioremap_at - Low level function to establish the page tables
>> * for an IO mapping
>> @@ -135,6 +46,10 @@ void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size,
>> if ((flags & _PAGE_PRESENT) == 0)
>> flags |= pgprot_val(PAGE_KERNEL);
>>
>> + /* Non-cacheable page cannot be coherent */
>> + if (flags & _PAGE_NO_CACHE)
>> + flags &= ~_PAGE_COHERENT;
>> +
>> /* We don't support the 4K PFN hack with ioremap */
>> if (flags & H_PAGE_4K_PFN)
>> return NULL;
>> @@ -187,6 +102,33 @@ void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size,
>> if ((size == 0) || (paligned == 0))
>> return NULL;
>>
>> + /*
>> + * If the address lies within the first 16 MB, assume it's in ISA
>> + * memory space
>> + */
>> + if (IS_ENABLED(CONFIG_PPC32) && paligned < 16*1024*1024)
>> + paligned += _ISA_MEM_BASE;
>> +
>> + /*
>> + * Don't allow anybody to remap normal RAM that we're using.
>> + * mem_init() sets high_memory so only do the check after that.
>> + */
>> + if (!IS_ENABLED(CONFIG_CRASH_DUMP) &&
>> + slab_is_available() && (paligned < virt_to_phys(high_memory)) &&
>> + page_is_ram(__phys_to_pfn(paligned))) {
>> + printk("__ioremap(): phys addr 0x%llx is RAM lr %ps\n",
>> + (u64)paligned, __builtin_return_address(0));
>> + return NULL;
>> + }
>> +
>> + /*
>> + * Is it already mapped? Perhaps overlapped by a previous
>> + * mapping.
>> + */
>> + ret = (void __iomem *)p_block_mapped(paligned);
>> + if (ret)
>> + goto out;
>> +
>> if (slab_is_available()) {
>> struct vm_struct *area;
>>
>> @@ -205,14 +147,12 @@ void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size,
>> if (ret)
>> ioremap_bot += size;
>> }
>> -
>> +out:
>> if (ret)
>> - ret += addr & ~PAGE_MASK;
>> + ret += (unsigned long)addr & ~PAGE_MASK;
>> return ret;
>> }
>>
>> -#endif
>> -
>> /*
>> * Unmap an IO region and remove it from imalloc'd list.
>> * Access to IO memory should be serialized by driver.
>> --
>> 2.13.3
More information about the Linuxppc-dev
mailing list