mm: make 'highmem' symbol ro_after_init
Subsystems (2)
PATCH 1/1 mm: make 'highmem' symbol ro_after_init
The 'highmem' variable is only set at boot, so we can make it ro_after_init and prevent it from being corrupted inadvertently, or from ending up in a contended cacheline.
--- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/memory.c +1 -1
@@ -106,7 +106,7 @@ EXPORT_SYMBOL(mem_map);* highstart_pfn must be the same; there must be no gap between ZONE_NORMAL * and ZONE_HIGHMEM. */ -void *high_memory; +void *high_memory__ro_after_init ;EXPORT_SYMBOL (high_memory);/*
Signature · 1 line
2.30.2
mm/memory.c EXPORT_SYMBOL(mem_map); · line 112
Quoted 13 lines · Ard Biesheuvel
mm/memory.c +1
-1@@ -106,7 +106,7 @@ EXPORT_SYMBOL(mem_map);* highstart_pfn must be the same; there must be no gap between ZONE_NORMAL * and ZONE_HIGHMEM. */ -void *high_memory; +void *high_memory__ro_after_init ;EXPORT_SYMBOL (high_memory);/*
Same should be true for the mm/nommu.c variant?
Quoted 3 lines · Ard Biesheuvel
The 'highmem' variable is only set at boot, so we can make it
ro_after_initand prevent it from being corrupted inadvertently, or from ending up in a contended cacheline.
I'm not against this patch, but it'd be nice to go further and remove it entirely for !CONFIG_HIGHMEM builds? Adding something like
static inline bool is_high_pfn(unsigned long pfn)
{
#ifdef CONFIG_HIGHMEM return pfn <= max_low_pfn; #else return false;
#endif
}
static inline bool is_high_phys(phys_addr_t pa)
{
return is_high_pfn(pa / PAGE_SIZE);
}static inline bool is_high_addr(void *addr)
{
return is_high_phys(virt_to_phys(addr));
}should be all the primitives you need, from a quick grep.
Quoted 22 lines
Signed-off-by Ard Biesheuvel <[email protected]>--- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)mm/memory.c +1
-1@@ -106,7 +106,7 @@ EXPORT_SYMBOL(mem_map);* highstart_pfn must be the same; there must be no gap between ZONE_NORMAL * and ZONE_HIGHMEM. */ -void *high_memory; +void *high_memory__ro_after_init ;EXPORT_SYMBOL (high_memory);/* Signature · 1 line
2.30.2
Quoted 5 lines · Ard Biesheuvel
The 'highmem' variable is only set at boot, so we can make it
ro_after_initand prevent it from being corrupted inadvertently, or from ending up in a contended cacheline.Signed-off-by Ard Biesheuvel <[email protected]>
Quoted 21 lines
--- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)mm/memory.c +1
-1@@ -106,7 +106,7 @@ EXPORT_SYMBOL(mem_map);* highstart_pfn must be the same; there must be no gap between ZONE_NORMAL * and ZONE_HIGHMEM. */ -void *high_memory; +void *high_memory__ro_after_init ;EXPORT_SYMBOL (high_memory);/* Signature · 1 line
2.30.2
Signature · 2 lines
Sincerely yours, Mike.
Quoted 26 lines · Mike Rapoport
Quoted 5 lines · Ard Biesheuvel
The 'highmem' variable is only set at boot, so we can make it
ro_after_initand prevent it from being corrupted inadvertently, or from ending up in a contended cacheline.Signed-off-by Ard Biesheuvel <[email protected]>Acked-by Mike Rapoport <[email protected]>Quoted 16 lines
--- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)mm/memory.c +1
-1@@ -106,7 +106,7 @@ EXPORT_SYMBOL(mem_map);* highstart_pfn must be the same; there must be no gap between ZONE_NORMAL * and ZONE_HIGHMEM. */ -void *high_memory; +void *high_memory__ro_after_init ;EXPORT_SYMBOL (high_memory);
Quoted 6 lines
Quoted 5 lines
mm/memory.c +0
-1/* -- 2.30.2
This turns out to break CONFIG_MEMORY_HOTPLUG on x86, as it updates max_pfn, max_low_pfn and high_memory after init.
So probably best to make all of those __read_mostly instead.