Commit c61c48df authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'xtensa-next-20130508' of git://github.com/czankel/xtensa-linux

Pull xtensa updates from Chris Zankel:
 "Support for the latest MMU architecture that allows for a larger
  accessible memory region, and various bug-fixes"

* tag 'xtensa-next-20130508' of git://github.com/czankel/xtensa-linux:
  xtensa: Switch to asm-generic/linkage.h
  xtensa: fix redboot load address
  xtensa: ISS: fix timer_lock usage in rs_open
  xtensa: disable IRQs while IRQ handler is running
  xtensa: enable lockdep support
  xtensa: fix arch_irqs_disabled_flags implementation
  xtensa: add irq flags trace support
  xtensa: provide custom CALLER_ADDR* implementations
  xtensa: add stacktrace support
  xtensa: clean up stpill_registers
  xtensa: don't use a7 in simcalls
  xtensa: don't attempt to use unconfigured timers
  xtensa: provide default platform_pcibios_init implementation
  xtensa: remove KCORE_ELF again
  xtensa: document MMUv3 setup sequence
  xtensa: add MMU v3 support
  xtensa: fix ibreakenable register update
  xtensa: fix oprofile building as module
parents e30f4192 b341d84c
MMUv3 initialization sequence.
The code in the initialize_mmu macro sets up MMUv3 memory mapping
identically to MMUv2 fixed memory mapping. Depending on
CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX symbol this code is
located in one of the following address ranges:
0xF0000000..0xFFFFFFFF (will keep same address in MMU v2 layout;
typically ROM)
0x00000000..0x07FFFFFF (system RAM; this code is actually linked
at 0xD0000000..0xD7FFFFFF [cached]
or 0xD8000000..0xDFFFFFFF [uncached];
in any case, initially runs elsewhere
than linked, so have to be careful)
The code has the following assumptions:
This code fragment is run only on an MMU v3.
TLBs are in their reset state.
ITLBCFG and DTLBCFG are zero (reset state).
RASID is 0x04030201 (reset state).
PS.RING is zero (reset state).
LITBASE is zero (reset state, PC-relative literals); required to be PIC.
TLB setup proceeds along the following steps.
Legend:
VA = virtual address (two upper nibbles of it);
PA = physical address (two upper nibbles of it);
pc = physical range that contains this code;
After step 2, we jump to virtual address in 0x40000000..0x5fffffff
that corresponds to next instruction to execute in this code.
After step 4, we jump to intended (linked) address of this code.
Step 0 Step1 Step 2 Step3 Step 4 Step5
============ ===== ============ ===== ============ =====
VA PA PA VA PA PA VA PA PA
------ -- -- ------ -- -- ------ -- --
E0..FF -> E0 -> E0 E0..FF -> E0 F0..FF -> F0 -> F0
C0..DF -> C0 -> C0 C0..DF -> C0 E0..EF -> F0 -> F0
A0..BF -> A0 -> A0 A0..BF -> A0 D8..DF -> 00 -> 00
80..9F -> 80 -> 80 80..9F -> 80 D0..D7 -> 00 -> 00
60..7F -> 60 -> 60 60..7F -> 60
40..5F -> 40 40..5F -> pc -> pc 40..5F -> pc
20..3F -> 20 -> 20 20..3F -> 20
00..1F -> 00 -> 00 00..1F -> 00
config FRAME_POINTER
def_bool n
config ZONE_DMA
def_bool y
config XTENSA
def_bool y
select ARCH_WANT_FRAME_POINTERS
select HAVE_IDE
select GENERIC_ATOMIC64
select HAVE_GENERIC_HARDIRQS
......@@ -49,6 +47,15 @@ config HZ
source "init/Kconfig"
source "kernel/Kconfig.freezer"
config LOCKDEP_SUPPORT
def_bool y
config STACKTRACE_SUPPORT
def_bool y
config TRACE_IRQFLAGS_SUPPORT
def_bool y
config MMU
def_bool n
......@@ -100,6 +107,35 @@ config MATH_EMULATION
help
Can we use information of configuration file?
config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
bool "Initialize Xtensa MMU inside the Linux kernel code"
default y
help
Earlier version initialized the MMU in the exception vector
before jumping to _startup in head.S and had an advantage that
it was possible to place a software breakpoint at 'reset' and
then enter your normal kernel breakpoints once the MMU was mapped
to the kernel mappings (0XC0000000).
This unfortunately doesn't work for U-Boot and likley also wont
work for using KEXEC to have a hot kernel ready for doing a
KDUMP.
So now the MMU is initialized in head.S but it's necessary to
use hardware breakpoints (gdb 'hbreak' cmd) to break at _startup.
xt-gdb can't place a Software Breakpoint in the 0XD region prior
to mapping the MMU and after mapping even if the area of low memory
was mapped gdb wouldn't remove the breakpoint on hitting it as the
PC wouldn't match. Since Hardware Breakpoints are recommended for
Linux configurations it seems reasonable to just assume they exist
and leave this older mechanism for unfortunate souls that choose
not to follow Tensilica's recommendation.
Selecting this will cause U-Boot to set the KERNEL Load and Entry
address at 0x00003000 instead of the mapped std of 0xD0003000.
If in doubt, say Y.
endmenu
config XTENSA_CALIBRATE_CCOUNT
......@@ -249,21 +285,6 @@ endmenu
menu "Executable file formats"
# only elf supported
config KCORE_ELF
def_bool y
depends on PROC_FS
help
If you enabled support for /proc file system then the file
/proc/kcore will contain the kernel core image in ELF format. This
can be used in gdb:
$ cd /usr/src/linux ; gdb vmlinux /proc/kcore
This is especially useful if you have compiled the kernel with the
"-g" option to preserve debugging information. It is mainly used
for examining kernel data structures on the live kernel.
source "fs/Kconfig.binfmt"
endmenu
......
......@@ -12,6 +12,7 @@ endif
export OBJCOPY_ARGS
export CPPFLAGS_boot.lds += -P -C
export KBUILD_AFLAGS += -mtext-section-literals
boot-y := bootstrap.o
......
#include <variant/core.h>
/*
* linux/arch/xtensa/boot/boot-elf/boot.lds.S
*
* Copyright (C) 2008 - 2013 by Tensilica Inc.
*
* Chris Zankel <chris@zankel.net>
* Marc Gauthier <marc@tensilica.com
* Pete Delaney <piet@tensilica.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <asm/vectors.h>
OUTPUT_ARCH(xtensa)
ENTRY(_ResetVector)
SECTIONS
{
.start 0xD0000000 : { *(.start) }
.text 0xD0000000:
{
__reloc_start = . ;
_text_start = . ;
*(.literal .text.literal .text)
_text_end = . ;
}
.rodata ALIGN(0x04):
{
*(.rodata)
*(.rodata1)
}
.data ALIGN(0x04):
.ResetVector.text XCHAL_RESET_VECTOR_VADDR :
{
*(.data)
*(.data1)
*(.sdata)
*(.sdata2)
*(.got.plt)
*(.got)
*(.dynamic)
*(.ResetVector.text)
}
__reloc_end = . ;
. = ALIGN(0x10);
__image_load = . ;
.image 0xd0001000:
.image KERNELOFFSET: AT (LOAD_MEMORY_ADDRESS)
{
_image_start = .;
*(image)
......@@ -43,7 +31,6 @@ SECTIONS
_image_end = . ;
}
.bss ((LOADADDR(.image) + SIZEOF(.image) + 3) & ~ 3):
{
__bss_start = .;
......@@ -53,14 +40,15 @@ SECTIONS
*(.bss)
__bss_end = .;
}
_end = .;
_param_start = .;
.ResetVector.text XCHAL_RESET_VECTOR_VADDR :
/*
* This is a remapped copy of the Reset Vector Code.
* It keeps gdb in sync with the PC after switching
* to the temporary mapping used while setting up
* the V2 MMU mappings for Linux.
*/
.ResetVector.remapped_text 0x46000000 (INFO):
{
*(.ResetVector.text)
*(.ResetVector.remapped_text)
}
PROVIDE (end = .);
}
/*
* arch/xtensa/boot/boot-elf/bootstrap.S
*
* Low-level exception handling
*
* 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.
*
* Copyright (C) 2004 - 2013 by Tensilica Inc.
*
* Chris Zankel <chris@zankel.net>
* Marc Gauthier <marc@tensilica.com>
* Piet Delaney <piet@tensilica.com>
*/
#include <asm/bootparam.h>
#include <asm/processor.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/cacheasm.h>
#include <asm/initialize_mmu.h>
#include <linux/linkage.h>
/* ResetVector
*/
.section .ResetVector.text, "ax"
.section .ResetVector.text, "ax"
.global _ResetVector
.global reset
_ResetVector:
_j reset
_j _SetupMMU
.begin no-absolute-literals
.literal_position
.align 4
RomInitAddr:
.word 0xd0001000
#if defined(CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX) && \
XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
.word 0x00003000
#else
.word 0xd0003000
#endif
RomBootParam:
.word _bootparam
_bootparam:
.short BP_TAG_FIRST
.short 4
.long BP_VERSION
.short BP_TAG_LAST
.short 0
.long 0
.align 4
_SetupMMU:
movi a0, 0
wsr a0, windowbase
rsync
movi a0, 1
wsr a0, windowstart
rsync
movi a0, 0x1F
wsr a0, ps
rsync
Offset = _SetupMMU - _ResetVector
#ifndef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
initialize_mmu
#endif
.end no-absolute-literals
rsil a0, XCHAL_DEBUGLEVEL-1
rsync
reset:
l32r a0, RomInitAddr
l32r a2, RomBootParam
......@@ -21,13 +80,25 @@ reset:
jx a0
.align 4
.section .bootstrap.data, "aw"
.globl _bootparam
_bootparam:
.short BP_TAG_FIRST
.short 4
.long BP_VERSION
.short BP_TAG_LAST
.short 0
.long 0
.section .ResetVector.remapped_text, "x"
.global _RemappedResetVector
/* Do org before literals */
.org 0
_RemappedResetVector:
.begin no-absolute-literals
.literal_position
_j _RemappedSetupMMU
/* Position Remapped code at the same location as the original code */
. = _RemappedResetVector + Offset
_RemappedSetupMMU:
#ifndef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
initialize_mmu
#endif
.end no-absolute-literals
......@@ -33,7 +33,7 @@ SECTIONS
. = ALIGN(0x10);
__image_load = . ;
.image 0xd0001000: AT(__image_load)
.image 0xd0003000: AT(__image_load)
{
_image_start = .;
*(image)
......
......@@ -4,7 +4,11 @@
# for more details.
#
UIMAGE_LOADADDR = 0xd0001000
ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
UIMAGE_LOADADDR = 0x00003000
else
UIMAGE_LOADADDR = 0xd0003000
endif
UIMAGE_COMPRESSION = gzip
$(obj)/../uImage: vmlinux.bin.gz FORCE
......
......@@ -15,6 +15,7 @@ generic-y += irq_regs.h
generic-y += kdebug.h
generic-y += kmap_types.h
generic-y += kvm_para.h
generic-y += linkage.h
generic-y += local.h
generic-y += local64.h
generic-y += percpu.h
......
/* empty */
/*
* arch/xtensa/include/asm/ftrace.h
*
* 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.
*
* Copyright (C) 2013 Tensilica Inc.
*/
#ifndef _XTENSA_FTRACE_H
#define _XTENSA_FTRACE_H
#include <asm/processor.h>
#define HAVE_ARCH_CALLER_ADDR
#define CALLER_ADDR0 ({ unsigned long a0, a1; \
__asm__ __volatile__ ( \
"mov %0, a0\n" \
"mov %1, a1\n" \
: "=r"(a0), "=r"(a1) : : ); \
MAKE_PC_FROM_RA(a0, a1); })
#ifdef CONFIG_FRAME_POINTER
extern unsigned long return_address(unsigned level);
#define CALLER_ADDR1 return_address(1)
#define CALLER_ADDR2 return_address(2)
#define CALLER_ADDR3 return_address(3)
#else
#define CALLER_ADDR1 (0)
#define CALLER_ADDR2 (0)
#define CALLER_ADDR3 (0)
#endif
#endif /* _XTENSA_FTRACE_H */
......@@ -23,6 +23,9 @@
#ifndef _XTENSA_INITIALIZE_MMU_H
#define _XTENSA_INITIALIZE_MMU_H
#include <asm/pgtable.h>
#include <asm/vectors.h>
#ifdef __ASSEMBLY__
#define XTENSA_HWVERSION_RC_2009_0 230000
......@@ -48,6 +51,110 @@
* (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0)
*/
#if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
/*
* Have MMU v3
*/
#if !XCHAL_HAVE_VECBASE
# error "MMU v3 requires reloc vectors"
#endif
movi a1, 0
_call0 1f
_j 2f
.align 4
1: movi a2, 0x10000000
movi a3, 0x18000000
add a2, a2, a0
9: bgeu a2, a3, 9b /* PC is out of the expected range */
/* Step 1: invalidate mapping at 0x40000000..0x5FFFFFFF. */
movi a2, 0x40000006
idtlb a2
iitlb a2
isync
/* Step 2: map 0x40000000..0x47FFFFFF to paddr containing this code
* and jump to the new mapping.
*/
#define CA_BYPASS (_PAGE_CA_BYPASS | _PAGE_HW_WRITE | _PAGE_HW_EXEC)
#define CA_WRITEBACK (_PAGE_CA_WB | _PAGE_HW_WRITE | _PAGE_HW_EXEC)
srli a3, a0, 27
slli a3, a3, 27
addi a3, a3, CA_BYPASS
addi a7, a2, -1
wdtlb a3, a7
witlb a3, a7
isync
slli a4, a0, 5
srli a4, a4, 5
addi a5, a2, -6
add a4, a4, a5
jx a4
/* Step 3: unmap everything other than current area.
* Start at 0x60000000, wrap around, and end with 0x20000000
*/
2: movi a4, 0x20000000
add a5, a2, a4
3: idtlb a5
iitlb a5
add a5, a5, a4
bne a5, a2, 3b
/* Step 4: Setup MMU with the old V2 mappings. */
movi a6, 0x01000000
wsr a6, ITLBCFG
wsr a6, DTLBCFG
isync
movi a5, 0xd0000005
movi a4, CA_WRITEBACK
wdtlb a4, a5
witlb a4, a5
movi a5, 0xd8000005
movi a4, CA_BYPASS
wdtlb a4, a5
witlb a4, a5
movi a5, 0xe0000006
movi a4, 0xf0000000 + CA_WRITEBACK
wdtlb a4, a5
witlb a4, a5
movi a5, 0xf0000006
movi a4, 0xf0000000 + CA_BYPASS
wdtlb a4, a5
witlb a4, a5
isync
/* Jump to self, using MMU v2 mappings. */
movi a4, 1f
jx a4
1:
movi a2, VECBASE_RESET_VADDR
wsr a2, vecbase
/* Step 5: remove temporary mapping. */
idtlb a7
iitlb a7
isync
movi a0, 0
wsr a0, ptevaddr
rsync
#endif /* defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU &&
XCHAL_HAVE_SPANNING_WAY */
.endm
#endif /*__ASSEMBLY__*/
......
......@@ -47,7 +47,10 @@ static inline void arch_local_irq_restore(unsigned long flags)
static inline bool arch_irqs_disabled_flags(unsigned long flags)
{
return (flags & 0xf) != 0;
#if XCHAL_EXCM_LEVEL < LOCKLEVEL || (1 << PS_EXCM_BIT) < LOCKLEVEL
#error "XCHAL_EXCM_LEVEL and 1<<PS_EXCM_BIT must be no less than LOCKLEVEL"
#endif
return (flags & (PS_INTLEVEL_MASK | (1 << PS_EXCM_BIT))) >= LOCKLEVEL;
}
static inline bool arch_irqs_disabled(void)
......
/*
* include/asm-xtensa/linkage.h
*
* 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.
*
* Copyright (C) 2001 - 2005 Tensilica Inc.
*/
#ifndef _XTENSA_LINKAGE_H
#define _XTENSA_LINKAGE_H
/* Nothing to do here ... */
#endif /* _XTENSA_LINKAGE_H */
/*
* arch/xtensa/include/asm/stacktrace.h
*
* 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.
*
* Copyright (C) 2001 - 2013 Tensilica Inc.
*/
#ifndef _XTENSA_STACKTRACE_H
#define _XTENSA_STACKTRACE_H
#include <linux/sched.h>
struct stackframe {
unsigned long pc;
unsigned long sp;
};
static __always_inline unsigned long *stack_pointer(struct task_struct *task)
{
unsigned long *sp;
if (!task || task == current)
__asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp));
else
sp = (unsigned long *)task->thread.sp;
return sp;
}
void walk_stackframe(unsigned long *sp,
int (*fn)(struct stackframe *frame, void *data),
void *data);
#endif /* _XTENSA_STACKTRACE_H */
......@@ -19,13 +19,16 @@
#define _INTLEVEL(x) XCHAL_INT ## x ## _LEVEL
#define INTLEVEL(x) _INTLEVEL(x)
#if INTLEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL
#if XCHAL_NUM_TIMERS > 0 && \
INTLEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL
# define LINUX_TIMER 0
# define LINUX_TIMER_INT XCHAL_TIMER0_INTERRUPT
#elif INTLEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL
#elif XCHAL_NUM_TIMERS > 1 && \
INTLEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL
# define LINUX_TIMER 1
# define LINUX_TIMER_INT XCHAL_TIMER1_INTERRUPT
#elif INTLEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL