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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'arc-4.6-rc7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc

Pull ARC fixes from Vineet Gupta:
"Late in the cycle, but this has fixes for couple of issues: a PAE40
boot crash and Arnd spotting lack of barriers in BE io-accessors.

The 3rd patch for enabling highmem in low physical mem ;-) honestly is
more than a "fix" but its been in works for some time, seems to be
stable in testing and enables 2 of our customers to go forward with
4.6 kernel.

- Fix for PTE truncation in PAE40 builds
- Fix for big endian IO accessors lacking IO barrier
- Allow HIGHMEM to work with low physical addresses"

* tag 'arc-4.6-rc7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc:
ARC: support HIGHMEM even without PAE40
ARC: Fix PAE40 boot failures due to PTE truncation
ARC: Add missing io barriers to io{read,write}{16,32}be()

+130 -35
+13
arch/arc/Kconfig
··· 58 58 config RWSEM_GENERIC_SPINLOCK 59 59 def_bool y 60 60 61 + config ARCH_DISCONTIGMEM_ENABLE 62 + def_bool y 63 + 61 64 config ARCH_FLATMEM_ENABLE 62 65 def_bool y 63 66 ··· 350 347 351 348 endchoice 352 349 350 + config NODES_SHIFT 351 + int "Maximum NUMA Nodes (as a power of 2)" 352 + default "1" if !DISCONTIGMEM 353 + default "2" if DISCONTIGMEM 354 + depends on NEED_MULTIPLE_NODES 355 + ---help--- 356 + Accessing memory beyond 1GB (with or w/o PAE) requires 2 memory 357 + zones. 358 + 353 359 if ISA_ARCOMPACT 354 360 355 361 config ARC_COMPACT_IRQ_LEVELS ··· 467 455 468 456 config HIGHMEM 469 457 bool "High Memory Support" 458 + select DISCONTIGMEM 470 459 help 471 460 With ARC 2G:2G address split, only upper 2G is directly addressable by 472 461 kernel. Enable this to potentially allow access to rest of 2G and PAE
+18 -9
arch/arc/include/asm/io.h
··· 13 13 #include <asm/byteorder.h> 14 14 #include <asm/page.h> 15 15 16 + #ifdef CONFIG_ISA_ARCV2 17 + #include <asm/barrier.h> 18 + #define __iormb() rmb() 19 + #define __iowmb() wmb() 20 + #else 21 + #define __iormb() do { } while (0) 22 + #define __iowmb() do { } while (0) 23 + #endif 24 + 16 25 extern void __iomem *ioremap(phys_addr_t paddr, unsigned long size); 17 26 extern void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size, 18 27 unsigned long flags); ··· 39 30 #define ioremap_nocache(phy, sz) ioremap(phy, sz) 40 31 #define ioremap_wc(phy, sz) ioremap(phy, sz) 41 32 #define ioremap_wt(phy, sz) ioremap(phy, sz) 33 + 34 + /* 35 + * io{read,write}{16,32}be() macros 36 + */ 37 + #define ioread16be(p) ({ u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; }) 38 + #define ioread32be(p) ({ u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; }) 39 + 40 + #define iowrite16be(v,p) ({ __iowmb(); __raw_writew((__force u16)cpu_to_be16(v), p); }) 41 + #define iowrite32be(v,p) ({ __iowmb(); __raw_writel((__force u32)cpu_to_be32(v), p); }) 42 42 43 43 /* Change struct page to physical address */ 44 44 #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) ··· 125 107 : "memory"); 126 108 127 109 } 128 - 129 - #ifdef CONFIG_ISA_ARCV2 130 - #include <asm/barrier.h> 131 - #define __iormb() rmb() 132 - #define __iowmb() wmb() 133 - #else 134 - #define __iormb() do { } while (0) 135 - #define __iowmb() do { } while (0) 136 - #endif 137 110 138 111 /* 139 112 * MMIO can also get buffered/optimized in micro-arch, so barriers needed
+43
arch/arc/include/asm/mmzone.h
··· 1 + /* 2 + * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com) 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + */ 8 + 9 + #ifndef _ASM_ARC_MMZONE_H 10 + #define _ASM_ARC_MMZONE_H 11 + 12 + #ifdef CONFIG_DISCONTIGMEM 13 + 14 + extern struct pglist_data node_data[]; 15 + #define NODE_DATA(nid) (&node_data[nid]) 16 + 17 + static inline int pfn_to_nid(unsigned long pfn) 18 + { 19 + int is_end_low = 1; 20 + 21 + if (IS_ENABLED(CONFIG_ARC_HAS_PAE40)) 22 + is_end_low = pfn <= virt_to_pfn(0xFFFFFFFFUL); 23 + 24 + /* 25 + * node 0: lowmem: 0x8000_0000 to 0xFFFF_FFFF 26 + * node 1: HIGHMEM w/o PAE40: 0x0 to 0x7FFF_FFFF 27 + * HIGHMEM with PAE40: 0x1_0000_0000 to ... 28 + */ 29 + if (pfn >= ARCH_PFN_OFFSET && is_end_low) 30 + return 0; 31 + 32 + return 1; 33 + } 34 + 35 + static inline int pfn_valid(unsigned long pfn) 36 + { 37 + int nid = pfn_to_nid(pfn); 38 + 39 + return (pfn <= node_end_pfn(nid)); 40 + } 41 + #endif /* CONFIG_DISCONTIGMEM */ 42 + 43 + #endif
+11 -4
arch/arc/include/asm/page.h
··· 72 72 73 73 typedef pte_t * pgtable_t; 74 74 75 + /* 76 + * Use virt_to_pfn with caution: 77 + * If used in pte or paddr related macros, it could cause truncation 78 + * in PAE40 builds 79 + * As a rule of thumb, only use it in helpers starting with virt_ 80 + * You have been warned ! 81 + */ 75 82 #define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) 76 83 77 84 #define ARCH_PFN_OFFSET virt_to_pfn(CONFIG_LINUX_LINK_BASE) 78 85 86 + #ifdef CONFIG_FLATMEM 79 87 #define pfn_valid(pfn) (((pfn) - ARCH_PFN_OFFSET) < max_mapnr) 88 + #endif 80 89 81 90 /* 82 91 * __pa, __va, virt_to_page (ALERT: deprecated, don't use them) ··· 94 85 * virt here means link-address/program-address as embedded in object code. 95 86 * And for ARC, link-addr = physical address 96 87 */ 97 - #define __pa(vaddr) ((unsigned long)vaddr) 88 + #define __pa(vaddr) ((unsigned long)(vaddr)) 98 89 #define __va(paddr) ((void *)((unsigned long)(paddr))) 99 90 100 - #define virt_to_page(kaddr) \ 101 - (mem_map + virt_to_pfn((kaddr) - CONFIG_LINUX_LINK_BASE)) 102 - 91 + #define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr)) 103 92 #define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr)) 104 93 105 94 /* Default Permissions for stack/heaps pages (Non Executable) */
+6 -7
arch/arc/include/asm/pgtable.h
··· 278 278 #define pmd_present(x) (pmd_val(x)) 279 279 #define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0) 280 280 281 - #define pte_page(pte) \ 282 - (mem_map + virt_to_pfn(pte_val(pte) - CONFIG_LINUX_LINK_BASE)) 283 - 281 + #define pte_page(pte) pfn_to_page(pte_pfn(pte)) 284 282 #define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot) 285 - #define pte_pfn(pte) virt_to_pfn(pte_val(pte)) 286 - #define pfn_pte(pfn, prot) (__pte(((pte_t)(pfn) << PAGE_SHIFT) | \ 287 - pgprot_val(prot))) 288 - #define __pte_index(addr) (virt_to_pfn(addr) & (PTRS_PER_PTE - 1)) 283 + #define pfn_pte(pfn, prot) (__pte(((pte_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) 284 + 285 + /* Don't use virt_to_pfn for macros below: could cause truncations for PAE40*/ 286 + #define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT) 287 + #define __pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) 289 288 290 289 /* 291 290 * pte_offset gets a @ptr to PMD entry (PGD in our 2-tier paging system)
+39 -15
arch/arc/mm/init.c
··· 30 30 static unsigned long low_mem_sz; 31 31 32 32 #ifdef CONFIG_HIGHMEM 33 - static unsigned long min_high_pfn; 33 + static unsigned long min_high_pfn, max_high_pfn; 34 34 static u64 high_mem_start; 35 35 static u64 high_mem_sz; 36 + #endif 37 + 38 + #ifdef CONFIG_DISCONTIGMEM 39 + struct pglist_data node_data[MAX_NUMNODES] __read_mostly; 40 + EXPORT_SYMBOL(node_data); 36 41 #endif 37 42 38 43 /* User can over-ride above with "mem=nnn[KkMm]" in cmdline */ ··· 114 109 /* Last usable page of low mem */ 115 110 max_low_pfn = max_pfn = PFN_DOWN(low_mem_start + low_mem_sz); 116 111 117 - #ifdef CONFIG_HIGHMEM 118 - min_high_pfn = PFN_DOWN(high_mem_start); 119 - max_pfn = PFN_DOWN(high_mem_start + high_mem_sz); 112 + #ifdef CONFIG_FLATMEM 113 + /* pfn_valid() uses this */ 114 + max_mapnr = max_low_pfn - min_low_pfn; 120 115 #endif 121 - 122 - max_mapnr = max_pfn - min_low_pfn; 123 116 124 117 /*------------- bootmem allocator setup -----------------------*/ 125 118 ··· 132 129 * the crash 133 130 */ 134 131 135 - memblock_add(low_mem_start, low_mem_sz); 132 + memblock_add_node(low_mem_start, low_mem_sz, 0); 136 133 memblock_reserve(low_mem_start, __pa(_end) - low_mem_start); 137 134 138 135 #ifdef CONFIG_BLK_DEV_INITRD ··· 152 149 zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn; 153 150 zones_holes[ZONE_NORMAL] = 0; 154 151 155 - #ifdef CONFIG_HIGHMEM 156 - zones_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn; 157 - 158 - /* This handles the peripheral address space hole */ 159 - zones_holes[ZONE_HIGHMEM] = min_high_pfn - max_low_pfn; 160 - #endif 161 - 162 152 /* 163 153 * We can't use the helper free_area_init(zones[]) because it uses 164 154 * PAGE_OFFSET to compute the @min_low_pfn which would be wrong ··· 164 168 zones_holes); /* holes */ 165 169 166 170 #ifdef CONFIG_HIGHMEM 171 + /* 172 + * Populate a new node with highmem 173 + * 174 + * On ARC (w/o PAE) HIGHMEM addresses are actually smaller (0 based) 175 + * than addresses in normal ala low memory (0x8000_0000 based). 176 + * Even with PAE, the huge peripheral space hole would waste a lot of 177 + * mem with single mem_map[]. This warrants a mem_map per region design. 178 + * Thus HIGHMEM on ARC is imlemented with DISCONTIGMEM. 179 + * 180 + * DISCONTIGMEM in turns requires multiple nodes. node 0 above is 181 + * populated with normal memory zone while node 1 only has highmem 182 + */ 183 + node_set_online(1); 184 + 185 + min_high_pfn = PFN_DOWN(high_mem_start); 186 + max_high_pfn = PFN_DOWN(high_mem_start + high_mem_sz); 187 + 188 + zones_size[ZONE_NORMAL] = 0; 189 + zones_holes[ZONE_NORMAL] = 0; 190 + 191 + zones_size[ZONE_HIGHMEM] = max_high_pfn - min_high_pfn; 192 + zones_holes[ZONE_HIGHMEM] = 0; 193 + 194 + free_area_init_node(1, /* node-id */ 195 + zones_size, /* num pages per zone */ 196 + min_high_pfn, /* first pfn of node */ 197 + zones_holes); /* holes */ 198 + 167 199 high_memory = (void *)(min_high_pfn << PAGE_SHIFT); 168 200 kmap_init(); 169 201 #endif ··· 209 185 unsigned long tmp; 210 186 211 187 reset_all_zones_managed_pages(); 212 - for (tmp = min_high_pfn; tmp < max_pfn; tmp++) 188 + for (tmp = min_high_pfn; tmp < max_high_pfn; tmp++) 213 189 free_highmem_page(pfn_to_page(tmp)); 214 190 #endif 215 191