mirror of https://gitee.com/openkylin/linux.git
Merge branch 'fixes' of http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm
* 'fixes' of http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm: ARM: 7099/1: futex: preserve oldval in SMP __futex_atomic_op ARM: dma-mapping: free allocated page if unable to map ARM: fix vmlinux.lds.S discarding sections ARM: nommu: fix warning with checksyscalls.sh ARM: 7091/1: errata: D-cache line maintenance operation by MVA may not succeed
This commit is contained in:
commit
a2b49102da
|
@ -1283,6 +1283,20 @@ config ARM_ERRATA_364296
|
||||||
processor into full low interrupt latency mode. ARM11MPCore
|
processor into full low interrupt latency mode. ARM11MPCore
|
||||||
is not affected.
|
is not affected.
|
||||||
|
|
||||||
|
config ARM_ERRATA_764369
|
||||||
|
bool "ARM errata: Data cache line maintenance operation by MVA may not succeed"
|
||||||
|
depends on CPU_V7 && SMP
|
||||||
|
help
|
||||||
|
This option enables the workaround for erratum 764369
|
||||||
|
affecting Cortex-A9 MPCore with two or more processors (all
|
||||||
|
current revisions). Under certain timing circumstances, a data
|
||||||
|
cache line maintenance operation by MVA targeting an Inner
|
||||||
|
Shareable memory region may fail to proceed up to either the
|
||||||
|
Point of Coherency or to the Point of Unification of the
|
||||||
|
system. This workaround adds a DSB instruction before the
|
||||||
|
relevant cache maintenance functions and sets a specific bit
|
||||||
|
in the diagnostic control register of the SCU.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
source "arch/arm/common/Kconfig"
|
source "arch/arm/common/Kconfig"
|
||||||
|
|
|
@ -25,17 +25,17 @@
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
|
||||||
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
|
#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \
|
||||||
smp_mb(); \
|
smp_mb(); \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
"1: ldrex %1, [%2]\n" \
|
"1: ldrex %1, [%3]\n" \
|
||||||
" " insn "\n" \
|
" " insn "\n" \
|
||||||
"2: strex %1, %0, [%2]\n" \
|
"2: strex %2, %0, [%3]\n" \
|
||||||
" teq %1, #0\n" \
|
" teq %2, #0\n" \
|
||||||
" bne 1b\n" \
|
" bne 1b\n" \
|
||||||
" mov %0, #0\n" \
|
" mov %0, #0\n" \
|
||||||
__futex_atomic_ex_table("%4") \
|
__futex_atomic_ex_table("%5") \
|
||||||
: "=&r" (ret), "=&r" (oldval) \
|
: "=&r" (ret), "=&r" (oldval), "=&r" (tmp) \
|
||||||
: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT) \
|
: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT) \
|
||||||
: "cc", "memory")
|
: "cc", "memory")
|
||||||
|
|
||||||
|
@ -73,14 +73,14 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||||
#include <linux/preempt.h>
|
#include <linux/preempt.h>
|
||||||
#include <asm/domain.h>
|
#include <asm/domain.h>
|
||||||
|
|
||||||
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
|
#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
"1: " T(ldr) " %1, [%2]\n" \
|
"1: " T(ldr) " %1, [%3]\n" \
|
||||||
" " insn "\n" \
|
" " insn "\n" \
|
||||||
"2: " T(str) " %0, [%2]\n" \
|
"2: " T(str) " %0, [%3]\n" \
|
||||||
" mov %0, #0\n" \
|
" mov %0, #0\n" \
|
||||||
__futex_atomic_ex_table("%4") \
|
__futex_atomic_ex_table("%5") \
|
||||||
: "=&r" (ret), "=&r" (oldval) \
|
: "=&r" (ret), "=&r" (oldval), "=&r" (tmp) \
|
||||||
: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT) \
|
: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT) \
|
||||||
: "cc", "memory")
|
: "cc", "memory")
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
int cmp = (encoded_op >> 24) & 15;
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
int oparg = (encoded_op << 8) >> 20;
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
int cmparg = (encoded_op << 20) >> 20;
|
||||||
int oldval = 0, ret;
|
int oldval = 0, ret, tmp;
|
||||||
|
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||||
oparg = 1 << oparg;
|
oparg = 1 << oparg;
|
||||||
|
@ -129,19 +129,19 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case FUTEX_OP_SET:
|
case FUTEX_OP_SET:
|
||||||
__futex_atomic_op("mov %0, %3", ret, oldval, uaddr, oparg);
|
__futex_atomic_op("mov %0, %4", ret, oldval, tmp, uaddr, oparg);
|
||||||
break;
|
break;
|
||||||
case FUTEX_OP_ADD:
|
case FUTEX_OP_ADD:
|
||||||
__futex_atomic_op("add %0, %1, %3", ret, oldval, uaddr, oparg);
|
__futex_atomic_op("add %0, %1, %4", ret, oldval, tmp, uaddr, oparg);
|
||||||
break;
|
break;
|
||||||
case FUTEX_OP_OR:
|
case FUTEX_OP_OR:
|
||||||
__futex_atomic_op("orr %0, %1, %3", ret, oldval, uaddr, oparg);
|
__futex_atomic_op("orr %0, %1, %4", ret, oldval, tmp, uaddr, oparg);
|
||||||
break;
|
break;
|
||||||
case FUTEX_OP_ANDN:
|
case FUTEX_OP_ANDN:
|
||||||
__futex_atomic_op("and %0, %1, %3", ret, oldval, uaddr, ~oparg);
|
__futex_atomic_op("and %0, %1, %4", ret, oldval, tmp, uaddr, ~oparg);
|
||||||
break;
|
break;
|
||||||
case FUTEX_OP_XOR:
|
case FUTEX_OP_XOR:
|
||||||
__futex_atomic_op("eor %0, %1, %3", ret, oldval, uaddr, oparg);
|
__futex_atomic_op("eor %0, %1, %4", ret, oldval, tmp, uaddr, oparg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
|
|
|
@ -478,8 +478,8 @@
|
||||||
/*
|
/*
|
||||||
* Unimplemented (or alternatively implemented) syscalls
|
* Unimplemented (or alternatively implemented) syscalls
|
||||||
*/
|
*/
|
||||||
#define __IGNORE_fadvise64_64 1
|
#define __IGNORE_fadvise64_64
|
||||||
#define __IGNORE_migrate_pages 1
|
#define __IGNORE_migrate_pages
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
#endif /* __ASM_ARM_UNISTD_H */
|
#endif /* __ASM_ARM_UNISTD_H */
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include <asm/smp_scu.h>
|
#include <asm/smp_scu.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/cputype.h>
|
||||||
|
|
||||||
#define SCU_CTRL 0x00
|
#define SCU_CTRL 0x00
|
||||||
#define SCU_CONFIG 0x04
|
#define SCU_CONFIG 0x04
|
||||||
|
@ -37,6 +38,15 @@ void __init scu_enable(void __iomem *scu_base)
|
||||||
{
|
{
|
||||||
u32 scu_ctrl;
|
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);
|
scu_ctrl = __raw_readl(scu_base + SCU_CTRL);
|
||||||
/* already enabled? */
|
/* already enabled? */
|
||||||
if (scu_ctrl & 1)
|
if (scu_ctrl & 1)
|
||||||
|
|
|
@ -23,8 +23,10 @@
|
||||||
|
|
||||||
#if defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)
|
#if defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)
|
||||||
#define ARM_EXIT_KEEP(x) x
|
#define ARM_EXIT_KEEP(x) x
|
||||||
|
#define ARM_EXIT_DISCARD(x)
|
||||||
#else
|
#else
|
||||||
#define ARM_EXIT_KEEP(x)
|
#define ARM_EXIT_KEEP(x)
|
||||||
|
#define ARM_EXIT_DISCARD(x) x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
OUTPUT_ARCH(arm)
|
OUTPUT_ARCH(arm)
|
||||||
|
@ -39,6 +41,11 @@ jiffies = jiffies_64 + 4;
|
||||||
SECTIONS
|
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 exit sections must be discarded before the rest of the
|
||||||
* unwind sections get included.
|
* unwind sections get included.
|
||||||
*/
|
*/
|
||||||
|
@ -47,6 +54,9 @@ SECTIONS
|
||||||
*(.ARM.extab.exit.text)
|
*(.ARM.extab.exit.text)
|
||||||
ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))
|
ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))
|
||||||
ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))
|
ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))
|
||||||
|
ARM_EXIT_DISCARD(EXIT_TEXT)
|
||||||
|
ARM_EXIT_DISCARD(EXIT_DATA)
|
||||||
|
EXIT_CALL
|
||||||
#ifndef CONFIG_HOTPLUG
|
#ifndef CONFIG_HOTPLUG
|
||||||
*(.ARM.exidx.devexit.text)
|
*(.ARM.exidx.devexit.text)
|
||||||
*(.ARM.extab.devexit.text)
|
*(.ARM.extab.devexit.text)
|
||||||
|
@ -58,6 +68,8 @@ SECTIONS
|
||||||
#ifndef CONFIG_SMP_ON_UP
|
#ifndef CONFIG_SMP_ON_UP
|
||||||
*(.alt.smp.init)
|
*(.alt.smp.init)
|
||||||
#endif
|
#endif
|
||||||
|
*(.discard)
|
||||||
|
*(.discard.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_XIP_KERNEL
|
#ifdef CONFIG_XIP_KERNEL
|
||||||
|
@ -279,9 +291,6 @@ SECTIONS
|
||||||
|
|
||||||
STABS_DEBUG
|
STABS_DEBUG
|
||||||
.comment 0 : { *(.comment) }
|
.comment 0 : { *(.comment) }
|
||||||
|
|
||||||
/* Default discards */
|
|
||||||
DISCARDS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -174,6 +174,10 @@ ENTRY(v7_coherent_user_range)
|
||||||
dcache_line_size r2, r3
|
dcache_line_size r2, r3
|
||||||
sub r3, r2, #1
|
sub r3, r2, #1
|
||||||
bic r12, r0, r3
|
bic r12, r0, r3
|
||||||
|
#ifdef CONFIG_ARM_ERRATA_764369
|
||||||
|
ALT_SMP(W(dsb))
|
||||||
|
ALT_UP(W(nop))
|
||||||
|
#endif
|
||||||
1:
|
1:
|
||||||
USER( mcr p15, 0, r12, c7, c11, 1 ) @ clean D line to the point of unification
|
USER( mcr p15, 0, r12, c7, c11, 1 ) @ clean D line to the point of unification
|
||||||
add r12, r12, r2
|
add r12, r12, r2
|
||||||
|
@ -223,6 +227,10 @@ ENTRY(v7_flush_kern_dcache_area)
|
||||||
add r1, r0, r1
|
add r1, r0, r1
|
||||||
sub r3, r2, #1
|
sub r3, r2, #1
|
||||||
bic r0, r0, r3
|
bic r0, r0, r3
|
||||||
|
#ifdef CONFIG_ARM_ERRATA_764369
|
||||||
|
ALT_SMP(W(dsb))
|
||||||
|
ALT_UP(W(nop))
|
||||||
|
#endif
|
||||||
1:
|
1:
|
||||||
mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line / unified line
|
mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line / unified line
|
||||||
add r0, r0, r2
|
add r0, r0, r2
|
||||||
|
@ -247,6 +255,10 @@ v7_dma_inv_range:
|
||||||
sub r3, r2, #1
|
sub r3, r2, #1
|
||||||
tst r0, r3
|
tst r0, r3
|
||||||
bic r0, r0, r3
|
bic r0, r0, r3
|
||||||
|
#ifdef CONFIG_ARM_ERRATA_764369
|
||||||
|
ALT_SMP(W(dsb))
|
||||||
|
ALT_UP(W(nop))
|
||||||
|
#endif
|
||||||
mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
|
mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
|
||||||
|
|
||||||
tst r1, r3
|
tst r1, r3
|
||||||
|
@ -270,6 +282,10 @@ v7_dma_clean_range:
|
||||||
dcache_line_size r2, r3
|
dcache_line_size r2, r3
|
||||||
sub r3, r2, #1
|
sub r3, r2, #1
|
||||||
bic r0, r0, r3
|
bic r0, r0, r3
|
||||||
|
#ifdef CONFIG_ARM_ERRATA_764369
|
||||||
|
ALT_SMP(W(dsb))
|
||||||
|
ALT_UP(W(nop))
|
||||||
|
#endif
|
||||||
1:
|
1:
|
||||||
mcr p15, 0, r0, c7, c10, 1 @ clean D / U line
|
mcr p15, 0, r0, c7, c10, 1 @ clean D / U line
|
||||||
add r0, r0, r2
|
add r0, r0, r2
|
||||||
|
@ -288,6 +304,10 @@ ENTRY(v7_dma_flush_range)
|
||||||
dcache_line_size r2, r3
|
dcache_line_size r2, r3
|
||||||
sub r3, r2, #1
|
sub r3, r2, #1
|
||||||
bic r0, r0, r3
|
bic r0, r0, r3
|
||||||
|
#ifdef CONFIG_ARM_ERRATA_764369
|
||||||
|
ALT_SMP(W(dsb))
|
||||||
|
ALT_UP(W(nop))
|
||||||
|
#endif
|
||||||
1:
|
1:
|
||||||
mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
|
mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
|
||||||
add r0, r0, r2
|
add r0, r0, r2
|
||||||
|
|
|
@ -324,6 +324,8 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
|
||||||
|
|
||||||
if (addr)
|
if (addr)
|
||||||
*handle = pfn_to_dma(dev, page_to_pfn(page));
|
*handle = pfn_to_dma(dev, page_to_pfn(page));
|
||||||
|
else
|
||||||
|
__dma_free_buffer(page, size);
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue