From 8940e2dfdaf50fcee56bf81baac00b9a9e94ba58 Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Mon, 25 Jan 2016 15:40:58 +0800 Subject: [PATCH] PD#118612: cortex-a53: fix ARM CPU errata 843419, 845719, 835769 1. Support toolchain both Linaro gcc 4.9.2 and 5.2 2. Fix ARM errata for issue 843419, 845719, 835769. 3. Fix comiple error due to toolchain update. 4. Change psci call of smc & hvc from inline assemble to assemble files, in order to avoid register arguments order problem due to toolchain Conflicts: drivers/amlogic/amlnf/dev/phydev.c drivers/amlogic/display/lcd/lcd_common.c drivers/amlogic/hdmi/hdmi_tx_20/hw/hdcpVerify.c drivers/amlogic/jtag/jtag_setup.c drivers/amlogic/mmc/amlsd.c Change-Id: I70f849b7496b434277c22eb961189c51b2417cb6 --- arch/arm64/Kconfig | 49 ++++++++++++++++++ arch/arm64/Makefile | 9 ++++ arch/arm64/configs/odroidc2_defconfig | 7 +++ arch/arm64/configs/odroidc2_i2c_defconfig | 7 +++ arch/arm64/include/asm/psci.h | 3 ++ arch/arm64/kernel/Makefile | 2 +- arch/arm64/kernel/entry.S | 10 ++++ arch/arm64/kernel/psci-call.S | 28 +++++++++++ arch/arm64/kernel/psci.c | 34 ------------- drivers/amlogic/amlnf/dev/phydev.c | 50 +++++++++++++++++++ drivers/amlogic/amports/video.c | 2 +- .../amlogic/hdmi/hdmi_tx_20/hw/hdmi_tx_hw.c | 2 +- drivers/amlogic/input/sensor/stk220x_poll.c | 2 +- drivers/amlogic/iomap/iomap.c | 13 ++--- drivers/amlogic/mmc/aml_sdhc_m8.c | 4 +- drivers/amlogic/pm/gxbb_pm.c | 19 ------- drivers/mtd/mtd_blkdevs.c | 8 +-- drivers/of/fdt.c | 2 +- fs/namespace.c | 4 +- fs/nfs/nfs4proc.c | 11 ++-- lib/decompress_unlzo.c | 4 +- mm/rmap.c | 2 +- 22 files changed, 184 insertions(+), 88 deletions(-) create mode 100644 arch/arm64/kernel/psci-call.S diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 905224f954c4..210c40f2112a 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -167,6 +167,55 @@ config ARM_AMBA endmenu +menu "ARM errata workarounds via the alternatives framework" + +config ARM64_ERRATUM_845719 + bool "Cortex-A53: 845719: a load might read incorrect data" + depends on COMPAT + default y + help + This option adds an alternative code sequence to work around ARM + erratum 845719 on Cortex-A53 parts up to r0p4. + + When running a compat (AArch32) userspace on an affected Cortex-A53 + part, a load at EL0 from a virtual address that matches the bottom 32 + bits of the virtual address used by a recent load at (AArch64) EL1 + might return incorrect data. + + The workaround is to write the contextidr_el1 register on exception + return to a 32-bit task. + Please note that this does not necessarily enable the workaround, + as it depends on the alternative framework, which will only patch + the kernel if an affected CPU is detected. + + If unsure, say Y. + +config ARM64_ERRATUM_843419 + bool "Cortex-A53: 843419: A load or store might access an incorrect address" + depends on MODULES + default y + help + This option builds kernel modules using the large memory model in + order to avoid the use of the ADRP instruction, which can cause + a subsequent memory access to use an incorrect address on Cortex-A53 + parts up to r0p4. + + Note that the kernel itself must be linked with a version of ld + which fixes potentially affected ADRP instructions through the + use of veneers. + + If unsure, say Y. + +config ARM64_ERRATUM_835769 + bool "Cortex-A53: 835769: AArch64 multiply-accumulate instruction might produce incorrect result" + depends on MODULES + default y + help + This option build kernel with option -mfix-cortex-a53-835769 to + fix mulity-accumulate bug of cpu + +endmenu + menu "Kernel Features" config ARM64_64K_PAGES diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 113b2f1ead2d..880f3b49213a 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -35,6 +35,15 @@ comma = , CHECKFLAGS += -D__aarch64__ +ifeq ($(CONFIG_ARM64_ERRATUM_843419), y) +KBUILD_CFLAGS_MODULE += $(call cc-option,-mfix-cortex-a53-843419) +endif + +ifeq ($(CONFIG_ARM64_ERRATUM_835769), y) +KBUILD_CFLAGS_MODULE += $(call cc-option,-mfix-cortex-a53-835769) +endif +$(info KBUILD_CFLAGS_MODULE:$(KBUILD_CFLAGS_MODULE)) + # Default value head-y := arch/arm64/kernel/head.o diff --git a/arch/arm64/configs/odroidc2_defconfig b/arch/arm64/configs/odroidc2_defconfig index 4298789532d2..5f0e13a73cdf 100644 --- a/arch/arm64/configs/odroidc2_defconfig +++ b/arch/arm64/configs/odroidc2_defconfig @@ -246,6 +246,13 @@ CONFIG_ARCH_MESON64_ODROIDC2=y # CONFIG_ARM_AMBA=y +# +# ARM errata workarounds via the alternatives framework +# +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_ERRATUM_835769=y + # # Kernel Features # diff --git a/arch/arm64/configs/odroidc2_i2c_defconfig b/arch/arm64/configs/odroidc2_i2c_defconfig index c20ed34ffc3b..6131fd1fb26c 100644 --- a/arch/arm64/configs/odroidc2_i2c_defconfig +++ b/arch/arm64/configs/odroidc2_i2c_defconfig @@ -246,6 +246,13 @@ CONFIG_ARCH_MESON64_ODROIDC2=y # CONFIG_ARM_AMBA=y +# +# ARM errata workarounds via the alternatives framework +# +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_ERRATUM_835769=y + # # Kernel Features # diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h index e5312ea0ec1a..c28c08f4e37f 100644 --- a/arch/arm64/include/asm/psci.h +++ b/arch/arm64/include/asm/psci.h @@ -16,4 +16,7 @@ int psci_init(void); +int __invoke_psci_fn_hvc(u64 function_id, u64 arg0, u64 arg1, u64 arg2); +int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2); + #endif /* __ASM_PSCI_H */ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 5a02c276debc..3fd3345e9cc6 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -14,7 +14,7 @@ arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ entry-fpsimd.o process.o ptrace.o setup.o signal.o \ sys.o stacktrace.o time.o traps.o io.o vdso.o \ hyp-stub.o psci.o cpu_ops.o insn.o return_address.o \ - opcodes.o + opcodes.o psci-call.o arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ sys_compat.o diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index a702f4d1dedd..58cec5054688 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -116,6 +116,16 @@ .if \el == 0 ct_user_enter ldr x23, [sp, #S_SP] // load return stack pointer +#ifdef CONFIG_ARM64_ERRATUM_845719 + tbz x22, #4, 1f +#ifdef CONFIG_PID_IN_CONTEXTIDR + mrs x29, contextidr_el1 + msr contextidr_el1, x29 +#else + msr contextidr_el1, xzr +#endif +1: +#endif .endif .if \ret ldr x1, [sp, #S_X1] // preserve x0 (syscall return) diff --git a/arch/arm64/kernel/psci-call.S b/arch/arm64/kernel/psci-call.S new file mode 100644 index 000000000000..cf83e61cd3b5 --- /dev/null +++ b/arch/arm64/kernel/psci-call.S @@ -0,0 +1,28 @@ +/* + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2015 ARM Limited + * + * Author: Will Deacon + */ + +#include + +/* int __invoke_psci_fn_hvc(u64 function_id, u64 arg0, u64 arg1, u64 arg2) */ +ENTRY(__invoke_psci_fn_hvc) + hvc #0 + ret +ENDPROC(__invoke_psci_fn_hvc) + +/* int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2) */ +ENTRY(__invoke_psci_fn_smc) + smc #0 + ret +ENDPROC(__invoke_psci_fn_smc) diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c index 20fa086e0f58..a9599be6a2fd 100644 --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c @@ -95,40 +95,6 @@ static u32 psci_power_state_pack(struct psci_power_state state) << PSCI_POWER_STATE_AFFL_SHIFT); } -/* - * The following two functions are invoked via the invoke_psci_fn pointer - * and will not be inlined, allowing us to piggyback on the AAPCS. - */ -static noinline int __invoke_psci_fn_hvc(u64 function_id, u64 arg0, u64 arg1, - u64 arg2) -{ - asm volatile( - __asmeq("%0", "x0") - __asmeq("%1", "x1") - __asmeq("%2", "x2") - __asmeq("%3", "x3") - "hvc #0\n" - : "+r" (function_id) - : "r" (arg0), "r" (arg1), "r" (arg2)); - - return function_id; -} - -static noinline int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1, - u64 arg2) -{ - asm volatile( - __asmeq("%0", "x0") - __asmeq("%1", "x1") - __asmeq("%2", "x2") - __asmeq("%3", "x3") - "smc #0\n" - : "+r" (function_id) - : "r" (arg0), "r" (arg1), "r" (arg2)); - - return function_id; -} - static int psci_cpu_suspend(struct psci_power_state state, unsigned long entry_point) { diff --git a/drivers/amlogic/amlnf/dev/phydev.c b/drivers/amlogic/amlnf/dev/phydev.c index ecf63b57c255..1024c6735162 100644 --- a/drivers/amlogic/amlnf/dev/phydev.c +++ b/drivers/amlogic/amlnf/dev/phydev.c @@ -1134,6 +1134,56 @@ static void show_phydev_info(void) } } +/* +this function alloc phydev and init it. +*/ +int aml_alloc_phydev(struct amlnand_phydev **phydev_pp, + struct amlnand_chip *aml_chip, + struct dev_para **dev_para, + int dev_idx) +{ + int ret = 0; + struct hw_controller *controller = &(aml_chip->controller); + /*struct nand_config *config = aml_chip->config_ptr;*/ + struct nand_flash *flash = &(aml_chip->flash); + struct amlnand_phydev *phydev_p = NULL; + + *phydev_pp = aml_nand_malloc(sizeof(struct amlnand_phydev)); + if (*phydev_pp == NULL) { + aml_nand_msg("malloc failed need %lx here", + (sizeof(struct amlnand_phydev))); + ret = -NAND_MALLOC_FAILURE; + return ret; + } + + phydev_p = *phydev_pp; + memset(phydev_p, 0, sizeof(struct amlnand_phydev)); + phydev_p->priv = aml_chip; + + *dev_para = &aml_chip->config_ptr->dev_para[dev_idx]; + memcpy((void *)&phydev_p->name, + &(*dev_para)->name, MAX_DEVICE_NAME_LEN*sizeof(char)); + + /*set default parameter*/ + phydev_p->writesize = flash->pagesize; + phydev_p->erasesize = flash->blocksize; + phydev_p->oobavail = controller->oobavail; + phydev_p->writesize_shift = ffs(phydev_p->writesize) - 1; + phydev_p->erasesize_shift = ffs(phydev_p->erasesize) - 1; + phydev_p->write = nand_write; + phydev_p->read = nand_read; + phydev_p->erase = nand_erase; + phydev_p->block_isbad = nand_block_isbad; + phydev_p->block_markbad = nand_block_markbad; + phydev_p->block_modifybbt = block_modifybbt; + phydev_p->update_bbt = update_bbt; + phydev_p->phydev_test_block = nand_test_block; +#ifndef AML_NAND_UBOOT + phydev_p->suspend = phydev_suspend; + phydev_p->resume = phydev_resume; +#endif + return ret; +} /****** *nand chip usage diff --git a/drivers/amlogic/amports/video.c b/drivers/amlogic/amports/video.c index 7e6fffc24bef..924bb98bf3be 100644 --- a/drivers/amlogic/amports/video.c +++ b/drivers/amlogic/amports/video.c @@ -519,7 +519,7 @@ static DEFINE_MUTEX(video_module_mutex); static DEFINE_SPINLOCK(lock); static u32 frame_par_ready_to_set, frame_par_force_to_set; static u32 vpts_remainder; -static bool video_property_changed; +static int video_property_changed; static u32 video_notify_flag; static int enable_video_discontinue_report = 1; diff --git a/drivers/amlogic/hdmi/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/amlogic/hdmi/hdmi_tx_20/hw/hdmi_tx_hw.c index 9455001a9533..9e3c659c24e8 100644 --- a/drivers/amlogic/hdmi/hdmi_tx_20/hw/hdmi_tx_hw.c +++ b/drivers/amlogic/hdmi/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -44,6 +44,7 @@ #include /*#include */ #include +#include #include "mach_reg.h" #include "hdmi_tx_reg.h" @@ -254,7 +255,6 @@ int hdmitx_ddc_hw_op(enum ddc_op cmd) return ret; } -#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t" int hdmitx_hdcp_opr(unsigned int val) { if (val == 1) { diff --git a/drivers/amlogic/input/sensor/stk220x_poll.c b/drivers/amlogic/input/sensor/stk220x_poll.c index 7c3dc70c954c..ada53839f083 100644 --- a/drivers/amlogic/input/sensor/stk220x_poll.c +++ b/drivers/amlogic/input/sensor/stk220x_poll.c @@ -124,7 +124,7 @@ inline int32_t get_reading(void) stk_readb(STK_ALS_DT2_REG)); } -inline int32_t alscode2lux(int32_t alscode) +int32_t alscode2lux(int32_t alscode) { /*R-set Def --> 500KOhm ==> x 5 IT --> x1 diff --git a/drivers/amlogic/iomap/iomap.c b/drivers/amlogic/iomap/iomap.c index f2db1454e05b..8863c3c6b28d 100644 --- a/drivers/amlogic/iomap/iomap.c +++ b/drivers/amlogic/iomap/iomap.c @@ -30,6 +30,8 @@ #include #ifndef CONFIG_ARM64 #include +#else +#include #endif #if 0 void meson_regmap_lock(void *p) @@ -296,16 +298,7 @@ static noinline int __invoke_sec_fn_smc(u32 function_id, u32 arg0, u32 arg1, static noinline int __invoke_sec_fn_smc(u32 function_id, u32 arg0, u32 arg1, u32 arg2) { - asm volatile( - __asmeq("%0", "x0") - __asmeq("%1", "x1") - __asmeq("%2", "x2") - __asmeq("%3", "x3") - "smc #0\n" - : "+r" (function_id) - : "r" (arg0), "r" (arg1), "r" (arg2)); - - return function_id; + return __invoke_psci_fn_smc(function_id, arg0, arg1, arg2); } #endif diff --git a/drivers/amlogic/mmc/aml_sdhc_m8.c b/drivers/amlogic/mmc/aml_sdhc_m8.c index 0f9bffaceef2..132d0a9b55d9 100644 --- a/drivers/amlogic/mmc/aml_sdhc_m8.c +++ b/drivers/amlogic/mmc/aml_sdhc_m8.c @@ -613,7 +613,7 @@ void aml_sdhc_clear_fifo(struct amlsd_host *host) } /*enable irq bit in reg SDHC_ICTL*/ -inline void aml_sdhc_enable_imask(struct amlsd_host *host, u32 irq) +void aml_sdhc_enable_imask(struct amlsd_host *host, u32 irq) { u32 ictl = readl(host->base+SDHC_ICTL); ictl |= irq; @@ -621,7 +621,7 @@ inline void aml_sdhc_enable_imask(struct amlsd_host *host, u32 irq) } /*disable irq bit in reg SDHC_ICTL*/ -inline void aml_sdhc_disable_imask(struct amlsd_host *host, u32 irq) +void aml_sdhc_disable_imask(struct amlsd_host *host, u32 irq) { u32 ictl = readl(host->base+SDHC_ICTL); ictl &= ~irq; diff --git a/drivers/amlogic/pm/gxbb_pm.c b/drivers/amlogic/pm/gxbb_pm.c index 46de6a924440..a50bfc787482 100644 --- a/drivers/amlogic/pm/gxbb_pm.c +++ b/drivers/amlogic/pm/gxbb_pm.c @@ -224,25 +224,6 @@ ssize_t time_out_store(struct device *dev, struct device_attribute *attr, DEVICE_ATTR(time_out, 0666, time_out_show, time_out_store); static int suspend_reason; -static noinline int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1, - u64 arg2) -{ - register long x0 asm("x0") = function_id; - register long x1 asm("x1") = arg0; - register long x2 asm("x2") = arg1; - register long x3 asm("x3") = arg2; - asm volatile( - __asmeq("%0", "x0") - __asmeq("%1", "x1") - __asmeq("%2", "x2") - __asmeq("%3", "x3") - "smc #0\n" - : "+r" (x0) - : "r" (x1), "r" (x2), "r" (x3)); - - return x0; -} - ssize_t suspend_reason_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 5073cbc796d8..039d78b144a9 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -96,14 +96,13 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, if (req->cmd_flags & REQ_DISCARD) return tr->discard(dev, block, nsect); - switch(rq_data_dir(req)) { - case READ: + if (rq_data_dir(req) == READ) { for (; nsect > 0; nsect--, block++, buf += tr->blksize) if (tr->readsect(dev, block, buf)) return -EIO; rq_flush_dcache_pages(req); return 0; - case WRITE: + } else { if (!tr->writesect) return -EIO; @@ -112,9 +111,6 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, if (tr->writesect(dev, block, buf)) return -EIO; return 0; - default: - printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req)); - return -EIO; } } diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 2b9811dc2851..2e9f7d966177 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -683,7 +683,7 @@ static inline void early_init_dt_check_for_initrd(unsigned long node) #include int is_instabooting; -inline void early_init_dt_check_for_instaboot(unsigned long node) +void early_init_dt_check_for_instaboot(unsigned long node) { unsigned long version_code; int len; diff --git a/fs/namespace.c b/fs/namespace.c index 039f3802d70e..a793eec26b23 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2695,9 +2695,9 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, char __user *, type, unsigned long, flags, void __user *, data) { int ret; - char *kernel_type; + char *kernel_type = NULL; struct filename *kernel_dir; - char *kernel_dev; + char *kernel_dev = NULL; unsigned long data_page; ret = copy_mount_string(type, &kernel_type); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 58258ad50d5f..39c896c3d871 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2964,16 +2964,13 @@ int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *info, bool auth_probe) { - int status; + int status = 0; - switch (auth_probe) { - case false: + if (!auth_probe) status = nfs4_lookup_root(server, fhandle, info); - if (status != -NFS4ERR_WRONGSEC) - break; - default: + + if (auth_probe || status == NFS4ERR_WRONGSEC) status = nfs4_do_find_root_sec(server, fhandle, info); - } if (status == 0) status = nfs4_server_capabilities(server, fhandle); diff --git a/lib/decompress_unlzo.c b/lib/decompress_unlzo.c index 960183d4258f..235c6d8bf502 100644 --- a/lib/decompress_unlzo.c +++ b/lib/decompress_unlzo.c @@ -51,7 +51,7 @@ static const unsigned char lzop_magic[] = { #define HEADER_SIZE_MIN (9 + 7 + 4 + 8 + 1 + 4) #define HEADER_SIZE_MAX (9 + 7 + 1 + 8 + 8 + 4 + 1 + 255 + 4) -STATIC inline int INIT parse_header(u8 *input, int *skip, int in_len) +STATIC int INIT parse_header(u8 *input, int *skip, int in_len) { int l; u8 *parse = input; @@ -108,7 +108,7 @@ STATIC inline int INIT parse_header(u8 *input, int *skip, int in_len) return 1; } -STATIC inline int INIT unlzo(u8 *input, int in_len, +STATIC int INIT unlzo(u8 *input, int in_len, int (*fill) (void *, unsigned int), int (*flush) (void *, unsigned int), u8 *output, int *posp, diff --git a/mm/rmap.c b/mm/rmap.c index cab982084e2b..45f18547e4eb 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -527,7 +527,7 @@ __vma_address(struct page *page, struct vm_area_struct *vma) return vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); } -inline unsigned long +static inline unsigned long vma_address(struct page *page, struct vm_area_struct *vma) { unsigned long address = __vma_address(page, vma);