diff options
Diffstat (limited to 'arch/arm/kernel')
| -rw-r--r-- | arch/arm/kernel/Makefile | 3 | ||||
| -rw-r--r-- | arch/arm/kernel/armksyms.c | 3 | ||||
| -rw-r--r-- | arch/arm/kernel/asm-offsets.c | 12 | ||||
| -rw-r--r-- | arch/arm/kernel/bios32.c | 9 | ||||
| -rw-r--r-- | arch/arm/kernel/calls.S | 2 | ||||
| -rw-r--r-- | arch/arm/kernel/debug.S | 4 | ||||
| -rw-r--r-- | arch/arm/kernel/ecard.c | 36 | ||||
| -rw-r--r-- | arch/arm/kernel/entry-armv.S | 44 | ||||
| -rw-r--r-- | arch/arm/kernel/head.S | 135 | ||||
| -rw-r--r-- | arch/arm/kernel/irq.c | 2 | ||||
| -rw-r--r-- | arch/arm/kernel/machine_kexec.c | 35 | ||||
| -rw-r--r-- | arch/arm/kernel/module.c | 2 | ||||
| -rw-r--r-- | arch/arm/kernel/perf_event_v7.c | 4 | ||||
| -rw-r--r-- | arch/arm/kernel/pmu.c | 26 | ||||
| -rw-r--r-- | arch/arm/kernel/process.c | 2 | ||||
| -rw-r--r-- | arch/arm/kernel/relocate_kernel.S | 3 | ||||
| -rw-r--r-- | arch/arm/kernel/setup.c | 52 | ||||
| -rw-r--r-- | arch/arm/kernel/smp.c | 55 | ||||
| -rw-r--r-- | arch/arm/kernel/smp_scu.c | 12 | ||||
| -rw-r--r-- | arch/arm/kernel/smp_twd.c | 4 | ||||
| -rw-r--r-- | arch/arm/kernel/time.c | 6 | ||||
| -rw-r--r-- | arch/arm/kernel/topology.c | 148 | ||||
| -rw-r--r-- | arch/arm/kernel/traps.c | 32 | ||||
| -rw-r--r-- | arch/arm/kernel/vmlinux.lds.S | 18 | 
24 files changed, 447 insertions, 202 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index f7887dc53c1..68036eece34 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -29,7 +29,7 @@ obj-$(CONFIG_MODULES)		+= armksyms.o module.o  obj-$(CONFIG_ARTHUR)		+= arthur.o  obj-$(CONFIG_ISA_DMA)		+= dma-isa.o  obj-$(CONFIG_PCI)		+= bios32.o isa.o -obj-$(CONFIG_PM_SLEEP)		+= sleep.o +obj-$(CONFIG_ARM_CPU_SUSPEND)	+= sleep.o  obj-$(CONFIG_HAVE_SCHED_CLOCK)	+= sched_clock.o  obj-$(CONFIG_SMP)		+= smp.o smp_tlb.o  obj-$(CONFIG_HAVE_ARM_SCU)	+= smp_scu.o @@ -66,6 +66,7 @@ obj-$(CONFIG_IWMMXT)		+= iwmmxt.o  obj-$(CONFIG_CPU_HAS_PMU)	+= pmu.o  obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o  AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt +obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o  ifneq ($(CONFIG_ARCH_EBSA110),y)    obj-y		+= io.o diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index aeef960ff79..8e3c6f11b0a 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -49,9 +49,6 @@ extern void __aeabi_ulcmp(void);  extern void fpundefinstr(void); - -EXPORT_SYMBOL(__backtrace); -  	/* platform dependent support */  EXPORT_SYMBOL(__udelay);  EXPORT_SYMBOL(__const_udelay); diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 16baba2e436..1429d8989fb 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -20,6 +20,7 @@  #include <asm/thread_info.h>  #include <asm/memory.h>  #include <asm/procinfo.h> +#include <asm/hardware/cache-l2x0.h>  #include <linux/kbuild.h>  /* @@ -92,6 +93,17 @@ int main(void)    DEFINE(S_OLD_R0,		offsetof(struct pt_regs, ARM_ORIG_r0));    DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));    BLANK(); +#ifdef CONFIG_CACHE_L2X0 +  DEFINE(L2X0_R_PHY_BASE,	offsetof(struct l2x0_regs, phy_base)); +  DEFINE(L2X0_R_AUX_CTRL,	offsetof(struct l2x0_regs, aux_ctrl)); +  DEFINE(L2X0_R_TAG_LATENCY,	offsetof(struct l2x0_regs, tag_latency)); +  DEFINE(L2X0_R_DATA_LATENCY,	offsetof(struct l2x0_regs, data_latency)); +  DEFINE(L2X0_R_FILTER_START,	offsetof(struct l2x0_regs, filter_start)); +  DEFINE(L2X0_R_FILTER_END,	offsetof(struct l2x0_regs, filter_end)); +  DEFINE(L2X0_R_PREFETCH_CTRL,	offsetof(struct l2x0_regs, prefetch_ctrl)); +  DEFINE(L2X0_R_PWR_CTRL,	offsetof(struct l2x0_regs, pwr_ctrl)); +  BLANK(); +#endif  #ifdef CONFIG_CPU_HAS_ASID    DEFINE(MM_CONTEXT_ID,		offsetof(struct mm_struct, context.id));    BLANK(); diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index d6df359408f..c0d9203fc75 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -412,6 +412,9 @@ void pcibios_fixup_bus(struct pci_bus *bus)  	printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",  		bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");  } +#ifdef CONFIG_HOTPLUG +EXPORT_SYMBOL(pcibios_fixup_bus); +#endif  /*   * Convert from Linux-centric to bus-centric addresses for bridge devices. @@ -431,6 +434,7 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,  	region->start = res->start - offset;  	region->end   = res->end - offset;  } +EXPORT_SYMBOL(pcibios_resource_to_bus);  void __devinit  pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, @@ -447,12 +451,7 @@ pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,  	res->start = region->start + offset;  	res->end   = region->end + offset;  } - -#ifdef CONFIG_HOTPLUG -EXPORT_SYMBOL(pcibios_fixup_bus); -EXPORT_SYMBOL(pcibios_resource_to_bus);  EXPORT_SYMBOL(pcibios_bus_to_resource); -#endif  /*   * Swizzle the device pin each time we cross a bridge. diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 80f7896cc01..9943e9e74a1 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -178,7 +178,7 @@  		CALL(sys_ni_syscall)		/* vm86 */  		CALL(sys_ni_syscall)		/* was sys_query_module */  		CALL(sys_poll) -		CALL(sys_nfsservctl) +		CALL(sys_ni_syscall)		/* was nfsservctl */  /* 170 */	CALL(sys_setresgid16)  		CALL(sys_getresgid16)  		CALL(sys_prctl) diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S index bcd66e00bdb..0f852d082fc 100644 --- a/arch/arm/kernel/debug.S +++ b/arch/arm/kernel/debug.S @@ -151,6 +151,8 @@ printhex:	adr	r2, hexbuf  		b	printascii  ENDPROC(printhex2) +hexbuf:		.space 16 +  		.ltorg  ENTRY(printascii) @@ -175,5 +177,3 @@ ENTRY(printch)  		mov	r0, #0  		b	1b  ENDPROC(printch) - -hexbuf:		.space 16 diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index d16500110ee..4dd0edab6a6 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -237,7 +237,7 @@ static void ecard_init_pgtables(struct mm_struct *mm)  	memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE)); -	src_pgd = pgd_offset(mm, EASI_BASE); +	src_pgd = pgd_offset(mm, (unsigned long)EASI_BASE);  	dst_pgd = pgd_offset(mm, EASI_START);  	memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (EASI_SIZE / PGDIR_SIZE)); @@ -674,44 +674,37 @@ static int __init ecard_probeirqhw(void)  #define ecard_probeirqhw() (0)  #endif -#ifndef IO_EC_MEMC8_BASE -#define IO_EC_MEMC8_BASE 0 -#endif - -static unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) +static void __iomem *__ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)  { -	unsigned long address = 0; +	void __iomem *address = NULL;  	int slot = ec->slot_no;  	if (ec->slot_no == 8) -		return IO_EC_MEMC8_BASE; +		return ECARD_MEMC8_BASE;  	ectcr &= ~(1 << slot);  	switch (type) {  	case ECARD_MEMC:  		if (slot < 4) -			address = IO_EC_MEMC_BASE + (slot << 12); +			address = ECARD_MEMC_BASE + (slot << 14);  		break;  	case ECARD_IOC:  		if (slot < 4) -			address = IO_EC_IOC_BASE + (slot << 12); -#ifdef IO_EC_IOC4_BASE +			address = ECARD_IOC_BASE + (slot << 14);  		else -			address = IO_EC_IOC4_BASE + ((slot - 4) << 12); -#endif +			address = ECARD_IOC4_BASE + ((slot - 4) << 14);  		if (address) -			address +=  speed << 17; +			address += speed << 19;  		break; -#ifdef IO_EC_EASI_BASE  	case ECARD_EASI: -		address = IO_EC_EASI_BASE + (slot << 22); +		address = ECARD_EASI_BASE + (slot << 24);  		if (speed == ECARD_FAST)  			ectcr |= 1 << slot;  		break; -#endif +  	default:  		break;  	} @@ -990,6 +983,7 @@ ecard_probe(int slot, card_type_t type)  	ecard_t **ecp;  	ecard_t *ec;  	struct ex_ecid cid; +	void __iomem *addr;  	int i, rc;  	ec = ecard_alloc_card(type, slot); @@ -999,7 +993,7 @@ ecard_probe(int slot, card_type_t type)  	}  	rc = -ENODEV; -	if ((ec->podaddr = __ecard_address(ec, type, ECARD_SYNC)) == 0) +	if ((addr = __ecard_address(ec, type, ECARD_SYNC)) == NULL)  		goto nodev;  	cid.r_zero = 1; @@ -1019,7 +1013,7 @@ ecard_probe(int slot, card_type_t type)  	ec->cid.fiqmask = cid.r_fiqmask;  	ec->cid.fiqoff  = ecard_gets24(cid.r_fiqoff);  	ec->fiqaddr	= -	ec->irqaddr	= (void __iomem *)ioaddr(ec->podaddr); +	ec->irqaddr	= addr;  	if (ec->cid.is) {  		ec->irqmask = ec->cid.irqmask; @@ -1048,10 +1042,8 @@ ecard_probe(int slot, card_type_t type)  		set_irq_flags(ec->irq, IRQF_VALID);  	} -#ifdef IO_EC_MEMC8_BASE  	if (slot == 8)  		ec->irq = 11; -#endif  #ifdef CONFIG_ARCH_RPC  	/* On RiscPC, only first two slots have DMA capability */  	if (slot < 2) @@ -1097,9 +1089,7 @@ static int __init ecard_init(void)  			ecard_probe(slot, ECARD_IOC);  	} -#ifdef IO_EC_MEMC8_BASE  	ecard_probe(8, ECARD_IOC); -#endif  	irqhw = ecard_probeirqhw(); diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index a87cbf889ff..9ad50c4208a 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -24,6 +24,7 @@  #include <asm/unwind.h>  #include <asm/unistd.h>  #include <asm/tls.h> +#include <asm/system.h>  #include "entry-header.S"  #include <asm/entry-macro-multi.S> @@ -262,8 +263,7 @@ __und_svc:  	ldr	r0, [r4, #-4]  #else  	ldrh	r0, [r4, #-2]			@ Thumb instruction at LR - 2 -	and	r9, r0, #0xf800 -	cmp	r9, #0xe800			@ 32-bit instruction if xx >= 0 +	cmp	r0, #0xe800			@ 32-bit instruction if xx >= 0  	ldrhhs	r9, [r4]			@ bottom 16 bits  	orrhs	r0, r9, r0, lsl #16  #endif @@ -440,18 +440,46 @@ __und_usr:  #endif  	beq	call_fpe  	@ Thumb instruction -#if __LINUX_ARM_ARCH__ >= 7 +#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7 +/* + * Thumb-2 instruction handling.  Note that because pre-v6 and >= v6 platforms + * can never be supported in a single kernel, this code is not applicable at + * all when __LINUX_ARM_ARCH__ < 6.  This allows simplifying assumptions to be + * made about .arch directives. + */ +#if __LINUX_ARM_ARCH__ < 7 +/* If the target CPU may not be Thumb-2-capable, a run-time check is needed: */ +#define NEED_CPU_ARCHITECTURE +	ldr	r5, .LCcpu_architecture +	ldr	r5, [r5] +	cmp	r5, #CPU_ARCH_ARMv7 +	blo	__und_usr_unknown +/* + * The following code won't get run unless the running CPU really is v7, so + * coding round the lack of ldrht on older arches is pointless.  Temporarily + * override the assembler target arch with the minimum required instead: + */ +	.arch	armv6t2 +#endif  2:   ARM(	ldrht	r5, [r4], #2	)   THUMB(	ldrht	r5, [r4]	)   THUMB(	add	r4, r4, #2	) -	and	r0, r5, #0xf800			@ mask bits 111x x... .... .... -	cmp	r0, #0xe800			@ 32bit instruction if xx != 0 +	cmp	r5, #0xe800			@ 32bit instruction if xx != 0  	blo	__und_usr_unknown  3:	ldrht	r0, [r4]  	add	r2, r2, #2			@ r2 is PC + 2, make it PC + 4  	orr	r0, r0, r5, lsl #16 + +#if __LINUX_ARM_ARCH__ < 7 +/* If the target arch was overridden, change it back: */ +#ifdef CONFIG_CPU_32v6K +	.arch	armv6k  #else +	.arch	armv6 +#endif +#endif /* __LINUX_ARM_ARCH__ < 7 */ +#else /* !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) */  	b	__und_usr_unknown  #endif   UNWIND(.fnend		) @@ -578,6 +606,12 @@ call_fpe:  	movw_pc	lr				@ CP#14 (Debug)  	movw_pc	lr				@ CP#15 (Control) +#ifdef NEED_CPU_ARCHITECTURE +	.align	2 +.LCcpu_architecture: +	.word	__cpu_architecture +#endif +  #ifdef CONFIG_NEON  	.align	6 diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 742b6108a00..239703dbdf4 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -21,6 +21,7 @@  #include <asm/memory.h>  #include <asm/thread_info.h>  #include <asm/system.h> +#include <asm/pgtable.h>  #ifdef CONFIG_DEBUG_LL  #include <mach/debug-macro.S> @@ -38,11 +39,14 @@  #error KERNEL_RAM_VADDR must start at 0xXXXX8000  #endif +#define PG_DIR_SIZE	0x4000 +#define PMD_ORDER	2 +  	.globl	swapper_pg_dir -	.equ	swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000 +	.equ	swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE  	.macro	pgtbl, rd, phys -	add	\rd, \phys, #TEXT_OFFSET - 0x4000 +	add	\rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE  	.endm  #ifdef CONFIG_XIP_KERNEL @@ -148,11 +152,11 @@ __create_page_tables:  	pgtbl	r4, r8				@ page table address  	/* -	 * Clear the 16K level 1 swapper page table +	 * Clear the swapper page table  	 */  	mov	r0, r4  	mov	r3, #0 -	add	r6, r0, #0x4000 +	add	r6, r0, #PG_DIR_SIZE  1:	str	r3, [r0], #4  	str	r3, [r0], #4  	str	r3, [r0], #4 @@ -171,30 +175,30 @@ __create_page_tables:  	sub	r0, r0, r3			@ virt->phys offset  	add	r5, r5, r0			@ phys __enable_mmu  	add	r6, r6, r0			@ phys __enable_mmu_end -	mov	r5, r5, lsr #20 -	mov	r6, r6, lsr #20 +	mov	r5, r5, lsr #SECTION_SHIFT +	mov	r6, r6, lsr #SECTION_SHIFT -1:	orr	r3, r7, r5, lsl #20		@ flags + kernel base -	str	r3, [r4, r5, lsl #2]		@ identity mapping -	teq	r5, r6 -	addne	r5, r5, #1			@ next section -	bne	1b +1:	orr	r3, r7, r5, lsl #SECTION_SHIFT	@ flags + kernel base +	str	r3, [r4, r5, lsl #PMD_ORDER]	@ identity mapping +	cmp	r5, r6 +	addlo	r5, r5, #1			@ next section +	blo	1b  	/*  	 * Now setup the pagetables for our kernel direct  	 * mapped region.  	 */  	mov	r3, pc -	mov	r3, r3, lsr #20 -	orr	r3, r7, r3, lsl #20 -	add	r0, r4,  #(KERNEL_START & 0xff000000) >> 18 -	str	r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]! +	mov	r3, r3, lsr #SECTION_SHIFT +	orr	r3, r7, r3, lsl #SECTION_SHIFT +	add	r0, r4,  #(KERNEL_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) +	str	r3, [r0, #((KERNEL_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]!  	ldr	r6, =(KERNEL_END - 1) -	add	r0, r0, #4 -	add	r6, r4, r6, lsr #18 +	add	r0, r0, #1 << PMD_ORDER +	add	r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER)  1:	cmp	r0, r6 -	add	r3, r3, #1 << 20 -	strls	r3, [r0], #4 +	add	r3, r3, #1 << SECTION_SHIFT +	strls	r3, [r0], #1 << PMD_ORDER  	bls	1b  #ifdef CONFIG_XIP_KERNEL @@ -203,11 +207,11 @@ __create_page_tables:  	 */  	add	r3, r8, #TEXT_OFFSET  	orr	r3, r3, r7 -	add	r0, r4,  #(KERNEL_RAM_VADDR & 0xff000000) >> 18 -	str	r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]! +	add	r0, r4,  #(KERNEL_RAM_VADDR & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) +	str	r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> (SECTION_SHIFT - PMD_ORDER)]!  	ldr	r6, =(_end - 1)  	add	r0, r0, #4 -	add	r6, r4, r6, lsr #18 +	add	r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER)  1:	cmp	r0, r6  	add	r3, r3, #1 << 20  	strls	r3, [r0], #4 @@ -218,12 +222,12 @@ __create_page_tables:  	 * Then map boot params address in r2 or  	 * the first 1MB of ram if boot params address is not specified.  	 */ -	mov	r0, r2, lsr #20 -	movs	r0, r0, lsl #20 +	mov	r0, r2, lsr #SECTION_SHIFT +	movs	r0, r0, lsl #SECTION_SHIFT  	moveq	r0, r8  	sub	r3, r0, r8  	add	r3, r3, #PAGE_OFFSET -	add	r3, r4, r3, lsr #18 +	add	r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER)  	orr	r6, r7, r0  	str	r6, [r3] @@ -236,21 +240,21 @@ __create_page_tables:  	 */  	addruart r7, r3 -	mov	r3, r3, lsr #20 -	mov	r3, r3, lsl #2 +	mov	r3, r3, lsr #SECTION_SHIFT +	mov	r3, r3, lsl #PMD_ORDER  	add	r0, r4, r3  	rsb	r3, r3, #0x4000			@ PTRS_PER_PGD*sizeof(long)  	cmp	r3, #0x0800			@ limit to 512MB  	movhi	r3, #0x0800  	add	r6, r0, r3 -	mov	r3, r7, lsr #20 +	mov	r3, r7, lsr #SECTION_SHIFT  	ldr	r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags -	orr	r3, r7, r3, lsl #20 +	orr	r3, r7, r3, lsl #SECTION_SHIFT  1:	str	r3, [r0], #4 -	add	r3, r3, #1 << 20 -	teq	r0, r6 -	bne	1b +	add	r3, r3, #1 << SECTION_SHIFT +	cmp	r0, r6 +	blo	1b  #else /* CONFIG_DEBUG_ICEDCC */  	/* we don't need any serial debugging mappings for ICEDCC */ @@ -262,7 +266,7 @@ __create_page_tables:  	 * If we're using the NetWinder or CATS, we also need to map  	 * in the 16550-type serial port for the debug messages  	 */ -	add	r0, r4, #0xff000000 >> 18 +	add	r0, r4, #0xff000000 >> (SECTION_SHIFT - PMD_ORDER)  	orr	r3, r7, #0x7c000000  	str	r3, [r0]  #endif @@ -272,10 +276,10 @@ __create_page_tables:  	 * Similar reasons here - for debug.  This is  	 * only for Acorn RiscPC architectures.  	 */ -	add	r0, r4, #0x02000000 >> 18 +	add	r0, r4, #0x02000000 >> (SECTION_SHIFT - PMD_ORDER)  	orr	r3, r7, #0x02000000  	str	r3, [r0] -	add	r0, r4, #0xd8000000 >> 18 +	add	r0, r4, #0xd8000000 >> (SECTION_SHIFT - PMD_ORDER)  	str	r3, [r0]  #endif  #endif @@ -488,13 +492,8 @@ __fixup_pv_table:  	add	r5, r5, r3	@ adjust table end address  	add	r7, r7, r3	@ adjust __pv_phys_offset address  	str	r8, [r7]	@ save computed PHYS_OFFSET to __pv_phys_offset -#ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT  	mov	r6, r3, lsr #24	@ constant for add/sub instructions  	teq	r3, r6, lsl #24 @ must be 16MiB aligned -#else -	mov	r6, r3, lsr #16	@ constant for add/sub instructions -	teq	r3, r6, lsl #16	@ must be 64kiB aligned -#endif  THUMB(	it	ne		@ cross section branch )  	bne	__error  	str	r6, [r7, #4]	@ save to __pv_offset @@ -510,20 +509,8 @@ ENDPROC(__fixup_pv_table)  	.text  __fixup_a_pv_table:  #ifdef CONFIG_THUMB2_KERNEL -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT -	lsls	r0, r6, #24 -	lsr	r6, #8 -	beq	1f -	clz	r7, r0 -	lsr	r0, #24 -	lsl	r0, r7 -	bic	r0, 0x0080 -	lsrs	r7, #1 -	orrcs   r0, #0x0080 -	orr	r0, r0, r7, lsl #12 -#endif -1:	lsls	r6, #24 -	beq	4f +	lsls	r6, #24 +	beq	2f  	clz	r7, r6  	lsr	r6, #24  	lsl	r6, r7 @@ -532,43 +519,25 @@ __fixup_a_pv_table:  	orrcs	r6, #0x0080  	orr	r6, r6, r7, lsl #12  	orr	r6, #0x4000 -	b	4f -2:	@ at this point the C flag is always clear -	add     r7, r3 -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT -	ldrh	ip, [r7] -	tst	ip, 0x0400	@ the i bit tells us LS or MS byte -	beq	3f -	cmp	r0, #0		@ set C flag, and ... -	biceq	ip, 0x0400	@ immediate zero value has a special encoding -	streqh	ip, [r7]	@ that requires the i bit cleared -#endif -3:	ldrh	ip, [r7, #2] +	b	2f +1:	add     r7, r3 +	ldrh	ip, [r7, #2]  	and	ip, 0x8f00 -	orrcc	ip, r6	@ mask in offset bits 31-24 -	orrcs	ip, r0	@ mask in offset bits 23-16 +	orr	ip, r6	@ mask in offset bits 31-24  	strh	ip, [r7, #2] -4:	cmp	r4, r5 +2:	cmp	r4, r5  	ldrcc	r7, [r4], #4	@ use branch for delay slot -	bcc	2b +	bcc	1b  	bx	lr  #else -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT -	and	r0, r6, #255	@ offset bits 23-16 -	mov	r6, r6, lsr #8	@ offset bits 31-24 -#else -	mov	r0, #0		@ just in case... -#endif -	b	3f -2:	ldr	ip, [r7, r3] +	b	2f +1:	ldr	ip, [r7, r3]  	bic	ip, ip, #0x000000ff -	tst	ip, #0x400	@ rotate shift tells us LS or MS byte -	orrne	ip, ip, r6	@ mask in offset bits 31-24 -	orreq	ip, ip, r0	@ mask in offset bits 23-16 +	orr	ip, ip, r6	@ mask in offset bits 31-24  	str	ip, [r7, r3] -3:	cmp	r4, r5 +2:	cmp	r4, r5  	ldrcc	r7, [r4], #4	@ use branch for delay slot -	bcc	2b +	bcc	1b  	mov	pc, lr  #endif  ENDPROC(__fixup_a_pv_table) diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index de3dcab8610..53919b230e8 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -35,8 +35,8 @@  #include <linux/list.h>  #include <linux/kallsyms.h>  #include <linux/proc_fs.h> -#include <linux/ftrace.h> +#include <asm/exception.h>  #include <asm/system.h>  #include <asm/mach/arch.h>  #include <asm/mach/irq.h> diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index e59bbd496c3..c1b4463dcc8 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -32,6 +32,24 @@ static atomic_t waiting_for_crash_ipi;  int machine_kexec_prepare(struct kimage *image)  { +	unsigned long page_list; +	void *reboot_code_buffer; +	page_list = image->head & PAGE_MASK; + +	reboot_code_buffer = page_address(image->control_code_page); + +	/* Prepare parameters for reboot_code_buffer*/ +	kexec_start_address = image->start; +	kexec_indirection_page = page_list; +	kexec_mach_type = machine_arch_type; +	kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; + +	/* copy our kernel relocation code to the control code page */ +	memcpy(reboot_code_buffer, +	       relocate_new_kernel, relocate_new_kernel_size); + +	flush_icache_range((unsigned long) reboot_code_buffer, +			   (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);  	return 0;  } @@ -82,31 +100,14 @@ void (*kexec_reinit)(void);  void machine_kexec(struct kimage *image)  { -	unsigned long page_list;  	unsigned long reboot_code_buffer_phys;  	void *reboot_code_buffer; - -	page_list = image->head & PAGE_MASK; -  	/* we need both effective and real address here */  	reboot_code_buffer_phys =  	    page_to_pfn(image->control_code_page) << PAGE_SHIFT;  	reboot_code_buffer = page_address(image->control_code_page); -	/* Prepare parameters for reboot_code_buffer*/ -	kexec_start_address = image->start; -	kexec_indirection_page = page_list; -	kexec_mach_type = machine_arch_type; -	kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; - -	/* copy our kernel relocation code to the control code page */ -	memcpy(reboot_code_buffer, -	       relocate_new_kernel, relocate_new_kernel_size); - - -	flush_icache_range((unsigned long) reboot_code_buffer, -			   (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);  	printk(KERN_INFO "Bye!\n");  	if (kexec_reinit) diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index cc2020c2c70..1e9be5d25e5 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -33,7 +33,7 @@   * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off.   */  #undef MODULES_VADDR -#define MODULES_VADDR	(((unsigned long)_etext + ~PGDIR_MASK) & PGDIR_MASK) +#define MODULES_VADDR	(((unsigned long)_etext + ~PMD_MASK) & PMD_MASK)  #endif  #ifdef CONFIG_MMU diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 4c851834f68..6be3e2e4d83 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -321,8 +321,8 @@ static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = {  	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,  	[PERF_COUNT_HW_INSTRUCTIONS]	    =  					ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE, -	[PERF_COUNT_HW_CACHE_REFERENCES]    = ARMV7_PERFCTR_COHERENT_LINE_HIT, -	[PERF_COUNT_HW_CACHE_MISSES]	    = ARMV7_PERFCTR_COHERENT_LINE_MISS, +	[PERF_COUNT_HW_CACHE_REFERENCES]    = ARMV7_PERFCTR_DCACHE_ACCESS, +	[PERF_COUNT_HW_CACHE_MISSES]	    = ARMV7_PERFCTR_DCACHE_REFILL,  	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,  	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,  	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES, diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c index 2b70709376c..c53474fe84d 100644 --- a/arch/arm/kernel/pmu.c +++ b/arch/arm/kernel/pmu.c @@ -31,7 +31,7 @@ static int __devinit pmu_register(struct platform_device *pdev,  {  	if (type < 0 || type >= ARM_NUM_PMU_DEVICES) {  		pr_warning("received registration request for unknown " -				"device %d\n", type); +				"PMU device type %d\n", type);  		return -EINVAL;  	} @@ -112,17 +112,17 @@ static int __init register_pmu_driver(void)  device_initcall(register_pmu_driver);  struct platform_device * -reserve_pmu(enum arm_pmu_type device) +reserve_pmu(enum arm_pmu_type type)  {  	struct platform_device *pdev; -	if (test_and_set_bit_lock(device, &pmu_lock)) { +	if (test_and_set_bit_lock(type, &pmu_lock)) {  		pdev = ERR_PTR(-EBUSY); -	} else if (pmu_devices[device] == NULL) { -		clear_bit_unlock(device, &pmu_lock); +	} else if (pmu_devices[type] == NULL) { +		clear_bit_unlock(type, &pmu_lock);  		pdev = ERR_PTR(-ENODEV);  	} else { -		pdev = pmu_devices[device]; +		pdev = pmu_devices[type];  	}  	return pdev; @@ -130,11 +130,11 @@ reserve_pmu(enum arm_pmu_type device)  EXPORT_SYMBOL_GPL(reserve_pmu);  int -release_pmu(enum arm_pmu_type device) +release_pmu(enum arm_pmu_type type)  { -	if (WARN_ON(!pmu_devices[device])) +	if (WARN_ON(!pmu_devices[type]))  		return -EINVAL; -	clear_bit_unlock(device, &pmu_lock); +	clear_bit_unlock(type, &pmu_lock);  	return 0;  }  EXPORT_SYMBOL_GPL(release_pmu); @@ -182,17 +182,17 @@ init_cpu_pmu(void)  }  int -init_pmu(enum arm_pmu_type device) +init_pmu(enum arm_pmu_type type)  {  	int err = 0; -	switch (device) { +	switch (type) {  	case ARM_PMU_DEVICE_CPU:  		err = init_cpu_pmu();  		break;  	default: -		pr_warning("attempt to initialise unknown device %d\n", -				device); +		pr_warning("attempt to initialise PMU of unknown " +			   "type %d\n", type);  		err = -EINVAL;  	} diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 1a347f481e5..fd0814076ff 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -319,7 +319,7 @@ void show_regs(struct pt_regs * regs)  	printk("\n");  	printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm);  	__show_regs(regs); -	__backtrace(); +	dump_stack();  }  ATOMIC_NOTIFIER_HEAD(thread_notify_head); diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S index 9cf4cbf8f95..d0cdedf4864 100644 --- a/arch/arm/kernel/relocate_kernel.S +++ b/arch/arm/kernel/relocate_kernel.S @@ -57,7 +57,8 @@ relocate_new_kernel:  	mov r0,#0  	ldr r1,kexec_mach_type  	ldr r2,kexec_boot_atags -	mov pc,lr + ARM(	mov pc, lr	) + THUMB(	bx lr		)  	.align diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 70bca649e92..3fe93f75b55 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -29,6 +29,8 @@  #include <linux/fs.h>  #include <linux/proc_fs.h>  #include <linux/memblock.h> +#include <linux/bug.h> +#include <linux/compiler.h>  #include <asm/unified.h>  #include <asm/cpu.h> @@ -42,6 +44,7 @@  #include <asm/cacheflush.h>  #include <asm/cachetype.h>  #include <asm/tlbflush.h> +#include <asm/system.h>  #include <asm/prom.h>  #include <asm/mach/arch.h> @@ -115,6 +118,13 @@ struct outer_cache_fns outer_cache __read_mostly;  EXPORT_SYMBOL(outer_cache);  #endif +/* + * Cached cpu_architecture() result for use by assembler code. + * C code should use the cpu_architecture() function instead of accessing this + * variable directly. + */ +int __cpu_architecture __read_mostly = CPU_ARCH_UNKNOWN; +  struct stack {  	u32 irq[3];  	u32 abt[3]; @@ -210,7 +220,7 @@ static const char *proc_arch[] = {  	"?(17)",  }; -int cpu_architecture(void) +static int __get_cpu_architecture(void)  {  	int cpu_arch; @@ -243,11 +253,22 @@ int cpu_architecture(void)  	return cpu_arch;  } +int __pure cpu_architecture(void) +{ +	BUG_ON(__cpu_architecture == CPU_ARCH_UNKNOWN); + +	return __cpu_architecture; +} +  static int cpu_has_aliasing_icache(unsigned int arch)  {  	int aliasing_icache;  	unsigned int id_reg, num_sets, line_size; +	/* PIPT caches never alias. */ +	if (icache_is_pipt()) +		return 0; +  	/* arch specifies the register format */  	switch (arch) {  	case CPU_ARCH_ARMv7: @@ -280,18 +301,25 @@ static void __init cacheid_init(void)  	if (arch >= CPU_ARCH_ARMv6) {  		if ((cachetype & (7 << 29)) == 4 << 29) {  			/* ARMv7 register format */ +			arch = CPU_ARCH_ARMv7;  			cacheid = CACHEID_VIPT_NONALIASING; -			if ((cachetype & (3 << 14)) == 1 << 14) +			switch (cachetype & (3 << 14)) { +			case (1 << 14):  				cacheid |= CACHEID_ASID_TAGGED; -			else if (cpu_has_aliasing_icache(CPU_ARCH_ARMv7)) -				cacheid |= CACHEID_VIPT_I_ALIASING; -		} else if (cachetype & (1 << 23)) { -			cacheid = CACHEID_VIPT_ALIASING; +				break; +			case (3 << 14): +				cacheid |= CACHEID_PIPT; +				break; +			}  		} else { -			cacheid = CACHEID_VIPT_NONALIASING; -			if (cpu_has_aliasing_icache(CPU_ARCH_ARMv6)) -				cacheid |= CACHEID_VIPT_I_ALIASING; +			arch = CPU_ARCH_ARMv6; +			if (cachetype & (1 << 23)) +				cacheid = CACHEID_VIPT_ALIASING; +			else +				cacheid = CACHEID_VIPT_NONALIASING;  		} +		if (cpu_has_aliasing_icache(arch)) +			cacheid |= CACHEID_VIPT_I_ALIASING;  	} else {  		cacheid = CACHEID_VIVT;  	} @@ -299,10 +327,11 @@ static void __init cacheid_init(void)  	printk("CPU: %s data cache, %s instruction cache\n",  		cache_is_vivt() ? "VIVT" :  		cache_is_vipt_aliasing() ? "VIPT aliasing" : -		cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown", +		cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",  		cache_is_vivt() ? "VIVT" :  		icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :  		icache_is_vipt_aliasing() ? "VIPT aliasing" : +		icache_is_pipt() ? "PIPT" :  		cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");  } @@ -413,6 +442,7 @@ static void __init setup_processor(void)  	}  	cpu_name = list->cpu_name; +	__cpu_architecture = __get_cpu_architecture();  #ifdef MULTI_CPU  	processor = *list->proc; @@ -860,7 +890,7 @@ static struct machine_desc * __init setup_machine_tags(unsigned int nr)  	}  	if (mdesc->fixup) -		mdesc->fixup(mdesc, tags, &from, &meminfo); +		mdesc->fixup(tags, &from, &meminfo);  	if (tags->hdr.tag == ATAG_CORE) {  		if (meminfo.nr_banks != 0) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index d88ff0230e8..854ce33715f 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -16,7 +16,6 @@  #include <linux/cache.h>  #include <linux/profile.h>  #include <linux/errno.h> -#include <linux/ftrace.h>  #include <linux/mm.h>  #include <linux/err.h>  #include <linux/cpu.h> @@ -31,6 +30,8 @@  #include <asm/cacheflush.h>  #include <asm/cpu.h>  #include <asm/cputype.h> +#include <asm/exception.h> +#include <asm/topology.h>  #include <asm/mmu_context.h>  #include <asm/pgtable.h>  #include <asm/pgalloc.h> @@ -39,6 +40,7 @@  #include <asm/tlbflush.h>  #include <asm/ptrace.h>  #include <asm/localtimer.h> +#include <asm/smp_plat.h>  /*   * as from 2.5, kernels no longer have an init_tasks structure @@ -259,6 +261,20 @@ void __ref cpu_die(void)  }  #endif /* CONFIG_HOTPLUG_CPU */ +int __cpu_logical_map[NR_CPUS]; + +void __init smp_setup_processor_id(void) +{ +	int i; +	u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0; + +	cpu_logical_map(0) = cpu; +	for (i = 1; i < NR_CPUS; ++i) +		cpu_logical_map(i) = i == cpu ? 0 : i; + +	printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu); +} +  /*   * Called by both boot and secondaries to move global data into   * per-processor storage. @@ -268,6 +284,8 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid)  	struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);  	cpu_info->loops_per_jiffy = loops_per_jiffy; + +	store_cpu_topology(cpuid);  }  /* @@ -301,17 +319,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)  	 */  	platform_secondary_init(cpu); -	/* -	 * Enable local interrupts. -	 */  	notify_cpu_starting(cpu); -	local_irq_enable(); -	local_fiq_enable(); - -	/* -	 * Setup the percpu timer for this CPU. -	 */ -	percpu_timer_setup();  	calibrate_delay(); @@ -323,10 +331,23 @@ asmlinkage void __cpuinit secondary_start_kernel(void)  	 * before we continue.  	 */  	set_cpu_online(cpu, true); + +	/* +	 * Setup the percpu timer for this CPU. +	 */ +	percpu_timer_setup(); +  	while (!cpu_active(cpu))  		cpu_relax();  	/* +	 * cpu_active bit is set, so it's safe to enalbe interrupts +	 * now. +	 */ +	local_irq_enable(); +	local_fiq_enable(); + +	/*  	 * OK, it's off to the idle thread for us  	 */  	cpu_idle(); @@ -358,6 +379,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)  {  	unsigned int ncores = num_possible_cpus(); +	init_cpu_topology(); +  	smp_store_cpu_info(smp_processor_id());  	/* @@ -460,6 +483,11 @@ static void ipi_timer(void)  #ifdef CONFIG_LOCAL_TIMERS  asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)  { +	handle_local_timer(regs); +} + +void handle_local_timer(struct pt_regs *regs) +{  	struct pt_regs *old_regs = set_irq_regs(regs);  	int cpu = smp_processor_id(); @@ -567,6 +595,11 @@ static void ipi_cpu_stop(unsigned int cpu)   */  asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)  { +	handle_IPI(ipinr, regs); +} + +void handle_IPI(int ipinr, struct pt_regs *regs) +{  	unsigned int cpu = smp_processor_id();  	struct pt_regs *old_regs = set_irq_regs(regs); diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c index 79ed5e7f204..8f5dd796335 100644 --- a/arch/arm/kernel/smp_scu.c +++ b/arch/arm/kernel/smp_scu.c @@ -13,6 +13,7 @@  #include <asm/smp_scu.h>  #include <asm/cacheflush.h> +#include <asm/cputype.h>  #define SCU_CTRL		0x00  #define SCU_CONFIG		0x04 @@ -33,10 +34,19 @@ unsigned int __init scu_get_core_count(void __iomem *scu_base)  /*   * Enable the SCU   */ -void __init scu_enable(void __iomem *scu_base) +void scu_enable(void __iomem *scu_base)  {  	u32 scu_ctrl; +#ifdef CONFIG_ARM_ERRATA_764369 +	/* Cortex-A9 only */ +	if ((read_cpuid(CPUID_ID) & 0xff0ffff0) == 0x410fc090) { +		scu_ctrl = __raw_readl(scu_base + 0x30); +		if (!(scu_ctrl & 1)) +			__raw_writel(scu_ctrl | 0x1, scu_base + 0x30); +	} +#endif +  	scu_ctrl = __raw_readl(scu_base + SCU_CTRL);  	/* already enabled? */  	if (scu_ctrl & 1) diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 2c277d40cee..01c186222f3 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -137,8 +137,8 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)  	clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);  	clk->min_delta_ns = clockevent_delta2ns(0xf, clk); +	clockevents_register_device(clk); +  	/* Make sure our local interrupt controller has this enabled */  	gic_enable_ppi(clk->irq); - -	clockevents_register_device(clk);  } diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index cb634c3e28e..5a54b95d6bd 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -39,13 +39,11 @@   */  static struct sys_timer *system_timer; -#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) +#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \ +    defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE)  /* this needs a better home */  DEFINE_SPINLOCK(rtc_lock); - -#ifdef CONFIG_RTC_DRV_CMOS_MODULE  EXPORT_SYMBOL(rtc_lock); -#endif  #endif	/* pc-style 'CMOS' RTC support */  /* change this if you have some constant time drift */ diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c new file mode 100644 index 00000000000..1040c00405d --- /dev/null +++ b/arch/arm/kernel/topology.c @@ -0,0 +1,148 @@ +/* + * arch/arm/kernel/topology.c + * + * Copyright (C) 2011 Linaro Limited. + * Written by: Vincent Guittot + * + * based on arch/sh/kernel/topology.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/cpu.h> +#include <linux/cpumask.h> +#include <linux/init.h> +#include <linux/percpu.h> +#include <linux/node.h> +#include <linux/nodemask.h> +#include <linux/sched.h> + +#include <asm/cputype.h> +#include <asm/topology.h> + +#define MPIDR_SMP_BITMASK (0x3 << 30) +#define MPIDR_SMP_VALUE (0x2 << 30) + +#define MPIDR_MT_BITMASK (0x1 << 24) + +/* + * These masks reflect the current use of the affinity levels. + * The affinity level can be up to 16 bits according to ARM ARM + */ + +#define MPIDR_LEVEL0_MASK 0x3 +#define MPIDR_LEVEL0_SHIFT 0 + +#define MPIDR_LEVEL1_MASK 0xF +#define MPIDR_LEVEL1_SHIFT 8 + +#define MPIDR_LEVEL2_MASK 0xFF +#define MPIDR_LEVEL2_SHIFT 16 + +struct cputopo_arm cpu_topology[NR_CPUS]; + +const struct cpumask *cpu_coregroup_mask(unsigned int cpu) +{ +	return &cpu_topology[cpu].core_sibling; +} + +/* + * store_cpu_topology is called at boot when only one cpu is running + * and with the mutex cpu_hotplug.lock locked, when several cpus have booted, + * which prevents simultaneous write access to cpu_topology array + */ +void store_cpu_topology(unsigned int cpuid) +{ +	struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; +	unsigned int mpidr; +	unsigned int cpu; + +	/* If the cpu topology has been already set, just return */ +	if (cpuid_topo->core_id != -1) +		return; + +	mpidr = read_cpuid_mpidr(); + +	/* create cpu topology mapping */ +	if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) { +		/* +		 * This is a multiprocessor system +		 * multiprocessor format & multiprocessor mode field are set +		 */ + +		if (mpidr & MPIDR_MT_BITMASK) { +			/* core performance interdependency */ +			cpuid_topo->thread_id = (mpidr >> MPIDR_LEVEL0_SHIFT) +				& MPIDR_LEVEL0_MASK; +			cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL1_SHIFT) +				& MPIDR_LEVEL1_MASK; +			cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL2_SHIFT) +				& MPIDR_LEVEL2_MASK; +		} else { +			/* largely independent cores */ +			cpuid_topo->thread_id = -1; +			cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL0_SHIFT) +				& MPIDR_LEVEL0_MASK; +			cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT) +				& MPIDR_LEVEL1_MASK; +		} +	} else { +		/* +		 * This is an uniprocessor system +		 * we are in multiprocessor format but uniprocessor system +		 * or in the old uniprocessor format +		 */ +		cpuid_topo->thread_id = -1; +		cpuid_topo->core_id = 0; +		cpuid_topo->socket_id = -1; +	} + +	/* update core and thread sibling masks */ +	for_each_possible_cpu(cpu) { +		struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; + +		if (cpuid_topo->socket_id == cpu_topo->socket_id) { +			cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); +			if (cpu != cpuid) +				cpumask_set_cpu(cpu, +					&cpuid_topo->core_sibling); + +			if (cpuid_topo->core_id == cpu_topo->core_id) { +				cpumask_set_cpu(cpuid, +					&cpu_topo->thread_sibling); +				if (cpu != cpuid) +					cpumask_set_cpu(cpu, +						&cpuid_topo->thread_sibling); +			} +		} +	} +	smp_wmb(); + +	printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", +		cpuid, cpu_topology[cpuid].thread_id, +		cpu_topology[cpuid].core_id, +		cpu_topology[cpuid].socket_id, mpidr); +} + +/* + * init_cpu_topology is called at boot when only one cpu is running + * which prevent simultaneous write access to cpu_topology array + */ +void init_cpu_topology(void) +{ +	unsigned int cpu; + +	/* init core mask */ +	for_each_possible_cpu(cpu) { +		struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]); + +		cpu_topo->thread_id = -1; +		cpu_topo->core_id =  -1; +		cpu_topo->socket_id = -1; +		cpumask_clear(&cpu_topo->core_sibling); +		cpumask_clear(&cpu_topo->thread_sibling); +	} +	smp_wmb(); +} diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index bc9f9da782c..7f5b99eb2c5 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -21,12 +21,14 @@  #include <linux/kdebug.h>  #include <linux/module.h>  #include <linux/kexec.h> +#include <linux/bug.h>  #include <linux/delay.h>  #include <linux/init.h>  #include <linux/sched.h>  #include <linux/atomic.h>  #include <asm/cacheflush.h> +#include <asm/exception.h>  #include <asm/system.h>  #include <asm/unistd.h>  #include <asm/traps.h> @@ -270,6 +272,8 @@ void die(const char *str, struct pt_regs *regs, int err)  	spin_lock_irq(&die_lock);  	console_verbose();  	bust_spinlocks(1); +	if (!user_mode(regs)) +		report_bug(regs->ARM_pc, regs);  	ret = __die(str, err, thread, regs);  	if (regs && kexec_should_crash(thread->task)) @@ -301,6 +305,24 @@ void arm_notify_die(const char *str, struct pt_regs *regs,  	}  } +#ifdef CONFIG_GENERIC_BUG + +int is_valid_bugaddr(unsigned long pc) +{ +#ifdef CONFIG_THUMB2_KERNEL +	unsigned short bkpt; +#else +	unsigned long bkpt; +#endif + +	if (probe_kernel_address((unsigned *)pc, bkpt)) +		return 0; + +	return bkpt == BUG_INSTR_VALUE; +} + +#endif +  static LIST_HEAD(undef_hook);  static DEFINE_SPINLOCK(undef_lock); @@ -706,16 +728,6 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)  	arm_notify_die("unknown data abort code", regs, &info, instr, 0);  } -void __attribute__((noreturn)) __bug(const char *file, int line) -{ -	printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line); -	*(int *)0 = 0; - -	/* Avoid "noreturn function does return" */ -	for (;;); -} -EXPORT_SYMBOL(__bug); -  void __readwrite_bug(const char *fn)  {  	printk("%s called, but not implemented\n", fn); diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index bf977f8514f..20b3041e086 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -21,10 +21,13 @@  #define ARM_CPU_KEEP(x)  #endif -#if defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK) +#if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \ +	defined(CONFIG_GENERIC_BUG)  #define ARM_EXIT_KEEP(x)	x +#define ARM_EXIT_DISCARD(x)  #else  #define ARM_EXIT_KEEP(x) +#define ARM_EXIT_DISCARD(x)	x  #endif  OUTPUT_ARCH(arm) @@ -39,6 +42,11 @@ jiffies = jiffies_64 + 4;  SECTIONS  {  	/* +	 * XXX: The linker does not define how output sections are +	 * assigned to input sections when there are multiple statements +	 * matching the same input section name.  There is no documented +	 * order of matching. +	 *  	 * unwind exit sections must be discarded before the rest of the  	 * unwind sections get included.  	 */ @@ -47,6 +55,9 @@ SECTIONS  		*(.ARM.extab.exit.text)  		ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))  		ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text)) +		ARM_EXIT_DISCARD(EXIT_TEXT) +		ARM_EXIT_DISCARD(EXIT_DATA) +		EXIT_CALL  #ifndef CONFIG_HOTPLUG  		*(.ARM.exidx.devexit.text)  		*(.ARM.extab.devexit.text) @@ -58,6 +69,8 @@ SECTIONS  #ifndef CONFIG_SMP_ON_UP  		*(.alt.smp.init)  #endif +		*(.discard) +		*(.discard.*)  	}  #ifdef CONFIG_XIP_KERNEL @@ -279,9 +292,6 @@ SECTIONS  	STABS_DEBUG  	.comment 0 : { *(.comment) } - -	/* Default discards */ -	DISCARDS  }  /*  |