Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xtensa: make fixmap region addressing grow with index

It's much easier to reason about alignment and coloring of regions
located in the fixmap when fixmap index is just a PFN within the fixmap
region. Change fixmap addressing so that index 0 corresponds to
FIXADDR_START instead of the FIXADDR_TOP.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>

+27 -6
+24 -3
arch/xtensa/include/asm/fixmap.h
··· 23 23 * Here we define all the compile-time 'special' virtual 24 24 * addresses. The point is to have a constant address at 25 25 * compile time, but to set the physical address only 26 - * in the boot process. We allocate these special addresses 27 - * from the end of the consistent memory region backwards. 26 + * in the boot process. We allocate these special addresses 27 + * from the start of the consistent memory region upwards. 28 28 * Also this lets us do fail-safe vmalloc(), we 29 29 * can guarantee that these special addresses and 30 30 * vmalloc()-ed addresses never overlap. ··· 47 47 #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) 48 48 #define FIXADDR_START ((FIXADDR_TOP - FIXADDR_SIZE) & PMD_MASK) 49 49 50 - #include <asm-generic/fixmap.h> 50 + #define __fix_to_virt(x) (FIXADDR_START + ((x) << PAGE_SHIFT)) 51 + #define __virt_to_fix(x) (((x) - FIXADDR_START) >> PAGE_SHIFT) 52 + 53 + #ifndef __ASSEMBLY__ 54 + /* 55 + * 'index to address' translation. If anyone tries to use the idx 56 + * directly without translation, we catch the bug with a NULL-deference 57 + * kernel oops. Illegal ranges of incoming indices are caught too. 58 + */ 59 + static __always_inline unsigned long fix_to_virt(const unsigned int idx) 60 + { 61 + BUILD_BUG_ON(idx >= __end_of_fixed_addresses); 62 + return __fix_to_virt(idx); 63 + } 64 + 65 + static inline unsigned long virt_to_fix(const unsigned long vaddr) 66 + { 67 + BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); 68 + return __virt_to_fix(vaddr); 69 + } 70 + 71 + #endif 51 72 52 73 #define kmap_get_fixmap_pte(vaddr) \ 53 74 pte_offset_kernel( \
+3 -3
arch/xtensa/mm/highmem.c
··· 28 28 idx = type + KM_TYPE_NR * smp_processor_id(); 29 29 vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); 30 30 #ifdef CONFIG_DEBUG_HIGHMEM 31 - BUG_ON(!pte_none(*(kmap_pte - idx))); 31 + BUG_ON(!pte_none(*(kmap_pte + idx))); 32 32 #endif 33 - set_pte(kmap_pte - idx, mk_pte(page, PAGE_KERNEL_EXEC)); 33 + set_pte(kmap_pte + idx, mk_pte(page, PAGE_KERNEL_EXEC)); 34 34 35 35 return (void *)vaddr; 36 36 } ··· 51 51 * is a bad idea also, in case the page changes cacheability 52 52 * attributes or becomes a protected page in a hypervisor. 53 53 */ 54 - pte_clear(&init_mm, kvaddr, kmap_pte - idx); 54 + pte_clear(&init_mm, kvaddr, kmap_pte + idx); 55 55 local_flush_tlb_kernel_range((unsigned long)kvaddr, 56 56 (unsigned long)kvaddr + PAGE_SIZE); 57 57