diff options
author | Chris Metcalf <cmetcalf@tilera.com> | 2013-08-15 16:29:02 -0400 |
---|---|---|
committer | Chris Metcalf <cmetcalf@tilera.com> | 2013-09-03 14:53:32 -0400 |
commit | ce61cdc270a5e0dd18057bbf29bd3471abccbda8 (patch) | |
tree | 354d229299b6b02d98f40e5c650e6ddbc3411b7b | |
parent | d7c9661115fd23b4dabb710b3080dd9919dfa891 (diff) |
tile: make __write_once a synonym for __read_mostly
This was really only useful for TILE64 when we mapped the
kernel data with small pages. Now we use a huge page and we
really don't want to map different parts of the kernel
data in different ways.
We retain the __write_once name in case we want to bring
it back to life at some point in the future.
Note that this change uncovered a latent bug where the
"smp_topology" variable happened to always be aligned mod 8
so we could store two "int" values at once, but when we
eliminated __write_once it ended up only aligned mod 4.
Fix with an explicit annotation.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
-rw-r--r-- | arch/tile/include/asm/cache.h | 13 | ||||
-rw-r--r-- | arch/tile/kernel/smp.c | 6 | ||||
-rw-r--r-- | arch/tile/kernel/vmlinux.lds.S | 12 | ||||
-rw-r--r-- | arch/tile/mm/init.c | 13 |
4 files changed, 17 insertions, 27 deletions
diff --git a/arch/tile/include/asm/cache.h b/arch/tile/include/asm/cache.h index a9a529964e07..6160761d5f61 100644 --- a/arch/tile/include/asm/cache.h +++ b/arch/tile/include/asm/cache.h | |||
@@ -49,9 +49,16 @@ | |||
49 | #define __read_mostly __attribute__((__section__(".data..read_mostly"))) | 49 | #define __read_mostly __attribute__((__section__(".data..read_mostly"))) |
50 | 50 | ||
51 | /* | 51 | /* |
52 | * Attribute for data that is kept read/write coherent until the end of | 52 | * Originally we used small TLB pages for kernel data and grouped some |
53 | * initialization, then bumped to read/only incoherent for performance. | 53 | * things together as "write once", enforcing the property at the end |
54 | * of initialization by making those pages read-only and non-coherent. | ||
55 | * This allowed better cache utilization since cache inclusion did not | ||
56 | * need to be maintained. However, to do this requires an extra TLB | ||
57 | * entry, which on balance is more of a performance hit than the | ||
58 | * non-coherence is a performance gain, so we now just make "read | ||
59 | * mostly" and "write once" be synonyms. We keep the attribute | ||
60 | * separate in case we change our minds at a future date. | ||
54 | */ | 61 | */ |
55 | #define __write_once __attribute__((__section__(".w1data"))) | 62 | #define __write_once __read_mostly |
56 | 63 | ||
57 | #endif /* _ASM_TILE_CACHE_H */ | 64 | #endif /* _ASM_TILE_CACHE_H */ |
diff --git a/arch/tile/kernel/smp.c b/arch/tile/kernel/smp.c index 0ae1c594d883..01e8ab29f43a 100644 --- a/arch/tile/kernel/smp.c +++ b/arch/tile/kernel/smp.c | |||
@@ -22,7 +22,11 @@ | |||
22 | #include <asm/cacheflush.h> | 22 | #include <asm/cacheflush.h> |
23 | #include <asm/homecache.h> | 23 | #include <asm/homecache.h> |
24 | 24 | ||
25 | HV_Topology smp_topology __write_once; | 25 | /* |
26 | * We write to width and height with a single store in head_NN.S, | ||
27 | * so make the variable aligned to "long". | ||
28 | */ | ||
29 | HV_Topology smp_topology __write_once __aligned(sizeof(long)); | ||
26 | EXPORT_SYMBOL(smp_topology); | 30 | EXPORT_SYMBOL(smp_topology); |
27 | 31 | ||
28 | #if CHIP_HAS_IPI() | 32 | #if CHIP_HAS_IPI() |
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S index 8b2016307eb0..f1819423ffc9 100644 --- a/arch/tile/kernel/vmlinux.lds.S +++ b/arch/tile/kernel/vmlinux.lds.S | |||
@@ -74,20 +74,8 @@ SECTIONS | |||
74 | __init_end = .; | 74 | __init_end = .; |
75 | 75 | ||
76 | _sdata = .; /* Start of data section */ | 76 | _sdata = .; /* Start of data section */ |
77 | |||
78 | RO_DATA_SECTION(PAGE_SIZE) | 77 | RO_DATA_SECTION(PAGE_SIZE) |
79 | |||
80 | /* initially writeable, then read-only */ | ||
81 | . = ALIGN(PAGE_SIZE); | ||
82 | __w1data_begin = .; | ||
83 | .w1data : AT(ADDR(.w1data) - LOAD_OFFSET) { | ||
84 | VMLINUX_SYMBOL(__w1data_begin) = .; | ||
85 | *(.w1data) | ||
86 | VMLINUX_SYMBOL(__w1data_end) = .; | ||
87 | } | ||
88 | |||
89 | RW_DATA_SECTION(L2_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) | 78 | RW_DATA_SECTION(L2_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) |
90 | |||
91 | _edata = .; | 79 | _edata = .; |
92 | 80 | ||
93 | EXCEPTION_TABLE(L2_CACHE_BYTES) | 81 | EXCEPTION_TABLE(L2_CACHE_BYTES) |
diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c index 22e41cf5a2a9..4e316deb92fd 100644 --- a/arch/tile/mm/init.c +++ b/arch/tile/mm/init.c | |||
@@ -271,21 +271,13 @@ static pgprot_t __init init_pgprot(ulong address) | |||
271 | return construct_pgprot(PAGE_KERNEL, PAGE_HOME_HASH); | 271 | return construct_pgprot(PAGE_KERNEL, PAGE_HOME_HASH); |
272 | 272 | ||
273 | /* | 273 | /* |
274 | * Make the w1data homed like heap to start with, to avoid | ||
275 | * making it part of the page-striped data area when we're just | ||
276 | * going to convert it to read-only soon anyway. | ||
277 | */ | ||
278 | if (address >= (ulong)__w1data_begin && address < (ulong)__w1data_end) | ||
279 | return construct_pgprot(PAGE_KERNEL, initial_heap_home()); | ||
280 | |||
281 | /* | ||
282 | * Otherwise we just hand out consecutive cpus. To avoid | 274 | * Otherwise we just hand out consecutive cpus. To avoid |
283 | * requiring this function to hold state, we just walk forward from | 275 | * requiring this function to hold state, we just walk forward from |
284 | * _sdata by PAGE_SIZE, skipping the readonly and init data, to reach | 276 | * _sdata by PAGE_SIZE, skipping the readonly and init data, to reach |
285 | * the requested address, while walking cpu home around kdata_mask. | 277 | * the requested address, while walking cpu home around kdata_mask. |
286 | * This is typically no more than a dozen or so iterations. | 278 | * This is typically no more than a dozen or so iterations. |
287 | */ | 279 | */ |
288 | page = (((ulong)__w1data_end) + PAGE_SIZE - 1) & PAGE_MASK; | 280 | page = (((ulong)__end_rodata) + PAGE_SIZE - 1) & PAGE_MASK; |
289 | BUG_ON(address < page || address >= (ulong)_end); | 281 | BUG_ON(address < page || address >= (ulong)_end); |
290 | cpu = cpumask_first(&kdata_mask); | 282 | cpu = cpumask_first(&kdata_mask); |
291 | for (; page < address; page += PAGE_SIZE) { | 283 | for (; page < address; page += PAGE_SIZE) { |
@@ -980,8 +972,7 @@ void free_initmem(void) | |||
980 | const unsigned long text_delta = MEM_SV_START - PAGE_OFFSET; | 972 | const unsigned long text_delta = MEM_SV_START - PAGE_OFFSET; |
981 | 973 | ||
982 | /* | 974 | /* |
983 | * Evict the dirty initdata on the boot cpu, evict the w1data | 975 | * Evict the cache on all cores to avoid incoherence. |
984 | * wherever it's homed, and evict all the init code everywhere. | ||
985 | * We are guaranteed that no one will touch the init pages any more. | 976 | * We are guaranteed that no one will touch the init pages any more. |
986 | */ | 977 | */ |
987 | homecache_evict(&cpu_cacheable_map); | 978 | homecache_evict(&cpu_cacheable_map); |