mirror of
https://github.com/torvalds/linux.git
synced 2024-11-19 02:21:47 +00:00
Merge branch 'ja-nommu-for-rmk-v2' of git://linux-arm.org/linux-ja into devel-stable
This includes the following series sent earlier to the list: - nommu-fixes - R7 Support - MPU support I've left out the ARCH_MULTIPLATFORM/!MMU stuff that Arnd and I were discussing today until we've reached a conclusion/that's had some more review. This is rebased (and re-tested) on your devel-stable branch because otherwise there were going to be conflicts with Uwe's V7M work now that you've merged that. I've included the fix for limiting MPU to CPU_V7.
This commit is contained in:
commit
04e71d72ab
@ -1414,7 +1414,7 @@ config SMP
|
||||
depends on CPU_V6K || CPU_V7
|
||||
depends on GENERIC_CLOCKEVENTS
|
||||
depends on HAVE_SMP
|
||||
depends on MMU
|
||||
depends on MMU || ARM_MPU
|
||||
select USE_GENERIC_SMP_HELPERS
|
||||
help
|
||||
This enables support for systems with more than one CPU. If you have
|
||||
@ -1435,7 +1435,7 @@ config SMP
|
||||
|
||||
config SMP_ON_UP
|
||||
bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)"
|
||||
depends on SMP && !XIP_KERNEL
|
||||
depends on SMP && !XIP_KERNEL && MMU
|
||||
default y
|
||||
help
|
||||
SMP kernels contain instructions which fail on non-SMP processors.
|
||||
|
@ -50,3 +50,15 @@ config REMAP_VECTORS_TO_RAM
|
||||
Otherwise, say 'y' here. In this case, the kernel will require
|
||||
external support to redirect the hardware exception vectors to
|
||||
the writable versions located at DRAM_BASE.
|
||||
|
||||
config ARM_MPU
|
||||
bool 'Use the ARM v7 PMSA Compliant MPU'
|
||||
depends on CPU_V7
|
||||
default y
|
||||
help
|
||||
Some ARM systems without an MMU have instead a Memory Protection
|
||||
Unit (MPU) that defines the type and permissions for regions of
|
||||
memory.
|
||||
|
||||
If your CPU has an MPU then you should choose 'y' here unless you
|
||||
know that you do not want to use the MPU.
|
||||
|
@ -476,6 +476,13 @@ choice
|
||||
of the tiles using the RS1 memory map, including all new A-class
|
||||
core tiles, FPGA-based SMMs and software models.
|
||||
|
||||
config DEBUG_VEXPRESS_UART0_CRX
|
||||
bool "Use PL011 UART0 at 0xb0090000 (Cortex-R compliant tiles)"
|
||||
depends on ARCH_VEXPRESS && !MMU
|
||||
help
|
||||
This option selects UART0 at 0xb0090000. This is appropriate for
|
||||
Cortex-R series tiles and SMMs, such as Cortex-R5 and Cortex-R7
|
||||
|
||||
config DEBUG_VT8500_UART0
|
||||
bool "Use UART0 on VIA/Wondermedia SoCs"
|
||||
depends on ARCH_VT8500
|
||||
@ -645,7 +652,8 @@ config DEBUG_LL_INCLUDE
|
||||
default "debug/tegra.S" if DEBUG_TEGRA_UART
|
||||
default "debug/ux500.S" if DEBUG_UX500_UART
|
||||
default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT || \
|
||||
DEBUG_VEXPRESS_UART0_CA9 || DEBUG_VEXPRESS_UART0_RS1
|
||||
DEBUG_VEXPRESS_UART0_CA9 || DEBUG_VEXPRESS_UART0_RS1 || \
|
||||
DEBUG_VEXPRESS_UART0_CRX
|
||||
default "debug/vt8500.S" if DEBUG_VT8500_UART0
|
||||
default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
|
||||
default "mach/debug-macro.S"
|
||||
|
@ -23,6 +23,11 @@
|
||||
#define CR_RR (1 << 14) /* Round Robin cache replacement */
|
||||
#define CR_L4 (1 << 15) /* LDR pc can set T bit */
|
||||
#define CR_DT (1 << 16)
|
||||
#ifdef CONFIG_MMU
|
||||
#define CR_HA (1 << 17) /* Hardware management of Access Flag */
|
||||
#else
|
||||
#define CR_BR (1 << 17) /* MPU Background region enable (PMSA) */
|
||||
#endif
|
||||
#define CR_IT (1 << 18)
|
||||
#define CR_ST (1 << 19)
|
||||
#define CR_FI (1 << 21) /* Fast interrupt (lower latency mode) */
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define CPUID_CACHETYPE 1
|
||||
#define CPUID_TCM 2
|
||||
#define CPUID_TLBTYPE 3
|
||||
#define CPUID_MPUIR 4
|
||||
#define CPUID_MPIDR 5
|
||||
|
||||
#ifdef CONFIG_CPU_V7M
|
||||
|
76
arch/arm/include/asm/mpu.h
Normal file
76
arch/arm/include/asm/mpu.h
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef __ARM_MPU_H
|
||||
#define __ARM_MPU_H
|
||||
|
||||
#ifdef CONFIG_ARM_MPU
|
||||
|
||||
/* MPUIR layout */
|
||||
#define MPUIR_nU 1
|
||||
#define MPUIR_DREGION 8
|
||||
#define MPUIR_IREGION 16
|
||||
#define MPUIR_DREGION_SZMASK (0xFF << MPUIR_DREGION)
|
||||
#define MPUIR_IREGION_SZMASK (0xFF << MPUIR_IREGION)
|
||||
|
||||
/* ID_MMFR0 data relevant to MPU */
|
||||
#define MMFR0_PMSA (0xF << 4)
|
||||
#define MMFR0_PMSAv7 (3 << 4)
|
||||
|
||||
/* MPU D/I Size Register fields */
|
||||
#define MPU_RSR_SZ 1
|
||||
#define MPU_RSR_EN 0
|
||||
|
||||
/* The D/I RSR value for an enabled region spanning the whole of memory */
|
||||
#define MPU_RSR_ALL_MEM 63
|
||||
|
||||
/* Individual bits in the DR/IR ACR */
|
||||
#define MPU_ACR_XN (1 << 12)
|
||||
#define MPU_ACR_SHARED (1 << 2)
|
||||
|
||||
/* C, B and TEX[2:0] bits only have semantic meanings when grouped */
|
||||
#define MPU_RGN_CACHEABLE 0xB
|
||||
#define MPU_RGN_SHARED_CACHEABLE (MPU_RGN_CACHEABLE | MPU_ACR_SHARED)
|
||||
#define MPU_RGN_STRONGLY_ORDERED 0
|
||||
|
||||
/* Main region should only be shared for SMP */
|
||||
#ifdef CONFIG_SMP
|
||||
#define MPU_RGN_NORMAL (MPU_RGN_CACHEABLE | MPU_ACR_SHARED)
|
||||
#else
|
||||
#define MPU_RGN_NORMAL MPU_RGN_CACHEABLE
|
||||
#endif
|
||||
|
||||
/* Access permission bits of ACR (only define those that we use)*/
|
||||
#define MPU_AP_PL1RW_PL0RW (0x3 << 8)
|
||||
#define MPU_AP_PL1RW_PL0R0 (0x2 << 8)
|
||||
#define MPU_AP_PL1RW_PL0NA (0x1 << 8)
|
||||
|
||||
/* For minimal static MPU region configurations */
|
||||
#define MPU_PROBE_REGION 0
|
||||
#define MPU_BG_REGION 1
|
||||
#define MPU_RAM_REGION 2
|
||||
#define MPU_VECTORS_REGION 3
|
||||
|
||||
/* Maximum number of regions Linux is interested in */
|
||||
#define MPU_MAX_REGIONS 16
|
||||
|
||||
#define MPU_DATA_SIDE 0
|
||||
#define MPU_INSTR_SIDE 1
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
struct mpu_rgn {
|
||||
/* Assume same attributes for d/i-side */
|
||||
u32 drbar;
|
||||
u32 drsr;
|
||||
u32 dracr;
|
||||
};
|
||||
|
||||
struct mpu_rgn_info {
|
||||
u32 mpuir;
|
||||
struct mpu_rgn rgns[MPU_MAX_REGIONS];
|
||||
};
|
||||
extern struct mpu_rgn_info mpu_rgn_info;
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* CONFIG_ARM_MPU */
|
||||
|
||||
#endif
|
@ -137,6 +137,10 @@ extern void cpu_resume(void);
|
||||
})
|
||||
#endif
|
||||
|
||||
#else /*!CONFIG_MMU */
|
||||
|
||||
#define cpu_switch_mm(pgd,mm) { }
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
@ -65,7 +65,10 @@ asmlinkage void secondary_start_kernel(void);
|
||||
* Initial data for bringing up a secondary CPU.
|
||||
*/
|
||||
struct secondary_data {
|
||||
unsigned long pgdir;
|
||||
union {
|
||||
unsigned long mpu_rgn_szr;
|
||||
unsigned long pgdir;
|
||||
};
|
||||
unsigned long swapper_pg_dir;
|
||||
void *stack;
|
||||
};
|
||||
|
@ -26,6 +26,9 @@ static inline bool is_smp(void)
|
||||
}
|
||||
|
||||
/* all SMP configurations have the extended CPUID registers */
|
||||
#ifndef CONFIG_MMU
|
||||
#define tlb_ops_need_broadcast() 0
|
||||
#else
|
||||
static inline int tlb_ops_need_broadcast(void)
|
||||
{
|
||||
if (!is_smp())
|
||||
@ -33,6 +36,7 @@ static inline int tlb_ops_need_broadcast(void)
|
||||
|
||||
return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_SMP) || __LINUX_ARM_ARCH__ >= 7
|
||||
#define cache_ops_need_broadcast() 0
|
||||
|
@ -537,6 +537,29 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
#elif defined(CONFIG_SMP) /* !CONFIG_MMU */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/mm_types.h>
|
||||
|
||||
static inline void local_flush_tlb_all(void) { }
|
||||
static inline void local_flush_tlb_mm(struct mm_struct *mm) { }
|
||||
static inline void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) { }
|
||||
static inline void local_flush_tlb_kernel_page(unsigned long kaddr) { }
|
||||
static inline void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { }
|
||||
static inline void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) { }
|
||||
static inline void local_flush_bp_all(void) { }
|
||||
|
||||
extern void flush_tlb_all(void);
|
||||
extern void flush_tlb_mm(struct mm_struct *mm);
|
||||
extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr);
|
||||
extern void flush_tlb_kernel_page(unsigned long kaddr);
|
||||
extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
|
||||
extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
|
||||
extern void flush_bp_all(void);
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -16,6 +16,8 @@
|
||||
#define DEBUG_LL_PHYS_BASE_RS1 0x1c000000
|
||||
#define DEBUG_LL_UART_OFFSET_RS1 0x00090000
|
||||
|
||||
#define DEBUG_LL_UART_PHYS_CRX 0xb0090000
|
||||
|
||||
#define DEBUG_LL_VIRT_BASE 0xf8000000
|
||||
|
||||
#if defined(CONFIG_DEBUG_VEXPRESS_UART0_DETECT)
|
||||
@ -67,6 +69,14 @@
|
||||
|
||||
#include <asm/hardware/debug-pl01x.S>
|
||||
|
||||
#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_CRX)
|
||||
|
||||
.macro addruart,rp,tmp,tmp2
|
||||
ldr \rp, =DEBUG_LL_UART_PHYS_CRX
|
||||
.endm
|
||||
|
||||
#include <asm/hardware/debug-pl01x.S>
|
||||
|
||||
#else /* CONFIG_DEBUG_LL_UART_NONE */
|
||||
|
||||
.macro addruart, rp, rv, tmp
|
||||
|
@ -38,7 +38,10 @@ obj-$(CONFIG_ARTHUR) += arthur.o
|
||||
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_SMP) += smp.o smp_tlb.o
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
ifdef CONFIG_MMU
|
||||
obj-$(CONFIG_SMP) += smp_tlb.o
|
||||
endif
|
||||
obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
|
||||
obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
|
||||
obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o
|
||||
|
@ -17,9 +17,12 @@
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/cp15.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/v7m.h>
|
||||
#include <asm/mpu.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
/*
|
||||
* Kernel startup entry point.
|
||||
@ -63,12 +66,74 @@ ENTRY(stext)
|
||||
movs r10, r5 @ invalid processor (r5=0)?
|
||||
beq __error_p @ yes, error 'p'
|
||||
|
||||
adr lr, BSYM(__after_proc_init) @ return (PIC) address
|
||||
#ifdef CONFIG_ARM_MPU
|
||||
/* Calculate the size of a region covering just the kernel */
|
||||
ldr r5, =PHYS_OFFSET @ Region start: PHYS_OFFSET
|
||||
ldr r6, =(_end) @ Cover whole kernel
|
||||
sub r6, r6, r5 @ Minimum size of region to map
|
||||
clz r6, r6 @ Region size must be 2^N...
|
||||
rsb r6, r6, #31 @ ...so round up region size
|
||||
lsl r6, r6, #MPU_RSR_SZ @ Put size in right field
|
||||
orr r6, r6, #(1 << MPU_RSR_EN) @ Set region enabled bit
|
||||
bl __setup_mpu
|
||||
#endif
|
||||
ldr r13, =__mmap_switched @ address to jump to after
|
||||
@ initialising sctlr
|
||||
adr lr, BSYM(1f) @ return (PIC) address
|
||||
ARM( add pc, r10, #PROCINFO_INITFUNC )
|
||||
THUMB( add r12, r10, #PROCINFO_INITFUNC )
|
||||
THUMB( mov pc, r12 )
|
||||
1: b __after_proc_init
|
||||
ENDPROC(stext)
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
__CPUINIT
|
||||
ENTRY(secondary_startup)
|
||||
/*
|
||||
* Common entry point for secondary CPUs.
|
||||
*
|
||||
* Ensure that we're in SVC mode, and IRQs are disabled. Lookup
|
||||
* the processor type - there is no need to check the machine type
|
||||
* as it has already been validated by the primary processor.
|
||||
*/
|
||||
setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9
|
||||
#ifndef CONFIG_CPU_CP15
|
||||
ldr r9, =CONFIG_PROCESSOR_ID
|
||||
#else
|
||||
mrc p15, 0, r9, c0, c0 @ get processor id
|
||||
#endif
|
||||
bl __lookup_processor_type @ r5=procinfo r9=cpuid
|
||||
movs r10, r5 @ invalid processor?
|
||||
beq __error_p @ yes, error 'p'
|
||||
|
||||
adr r4, __secondary_data
|
||||
ldmia r4, {r7, r12}
|
||||
|
||||
#ifdef CONFIG_ARM_MPU
|
||||
/* Use MPU region info supplied by __cpu_up */
|
||||
ldr r6, [r7] @ get secondary_data.mpu_szr
|
||||
bl __setup_mpu @ Initialize the MPU
|
||||
#endif
|
||||
|
||||
adr lr, BSYM(__after_proc_init) @ return address
|
||||
mov r13, r12 @ __secondary_switched address
|
||||
ARM( add pc, r10, #PROCINFO_INITFUNC )
|
||||
THUMB( add r12, r10, #PROCINFO_INITFUNC )
|
||||
THUMB( mov pc, r12 )
|
||||
ENDPROC(secondary_startup)
|
||||
|
||||
ENTRY(__secondary_switched)
|
||||
ldr sp, [r7, #8] @ set up the stack pointer
|
||||
mov fp, #0
|
||||
b secondary_start_kernel
|
||||
ENDPROC(__secondary_switched)
|
||||
|
||||
.type __secondary_data, %object
|
||||
__secondary_data:
|
||||
.long secondary_data
|
||||
.long __secondary_switched
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
/*
|
||||
* Set the Control Register and Read the process ID.
|
||||
*/
|
||||
@ -99,10 +164,97 @@ __after_proc_init:
|
||||
#endif
|
||||
mcr p15, 0, r0, c1, c0, 0 @ write control reg
|
||||
#endif /* CONFIG_CPU_CP15 */
|
||||
|
||||
b __mmap_switched @ clear the BSS and jump
|
||||
@ to start_kernel
|
||||
mov pc, r13
|
||||
ENDPROC(__after_proc_init)
|
||||
.ltorg
|
||||
|
||||
#ifdef CONFIG_ARM_MPU
|
||||
|
||||
|
||||
/* Set which MPU region should be programmed */
|
||||
.macro set_region_nr tmp, rgnr
|
||||
mov \tmp, \rgnr @ Use static region numbers
|
||||
mcr p15, 0, \tmp, c6, c2, 0 @ Write RGNR
|
||||
.endm
|
||||
|
||||
/* Setup a single MPU region, either D or I side (D-side for unified) */
|
||||
.macro setup_region bar, acr, sr, side = MPU_DATA_SIDE
|
||||
mcr p15, 0, \bar, c6, c1, (0 + \side) @ I/DRBAR
|
||||
mcr p15, 0, \acr, c6, c1, (4 + \side) @ I/DRACR
|
||||
mcr p15, 0, \sr, c6, c1, (2 + \side) @ I/DRSR
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Setup the MPU and initial MPU Regions. We create the following regions:
|
||||
* Region 0: Use this for probing the MPU details, so leave disabled.
|
||||
* Region 1: Background region - covers the whole of RAM as strongly ordered
|
||||
* Region 2: Normal, Shared, cacheable for RAM. From PHYS_OFFSET, size from r6
|
||||
* Region 3: Normal, shared, inaccessible from PL0 to protect the vectors page
|
||||
*
|
||||
* r6: Value to be written to DRSR (and IRSR if required) for MPU_RAM_REGION
|
||||
*/
|
||||
|
||||
ENTRY(__setup_mpu)
|
||||
|
||||
/* Probe for v7 PMSA compliance */
|
||||
mrc p15, 0, r0, c0, c1, 4 @ Read ID_MMFR0
|
||||
and r0, r0, #(MMFR0_PMSA) @ PMSA field
|
||||
teq r0, #(MMFR0_PMSAv7) @ PMSA v7
|
||||
bne __error_p @ Fail: ARM_MPU on NOT v7 PMSA
|
||||
|
||||
/* Determine whether the D/I-side memory map is unified. We set the
|
||||
* flags here and continue to use them for the rest of this function */
|
||||
mrc p15, 0, r0, c0, c0, 4 @ MPUIR
|
||||
ands r5, r0, #MPUIR_DREGION_SZMASK @ 0 size d region => No MPU
|
||||
beq __error_p @ Fail: ARM_MPU and no MPU
|
||||
tst r0, #MPUIR_nU @ MPUIR_nU = 0 for unified
|
||||
|
||||
/* Setup second region first to free up r6 */
|
||||
set_region_nr r0, #MPU_RAM_REGION
|
||||
isb
|
||||
/* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */
|
||||
ldr r0, =PHYS_OFFSET @ RAM starts at PHYS_OFFSET
|
||||
ldr r5,=(MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL)
|
||||
|
||||
setup_region r0, r5, r6, MPU_DATA_SIDE @ PHYS_OFFSET, shared, enabled
|
||||
beq 1f @ Memory-map not unified
|
||||
setup_region r0, r5, r6, MPU_INSTR_SIDE @ PHYS_OFFSET, shared, enabled
|
||||
1: isb
|
||||
|
||||
/* First/background region */
|
||||
set_region_nr r0, #MPU_BG_REGION
|
||||
isb
|
||||
/* Execute Never, strongly ordered, inaccessible to PL0, rw PL1 */
|
||||
mov r0, #0 @ BG region starts at 0x0
|
||||
ldr r5,=(MPU_ACR_XN | MPU_RGN_STRONGLY_ORDERED | MPU_AP_PL1RW_PL0NA)
|
||||
mov r6, #MPU_RSR_ALL_MEM @ 4GB region, enabled
|
||||
|
||||
setup_region r0, r5, r6, MPU_DATA_SIDE @ 0x0, BG region, enabled
|
||||
beq 2f @ Memory-map not unified
|
||||
setup_region r0, r5, r6, MPU_INSTR_SIDE @ 0x0, BG region, enabled
|
||||
2: isb
|
||||
|
||||
/* Vectors region */
|
||||
set_region_nr r0, #MPU_VECTORS_REGION
|
||||
isb
|
||||
/* Shared, inaccessible to PL0, rw PL1 */
|
||||
mov r0, #CONFIG_VECTORS_BASE @ Cover from VECTORS_BASE
|
||||
ldr r5,=(MPU_AP_PL1RW_PL0NA | MPU_RGN_NORMAL)
|
||||
/* Writing N to bits 5:1 (RSR_SZ) --> region size 2^N+1 */
|
||||
mov r6, #(((PAGE_SHIFT - 1) << MPU_RSR_SZ) | 1 << MPU_RSR_EN)
|
||||
|
||||
setup_region r0, r5, r6, MPU_DATA_SIDE @ VECTORS_BASE, PL0 NA, enabled
|
||||
beq 3f @ Memory-map not unified
|
||||
setup_region r0, r5, r6, MPU_INSTR_SIDE @ VECTORS_BASE, PL0 NA, enabled
|
||||
3: isb
|
||||
|
||||
/* Enable the MPU */
|
||||
mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR
|
||||
bic r0, r0, #CR_BR @ Disable the 'default mem-map'
|
||||
orr r0, r0, #CR_M @ Set SCTRL.M (MPU on)
|
||||
mcr p15, 0, r0, c1, c0, 0 @ Enable MPU
|
||||
isb
|
||||
mov pc,lr
|
||||
ENDPROC(__setup_mpu)
|
||||
#endif
|
||||
#include "head-common.S"
|
||||
|
@ -392,14 +392,19 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
idx += 3;
|
||||
|
||||
/*
|
||||
* Put the sigreturn code on the stack no matter which return
|
||||
* mechanism we use in order to remain ABI compliant
|
||||
*/
|
||||
if (__put_user(sigreturn_codes[idx], rc) ||
|
||||
__put_user(sigreturn_codes[idx+1], rc+1))
|
||||
return 1;
|
||||
|
||||
if (cpsr & MODE32_BIT) {
|
||||
if ((cpsr & MODE32_BIT) && !IS_ENABLED(CONFIG_ARM_MPU)) {
|
||||
/*
|
||||
* 32-bit code can use the new high-page
|
||||
* signal return code support.
|
||||
* signal return code support except when the MPU has
|
||||
* protected the vectors page from PL0
|
||||
*/
|
||||
retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb;
|
||||
} else {
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/virt.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mpu.h>
|
||||
|
||||
/*
|
||||
* as from 2.5, kernels no longer have an init_tasks structure
|
||||
@ -87,8 +88,14 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
|
||||
* its stack and the page tables.
|
||||
*/
|
||||
secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
|
||||
#ifdef CONFIG_ARM_MPU
|
||||
secondary_data.mpu_rgn_szr = mpu_rgn_info.rgns[MPU_RAM_REGION].drsr;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
secondary_data.pgdir = virt_to_phys(idmap_pgd);
|
||||
secondary_data.swapper_pg_dir = virt_to_phys(swapper_pg_dir);
|
||||
#endif
|
||||
__cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data));
|
||||
outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1));
|
||||
|
||||
@ -112,9 +119,8 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
|
||||
pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
|
||||
}
|
||||
|
||||
secondary_data.stack = NULL;
|
||||
secondary_data.pgdir = 0;
|
||||
|
||||
memset(&secondary_data, 0, sizeof(secondary_data));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,42 @@
|
||||
extern int __cpu_suspend(unsigned long, int (*)(unsigned long));
|
||||
extern void cpu_resume_mmu(void);
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
/*
|
||||
* Hide the first two arguments to __cpu_suspend - these are an implementation
|
||||
* detail which platform code shouldn't have to know about.
|
||||
*/
|
||||
int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
|
||||
{
|
||||
struct mm_struct *mm = current->active_mm;
|
||||
int ret;
|
||||
|
||||
if (!idmap_pgd)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Provide a temporary page table with an identity mapping for
|
||||
* the MMU-enable code, required for resuming. On successful
|
||||
* resume (indicated by a zero return code), we need to switch
|
||||
* back to the correct page tables.
|
||||
*/
|
||||
ret = __cpu_suspend(arg, fn);
|
||||
if (ret == 0) {
|
||||
cpu_switch_mm(mm->pgd, mm);
|
||||
local_flush_bp_all();
|
||||
local_flush_tlb_all();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
|
||||
{
|
||||
return __cpu_suspend(arg, fn);
|
||||
}
|
||||
#define idmap_pgd NULL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is called by __cpu_suspend() to save the state, and do whatever
|
||||
* flushing is required to ensure that when the CPU goes to sleep we have
|
||||
@ -46,31 +82,3 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
|
||||
outer_clean_range(virt_to_phys(save_ptr),
|
||||
virt_to_phys(save_ptr) + sizeof(*save_ptr));
|
||||
}
|
||||
|
||||
/*
|
||||
* Hide the first two arguments to __cpu_suspend - these are an implementation
|
||||
* detail which platform code shouldn't have to know about.
|
||||
*/
|
||||
int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
|
||||
{
|
||||
struct mm_struct *mm = current->active_mm;
|
||||
int ret;
|
||||
|
||||
if (!idmap_pgd)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Provide a temporary page table with an identity mapping for
|
||||
* the MMU-enable code, required for resuming. On successful
|
||||
* resume (indicated by a zero return code), we need to switch
|
||||
* back to the correct page tables.
|
||||
*/
|
||||
ret = __cpu_suspend(arg, fn);
|
||||
if (ret == 0) {
|
||||
cpu_switch_mm(mm->pgd, mm);
|
||||
local_flush_bp_all();
|
||||
local_flush_tlb_all();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -392,7 +392,8 @@ config CPU_V7
|
||||
select CPU_CACHE_V7
|
||||
select CPU_CACHE_VIPT
|
||||
select CPU_COPY_V6 if MMU
|
||||
select CPU_CP15_MMU
|
||||
select CPU_CP15_MMU if MMU
|
||||
select CPU_CP15_MPU if !MMU
|
||||
select CPU_HAS_ASID if MMU
|
||||
select CPU_PABRT_V7
|
||||
select CPU_TLB_V7 if MMU
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/sections.h>
|
||||
@ -15,9 +16,260 @@
|
||||
#include <asm/setup.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/mpu.h>
|
||||
|
||||
#include "mm.h"
|
||||
|
||||
#ifdef CONFIG_ARM_MPU
|
||||
struct mpu_rgn_info mpu_rgn_info;
|
||||
|
||||
/* Region number */
|
||||
static void rgnr_write(u32 v)
|
||||
{
|
||||
asm("mcr p15, 0, %0, c6, c2, 0" : : "r" (v));
|
||||
}
|
||||
|
||||
/* Data-side / unified region attributes */
|
||||
|
||||
/* Region access control register */
|
||||
static void dracr_write(u32 v)
|
||||
{
|
||||
asm("mcr p15, 0, %0, c6, c1, 4" : : "r" (v));
|
||||
}
|
||||
|
||||
/* Region size register */
|
||||
static void drsr_write(u32 v)
|
||||
{
|
||||
asm("mcr p15, 0, %0, c6, c1, 2" : : "r" (v));
|
||||
}
|
||||
|
||||
/* Region base address register */
|
||||
static void drbar_write(u32 v)
|
||||
{
|
||||
asm("mcr p15, 0, %0, c6, c1, 0" : : "r" (v));
|
||||
}
|
||||
|
||||
static u32 drbar_read(void)
|
||||
{
|
||||
u32 v;
|
||||
asm("mrc p15, 0, %0, c6, c1, 0" : "=r" (v));
|
||||
return v;
|
||||
}
|
||||
/* Optional instruction-side region attributes */
|
||||
|
||||
/* I-side Region access control register */
|
||||
static void iracr_write(u32 v)
|
||||
{
|
||||
asm("mcr p15, 0, %0, c6, c1, 5" : : "r" (v));
|
||||
}
|
||||
|
||||
/* I-side Region size register */
|
||||
static void irsr_write(u32 v)
|
||||
{
|
||||
asm("mcr p15, 0, %0, c6, c1, 3" : : "r" (v));
|
||||
}
|
||||
|
||||
/* I-side Region base address register */
|
||||
static void irbar_write(u32 v)
|
||||
{
|
||||
asm("mcr p15, 0, %0, c6, c1, 1" : : "r" (v));
|
||||
}
|
||||
|
||||
static unsigned long irbar_read(void)
|
||||
{
|
||||
unsigned long v;
|
||||
asm("mrc p15, 0, %0, c6, c1, 1" : "=r" (v));
|
||||
return v;
|
||||
}
|
||||
|
||||
/* MPU initialisation functions */
|
||||
void __init sanity_check_meminfo_mpu(void)
|
||||
{
|
||||
int i;
|
||||
struct membank *bank = meminfo.bank;
|
||||
phys_addr_t phys_offset = PHYS_OFFSET;
|
||||
phys_addr_t aligned_region_size, specified_mem_size, rounded_mem_size;
|
||||
|
||||
/* Initially only use memory continuous from PHYS_OFFSET */
|
||||
if (bank_phys_start(&bank[0]) != phys_offset)
|
||||
panic("First memory bank must be contiguous from PHYS_OFFSET");
|
||||
|
||||
/* Banks have already been sorted by start address */
|
||||
for (i = 1; i < meminfo.nr_banks; i++) {
|
||||
if (bank[i].start <= bank_phys_end(&bank[0]) &&
|
||||
bank_phys_end(&bank[i]) > bank_phys_end(&bank[0])) {
|
||||
bank[0].size = bank_phys_end(&bank[i]) - bank[0].start;
|
||||
} else {
|
||||
pr_notice("Ignoring RAM after 0x%.8lx. "
|
||||
"First non-contiguous (ignored) bank start: 0x%.8lx\n",
|
||||
(unsigned long)bank_phys_end(&bank[0]),
|
||||
(unsigned long)bank_phys_start(&bank[i]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* All contiguous banks are now merged in to the first bank */
|
||||
meminfo.nr_banks = 1;
|
||||
specified_mem_size = bank[0].size;
|
||||
|
||||
/*
|
||||
* MPU has curious alignment requirements: Size must be power of 2, and
|
||||
* region start must be aligned to the region size
|
||||
*/
|
||||
if (phys_offset != 0)
|
||||
pr_info("PHYS_OFFSET != 0 => MPU Region size constrained by alignment requirements\n");
|
||||
|
||||
/*
|
||||
* Maximum aligned region might overflow phys_addr_t if phys_offset is
|
||||
* 0. Hence we keep everything below 4G until we take the smaller of
|
||||
* the aligned_region_size and rounded_mem_size, one of which is
|
||||
* guaranteed to be smaller than the maximum physical address.
|
||||
*/
|
||||
aligned_region_size = (phys_offset - 1) ^ (phys_offset);
|
||||
/* Find the max power-of-two sized region that fits inside our bank */
|
||||
rounded_mem_size = (1 << __fls(bank[0].size)) - 1;
|
||||
|
||||
/* The actual region size is the smaller of the two */
|
||||
aligned_region_size = aligned_region_size < rounded_mem_size
|
||||
? aligned_region_size + 1
|
||||
: rounded_mem_size + 1;
|
||||
|
||||
if (aligned_region_size != specified_mem_size)
|
||||
pr_warn("Truncating memory from 0x%.8lx to 0x%.8lx (MPU region constraints)",
|
||||
(unsigned long)specified_mem_size,
|
||||
(unsigned long)aligned_region_size);
|
||||
|
||||
meminfo.bank[0].size = aligned_region_size;
|
||||
pr_debug("MPU Region from 0x%.8lx size 0x%.8lx (end 0x%.8lx))\n",
|
||||
(unsigned long)phys_offset,
|
||||
(unsigned long)aligned_region_size,
|
||||
(unsigned long)bank_phys_end(&bank[0]));
|
||||
|
||||
}
|
||||
|
||||
static int mpu_present(void)
|
||||
{
|
||||
return ((read_cpuid_ext(CPUID_EXT_MMFR0) & MMFR0_PMSA) == MMFR0_PMSAv7);
|
||||
}
|
||||
|
||||
static int mpu_max_regions(void)
|
||||
{
|
||||
/*
|
||||
* We don't support a different number of I/D side regions so if we
|
||||
* have separate instruction and data memory maps then return
|
||||
* whichever side has a smaller number of supported regions.
|
||||
*/
|
||||
u32 dregions, iregions, mpuir;
|
||||
mpuir = read_cpuid(CPUID_MPUIR);
|
||||
|
||||
dregions = iregions = (mpuir & MPUIR_DREGION_SZMASK) >> MPUIR_DREGION;
|
||||
|
||||
/* Check for separate d-side and i-side memory maps */
|
||||
if (mpuir & MPUIR_nU)
|
||||
iregions = (mpuir & MPUIR_IREGION_SZMASK) >> MPUIR_IREGION;
|
||||
|
||||
/* Use the smallest of the two maxima */
|
||||
return min(dregions, iregions);
|
||||
}
|
||||
|
||||
static int mpu_iside_independent(void)
|
||||
{
|
||||
/* MPUIR.nU specifies whether there is *not* a unified memory map */
|
||||
return read_cpuid(CPUID_MPUIR) & MPUIR_nU;
|
||||
}
|
||||
|
||||
static int mpu_min_region_order(void)
|
||||
{
|
||||
u32 drbar_result, irbar_result;
|
||||
/* We've kept a region free for this probing */
|
||||
rgnr_write(MPU_PROBE_REGION);
|
||||
isb();
|
||||
/*
|
||||
* As per ARM ARM, write 0xFFFFFFFC to DRBAR to find the minimum
|
||||
* region order
|
||||
*/
|
||||
drbar_write(0xFFFFFFFC);
|
||||
drbar_result = irbar_result = drbar_read();
|
||||
drbar_write(0x0);
|
||||
/* If the MPU is non-unified, we use the larger of the two minima*/
|
||||
if (mpu_iside_independent()) {
|
||||
irbar_write(0xFFFFFFFC);
|
||||
irbar_result = irbar_read();
|
||||
irbar_write(0x0);
|
||||
}
|
||||
isb(); /* Ensure that MPU region operations have completed */
|
||||
/* Return whichever result is larger */
|
||||
return __ffs(max(drbar_result, irbar_result));
|
||||
}
|
||||
|
||||
static int mpu_setup_region(unsigned int number, phys_addr_t start,
|
||||
unsigned int size_order, unsigned int properties)
|
||||
{
|
||||
u32 size_data;
|
||||
|
||||
/* We kept a region free for probing resolution of MPU regions*/
|
||||
if (number > mpu_max_regions() || number == MPU_PROBE_REGION)
|
||||
return -ENOENT;
|
||||
|
||||
if (size_order > 32)
|
||||
return -ENOMEM;
|
||||
|
||||
if (size_order < mpu_min_region_order())
|
||||
return -ENOMEM;
|
||||
|
||||
/* Writing N to bits 5:1 (RSR_SZ) specifies region size 2^N+1 */
|
||||
size_data = ((size_order - 1) << MPU_RSR_SZ) | 1 << MPU_RSR_EN;
|
||||
|
||||
dsb(); /* Ensure all previous data accesses occur with old mappings */
|
||||
rgnr_write(number);
|
||||
isb();
|
||||
drbar_write(start);
|
||||
dracr_write(properties);
|
||||
isb(); /* Propagate properties before enabling region */
|
||||
drsr_write(size_data);
|
||||
|
||||
/* Check for independent I-side registers */
|
||||
if (mpu_iside_independent()) {
|
||||
irbar_write(start);
|
||||
iracr_write(properties);
|
||||
isb();
|
||||
irsr_write(size_data);
|
||||
}
|
||||
isb();
|
||||
|
||||
/* Store region info (we treat i/d side the same, so only store d) */
|
||||
mpu_rgn_info.rgns[number].dracr = properties;
|
||||
mpu_rgn_info.rgns[number].drbar = start;
|
||||
mpu_rgn_info.rgns[number].drsr = size_data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up default MPU regions, doing nothing if there is no MPU
|
||||
*/
|
||||
void __init mpu_setup(void)
|
||||
{
|
||||
int region_err;
|
||||
if (!mpu_present())
|
||||
return;
|
||||
|
||||
region_err = mpu_setup_region(MPU_RAM_REGION, PHYS_OFFSET,
|
||||
ilog2(meminfo.bank[0].size),
|
||||
MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL);
|
||||
if (region_err) {
|
||||
panic("MPU region initialization failure! %d", region_err);
|
||||
} else {
|
||||
pr_info("Using ARMv7 PMSA Compliant MPU. "
|
||||
"Region independence: %s, Max regions: %d\n",
|
||||
mpu_iside_independent() ? "Yes" : "No",
|
||||
mpu_max_regions());
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void sanity_check_meminfo_mpu(void) {}
|
||||
static void __init mpu_setup(void) {}
|
||||
#endif /* CONFIG_ARM_MPU */
|
||||
|
||||
void __init arm_mm_memblock_reserve(void)
|
||||
{
|
||||
#ifndef CONFIG_CPU_V7M
|
||||
@ -37,7 +289,9 @@ void __init arm_mm_memblock_reserve(void)
|
||||
|
||||
void __init sanity_check_meminfo(void)
|
||||
{
|
||||
phys_addr_t end = bank_phys_end(&meminfo.bank[meminfo.nr_banks - 1]);
|
||||
phys_addr_t end;
|
||||
sanity_check_meminfo_mpu();
|
||||
end = bank_phys_end(&meminfo.bank[meminfo.nr_banks - 1]);
|
||||
high_memory = __va(end - 1) + 1;
|
||||
}
|
||||
|
||||
@ -48,6 +302,7 @@ void __init sanity_check_meminfo(void)
|
||||
void __init paging_init(struct machine_desc *mdesc)
|
||||
{
|
||||
early_trap_init((void *)CONFIG_VECTORS_BASE);
|
||||
mpu_setup();
|
||||
bootmem_init();
|
||||
}
|
||||
|
||||
|
@ -140,8 +140,10 @@ ENTRY(cpu_v6_set_pte_ext)
|
||||
ENTRY(cpu_v6_do_suspend)
|
||||
stmfd sp!, {r4 - r9, lr}
|
||||
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
||||
#ifdef CONFIG_MMU
|
||||
mrc p15, 0, r5, c3, c0, 0 @ Domain ID
|
||||
mrc p15, 0, r6, c2, c0, 1 @ Translation table base 1
|
||||
#endif
|
||||
mrc p15, 0, r7, c1, c0, 1 @ auxiliary control register
|
||||
mrc p15, 0, r8, c1, c0, 2 @ co-processor access control
|
||||
mrc p15, 0, r9, c1, c0, 0 @ control register
|
||||
@ -158,14 +160,16 @@ ENTRY(cpu_v6_do_resume)
|
||||
mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID
|
||||
ldmia r0, {r4 - r9}
|
||||
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
||||
#ifdef CONFIG_MMU
|
||||
mcr p15, 0, r5, c3, c0, 0 @ Domain ID
|
||||
ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
|
||||
ALT_UP(orr r1, r1, #TTB_FLAGS_UP)
|
||||
mcr p15, 0, r1, c2, c0, 0 @ Translation table base 0
|
||||
mcr p15, 0, r6, c2, c0, 1 @ Translation table base 1
|
||||
mcr p15, 0, ip, c2, c0, 2 @ TTB control register
|
||||
#endif
|
||||
mcr p15, 0, r7, c1, c0, 1 @ auxiliary control register
|
||||
mcr p15, 0, r8, c1, c0, 2 @ co-processor access control
|
||||
mcr p15, 0, ip, c2, c0, 2 @ TTB control register
|
||||
mcr p15, 0, ip, c7, c5, 4 @ ISB
|
||||
mov r0, r9 @ control register
|
||||
b cpu_resume_mmu
|
||||
|
@ -98,9 +98,11 @@ ENTRY(cpu_v7_do_suspend)
|
||||
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
||||
mrc p15, 0, r5, c13, c0, 3 @ User r/o thread ID
|
||||
stmia r0!, {r4 - r5}
|
||||
#ifdef CONFIG_MMU
|
||||
mrc p15, 0, r6, c3, c0, 0 @ Domain ID
|
||||
mrc p15, 0, r7, c2, c0, 1 @ TTB 1
|
||||
mrc p15, 0, r11, c2, c0, 2 @ TTB control register
|
||||
#endif
|
||||
mrc p15, 0, r8, c1, c0, 0 @ Control register
|
||||
mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register
|
||||
mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control
|
||||
@ -110,13 +112,14 @@ ENDPROC(cpu_v7_do_suspend)
|
||||
|
||||
ENTRY(cpu_v7_do_resume)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs
|
||||
mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
|
||||
mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID
|
||||
ldmia r0!, {r4 - r5}
|
||||
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
||||
mcr p15, 0, r5, c13, c0, 3 @ User r/o thread ID
|
||||
ldmia r0, {r6 - r11}
|
||||
#ifdef CONFIG_MMU
|
||||
mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs
|
||||
mcr p15, 0, r6, c3, c0, 0 @ Domain ID
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
|
||||
@ -125,14 +128,15 @@ ENTRY(cpu_v7_do_resume)
|
||||
mcr p15, 0, r1, c2, c0, 0 @ TTB 0
|
||||
mcr p15, 0, r7, c2, c0, 1 @ TTB 1
|
||||
mcr p15, 0, r11, c2, c0, 2 @ TTB control register
|
||||
mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register
|
||||
teq r4, r9 @ Is it already set?
|
||||
mcrne p15, 0, r9, c1, c0, 1 @ No, so write it
|
||||
mcr p15, 0, r10, c1, c0, 2 @ Co-processor access control
|
||||
ldr r4, =PRRR @ PRRR
|
||||
ldr r5, =NMRR @ NMRR
|
||||
mcr p15, 0, r4, c10, c2, 0 @ write PRRR
|
||||
mcr p15, 0, r5, c10, c2, 1 @ write NMRR
|
||||
#endif /* CONFIG_MMU */
|
||||
mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register
|
||||
teq r4, r9 @ Is it already set?
|
||||
mcrne p15, 0, r9, c1, c0, 1 @ No, so write it
|
||||
mcr p15, 0, r10, c1, c0, 2 @ Co-processor access control
|
||||
isb
|
||||
dsb
|
||||
mov r0, r8 @ control register
|
||||
@ -155,7 +159,8 @@ ENDPROC(cpu_v7_do_resume)
|
||||
*/
|
||||
__v7_ca5mp_setup:
|
||||
__v7_ca9mp_setup:
|
||||
mov r10, #(1 << 0) @ TLB ops broadcasting
|
||||
__v7_cr7mp_setup:
|
||||
mov r10, #(1 << 0) @ Cache/TLB ops broadcasting
|
||||
b 1f
|
||||
__v7_ca7mp_setup:
|
||||
__v7_ca15mp_setup:
|
||||
@ -414,6 +419,16 @@ __v7_pj4b_proc_info:
|
||||
__v7_proc __v7_pj4b_setup
|
||||
.size __v7_pj4b_proc_info, . - __v7_pj4b_proc_info
|
||||
|
||||
/*
|
||||
* ARM Ltd. Cortex R7 processor.
|
||||
*/
|
||||
.type __v7_cr7mp_proc_info, #object
|
||||
__v7_cr7mp_proc_info:
|
||||
.long 0x410fc170
|
||||
.long 0xff0ffff0
|
||||
__v7_proc __v7_cr7mp_setup
|
||||
.size __v7_cr7mp_proc_info, . - __v7_cr7mp_proc_info
|
||||
|
||||
/*
|
||||
* ARM Ltd. Cortex A7 processor.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user