OSDN Git Service

Merge branches 'alignment', 'fixes', 'l2c' (early part) and 'misc' into for-next
authorRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 5 Jun 2014 11:35:52 +0000 (12:35 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 5 Jun 2014 11:35:52 +0000 (12:35 +0100)
17 files changed:
1  2  3  4 
arch/arm/Kconfig
arch/arm/common/mcpm_entry.c
arch/arm/include/asm/cputype.h
arch/arm/include/asm/mach/arch.h
arch/arm/include/asm/mcpm.h
arch/arm/kernel/Makefile
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-header.S
arch/arm/kernel/head.S
arch/arm/kernel/iwmmxt.S
arch/arm/kernel/setup.c
arch/arm/mach-orion5x/common.h
arch/arm/mach-realview/realview_pb1176.c
arch/arm/mach-realview/realview_pbx.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/init.c
arch/arm/mm/mmu.c

diff --combined arch/arm/Kconfig
@@@@@ -30,9 -30,9 -30,9 -30,9 +30,9 @@@@@ config AR
        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
@@@@@ -165,12 -165,12 -165,12 -165,9 +165,9 @@@@@ config TRACE_IRQFLAGS_SUPPOR
        bool
        default y
    
--- config RWSEM_GENERIC_SPINLOCK
---     bool
---     default y
--- 
    config RWSEM_XCHGADD_ALGORITHM
        bool
+++     default y
    
    config ARCH_HAS_ILOG2_U32
        bool
@@@@@ -311,7 -311,7 -311,7 -308,6 +308,7 @@@@@ config ARCH_MULTIPLATFOR
        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
@@@@@ -423,8 -423,8 -423,8 -419,8 +420,8 @@@@@ config ARCH_EFM3
        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
@@@@@ -512,8 -512,8 -512,8 -508,8 +509,8 @@@@@ config ARCH_IXP4X
        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
@@@@@ -1105,15 -1105,15 -1105,15 -1101,10 +1102,10 @@@@@ source "arch/arm/firmware/Kconfig
    
    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.
@@@@@ -1230,19 -1230,19 -1230,6 -1221,19 +1222,6 @@@@@ config ARM_ERRATA_74223
          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
@@@@@ -1265,17 -1265,17 -1252,6 -1256,17 +1244,6 @@@@@ config ARM_ERRATA_72078
          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
@@@@@ -1301,21 -1301,21 -1277,6 -1292,21 +1269,6 @@@@@ config ARM_ERRATA_75147
          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
@@@@@ -1364,18 -1364,18 -1325,6 -1355,18 +1317,6 @@@@@ config ARM_ERRATA_76436
          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
@@@@@ -1576,8 -1576,8 -1525,8 -1567,8 +1517,8 @@@@@ config BIG_LITTL
    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
@@@@@ -1921,9 -1921,9 -1870,9 -1912,9 +1862,9 @@@@@ config XE
        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.
    
@@@@@ -2295,6 -2295,6 -2244,6 -2286,11 +2236,11 @@@@@ config ARCH_SUSPEND_POSSIBL
    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"
@@@@@ -48,11 -48,11 -48,11 -48,6 +48,11 @@@@@ int __init mcpm_platform_register(cons
        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)
@@@@@ -106,14 -106,14 -106,14 -101,14 +106,14 @@@@@ void mcpm_cpu_power_down(void
        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
@@@@@ -222,22 -222,22 -222,22 -223,22 +223,22 @@@@@ static inline int cpu_is_xsc3(void
    #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
@@@@@ -45,10 -45,10 -45,13 -44,9 +44,12 @@@@@ struct machine_desc 
        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  */
@@@@@ -54,13 -54,13 -54,13 -54,6 +54,13 @@@@@ void mcpm_set_early_poke(unsigned cpu, 
     */
    
    /**
   + * 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
@@@@@ -98,14 -98,14 -98,14 -91,14 +98,14 @@@@@ int mcpm_cpu_power_up(unsigned int cpu
     * 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
@@@@@ -171,7 -171,7 -171,7 -164,7 +171,7 @@@@@ int mcpm_cpu_powered_up(void)
    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);
    };
diff --combined arch/arm/kernel/Makefile
@@@@@ -39,6 -39,6 -39,6 -39,7 +39,7 @@@@@ obj-$(CONFIG_ARTHUR)          += arthur.
    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
@@@@@ -79,7 -79,7 -79,7 -80,6 +80,7 @@@@@ obj-$(CONFIG_CPU_XSCALE)      += xscale-cp0.
    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
@@@@@ -344,7 -344,7 -344,7 -344,7 +344,7 @@@@@ ENDPROC(__pabt_svc
        @
        @ Enable the alignment trap while in kernel mode
        @
 ---    alignment_trap r0
 +++    alignment_trap r0, .LCcralign
    
        @
        @ Clear FP to mark the first stack frame
@@@@@ -413,6 -413,6 -413,6 -413,11 +413,11 @@@@@ __und_usr
        @
        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
@@@@@ -484,7 -484,7 -484,7 -489,8 +489,8 @@@@@ ENDPROC(__und_usr
     */
        .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
@@@@@ -624,7 -624,7 -624,7 -630,6 +630,6 @@@@@ call_fpe
    #endif
    
    do_fpe:
---     enable_irq
        ldr     r4, .LCfp
        add     r10, r10, #TI_FPSTATE           @ r10 = workspace
        ldr     pc, [r4]                        @ Call FP module USR entry point
@@@@@ -652,8 -652,8 -652,8 -657,7 +657,7 @@@@@ __und_usr_fault_32
        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)
@@@@@ -1143,8 -1143,11 -1143,11 -1147,11 +1147,8 @@@@@ __vectors_start
        .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}
diff --combined arch/arm/kernel/head.S
@@@@@ -475,7 -475,7 -475,7 -475,7 +475,7 @@@@@ ENDPROC(__turn_mmu_on
    
    
    #ifdef CONFIG_SMP_ON_UP
---     __INIT
+++     __HEAD
    __fixup_smp:
        and     r3, r9, #0x000f0000     @ architecture version
        teq     r3, #0x000f0000         @ CPU ID supported?
@@@@@ -587,7 -587,7 -587,7 -587,7 +587,7 @@@@@ __fixup_pv_table
        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
diff --combined arch/arm/kernel/iwmmxt.S
    #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)
@@@@@ -136,7 -136,7 -136,7 -134,7 +138,7 @@@@@ concan_dump
        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
    
    /*
diff --combined arch/arm/kernel/setup.c
@@@@@ -72,7 -72,6 -72,6 -72,6 +72,7 @@@@@ static int __init fpe_setup(char *line
    __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 *);
@@@@@ -591,7 -590,7 -590,7 -590,7 +591,7 @@@@@ static void __init setup_processor(void
    
        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();
@@@@@ -631,15 -628,15 -628,15 -628,8 +631,8 @@@@@ void __init dump_machine_table(void
    
    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;
@@@@@ -857,13 -854,13 -854,13 -849,6 +852,6 @@@@@ static void __init reserve_crashkernel(
    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
@@@@@ -906,12 -903,12 -903,12 -891,10 +894,10 @@@@@ void __init setup_arch(char **cmdline_p
    
        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);
@@@@@ -21,7 -21,7 -21,7 -21,7 +21,7 @@@@@ struct mv_sata_platform_data
    #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
    
    /*
@@@@@ -71,9 -71,9 -71,9 -71,8 +71,8 @@@@@ void edmini_v2_init(void)
    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>
@@@@@ -339,15 -339,15 -339,15 -340,12 +340,12 @@@@@ static void realview_pb1176_restart(enu
        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>
@@@@@ -325,23 -325,23 -325,23 -326,19 +326,19 @@@@@ static void __init realview_pbx_timer_i
        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
    }
    
@@@@@ -370,8 -370,8 -370,8 -367,8 +367,8 @@@@@ static void __init realview_pbx_init(vo
                        __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 .... .... .... */
@@@@@ -904,11 -904,11 -904,11 -904,12 +904,12 @@@@@ static void __dma_page_dev_to_cpu(struc
        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.
@@@@@ -1963,8 -1963,8 -1963,8 -1964,8 +1964,8 @@@@@ arm_iommu_create_mapping(struct bus_typ
        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);
    
diff --combined arch/arm/mm/init.c
    #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;
    
@@@@@ -90,24 -81,24 -81,24 -81,21 +90,21 @@@@@ __tagtable(ATAG_INITRD2, parse_tag_init
     * 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
@@@@@ -283,14 -274,14 -274,14 -265,8 +274,8 @@@@@ phys_addr_t __init arm_memblock_steal(p
        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);
@@@@@ -422,54 -413,54 -413,54 -398,53 +407,53 @@@@@ free_memmap(unsigned long start_pfn, un
    /*
     * 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
    }
    
@@@@@ -545,7 -536,7 -536,7 -520,7 +529,7 @@@@@ void __init mem_init(void
        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
diff --combined arch/arm/mm/mmu.c
    #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"
@@@@@ -117,54 -117,28 -117,28 -118,28 +118,54 @@@@@ static struct cachepolicy cache_policie
    };
    
    #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);
@@@@@ -218,6 -186,35 -186,35 -187,35 +219,6 @@@@@ static int __init early_ecc(char *p
    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)
@@@@@ -417,17 -414,8 -414,8 -415,8 +418,17 @@@@@ static void __init build_mem_type_table
                        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;
@@@@@ -1074,74 -1061,74 -1061,74 -1062,47 +1075,47 @@@@@ phys_addr_t arm_lowmem_limit __initdat
    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;
    
        /*
@@@@@ -1372,6 -1359,6 -1359,6 -1313,9 +1326,9 @@@@@ static void __init kmap_init(void
    #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
    }
    
@@@@@ -1474,7 -1461,7 -1461,7 -1418,7 +1431,7 @@@@@ void __init early_paging_init(const str
         * just complicate the code.
         */
        flush_cache_louis();
---     dsb();
+++     dsb(ishst);
        isb();
    
        /* remap level 1 table */