Merge branch 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm
Pull ARM updates from Russell King: "These are late by a week; they should have been merged during the merge window, but unfortunately, the ARM kernel build/boot farms were indicating random failures, and it wasn't clear whether the cause was something in these changes or something during the merge window. This is a set of merge window fixes with some documentation additions" * 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm: ARM: avoid unwanted GCC memset()/memcpy() optimisations for IO variants ARM: pgtable: document mapping types ARM: io: convert ioremap*() to functions ARM: io: fix ioremap_wt() implementation ARM: io: document ARM specific behaviour of ioremap*() implementations ARM: fix lockdep unannotated irqs-off warning ARM: 8397/1: fix vdsomunge not to depend on glibc specific error.h ARM: add helpful message when truncating physical memory ARM: add help text for HIGHPTE configuration entry ARM: fix DEBUG_SET_MODULE_RONX build dependencies ARM: 8396/1: use phys_addr_t in pfn_to_kaddr() ARM: 8394/1: update memblock limit after mapping lowmem ARM: 8393/1: smp: Fix suspicious RCU usage with ipi tracepoints
This commit is contained in:
commit
d6ac4ffc61
|
@ -1693,6 +1693,12 @@ config HIGHMEM
|
||||||
config HIGHPTE
|
config HIGHPTE
|
||||||
bool "Allocate 2nd-level pagetables from highmem"
|
bool "Allocate 2nd-level pagetables from highmem"
|
||||||
depends on HIGHMEM
|
depends on HIGHMEM
|
||||||
|
help
|
||||||
|
The VM uses one page of physical memory for each page table.
|
||||||
|
For systems with a lot of processes, this can use a lot of
|
||||||
|
precious low memory, eventually leading to low memory being
|
||||||
|
consumed by page tables. Setting this option will allow
|
||||||
|
user-space 2nd level page tables to reside in high memory.
|
||||||
|
|
||||||
config HW_PERF_EVENTS
|
config HW_PERF_EVENTS
|
||||||
bool "Enable hardware performance counter support for perf events"
|
bool "Enable hardware performance counter support for perf events"
|
||||||
|
|
|
@ -1635,7 +1635,7 @@ config PID_IN_CONTEXTIDR
|
||||||
|
|
||||||
config DEBUG_SET_MODULE_RONX
|
config DEBUG_SET_MODULE_RONX
|
||||||
bool "Set loadable kernel module data as NX and text as RO"
|
bool "Set loadable kernel module data as NX and text as RO"
|
||||||
depends on MODULES
|
depends on MODULES && MMU
|
||||||
---help---
|
---help---
|
||||||
This option helps catch unintended modifications to loadable
|
This option helps catch unintended modifications to loadable
|
||||||
kernel module's text and read-only data. It also prevents execution
|
kernel module's text and read-only data. It also prevents execution
|
||||||
|
|
|
@ -140,16 +140,11 @@ static inline u32 __raw_readl(const volatile void __iomem *addr)
|
||||||
* The _caller variety takes a __builtin_return_address(0) value for
|
* The _caller variety takes a __builtin_return_address(0) value for
|
||||||
* /proc/vmalloc to use - and should only be used in non-inline functions.
|
* /proc/vmalloc to use - and should only be used in non-inline functions.
|
||||||
*/
|
*/
|
||||||
extern void __iomem *__arm_ioremap_pfn_caller(unsigned long, unsigned long,
|
|
||||||
size_t, unsigned int, void *);
|
|
||||||
extern void __iomem *__arm_ioremap_caller(phys_addr_t, size_t, unsigned int,
|
extern void __iomem *__arm_ioremap_caller(phys_addr_t, size_t, unsigned int,
|
||||||
void *);
|
void *);
|
||||||
|
|
||||||
extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int);
|
extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int);
|
||||||
extern void __iomem *__arm_ioremap(phys_addr_t, size_t, unsigned int);
|
|
||||||
extern void __iomem *__arm_ioremap_exec(phys_addr_t, size_t, bool cached);
|
extern void __iomem *__arm_ioremap_exec(phys_addr_t, size_t, bool cached);
|
||||||
extern void __iounmap(volatile void __iomem *addr);
|
extern void __iounmap(volatile void __iomem *addr);
|
||||||
extern void __arm_iounmap(volatile void __iomem *addr);
|
|
||||||
|
|
||||||
extern void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t,
|
extern void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t,
|
||||||
unsigned int, void *);
|
unsigned int, void *);
|
||||||
|
@ -321,21 +316,24 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
|
||||||
static inline void memset_io(volatile void __iomem *dst, unsigned c,
|
static inline void memset_io(volatile void __iomem *dst, unsigned c,
|
||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
memset((void __force *)dst, c, count);
|
extern void mmioset(void *, unsigned int, size_t);
|
||||||
|
mmioset((void __force *)dst, c, count);
|
||||||
}
|
}
|
||||||
#define memset_io(dst,c,count) memset_io(dst,c,count)
|
#define memset_io(dst,c,count) memset_io(dst,c,count)
|
||||||
|
|
||||||
static inline void memcpy_fromio(void *to, const volatile void __iomem *from,
|
static inline void memcpy_fromio(void *to, const volatile void __iomem *from,
|
||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
memcpy(to, (const void __force *)from, count);
|
extern void mmiocpy(void *, const void *, size_t);
|
||||||
|
mmiocpy(to, (const void __force *)from, count);
|
||||||
}
|
}
|
||||||
#define memcpy_fromio(to,from,count) memcpy_fromio(to,from,count)
|
#define memcpy_fromio(to,from,count) memcpy_fromio(to,from,count)
|
||||||
|
|
||||||
static inline void memcpy_toio(volatile void __iomem *to, const void *from,
|
static inline void memcpy_toio(volatile void __iomem *to, const void *from,
|
||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
memcpy((void __force *)to, from, count);
|
extern void mmiocpy(void *, const void *, size_t);
|
||||||
|
mmiocpy((void __force *)to, from, count);
|
||||||
}
|
}
|
||||||
#define memcpy_toio(to,from,count) memcpy_toio(to,from,count)
|
#define memcpy_toio(to,from,count) memcpy_toio(to,from,count)
|
||||||
|
|
||||||
|
@ -348,18 +346,61 @@ static inline void memcpy_toio(volatile void __iomem *to, const void *from,
|
||||||
#endif /* readl */
|
#endif /* readl */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ioremap and friends.
|
* ioremap() and friends.
|
||||||
*
|
*
|
||||||
* ioremap takes a PCI memory address, as specified in
|
* ioremap() takes a resource address, and size. Due to the ARM memory
|
||||||
* Documentation/io-mapping.txt.
|
* types, it is important to use the correct ioremap() function as each
|
||||||
|
* mapping has specific properties.
|
||||||
*
|
*
|
||||||
|
* Function Memory type Cacheability Cache hint
|
||||||
|
* ioremap() Device n/a n/a
|
||||||
|
* ioremap_nocache() Device n/a n/a
|
||||||
|
* ioremap_cache() Normal Writeback Read allocate
|
||||||
|
* ioremap_wc() Normal Non-cacheable n/a
|
||||||
|
* ioremap_wt() Normal Non-cacheable n/a
|
||||||
|
*
|
||||||
|
* All device mappings have the following properties:
|
||||||
|
* - no access speculation
|
||||||
|
* - no repetition (eg, on return from an exception)
|
||||||
|
* - number, order and size of accesses are maintained
|
||||||
|
* - unaligned accesses are "unpredictable"
|
||||||
|
* - writes may be delayed before they hit the endpoint device
|
||||||
|
*
|
||||||
|
* ioremap_nocache() is the same as ioremap() as there are too many device
|
||||||
|
* drivers using this for device registers, and documentation which tells
|
||||||
|
* people to use it for such for this to be any different. This is not a
|
||||||
|
* safe fallback for memory-like mappings, or memory regions where the
|
||||||
|
* compiler may generate unaligned accesses - eg, via inlining its own
|
||||||
|
* memcpy.
|
||||||
|
*
|
||||||
|
* All normal memory mappings have the following properties:
|
||||||
|
* - reads can be repeated with no side effects
|
||||||
|
* - repeated reads return the last value written
|
||||||
|
* - reads can fetch additional locations without side effects
|
||||||
|
* - writes can be repeated (in certain cases) with no side effects
|
||||||
|
* - writes can be merged before accessing the target
|
||||||
|
* - unaligned accesses can be supported
|
||||||
|
* - ordering is not guaranteed without explicit dependencies or barrier
|
||||||
|
* instructions
|
||||||
|
* - writes may be delayed before they hit the endpoint memory
|
||||||
|
*
|
||||||
|
* The cache hint is only a performance hint: CPUs may alias these hints.
|
||||||
|
* Eg, a CPU not implementing read allocate but implementing write allocate
|
||||||
|
* will provide a write allocate mapping instead.
|
||||||
*/
|
*/
|
||||||
#define ioremap(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE)
|
void __iomem *ioremap(resource_size_t res_cookie, size_t size);
|
||||||
#define ioremap_nocache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE)
|
#define ioremap ioremap
|
||||||
#define ioremap_cache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
|
#define ioremap_nocache ioremap
|
||||||
#define ioremap_wc(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_WC)
|
|
||||||
#define ioremap_wt(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE)
|
void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size);
|
||||||
#define iounmap __arm_iounmap
|
#define ioremap_cache ioremap_cache
|
||||||
|
|
||||||
|
void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size);
|
||||||
|
#define ioremap_wc ioremap_wc
|
||||||
|
#define ioremap_wt ioremap_wc
|
||||||
|
|
||||||
|
void iounmap(volatile void __iomem *iomem_cookie);
|
||||||
|
#define iounmap iounmap
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* io{read,write}{16,32}be() macros
|
* io{read,write}{16,32}be() macros
|
||||||
|
|
|
@ -275,7 +275,7 @@ static inline void *phys_to_virt(phys_addr_t x)
|
||||||
*/
|
*/
|
||||||
#define __pa(x) __virt_to_phys((unsigned long)(x))
|
#define __pa(x) __virt_to_phys((unsigned long)(x))
|
||||||
#define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x)))
|
#define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x)))
|
||||||
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
|
#define pfn_to_kaddr(pfn) __va((phys_addr_t)(pfn) << PAGE_SHIFT)
|
||||||
|
|
||||||
extern phys_addr_t (*arch_virt_to_idmap)(unsigned long x);
|
extern phys_addr_t (*arch_virt_to_idmap)(unsigned long x);
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,36 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are the memory types, defined to be compatible with
|
* These are the memory types, defined to be compatible with
|
||||||
* pre-ARMv6 CPUs cacheable and bufferable bits: XXCB
|
* pre-ARMv6 CPUs cacheable and bufferable bits: n/a,n/a,C,B
|
||||||
|
* ARMv6+ without TEX remapping, they are a table index.
|
||||||
|
* ARMv6+ with TEX remapping, they correspond to n/a,TEX(0),C,B
|
||||||
|
*
|
||||||
|
* MT type Pre-ARMv6 ARMv6+ type / cacheable status
|
||||||
|
* UNCACHED Uncached Strongly ordered
|
||||||
|
* BUFFERABLE Bufferable Normal memory / non-cacheable
|
||||||
|
* WRITETHROUGH Writethrough Normal memory / write through
|
||||||
|
* WRITEBACK Writeback Normal memory / write back, read alloc
|
||||||
|
* MINICACHE Minicache N/A
|
||||||
|
* WRITEALLOC Writeback Normal memory / write back, write alloc
|
||||||
|
* DEV_SHARED Uncached Device memory (shared)
|
||||||
|
* DEV_NONSHARED Uncached Device memory (non-shared)
|
||||||
|
* DEV_WC Bufferable Normal memory / non-cacheable
|
||||||
|
* DEV_CACHED Writeback Normal memory / write back, read alloc
|
||||||
|
* VECTORS Variable Normal memory / variable
|
||||||
|
*
|
||||||
|
* All normal memory mappings have the following properties:
|
||||||
|
* - reads can be repeated with no side effects
|
||||||
|
* - repeated reads return the last value written
|
||||||
|
* - reads can fetch additional locations without side effects
|
||||||
|
* - writes can be repeated (in certain cases) with no side effects
|
||||||
|
* - writes can be merged before accessing the target
|
||||||
|
* - unaligned accesses can be supported
|
||||||
|
*
|
||||||
|
* All device mappings have the following properties:
|
||||||
|
* - no access speculation
|
||||||
|
* - no repetition (eg, on return from an exception)
|
||||||
|
* - number, order and size of accesses are maintained
|
||||||
|
* - unaligned accesses are "unpredictable"
|
||||||
*/
|
*/
|
||||||
#define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */
|
#define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */
|
||||||
#define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */
|
#define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */
|
||||||
|
|
|
@ -50,6 +50,9 @@ extern void __aeabi_ulcmp(void);
|
||||||
|
|
||||||
extern void fpundefinstr(void);
|
extern void fpundefinstr(void);
|
||||||
|
|
||||||
|
void mmioset(void *, unsigned int, size_t);
|
||||||
|
void mmiocpy(void *, const void *, size_t);
|
||||||
|
|
||||||
/* platform dependent support */
|
/* platform dependent support */
|
||||||
EXPORT_SYMBOL(arm_delay_ops);
|
EXPORT_SYMBOL(arm_delay_ops);
|
||||||
|
|
||||||
|
@ -88,6 +91,9 @@ EXPORT_SYMBOL(memmove);
|
||||||
EXPORT_SYMBOL(memchr);
|
EXPORT_SYMBOL(memchr);
|
||||||
EXPORT_SYMBOL(__memzero);
|
EXPORT_SYMBOL(__memzero);
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(mmioset);
|
||||||
|
EXPORT_SYMBOL(mmiocpy);
|
||||||
|
|
||||||
#ifdef CONFIG_MMU
|
#ifdef CONFIG_MMU
|
||||||
EXPORT_SYMBOL(copy_page);
|
EXPORT_SYMBOL(copy_page);
|
||||||
|
|
||||||
|
|
|
@ -410,7 +410,7 @@ ENDPROC(__fiq_abt)
|
||||||
zero_fp
|
zero_fp
|
||||||
|
|
||||||
.if \trace
|
.if \trace
|
||||||
#ifdef CONFIG_IRQSOFF_TRACER
|
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||||
bl trace_hardirqs_off
|
bl trace_hardirqs_off
|
||||||
#endif
|
#endif
|
||||||
ct_user_exit save = 0
|
ct_user_exit save = 0
|
||||||
|
|
|
@ -578,7 +578,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
|
||||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||||
|
|
||||||
if ((unsigned)ipinr < NR_IPI) {
|
if ((unsigned)ipinr < NR_IPI) {
|
||||||
trace_ipi_entry(ipi_types[ipinr]);
|
trace_ipi_entry_rcuidle(ipi_types[ipinr]);
|
||||||
__inc_irq_stat(cpu, ipi_irqs[ipinr]);
|
__inc_irq_stat(cpu, ipi_irqs[ipinr]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,7 +637,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((unsigned)ipinr < NR_IPI)
|
if ((unsigned)ipinr < NR_IPI)
|
||||||
trace_ipi_exit(ipi_types[ipinr]);
|
trace_ipi_exit_rcuidle(ipi_types[ipinr]);
|
||||||
set_irq_regs(old_regs);
|
set_irq_regs(old_regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,10 @@
|
||||||
|
|
||||||
/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
|
/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
|
||||||
|
|
||||||
|
ENTRY(mmiocpy)
|
||||||
ENTRY(memcpy)
|
ENTRY(memcpy)
|
||||||
|
|
||||||
#include "copy_template.S"
|
#include "copy_template.S"
|
||||||
|
|
||||||
ENDPROC(memcpy)
|
ENDPROC(memcpy)
|
||||||
|
ENDPROC(mmiocpy)
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
.text
|
.text
|
||||||
.align 5
|
.align 5
|
||||||
|
|
||||||
|
ENTRY(mmioset)
|
||||||
ENTRY(memset)
|
ENTRY(memset)
|
||||||
UNWIND( .fnstart )
|
UNWIND( .fnstart )
|
||||||
ands r3, r0, #3 @ 1 unaligned?
|
ands r3, r0, #3 @ 1 unaligned?
|
||||||
|
@ -133,3 +134,4 @@ UNWIND( .fnstart )
|
||||||
b 1b
|
b 1b
|
||||||
UNWIND( .fnend )
|
UNWIND( .fnend )
|
||||||
ENDPROC(memset)
|
ENDPROC(memset)
|
||||||
|
ENDPROC(mmioset)
|
||||||
|
|
|
@ -255,7 +255,7 @@ remap_area_supersections(unsigned long virt, unsigned long pfn,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
|
static void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
|
||||||
unsigned long offset, size_t size, unsigned int mtype, void *caller)
|
unsigned long offset, size_t size, unsigned int mtype, void *caller)
|
||||||
{
|
{
|
||||||
const struct mem_type *type;
|
const struct mem_type *type;
|
||||||
|
@ -363,7 +363,7 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
|
||||||
unsigned int mtype)
|
unsigned int mtype)
|
||||||
{
|
{
|
||||||
return __arm_ioremap_pfn_caller(pfn, offset, size, mtype,
|
return __arm_ioremap_pfn_caller(pfn, offset, size, mtype,
|
||||||
__builtin_return_address(0));
|
__builtin_return_address(0));
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__arm_ioremap_pfn);
|
EXPORT_SYMBOL(__arm_ioremap_pfn);
|
||||||
|
|
||||||
|
@ -371,13 +371,26 @@ void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t,
|
||||||
unsigned int, void *) =
|
unsigned int, void *) =
|
||||||
__arm_ioremap_caller;
|
__arm_ioremap_caller;
|
||||||
|
|
||||||
void __iomem *
|
void __iomem *ioremap(resource_size_t res_cookie, size_t size)
|
||||||
__arm_ioremap(phys_addr_t phys_addr, size_t size, unsigned int mtype)
|
|
||||||
{
|
{
|
||||||
return arch_ioremap_caller(phys_addr, size, mtype,
|
return arch_ioremap_caller(res_cookie, size, MT_DEVICE,
|
||||||
__builtin_return_address(0));
|
__builtin_return_address(0));
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__arm_ioremap);
|
EXPORT_SYMBOL(ioremap);
|
||||||
|
|
||||||
|
void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size)
|
||||||
|
{
|
||||||
|
return arch_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED,
|
||||||
|
__builtin_return_address(0));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ioremap_cache);
|
||||||
|
|
||||||
|
void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size)
|
||||||
|
{
|
||||||
|
return arch_ioremap_caller(res_cookie, size, MT_DEVICE_WC,
|
||||||
|
__builtin_return_address(0));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ioremap_wc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remap an arbitrary physical address space into the kernel virtual
|
* Remap an arbitrary physical address space into the kernel virtual
|
||||||
|
@ -431,11 +444,11 @@ void __iounmap(volatile void __iomem *io_addr)
|
||||||
|
|
||||||
void (*arch_iounmap)(volatile void __iomem *) = __iounmap;
|
void (*arch_iounmap)(volatile void __iomem *) = __iounmap;
|
||||||
|
|
||||||
void __arm_iounmap(volatile void __iomem *io_addr)
|
void iounmap(volatile void __iomem *cookie)
|
||||||
{
|
{
|
||||||
arch_iounmap(io_addr);
|
arch_iounmap(cookie);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__arm_iounmap);
|
EXPORT_SYMBOL(iounmap);
|
||||||
|
|
||||||
#ifdef CONFIG_PCI
|
#ifdef CONFIG_PCI
|
||||||
static int pci_ioremap_mem_type = MT_DEVICE;
|
static int pci_ioremap_mem_type = MT_DEVICE;
|
||||||
|
|
|
@ -1072,6 +1072,7 @@ void __init sanity_check_meminfo(void)
|
||||||
int highmem = 0;
|
int highmem = 0;
|
||||||
phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1;
|
phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1;
|
||||||
struct memblock_region *reg;
|
struct memblock_region *reg;
|
||||||
|
bool should_use_highmem = false;
|
||||||
|
|
||||||
for_each_memblock(memory, reg) {
|
for_each_memblock(memory, reg) {
|
||||||
phys_addr_t block_start = reg->base;
|
phys_addr_t block_start = reg->base;
|
||||||
|
@ -1090,6 +1091,7 @@ void __init sanity_check_meminfo(void)
|
||||||
pr_notice("Ignoring RAM at %pa-%pa (!CONFIG_HIGHMEM)\n",
|
pr_notice("Ignoring RAM at %pa-%pa (!CONFIG_HIGHMEM)\n",
|
||||||
&block_start, &block_end);
|
&block_start, &block_end);
|
||||||
memblock_remove(reg->base, reg->size);
|
memblock_remove(reg->base, reg->size);
|
||||||
|
should_use_highmem = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1100,6 +1102,7 @@ void __init sanity_check_meminfo(void)
|
||||||
&block_start, &block_end, &vmalloc_limit);
|
&block_start, &block_end, &vmalloc_limit);
|
||||||
memblock_remove(vmalloc_limit, overlap_size);
|
memblock_remove(vmalloc_limit, overlap_size);
|
||||||
block_end = vmalloc_limit;
|
block_end = vmalloc_limit;
|
||||||
|
should_use_highmem = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1134,6 +1137,9 @@ void __init sanity_check_meminfo(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (should_use_highmem)
|
||||||
|
pr_notice("Consider using a HIGHMEM enabled kernel.\n");
|
||||||
|
|
||||||
high_memory = __va(arm_lowmem_limit - 1) + 1;
|
high_memory = __va(arm_lowmem_limit - 1) + 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1494,6 +1500,7 @@ void __init paging_init(const struct machine_desc *mdesc)
|
||||||
build_mem_type_table();
|
build_mem_type_table();
|
||||||
prepare_page_table();
|
prepare_page_table();
|
||||||
map_lowmem();
|
map_lowmem();
|
||||||
|
memblock_set_current_limit(arm_lowmem_limit);
|
||||||
dma_contiguous_remap();
|
dma_contiguous_remap();
|
||||||
devicemaps_init(mdesc);
|
devicemaps_init(mdesc);
|
||||||
kmap_init();
|
kmap_init();
|
||||||
|
|
|
@ -351,30 +351,43 @@ void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__arm_ioremap_pfn);
|
EXPORT_SYMBOL(__arm_ioremap_pfn);
|
||||||
|
|
||||||
void __iomem *__arm_ioremap_pfn_caller(unsigned long pfn, unsigned long offset,
|
|
||||||
size_t size, unsigned int mtype, void *caller)
|
|
||||||
{
|
|
||||||
return __arm_ioremap_pfn(pfn, offset, size, mtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __iomem *__arm_ioremap(phys_addr_t phys_addr, size_t size,
|
|
||||||
unsigned int mtype)
|
|
||||||
{
|
|
||||||
return (void __iomem *)phys_addr;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(__arm_ioremap);
|
|
||||||
|
|
||||||
void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *);
|
|
||||||
|
|
||||||
void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size,
|
void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size,
|
||||||
unsigned int mtype, void *caller)
|
unsigned int mtype, void *caller)
|
||||||
{
|
{
|
||||||
return __arm_ioremap(phys_addr, size, mtype);
|
return (void __iomem *)phys_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *);
|
||||||
|
|
||||||
|
void __iomem *ioremap(resource_size_t res_cookie, size_t size)
|
||||||
|
{
|
||||||
|
return __arm_ioremap_caller(res_cookie, size, MT_DEVICE,
|
||||||
|
__builtin_return_address(0));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ioremap);
|
||||||
|
|
||||||
|
void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size)
|
||||||
|
{
|
||||||
|
return __arm_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED,
|
||||||
|
__builtin_return_address(0));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ioremap_cache);
|
||||||
|
|
||||||
|
void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size)
|
||||||
|
{
|
||||||
|
return __arm_ioremap_caller(res_cookie, size, MT_DEVICE_WC,
|
||||||
|
__builtin_return_address(0));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ioremap_wc);
|
||||||
|
|
||||||
|
void __iounmap(volatile void __iomem *addr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__iounmap);
|
||||||
|
|
||||||
void (*arch_iounmap)(volatile void __iomem *);
|
void (*arch_iounmap)(volatile void __iomem *);
|
||||||
|
|
||||||
void __arm_iounmap(volatile void __iomem *addr)
|
void iounmap(volatile void __iomem *addr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__arm_iounmap);
|
EXPORT_SYMBOL(iounmap);
|
||||||
|
|
|
@ -45,13 +45,11 @@
|
||||||
* it does.
|
* it does.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
|
|
||||||
#include <byteswap.h>
|
#include <byteswap.h>
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <error.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -82,11 +80,25 @@
|
||||||
#define EF_ARM_ABI_FLOAT_HARD 0x400
|
#define EF_ARM_ABI_FLOAT_HARD 0x400
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int failed;
|
||||||
|
static const char *argv0;
|
||||||
static const char *outfile;
|
static const char *outfile;
|
||||||
|
|
||||||
|
static void fail(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
failed = 1;
|
||||||
|
fprintf(stderr, "%s: ", argv0);
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
static void cleanup(void)
|
static void cleanup(void)
|
||||||
{
|
{
|
||||||
if (error_message_count > 0 && outfile != NULL)
|
if (failed && outfile != NULL)
|
||||||
unlink(outfile);
|
unlink(outfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,68 +131,66 @@ int main(int argc, char **argv)
|
||||||
int infd;
|
int infd;
|
||||||
|
|
||||||
atexit(cleanup);
|
atexit(cleanup);
|
||||||
|
argv0 = argv[0];
|
||||||
|
|
||||||
if (argc != 3)
|
if (argc != 3)
|
||||||
error(EXIT_FAILURE, 0, "Usage: %s [infile] [outfile]", argv[0]);
|
fail("Usage: %s [infile] [outfile]\n", argv[0]);
|
||||||
|
|
||||||
infile = argv[1];
|
infile = argv[1];
|
||||||
outfile = argv[2];
|
outfile = argv[2];
|
||||||
|
|
||||||
infd = open(infile, O_RDONLY);
|
infd = open(infile, O_RDONLY);
|
||||||
if (infd < 0)
|
if (infd < 0)
|
||||||
error(EXIT_FAILURE, errno, "Cannot open %s", infile);
|
fail("Cannot open %s: %s\n", infile, strerror(errno));
|
||||||
|
|
||||||
if (fstat(infd, &stat) != 0)
|
if (fstat(infd, &stat) != 0)
|
||||||
error(EXIT_FAILURE, errno, "Failed stat for %s", infile);
|
fail("Failed stat for %s: %s\n", infile, strerror(errno));
|
||||||
|
|
||||||
inbuf = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, infd, 0);
|
inbuf = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, infd, 0);
|
||||||
if (inbuf == MAP_FAILED)
|
if (inbuf == MAP_FAILED)
|
||||||
error(EXIT_FAILURE, errno, "Failed to map %s", infile);
|
fail("Failed to map %s: %s\n", infile, strerror(errno));
|
||||||
|
|
||||||
close(infd);
|
close(infd);
|
||||||
|
|
||||||
inhdr = inbuf;
|
inhdr = inbuf;
|
||||||
|
|
||||||
if (memcmp(&inhdr->e_ident, ELFMAG, SELFMAG) != 0)
|
if (memcmp(&inhdr->e_ident, ELFMAG, SELFMAG) != 0)
|
||||||
error(EXIT_FAILURE, 0, "Not an ELF file");
|
fail("Not an ELF file\n");
|
||||||
|
|
||||||
if (inhdr->e_ident[EI_CLASS] != ELFCLASS32)
|
if (inhdr->e_ident[EI_CLASS] != ELFCLASS32)
|
||||||
error(EXIT_FAILURE, 0, "Unsupported ELF class");
|
fail("Unsupported ELF class\n");
|
||||||
|
|
||||||
swap = inhdr->e_ident[EI_DATA] != HOST_ORDER;
|
swap = inhdr->e_ident[EI_DATA] != HOST_ORDER;
|
||||||
|
|
||||||
if (read_elf_half(inhdr->e_type, swap) != ET_DYN)
|
if (read_elf_half(inhdr->e_type, swap) != ET_DYN)
|
||||||
error(EXIT_FAILURE, 0, "Not a shared object");
|
fail("Not a shared object\n");
|
||||||
|
|
||||||
if (read_elf_half(inhdr->e_machine, swap) != EM_ARM) {
|
if (read_elf_half(inhdr->e_machine, swap) != EM_ARM)
|
||||||
error(EXIT_FAILURE, 0, "Unsupported architecture %#x",
|
fail("Unsupported architecture %#x\n", inhdr->e_machine);
|
||||||
inhdr->e_machine);
|
|
||||||
}
|
|
||||||
|
|
||||||
e_flags = read_elf_word(inhdr->e_flags, swap);
|
e_flags = read_elf_word(inhdr->e_flags, swap);
|
||||||
|
|
||||||
if (EF_ARM_EABI_VERSION(e_flags) != EF_ARM_EABI_VER5) {
|
if (EF_ARM_EABI_VERSION(e_flags) != EF_ARM_EABI_VER5) {
|
||||||
error(EXIT_FAILURE, 0, "Unsupported EABI version %#x",
|
fail("Unsupported EABI version %#x\n",
|
||||||
EF_ARM_EABI_VERSION(e_flags));
|
EF_ARM_EABI_VERSION(e_flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e_flags & EF_ARM_ABI_FLOAT_HARD)
|
if (e_flags & EF_ARM_ABI_FLOAT_HARD)
|
||||||
error(EXIT_FAILURE, 0,
|
fail("Unexpected hard-float flag set in e_flags\n");
|
||||||
"Unexpected hard-float flag set in e_flags");
|
|
||||||
|
|
||||||
clear_soft_float = !!(e_flags & EF_ARM_ABI_FLOAT_SOFT);
|
clear_soft_float = !!(e_flags & EF_ARM_ABI_FLOAT_SOFT);
|
||||||
|
|
||||||
outfd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
outfd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||||
if (outfd < 0)
|
if (outfd < 0)
|
||||||
error(EXIT_FAILURE, errno, "Cannot open %s", outfile);
|
fail("Cannot open %s: %s\n", outfile, strerror(errno));
|
||||||
|
|
||||||
if (ftruncate(outfd, stat.st_size) != 0)
|
if (ftruncate(outfd, stat.st_size) != 0)
|
||||||
error(EXIT_FAILURE, errno, "Cannot truncate %s", outfile);
|
fail("Cannot truncate %s: %s\n", outfile, strerror(errno));
|
||||||
|
|
||||||
outbuf = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
outbuf = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||||
outfd, 0);
|
outfd, 0);
|
||||||
if (outbuf == MAP_FAILED)
|
if (outbuf == MAP_FAILED)
|
||||||
error(EXIT_FAILURE, errno, "Failed to map %s", outfile);
|
fail("Failed to map %s: %s\n", outfile, strerror(errno));
|
||||||
|
|
||||||
close(outfd);
|
close(outfd);
|
||||||
|
|
||||||
|
@ -195,7 +205,7 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msync(outbuf, stat.st_size, MS_SYNC) != 0)
|
if (msync(outbuf, stat.st_size, MS_SYNC) != 0)
|
||||||
error(EXIT_FAILURE, errno, "Failed to sync %s", outfile);
|
fail("Failed to sync %s: %s\n", outfile, strerror(errno));
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue