select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT)
select HAVE_ARCH_TRACEHOOK
select HAVE_BPF_JIT
+ select HAVE_CC_STACKPROTECTOR
select HAVE_CONTEXT_TRACKING
select HAVE_C_RECORDMCOUNT
- select HAVE_CC_STACKPROTECTOR
select HAVE_DEBUG_KMEMLEAK
select HAVE_DMA_API_DEBUG
select HAVE_DMA_ATTRS
bool
default y
--- config RWSEM_GENERIC_SPINLOCK
--- bool
--- default y
---
config RWSEM_XCHGADD_ALGORITHM
bool
+++ default y
config ARCH_HAS_ILOG2_U32
bool
select ARM_HAS_SG_CHAIN
select ARM_PATCH_PHYS_VIRT
select AUTO_ZRELADDR
+ select CLKSRC_OF
select COMMON_CLK
select GENERIC_CLOCKEVENTS
select MULTI_IRQ_HANDLER
bool "Energy Micro efm32"
depends on !MMU
select ARCH_REQUIRE_GPIOLIB
- select AUTO_ZRELADDR
select ARM_NVIC
+ select AUTO_ZRELADDR
select CLKSRC_OF
select COMMON_CLK
select CPU_V7M
bool "IXP4xx-based"
depends on MMU
select ARCH_HAS_DMA_SET_COHERENT_MASK
- select ARCH_SUPPORTS_BIG_ENDIAN
select ARCH_REQUIRE_GPIOLIB
+ select ARCH_SUPPORTS_BIG_ENDIAN
select CLKSRC_MMIO
select CPU_XSCALE
select DMABOUNCE if PCI
source arch/arm/mm/Kconfig
--- config ARM_NR_BANKS
--- int
--- default 16 if ARCH_EP93XX
--- default 8
---
config IWMMXT
- bool "Enable iWMMXt support" if !CPU_PJ4
- depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4
- default y if PXA27x || PXA3xx || ARCH_MMP || CPU_PJ4
+ bool "Enable iWMMXt support"
+ depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4 || CPU_PJ4B
+ default y if PXA27x || PXA3xx || ARCH_MMP || CPU_PJ4 || CPU_PJ4B
help
Enable support for iWMMXt context switching at run time if
running on a CPU that supports it.
register of the Cortex-A9 which reduces the linefill issuing
capabilities of the processor.
-- -config PL310_ERRATA_588369
-- - bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines"
-- - depends on CACHE_L2X0
-- - help
-- - The PL310 L2 cache controller implements three types of Clean &
-- - Invalidate maintenance operations: by Physical Address
-- - (offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC).
-- - They are architecturally defined to behave as the execution of a
-- - clean operation followed immediately by an invalidate operation,
-- - both performing to the same memory location. This functionality
-- - is not correctly implemented in PL310 as clean lines are not
-- - invalidated as a result of these operations.
-- -
config ARM_ERRATA_643719
bool "ARM errata: LoUIS bit field in CLIDR register is incorrect"
depends on CPU_V7 && SMP
tables. The workaround changes the TLB flushing routines to invalidate
entries regardless of the ASID.
-- -config PL310_ERRATA_727915
-- - bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption"
-- - depends on CACHE_L2X0
-- - help
-- - PL310 implements the Clean & Invalidate by Way L2 cache maintenance
-- - operation (offset 0x7FC). This operation runs in background so that
-- - PL310 can handle normal accesses while it is in progress. Under very
-- - rare circumstances, due to this erratum, write data can be lost when
-- - PL310 treats a cacheable write transaction during a Clean &
-- - Invalidate by Way operation.
-- -
config ARM_ERRATA_743622
bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption"
depends on CPU_V7
operation is received by a CPU before the ICIALLUIS has completed,
potentially leading to corrupted entries in the cache or TLB.
-- -config PL310_ERRATA_753970
-- - bool "PL310 errata: cache sync operation may be faulty"
-- - depends on CACHE_PL310
-- - help
-- - This option enables the workaround for the 753970 PL310 (r3p0) erratum.
-- -
-- - Under some condition the effect of cache sync operation on
-- - the store buffer still remains when the operation completes.
-- - This means that the store buffer is always asked to drain and
-- - this prevents it from merging any further writes. The workaround
-- - is to replace the normal offset of cache sync operation (0x730)
-- - by another offset targeting an unmapped PL310 register 0x740.
-- - This has the same effect as the cache sync operation: store buffer
-- - drain and waiting for all buffers empty.
-- -
config ARM_ERRATA_754322
bool "ARM errata: possible faulty MMU translations following an ASID switch"
depends on CPU_V7
relevant cache maintenance functions and sets a specific bit
in the diagnostic control register of the SCU.
-- -config PL310_ERRATA_769419
-- - bool "PL310 errata: no automatic Store Buffer drain"
-- - depends on CACHE_L2X0
-- - help
-- - On revisions of the PL310 prior to r3p2, the Store Buffer does
-- - not automatically drain. This can cause normal, non-cacheable
-- - writes to be retained when the memory system is idle, leading
-- - to suboptimal I/O performance for drivers using coherent DMA.
-- - This option adds a write barrier to the cpu_idle loop so that,
-- - on systems with an outer cache, the store buffer is drained
-- - explicitly.
-- -
config ARM_ERRATA_775420
bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock"
depends on CPU_V7
config BL_SWITCHER
bool "big.LITTLE switcher support"
depends on BIG_LITTLE && MCPM && HOTPLUG_CPU
- select CPU_PM
select ARM_CPU_SUSPEND
+ select CPU_PM
help
The big.LITTLE "switcher" provides the core functionality to
transparently handle transition between a cluster of A15's
depends on CPU_V7 && !CPU_V6
depends on !GENERIC_ATOMIC64
depends on MMU
+ select ARCH_DMA_ADDR_T_64BIT
select ARM_PSCI
select SWIOTLB_XEN
- select ARCH_DMA_ADDR_T_64BIT
help
Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
config ARM_CPU_SUSPEND
def_bool PM_SLEEP
+++ config ARCH_HIBERNATION_POSSIBLE
+++ bool
+++ depends on MMU
+++ default y if ARCH_SUSPEND_POSSIBLE
+++
endmenu
source "net/Kconfig"
return 0;
}
+bool mcpm_is_available(void)
+{
+ return (platform_ops) ? true : false;
+}
+
int mcpm_cpu_power_up(unsigned int cpu, unsigned int cluster)
{
if (!platform_ops)
BUG();
}
--- int mcpm_cpu_power_down_finish(unsigned int cpu, unsigned int cluster)
+++ int mcpm_wait_for_cpu_powerdown(unsigned int cpu, unsigned int cluster)
{
int ret;
--- if (WARN_ON_ONCE(!platform_ops || !platform_ops->power_down_finish))
+++ if (WARN_ON_ONCE(!platform_ops || !platform_ops->wait_for_powerdown))
return -EUNATCH;
--- ret = platform_ops->power_down_finish(cpu, cluster);
+++ ret = platform_ops->wait_for_powerdown(cpu, cluster);
if (ret)
pr_warn("%s: cpu %u, cluster %u failed to power down (%d)\n",
__func__, cpu, cluster, ret);
#define ARM_CPU_PART_CORTEX_A15 0xC0F0
#define ARM_CPU_PART_CORTEX_A7 0xC070
#define ARM_CPU_PART_CORTEX_A12 0xC0D0
+++ #define ARM_CPU_PART_CORTEX_A17 0xC0E0
#define ARM_CPU_XSCALE_ARCH_MASK 0xe000
#define ARM_CPU_XSCALE_ARCH_V1 0x2000
#endif
/*
- * Marvell's PJ4 core is based on V7 version. It has some modification
- * for coprocessor setting. For this reason, we need a way to distinguish
- * it.
+ * Marvell's PJ4 and PJ4B cores are based on V7 version,
+ * but require a specical sequence for enabling coprocessors.
+ * For this reason, we need a way to distinguish them.
*/
-#ifndef CONFIG_CPU_PJ4
-#define cpu_is_pj4() 0
-#else
+#if defined(CONFIG_CPU_PJ4) || defined(CONFIG_CPU_PJ4B)
static inline int cpu_is_pj4(void)
{
unsigned int id;
id = read_cpuid_id();
- if ((id & 0xfffffff0) == 0x562f5840)
+ if ((id & 0xff0fff00) == 0x560f5800)
return 1;
return 0;
}
+#else
+#define cpu_is_pj4() 0
#endif
#endif
#include <linux/reboot.h>
struct tag;
--- struct meminfo;
struct pt_regs;
struct smp_operations;
#ifdef CONFIG_SMP
unsigned char reserve_lp1 :1; /* never has lp1 */
unsigned char reserve_lp2 :1; /* never has lp2 */
enum reboot_mode reboot_mode; /* default restart mode */
++ + unsigned l2c_aux_val; /* L2 cache aux value */
++ + unsigned l2c_aux_mask; /* L2 cache aux mask */
++ + void (*l2c_write_sec)(unsigned long, unsigned);
struct smp_operations *smp; /* SMP operations */
bool (*smp_init)(void);
--- void (*fixup)(struct tag *, char **,
--- struct meminfo *);
+++ void (*fixup)(struct tag *, char **);
void (*init_meminfo)(void);
void (*reserve)(void);/* reserve mem blocks */
void (*map_io)(void);/* IO mapping function */
*/
/**
+ * mcpm_is_available - returns whether MCPM is initialized and available
+ *
+ * This returns true or false accordingly.
+ */
+bool mcpm_is_available(void);
+
+/**
* mcpm_cpu_power_up - make given CPU in given cluster runable
*
* @cpu: CPU number within given cluster
* previously in which case the caller should take appropriate action.
*
* On success, the CPU is not guaranteed to be truly halted until
--- * mcpm_cpu_power_down_finish() subsequently returns non-zero for the
+++ * mcpm_wait_for_cpu_powerdown() subsequently returns non-zero for the
* specified cpu. Until then, other CPUs should make sure they do not
* trash memory the target CPU might be executing/accessing.
*/
void mcpm_cpu_power_down(void);
/**
--- * mcpm_cpu_power_down_finish - wait for a specified CPU to halt, and
+++ * mcpm_wait_for_cpu_powerdown - wait for a specified CPU to halt, and
* make sure it is powered off
*
* @cpu: CPU number within given cluster
* - zero if the CPU is in a safely parked state
* - nonzero otherwise (e.g., timeout)
*/
--- int mcpm_cpu_power_down_finish(unsigned int cpu, unsigned int cluster);
+++ int mcpm_wait_for_cpu_powerdown(unsigned int cpu, unsigned int cluster);
/**
* mcpm_cpu_suspend - bring the calling CPU in a suspended state
struct mcpm_platform_ops {
int (*power_up)(unsigned int cpu, unsigned int cluster);
void (*power_down)(void);
--- int (*power_down_finish)(unsigned int cpu, unsigned int cluster);
+++ int (*wait_for_powerdown)(unsigned int cpu, unsigned int cluster);
void (*suspend)(u64);
void (*powered_up)(void);
};
obj-$(CONFIG_ISA_DMA) += dma-isa.o
obj-$(CONFIG_PCI) += bios32.o isa.o
obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o
+++ obj-$(CONFIG_HIBERNATION) += hibernate.o
obj-$(CONFIG_SMP) += smp.o
ifdef CONFIG_MMU
obj-$(CONFIG_SMP) += smp_tlb.o
obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o
obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o
obj-$(CONFIG_CPU_PJ4) += pj4-cp0.o
+obj-$(CONFIG_CPU_PJ4B) += pj4-cp0.o
obj-$(CONFIG_IWMMXT) += iwmmxt.o
obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o perf_event_cpu.o
@
@ Enable the alignment trap while in kernel mode
@
--- alignment_trap r0
+++ alignment_trap r0, .LCcralign
@
@ Clear FP to mark the first stack frame
@
adr r9, BSYM(ret_from_exception)
+++ @ IRQs must be enabled before attempting to read the instruction from
+++ @ user space since that could cause a page/translation fault if the
+++ @ page table was modified by another CPU.
+++ enable_irq
+++
tst r3, #PSR_T_BIT @ Thumb mode?
bne __und_usr_thumb
sub r4, r2, #4 @ ARM instr at LR - 4
*/
.pushsection .fixup, "ax"
.align 2
--- 4: mov pc, r9
+++ 4: str r4, [sp, #S_PC] @ retry current instruction
+++ mov pc, r9
.popsection
.pushsection __ex_table,"a"
.long 1b, 4b
* r9 = normal "successful" return address
* r10 = this threads thread_info structure
* lr = unrecognised instruction return address
--- * IRQs disabled, FIQs enabled.
+++ * IRQs enabled, FIQs enabled.
*/
@
@ Fall-through from Thumb-2 __und_usr
#endif
do_fpe:
--- enable_irq
ldr r4, .LCfp
add r10, r10, #TI_FPSTATE @ r10 = workspace
ldr pc, [r4] @ Call FP module USR entry point
b 1f
__und_usr_fault_16:
mov r1, #2
--- 1: enable_irq
--- mov r0, sp
+++ 1: mov r0, sp
adr lr, BSYM(ret_from_exception)
b __und_fault
ENDPROC(__und_usr_fault_32)
.data
.globl cr_alignment
--- .globl cr_no_alignment
cr_alignment:
.space 4
---cr_no_alignment:
--- .space 4
#ifdef CONFIG_MULTI_IRQ_HANDLER
.globl handle_arch_irq
#endif
.endm
--- .macro alignment_trap, rtemp
+++ .macro alignment_trap, rtemp, label
#ifdef CONFIG_ALIGNMENT_TRAP
--- ldr \rtemp, .LCcralign
+++ ldr \rtemp, \label
ldr \rtemp, [\rtemp]
mcr p15, 0, \rtemp, c1, c0
#endif
orrne r5, V7M_xPSR_FRAMEPTRALIGN
biceq r5, V7M_xPSR_FRAMEPTRALIGN
+ ++ @ ensure bit 0 is cleared in the PC, otherwise behaviour is
+ ++ @ unpredictable
+ ++ bic r4, #1
+ ++
@ write basic exception frame
stmdb r2!, {r1, r3-r5}
ldmia sp, {r1, r3-r5}
#ifdef CONFIG_SMP_ON_UP
--- __INIT
+++ __HEAD
__fixup_smp:
and r3, r9, #0x000f0000 @ architecture version
teq r3, #0x000f0000 @ CPU ID supported?
add r6, r6, r3 @ adjust __pv_phys_pfn_offset address
add r7, r7, r3 @ adjust __pv_offset address
mov r0, r8, lsr #12 @ convert to PFN
- str r0, [r6, #LOW_OFFSET] @ save computed PHYS_OFFSET to __pv_phys_pfn_offset
+ str r0, [r6] @ save computed PHYS_OFFSET to __pv_phys_pfn_offset
strcc ip, [r7, #HIGH_OFFSET] @ save to __pv_offset high bits
mov r6, r3, lsr #24 @ constant for add/sub instructions
teq r3, r6, lsl #24 @ must be 16MiB aligned
#include <asm/ptrace.h>
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
+++ #include <asm/assembler.h>
-#if defined(CONFIG_CPU_PJ4)
+#if defined(CONFIG_CPU_PJ4) || defined(CONFIG_CPU_PJ4B)
#define PJ4(code...) code
#define XSC(code...)
-#else
+#elif defined(CONFIG_CPU_MOHAWK) || \
+ defined(CONFIG_CPU_XSC3) || \
+ defined(CONFIG_CPU_XSCALE)
#define PJ4(code...)
#define XSC(code...) code
+#else
+#error "Unsupported iWMMXt architecture"
#endif
#define MMX_WR0 (0x00)
* r9 = ret_from_exception
* lr = undefined instr exit
*
--- * called from prefetch exception handler with interrupts disabled
+++ * called from prefetch exception handler with interrupts enabled
*/
ENTRY(iwmmxt_task_enable)
+++ inc_preempt_count r10, r3
XSC(mrc p15, 0, r2, c15, c1, 0)
PJ4(mrc p15, 0, r2, c1, c0, 2)
@ CP0 and CP1 accessible?
XSC(tst r2, #0x3)
PJ4(tst r2, #0xf)
--- movne pc, lr @ if so no business here
+++ bne 4f @ if so no business here
@ enable access to CP0 and CP1
XSC(orr r2, r2, #0x3)
XSC(mcr p15, 0, r2, c15, c1, 0)
wstrd wR15, [r1, #MMX_WR15]
2: teq r0, #0 @ anything to load?
--- moveq pc, lr
+++ beq 3f
concan_load:
@ clear CUP/MUP (only if r1 != 0)
teq r1, #0
mov r2, #0
--- moveq pc, lr
+++ beq 3f
tmcr wCon, r2
+++
+++ 3:
+++ #ifdef CONFIG_PREEMPT_COUNT
+++ get_thread_info r10
+++ #endif
+++ 4: dec_preempt_count r10, r3
mov pc, lr
/*
__setup("fpe=", fpe_setup);
#endif
+++extern void init_default_cache_policy(unsigned long);
extern void paging_init(const struct machine_desc *desc);
extern void early_paging_init(const struct machine_desc *,
struct proc_info_list *);
pr_info("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
--- proc_arch[cpu_architecture()], cr_alignment);
+++ proc_arch[cpu_architecture()], get_cr());
snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
list->arch_name, ENDIANNESS);
#ifndef CONFIG_ARM_THUMB
elf_hwcap &= ~(HWCAP_THUMB | HWCAP_IDIVT);
#endif
---
+++#ifdef CONFIG_MMU
+++ init_default_cache_policy(list->__cpu_mm_mmu_flags);
+++#endif
erratum_a15_798181_init();
feat_v6_fixup();
int __init arm_add_memory(u64 start, u64 size)
{
--- struct membank *bank = &meminfo.bank[meminfo.nr_banks];
u64 aligned_start;
--- if (meminfo.nr_banks >= NR_BANKS) {
--- pr_crit("NR_BANKS too low, ignoring memory at 0x%08llx\n",
--- (long long)start);
--- return -EINVAL;
--- }
---
/*
* Ensure that start/size are aligned to a page boundary.
* Size is appropriately rounded down, start is rounded up.
aligned_start = PHYS_OFFSET;
}
--- bank->start = aligned_start;
--- bank->size = size & ~(phys_addr_t)(PAGE_SIZE - 1);
+++ start = aligned_start;
+++ size = size & ~(phys_addr_t)(PAGE_SIZE - 1);
/*
* Check whether this memory region has non-zero size or
* invalid node number.
*/
--- if (bank->size == 0)
+++ if (size == 0)
return -EINVAL;
--- meminfo.nr_banks++;
+++ memblock_add(start, size);
return 0;
}
* Pick out the memory size. We look for mem=size@start,
* where start and size are "size[KkMm]"
*/
+++
static int __init early_mem(char *p)
{
static int usermem __initdata = 0;
*/
if (usermem == 0) {
usermem = 1;
--- meminfo.nr_banks = 0;
+++ memblock_remove(memblock_start_of_DRAM(),
+++ memblock_end_of_DRAM() - memblock_start_of_DRAM());
}
start = PHYS_OFFSET;
static inline void reserve_crashkernel(void) {}
#endif /* CONFIG_KEXEC */
--- static int __init meminfo_cmp(const void *_a, const void *_b)
--- {
--- const struct membank *a = _a, *b = _b;
--- long cmp = bank_pfn_start(a) - bank_pfn_start(b);
--- return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
--- }
---
void __init hyp_mode_check(void)
{
#ifdef CONFIG_ARM_VIRT_EXT
parse_early_param();
--- sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
---
early_paging_init(mdesc, lookup_processor_type(read_cpuid_id()));
setup_dma_zone(mdesc);
sanity_check_meminfo();
--- arm_memblock_init(&meminfo, mdesc);
+++ arm_memblock_init(mdesc);
paging_init(mdesc);
request_standard_resources(mdesc);
#define ORION_MBUS_DEVBUS_BOOT_ATTR 0x0f
#define ORION_MBUS_DEVBUS_TARGET(cs) 0x01
#define ORION_MBUS_DEVBUS_ATTR(cs) (~(1 << cs))
-#define ORION_MBUS_SRAM_TARGET 0x00
+#define ORION_MBUS_SRAM_TARGET 0x09
#define ORION_MBUS_SRAM_ATTR 0x00
/*
static inline void edmini_v2_init(void) {};
#endif
--- struct meminfo;
struct tag;
--- extern void __init tag_fixup_mem32(struct tag *, char **, struct meminfo *);
+++ extern void __init tag_fixup_mem32(struct tag *, char **);
/*****************************************************************************
* Helpers to access Orion registers
#include <linux/irqchip/arm-gic.h>
#include <linux/platform_data/clk-realview.h>
#include <linux/reboot.h>
+++ #include <linux/memblock.h>
#include <mach/hardware.h>
#include <asm/irq.h>
dsb();
}
--- static void realview_pb1176_fixup(struct tag *tags, char **from,
--- struct meminfo *meminfo)
+++ static void realview_pb1176_fixup(struct tag *tags, char **from)
{
/*
* RealView PB1176 only has 128MB of RAM mapped at 0.
*/
--- meminfo->bank[0].start = 0;
--- meminfo->bank[0].size = SZ_128M;
--- meminfo->nr_banks = 1;
+++ memblock_add(0, SZ_128M);
}
static void __init realview_pb1176_init(void)
int i;
#ifdef CONFIG_CACHE_L2X0
-- - /* 128Kb (16Kb/way) 8-way associativity. evmon/parity/share enabled. */
++ + /*
++ + * The PL220 needs to be manually configured as the hardware
++ + * doesn't report the correct sizes.
++ + * 128kB (16kB/way), 8-way associativity, event monitor and
++ + * parity enabled, ignore share bit, no force write allocate
++ + * Bits: .... ...0 0111 0011 0000 .... .... ....
++ + */
l2x0_init(__io_address(REALVIEW_PB1176_L220_BASE), 0x00730000, 0xfe000fff);
#endif
#include <linux/irqchip/arm-gic.h>
#include <linux/platform_data/clk-realview.h>
#include <linux/reboot.h>
+++ #include <linux/memblock.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
realview_pbx_twd_init();
}
--- static void realview_pbx_fixup(struct tag *tags, char **from,
--- struct meminfo *meminfo)
+++ static void realview_pbx_fixup(struct tag *tags, char **from)
{
#ifdef CONFIG_SPARSEMEM
/*
* Memory configuration with SPARSEMEM enabled on RealView PBX (see
* asm/mach/memory.h for more information).
*/
--- meminfo->bank[0].start = 0;
--- meminfo->bank[0].size = SZ_256M;
--- meminfo->bank[1].start = 0x20000000;
--- meminfo->bank[1].size = SZ_512M;
--- meminfo->bank[2].start = 0x80000000;
--- meminfo->bank[2].size = SZ_256M;
--- meminfo->nr_banks = 3;
+++
+++ memblock_add(0, SZ_256M);
+++ memblock_add(0x20000000, SZ_512M);
+++ memblock_add(0x80000000, SZ_256M);
#else
--- realview_fixup(tags, from, meminfo);
+++ realview_fixup(tags, from);
#endif
}
__io_address(REALVIEW_PBX_TILE_L220_BASE);
/* set RAM latencies to 1 cycle for eASIC */
-- - writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL);
-- - writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL);
++ + writel(0, l2x0_base + L310_TAG_LATENCY_CTRL);
++ + writel(0, l2x0_base + L310_DATA_LATENCY_CTRL);
/* 16KB way size, 8-way associativity, parity disabled
* Bits: .. 0 0 0 0 1 00 1 0 1 001 0 000 0 .... .... .... */
unsigned long paddr = page_to_phys(page) + off;
/* FIXME: non-speculating: not required */
--- /* don't bother invalidating if DMA to device */
--- if (dir != DMA_TO_DEVICE)
+++ /* in any case, don't bother invalidating if DMA to device */
+++ if (dir != DMA_TO_DEVICE) {
outer_inv_range(paddr, paddr + size);
--- dma_cache_maint_page(page, off, size, dir, dmac_unmap_area);
+++ dma_cache_maint_page(page, off, size, dir, dmac_unmap_area);
+++ }
/*
* Mark the D-cache clean for these pages to avoid extra flushing.
mapping->nr_bitmaps = 1;
mapping->extensions = extensions;
mapping->base = base;
- mapping->size = bitmap_size << PAGE_SHIFT;
mapping->bits = BITS_PER_BYTE * bitmap_size;
+ mapping->size = mapping->bits << PAGE_SHIFT;
spin_lock_init(&mapping->lock);
#include <linux/dma-contiguous.h>
#include <linux/sizes.h>
+++#include <asm/cp15.h>
#include <asm/mach-types.h>
#include <asm/memblock.h>
#include <asm/prom.h>
#include "mm.h"
+++#ifdef CONFIG_CPU_CP15_MMU
+++unsigned long __init __clear_cr(unsigned long mask)
+++{
+++ cr_alignment = cr_alignment & ~mask;
+++ return cr_alignment;
+++}
+++#endif
+++
static phys_addr_t phys_initrd_start __initdata = 0;
static unsigned long phys_initrd_size __initdata = 0;
* initialization functions, as well as show_mem() for the skipping
* of holes in the memory map. It is populated by arm_add_memory().
*/
--- struct meminfo meminfo;
---
void show_mem(unsigned int filter)
{
int free = 0, total = 0, reserved = 0;
--- int shared = 0, cached = 0, slab = 0, i;
--- struct meminfo * mi = &meminfo;
+++ int shared = 0, cached = 0, slab = 0;
+++ struct memblock_region *reg;
printk("Mem-info:\n");
show_free_areas(filter);
--- for_each_bank (i, mi) {
--- struct membank *bank = &mi->bank[i];
+++ for_each_memblock (memory, reg) {
unsigned int pfn1, pfn2;
struct page *page, *end;
--- pfn1 = bank_pfn_start(bank);
--- pfn2 = bank_pfn_end(bank);
+++ pfn1 = memblock_region_memory_base_pfn(reg);
+++ pfn2 = memblock_region_memory_end_pfn(reg);
page = pfn_to_page(pfn1);
end = pfn_to_page(pfn2 - 1) + 1;
free++;
else
shared += page_count(page) - 1;
--- page++;
--- } while (page < end);
+++ pfn1++;
+++ page = pfn_to_page(pfn1);
+++ } while (pfn1 < pfn2);
}
printk("%d pages of RAM\n", total);
static void __init find_limits(unsigned long *min, unsigned long *max_low,
unsigned long *max_high)
{
--- struct meminfo *mi = &meminfo;
--- int i;
---
--- /* This assumes the meminfo array is properly sorted */
--- *min = bank_pfn_start(&mi->bank[0]);
--- for_each_bank (i, mi)
--- if (mi->bank[i].highmem)
--- break;
--- *max_low = bank_pfn_end(&mi->bank[i - 1]);
--- *max_high = bank_pfn_end(&mi->bank[mi->nr_banks - 1]);
+++ *max_low = PFN_DOWN(memblock_get_current_limit());
+++ *min = PFN_UP(memblock_start_of_DRAM());
+++ *max_high = PFN_DOWN(memblock_end_of_DRAM());
}
#ifdef CONFIG_ZONE_DMA
return phys;
}
--- void __init arm_memblock_init(struct meminfo *mi,
--- const struct machine_desc *mdesc)
+++ void __init arm_memblock_init(const struct machine_desc *mdesc)
{
--- int i;
---
--- for (i = 0; i < mi->nr_banks; i++)
--- memblock_add(mi->bank[i].start, mi->bank[i].size);
---
/* Register the kernel text, kernel data and initrd with memblock. */
#ifdef CONFIG_XIP_KERNEL
memblock_reserve(__pa(_sdata), _end - _sdata);
/*
* The mem_map array can get very big. Free the unused area of the memory map.
*/
--- static void __init free_unused_memmap(struct meminfo *mi)
+++ static void __init free_unused_memmap(void)
{
--- unsigned long bank_start, prev_bank_end = 0;
--- unsigned int i;
+++ unsigned long start, prev_end = 0;
+++ struct memblock_region *reg;
/*
* This relies on each bank being in address order.
* The banks are sorted previously in bootmem_init().
*/
--- for_each_bank(i, mi) {
--- struct membank *bank = &mi->bank[i];
---
--- bank_start = bank_pfn_start(bank);
+++ for_each_memblock(memory, reg) {
+++ start = memblock_region_memory_base_pfn(reg);
#ifdef CONFIG_SPARSEMEM
/*
* Take care not to free memmap entries that don't exist
* due to SPARSEMEM sections which aren't present.
*/
--- bank_start = min(bank_start,
--- ALIGN(prev_bank_end, PAGES_PER_SECTION));
+++ start = min(start,
+++ ALIGN(prev_end, PAGES_PER_SECTION));
#else
/*
* Align down here since the VM subsystem insists that the
* memmap entries are valid from the bank start aligned to
* MAX_ORDER_NR_PAGES.
*/
--- bank_start = round_down(bank_start, MAX_ORDER_NR_PAGES);
+++ start = round_down(start, MAX_ORDER_NR_PAGES);
#endif
/*
* If we had a previous bank, and there is a space
* between the current bank and the previous, free it.
*/
--- if (prev_bank_end && prev_bank_end < bank_start)
--- free_memmap(prev_bank_end, bank_start);
+++ if (prev_end && prev_end < start)
+++ free_memmap(prev_end, start);
/*
* Align up here since the VM subsystem insists that the
* memmap entries are valid from the bank end aligned to
* MAX_ORDER_NR_PAGES.
*/
--- prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES);
+++ prev_end = ALIGN(memblock_region_memory_end_pfn(reg),
+++ MAX_ORDER_NR_PAGES);
}
#ifdef CONFIG_SPARSEMEM
--- if (!IS_ALIGNED(prev_bank_end, PAGES_PER_SECTION))
--- free_memmap(prev_bank_end,
--- ALIGN(prev_bank_end, PAGES_PER_SECTION));
+++ if (!IS_ALIGNED(prev_end, PAGES_PER_SECTION))
+++ free_memmap(prev_end,
+++ ALIGN(prev_end, PAGES_PER_SECTION));
#endif
}
set_max_mapnr(pfn_to_page(max_pfn) - mem_map);
/* this will put all unused low memory onto the freelists */
--- free_unused_memmap(&meminfo);
+++ free_unused_memmap();
free_all_bootmem();
#ifdef CONFIG_SA1111
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/pci.h>
+++ #include <asm/fixmap.h>
#include "mm.h"
#include "tcm.h"
};
#ifdef CONFIG_CPU_CP15
+++static unsigned long initial_pmd_value __initdata = 0;
+++
/*
--- * These are useful for identifying cache coherency
--- * problems by allowing the cache or the cache and
--- * writebuffer to be turned off. (Note: the write
--- * buffer should not be on and the cache off).
+++ * Initialise the cache_policy variable with the initial state specified
+++ * via the "pmd" value. This is used to ensure that on ARMv6 and later,
+++ * the C code sets the page tables up with the same policy as the head
+++ * assembly code, which avoids an illegal state where the TLBs can get
+++ * confused. See comments in early_cachepolicy() for more information.
*/
---static int __init early_cachepolicy(char *p)
+++void __init init_default_cache_policy(unsigned long pmd)
{
int i;
+++ initial_pmd_value = pmd;
+++
+++ pmd &= PMD_SECT_TEX(1) | PMD_SECT_BUFFERABLE | PMD_SECT_CACHEABLE;
+++
+++ for (i = 0; i < ARRAY_SIZE(cache_policies); i++)
+++ if (cache_policies[i].pmd == pmd) {
+++ cachepolicy = i;
+++ break;
+++ }
+++
+++ if (i == ARRAY_SIZE(cache_policies))
+++ pr_err("ERROR: could not find cache policy\n");
+++}
+++
+++/*
+++ * These are useful for identifying cache coherency problems by allowing
+++ * the cache or the cache and writebuffer to be turned off. (Note: the
+++ * write buffer should not be on and the cache off).
+++ */
+++static int __init early_cachepolicy(char *p)
+++{
+++ int i, selected = -1;
+++
for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {
int len = strlen(cache_policies[i].policy);
if (memcmp(p, cache_policies[i].policy, len) == 0) {
--- cachepolicy = i;
--- cr_alignment &= ~cache_policies[i].cr_mask;
--- cr_no_alignment &= ~cache_policies[i].cr_mask;
+++ selected = i;
break;
}
}
--- if (i == ARRAY_SIZE(cache_policies))
--- printk(KERN_ERR "ERROR: unknown or unsupported cache policy\n");
+++
+++ if (selected == -1)
+++ pr_err("ERROR: unknown or unsupported cache policy\n");
+++
/*
* This restriction is partly to do with the way we boot; it is
* unpredictable to have memory mapped using two different sets of
* change these attributes once the initial assembly has setup the
* page tables.
*/
--- if (cpu_architecture() >= CPU_ARCH_ARMv6) {
--- printk(KERN_WARNING "Only cachepolicy=writeback supported on ARMv6 and later\n");
--- cachepolicy = CPOLICY_WRITEBACK;
+++ if (cpu_architecture() >= CPU_ARCH_ARMv6 && selected != cachepolicy) {
+++ pr_warn("Only cachepolicy=%s supported on ARMv6 and later\n",
+++ cache_policies[cachepolicy].policy);
+++ return 0;
+++ }
+++
+++ if (selected != cachepolicy) {
+++ unsigned long cr = __clear_cr(cache_policies[selected].cr_mask);
+++ cachepolicy = selected;
+++ flush_cache_all();
+++ set_cr(cr);
}
--- flush_cache_all();
--- set_cr(cr_alignment);
return 0;
}
early_param("cachepolicy", early_cachepolicy);
early_param("ecc", early_ecc);
#endif
---static int __init noalign_setup(char *__unused)
---{
--- cr_alignment &= ~CR_A;
--- cr_no_alignment &= ~CR_A;
--- set_cr(cr_alignment);
--- return 1;
---}
---__setup("noalign", noalign_setup);
---
---#ifndef CONFIG_SMP
---void adjust_cr(unsigned long mask, unsigned long set)
---{
--- unsigned long flags;
---
--- mask &= ~CR_A;
---
--- set &= mask;
---
--- local_irq_save(flags);
---
--- cr_no_alignment = (cr_no_alignment & ~mask) | set;
--- cr_alignment = (cr_alignment & ~mask) | set;
---
--- set_cr((get_cr() & ~mask) | set);
---
--- local_irq_restore(flags);
---}
---#endif
---
#else /* ifdef CONFIG_CPU_CP15 */
static int __init early_cachepolicy(char *p)
cachepolicy = CPOLICY_WRITEBACK;
ecc_mask = 0;
}
--- if (is_smp())
--- cachepolicy = CPOLICY_WRITEALLOC;
+++
+++ if (is_smp()) {
+++ if (cachepolicy != CPOLICY_WRITEALLOC) {
+++ pr_warn("Forcing write-allocate cache policy for SMP\n");
+++ cachepolicy = CPOLICY_WRITEALLOC;
+++ }
+++ if (!(initial_pmd_value & PMD_SECT_S)) {
+++ pr_warn("Forcing shared mappings for SMP\n");
+++ initial_pmd_value |= PMD_SECT_S;
+++ }
+++ }
/*
* Strip out features not present on earlier architectures.
mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
#endif
--- if (is_smp()) {
--- /*
--- * Mark memory with the "shared" attribute
--- * for SMP systems
--- */
+++ /*
+++ * If the initial page tables were created with the S bit
+++ * set, then we need to do the same here for the same
+++ * reasons given in early_cachepolicy().
+++ */
+++ if (initial_pmd_value & PMD_SECT_S) {
user_pgprot |= L_PTE_SHARED;
kern_pgprot |= L_PTE_SHARED;
vecs_pgprot |= L_PTE_SHARED;
void __init sanity_check_meminfo(void)
{
phys_addr_t memblock_limit = 0;
--- int i, j, highmem = 0;
+++ int highmem = 0;
phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1;
+++ struct memblock_region *reg;
--- for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
--- struct membank *bank = &meminfo.bank[j];
--- phys_addr_t size_limit;
---
--- *bank = meminfo.bank[i];
--- size_limit = bank->size;
+++ for_each_memblock(memory, reg) {
+++ phys_addr_t block_start = reg->base;
+++ phys_addr_t block_end = reg->base + reg->size;
+++ phys_addr_t size_limit = reg->size;
--- if (bank->start >= vmalloc_limit)
+++ if (reg->base >= vmalloc_limit)
highmem = 1;
else
--- size_limit = vmalloc_limit - bank->start;
+++ size_limit = vmalloc_limit - reg->base;
--- bank->highmem = highmem;
--- #ifdef CONFIG_HIGHMEM
--- /*
--- * Split those memory banks which are partially overlapping
--- * the vmalloc area greatly simplifying things later.
--- */
--- if (!highmem && bank->size > size_limit) {
--- if (meminfo.nr_banks >= NR_BANKS) {
--- printk(KERN_CRIT "NR_BANKS too low, "
--- "ignoring high memory\n");
--- } else {
--- memmove(bank + 1, bank,
--- (meminfo.nr_banks - i) * sizeof(*bank));
--- meminfo.nr_banks++;
--- i++;
--- bank[1].size -= size_limit;
--- bank[1].start = vmalloc_limit;
--- bank[1].highmem = highmem = 1;
--- j++;
+++ if (!IS_ENABLED(CONFIG_HIGHMEM) || cache_is_vipt_aliasing()) {
+++
+++ if (highmem) {
+++ pr_notice("Ignoring RAM at %pa-%pa (!CONFIG_HIGHMEM)\n",
+++ &block_start, &block_end);
+++ memblock_remove(reg->base, reg->size);
+++ continue;
}
--- bank->size = size_limit;
--- }
--- #else
--- /*
--- * Highmem banks not allowed with !CONFIG_HIGHMEM.
--- */
--- if (highmem) {
--- printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx "
--- "(!CONFIG_HIGHMEM).\n",
--- (unsigned long long)bank->start,
--- (unsigned long long)bank->start + bank->size - 1);
--- continue;
--- }
--- /*
--- * Check whether this memory bank would partially overlap
--- * the vmalloc area.
--- */
--- if (bank->size > size_limit) {
--- printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx "
--- "to -%.8llx (vmalloc region overlap).\n",
--- (unsigned long long)bank->start,
--- (unsigned long long)bank->start + bank->size - 1,
--- (unsigned long long)bank->start + size_limit - 1);
--- bank->size = size_limit;
+++ if (reg->size > size_limit) {
+++ phys_addr_t overlap_size = reg->size - size_limit;
+++
+++ pr_notice("Truncating RAM at %pa-%pa to -%pa",
+++ &block_start, &block_end, &vmalloc_limit);
+++ memblock_remove(vmalloc_limit, overlap_size);
+++ block_end = vmalloc_limit;
+++ }
}
--- #endif
--- if (!bank->highmem) {
--- phys_addr_t bank_end = bank->start + bank->size;
--- if (bank_end > arm_lowmem_limit)
--- arm_lowmem_limit = bank_end;
+++ if (!highmem) {
+++ if (block_end > arm_lowmem_limit) {
+++ if (reg->size > size_limit)
+++ arm_lowmem_limit = vmalloc_limit;
+++ else
+++ arm_lowmem_limit = block_end;
+++ }
/*
* Find the first non-section-aligned page, and point
* occurs before any free memory is mapped.
*/
if (!memblock_limit) {
--- if (!IS_ALIGNED(bank->start, SECTION_SIZE))
--- memblock_limit = bank->start;
--- else if (!IS_ALIGNED(bank_end, SECTION_SIZE))
--- memblock_limit = bank_end;
+++ if (!IS_ALIGNED(block_start, SECTION_SIZE))
+++ memblock_limit = block_start;
+++ else if (!IS_ALIGNED(block_end, SECTION_SIZE))
+++ memblock_limit = arm_lowmem_limit;
}
--- }
--- j++;
--- }
--- #ifdef CONFIG_HIGHMEM
--- if (highmem) {
--- const char *reason = NULL;
--- if (cache_is_vipt_aliasing()) {
--- /*
--- * Interactions between kmap and other mappings
--- * make highmem support with aliasing VIPT caches
--- * rather difficult.
--- */
--- reason = "with VIPT aliasing cache";
--- }
--- if (reason) {
--- printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n",
--- reason);
--- while (j > 0 && meminfo.bank[j - 1].highmem)
--- j--;
}
}
--- #endif
--- meminfo.nr_banks = j;
+++
high_memory = __va(arm_lowmem_limit - 1) + 1;
/*
#ifdef CONFIG_HIGHMEM
pkmap_page_table = early_pte_alloc(pmd_off_k(PKMAP_BASE),
PKMAP_BASE, _PAGE_KERNEL_TABLE);
+++
+++ fixmap_page_table = early_pte_alloc(pmd_off_k(FIXADDR_START),
+++ FIXADDR_START, _PAGE_KERNEL_TABLE);
#endif
}
* just complicate the code.
*/
flush_cache_louis();
--- dsb();
+++ dsb(ishst);
isb();
/* remap level 1 table */