mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-24 19:40:21 +09:00
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
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
#
|
||||
|
||||
@@ -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
|
||||
#
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
28
arch/arm64/kernel/psci-call.S
Normal file
28
arch/arm64/kernel/psci-call.S
Normal file
@@ -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 <will.deacon@arm.com>
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
/* 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)
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <linux/amlogic/hdmi_tx/hdmi_tx_ddc.h>
|
||||
/*#include <linux/amlogic/hdmi_tx/hdmi_tx_cec.h>*/
|
||||
#include <linux/reset.h>
|
||||
#include <linux/compiler.h>
|
||||
#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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <asm/compiler.h>
|
||||
#ifndef CONFIG_ARM64
|
||||
#include <asm/opcodes-sec.h>
|
||||
#else
|
||||
#include <asm/psci.h>
|
||||
#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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -683,7 +683,7 @@ static inline void early_init_dt_check_for_initrd(unsigned long node)
|
||||
#include <linux/version.h>
|
||||
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user