[PATCH] POWERPC: CPU15 workaround for mpc8xx
Vitaly Bordug
vbordug at ru.mvista.com
Tue Apr 3 08:11:10 EST 2007
Implements workaround for CPU15 Silicon Errata on MPC8xx processors.
Based on the DENX workaround patches.
Original commit ids from linuxppc_32_4_devel:
Commit: baf9a6caca75b1f338ae370669e5882809000164
Author: wd <wd> Wed, 25 Aug 2004 15:16:30 +0000
Implement work-around for CPU15 Silicon Errata on MPC8xx
processors.
Commit: 3ad403717f1d9c6a09ec41a5b016ac5245591122
Author: wd <wd> Sun, 13 Feb 2005 20:04:14 +0000
Improve CPU15 workaround.
Based on comments by Joakim Tjernlund
- make the sysctl support a compile time option as the overhead
for sysctl support in the TLB handler is 6 instrunctions when the
fix itself is only 4 instructions
- moved code out of CPU6 workaround code to avoid conflicts
Signed-off-by: Nick Ivanter <nick at emcraft.com>
Signed-off-by: Wolfgang Denk <wd at denx.de>
Signed-off-by: Vitaly Bordug <vbordug at ru.mvista.com>
---
arch/powerpc/kernel/head_8xx.S | 17 +++++++++
arch/powerpc/platforms/8xx/Kconfig | 12 ++++++
include/linux/sysctl.h | 1 +
kernel/sysctl.c | 67 ++++++++++++++++++++++++++++++++++++
4 files changed, 97 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 901be47..dd67da9 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -301,6 +301,23 @@ InstructionTLBMiss:
stw r10, 0(r0)
stw r11, 4(r0)
mfspr r10, SPRN_SRR0 /* Get effective address of fault */
+#ifdef CONFIG_8xx_CPU15
+#ifdef CONFIG_8xx_CPU15_SYSCTL
+ lis r11, cpu15_fix at h
+ ori r11, r11, cpu15_fix at l
+ tophys(r11,r11)
+ lwz r11, 0(r11) /* value of cpu15 variable */
+ cmpwi r11, 0
+ beq 4f
+#endif
+ subi r11, r10, 0x1000 /* EA of prev page */
+ tlbie r11
+ addi r11, r10, 0x1000 /* EA of next page */
+ tlbie r11
+#ifdef CONFIG_8xx_CPU15_SYSCTL
+4:
+#endif
+#endif
DO_8xx_CPU6(0x3780, r3)
mtspr SPRN_MD_EPN, r10 /* Have to use MD_EPN for walk, MI_EPN can't */
mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig
index beea683..3bce162 100644
--- a/arch/powerpc/platforms/8xx/Kconfig
+++ b/arch/powerpc/platforms/8xx/Kconfig
@@ -103,6 +103,18 @@ config 8xx_CPU6
If in doubt, say N here.
+config 8xx_CPU15
+ bool "CPU15 Silicon Errata"
+ help
+ MPC8xx CPUs have a bug in the silicon, which may cause the
+ incorrect code execution after branch on MMU page boundary.
+ Say Y to enable a workaround for this problem.
+
+config 8xx_CPU15_SYSCTL
+ bool "CPU15 Silicon Errata Sysctl"
+ depends on 8xx_CPU15
+ default y
+
choice
prompt "Microcode patch selection"
default NO_UCODE_PATCH
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 2c5fb38..6109ffe 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -165,6 +165,7 @@ enum
KERN_MAX_LOCK_DEPTH=74,
KERN_NMI_WATCHDOG=75, /* int: enable/disable nmi watchdog */
KERN_PANIC_ON_NMI=76, /* int: whether we will panic on an unrecovered */
+ KERN_8XX_CPU15=77, /* boolean: patch cpu15 errata on mpc8xx cpu */
};
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 1b255df..3391b14 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -158,6 +158,63 @@ extern ctl_table inotify_table[];
int sysctl_legacy_va_layout;
#endif
+static void *get_uts(ctl_table *table, int write)
+{
+ char *which = table->data;
+#ifdef CONFIG_UTS_NS
+ struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
+ which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
+#endif
+ if (!write)
+ down_read(&uts_sem);
+ else
+ down_write(&uts_sem);
+ return which;
+}
+
+static void put_uts(ctl_table *table, int write, void *which)
+{
+ if (!write)
+ up_read(&uts_sem);
+ else
+ up_write(&uts_sem);
+}
+
+#ifdef CONFIG_SYSVIPC
+static void *get_ipc(ctl_table *table, int write)
+{
+ char *which = table->data;
+ struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
+ which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
+ return which;
+}
+#else
+#define get_ipc(T,W) ((T)->data)
+#endif
+
+/* /proc declarations: */
+
+#ifdef CONFIG_PROC_SYSCTL
+
+static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
+static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
+static int proc_opensys(struct inode *, struct file *);
+
+const struct file_operations proc_sys_file_operations = {
+ .open = proc_opensys,
+ .read = proc_readsys,
+ .write = proc_writesys,
+};
+
+extern struct proc_dir_entry *proc_sys_root;
+
+static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *);
+static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
+#endif
+
+#ifdef CONFIG_8xx_CPU15_SYSCTL
+int cpu15_fix = 0; /* disabled by default */
+#endif
/* The default sysctl tables: */
@@ -603,6 +660,16 @@ static ctl_table kern_table[] = {
.proc_handler = &proc_dointvec,
},
#endif
+#ifdef CONFIG_8xx_CPU15_SYSCTL
+ {
+ .ctl_name = KERN_8XX_CPU15,
+ .procname = "8xx_cpu15",
+ .data = &cpu15_fix,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+#endif
{ .ctl_name = 0 }
};
More information about the Linuxppc-dev
mailing list