aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/include/asm/mmu_context.h15
-rw-r--r--arch/mips/kernel/traps.c93
2 files changed, 81 insertions, 27 deletions
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index e277bbad2871..ecae1dc260fd 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -31,11 +31,15 @@ do { \
31} while (0) 31} while (0)
32 32
33#ifdef CONFIG_MIPS_PGD_C0_CONTEXT 33#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
34
35#define TLBMISS_HANDLER_RESTORE() \
36 write_c0_xcontext((unsigned long) smp_processor_id() << \
37 SMP_CPUID_REGSHIFT)
38
34#define TLBMISS_HANDLER_SETUP() \ 39#define TLBMISS_HANDLER_SETUP() \
35 do { \ 40 do { \
36 TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir); \ 41 TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir); \
37 write_c0_xcontext((unsigned long) smp_processor_id() << \ 42 TLBMISS_HANDLER_RESTORE(); \
38 SMP_CPUID_REGSHIFT); \
39 } while (0) 43 } while (0)
40 44
41#else /* !CONFIG_MIPS_PGD_C0_CONTEXT: using pgd_current*/ 45#else /* !CONFIG_MIPS_PGD_C0_CONTEXT: using pgd_current*/
@@ -47,9 +51,12 @@ do { \
47 */ 51 */
48extern unsigned long pgd_current[]; 52extern unsigned long pgd_current[];
49 53
50#define TLBMISS_HANDLER_SETUP() \ 54#define TLBMISS_HANDLER_RESTORE() \
51 write_c0_context((unsigned long) smp_processor_id() << \ 55 write_c0_context((unsigned long) smp_processor_id() << \
52 SMP_CPUID_REGSHIFT); \ 56 SMP_CPUID_REGSHIFT)
57
58#define TLBMISS_HANDLER_SETUP() \
59 TLBMISS_HANDLER_RESTORE(); \
53 back_to_back_c0_hazard(); \ 60 back_to_back_c0_hazard(); \
54 TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) 61 TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
55#endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/ 62#endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 074e857ced28..9651f68c2116 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -15,6 +15,7 @@
15#include <linux/bug.h> 15#include <linux/bug.h>
16#include <linux/compiler.h> 16#include <linux/compiler.h>
17#include <linux/context_tracking.h> 17#include <linux/context_tracking.h>
18#include <linux/cpu_pm.h>
18#include <linux/kexec.h> 19#include <linux/kexec.h>
19#include <linux/init.h> 20#include <linux/init.h>
20#include <linux/kernel.h> 21#include <linux/kernel.h>
@@ -1865,32 +1866,16 @@ static int __init ulri_disable(char *s)
1865} 1866}
1866__setup("noulri", ulri_disable); 1867__setup("noulri", ulri_disable);
1867 1868
1868void per_cpu_trap_init(bool is_boot_cpu) 1869/* configure STATUS register */
1870static void configure_status(void)
1869{ 1871{
1870 unsigned int cpu = smp_processor_id();
1871 unsigned int status_set = ST0_CU0;
1872 unsigned int hwrena = cpu_hwrena_impl_bits;
1873#ifdef CONFIG_MIPS_MT_SMTC
1874 int secondaryTC = 0;
1875 int bootTC = (cpu == 0);
1876
1877 /*
1878 * Only do per_cpu_trap_init() for first TC of Each VPE.
1879 * Note that this hack assumes that the SMTC init code
1880 * assigns TCs consecutively and in ascending order.
1881 */
1882
1883 if (((read_c0_tcbind() & TCBIND_CURTC) != 0) &&
1884 ((read_c0_tcbind() & TCBIND_CURVPE) == cpu_data[cpu - 1].vpe_id))
1885 secondaryTC = 1;
1886#endif /* CONFIG_MIPS_MT_SMTC */
1887
1888 /* 1872 /*
1889 * Disable coprocessors and select 32-bit or 64-bit addressing 1873 * Disable coprocessors and select 32-bit or 64-bit addressing
1890 * and the 16/32 or 32/32 FPR register model. Reset the BEV 1874 * and the 16/32 or 32/32 FPR register model. Reset the BEV
1891 * flag that some firmware may have left set and the TS bit (for 1875 * flag that some firmware may have left set and the TS bit (for
1892 * IP27). Set XX for ISA IV code to work. 1876 * IP27). Set XX for ISA IV code to work.
1893 */ 1877 */
1878 unsigned int status_set = ST0_CU0;
1894#ifdef CONFIG_64BIT 1879#ifdef CONFIG_64BIT
1895 status_set |= ST0_FR|ST0_KX|ST0_SX|ST0_UX; 1880 status_set |= ST0_FR|ST0_KX|ST0_SX|ST0_UX;
1896#endif 1881#endif
@@ -1901,6 +1886,12 @@ void per_cpu_trap_init(bool is_boot_cpu)
1901 1886
1902 change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX, 1887 change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
1903 status_set); 1888 status_set);
1889}
1890
1891/* configure HWRENA register */
1892static void configure_hwrena(void)
1893{
1894 unsigned int hwrena = cpu_hwrena_impl_bits;
1904 1895
1905 if (cpu_has_mips_r2) 1896 if (cpu_has_mips_r2)
1906 hwrena |= 0x0000000f; 1897 hwrena |= 0x0000000f;
@@ -1910,11 +1901,10 @@ void per_cpu_trap_init(bool is_boot_cpu)
1910 1901
1911 if (hwrena) 1902 if (hwrena)
1912 write_c0_hwrena(hwrena); 1903 write_c0_hwrena(hwrena);
1904}
1913 1905
1914#ifdef CONFIG_MIPS_MT_SMTC 1906static void configure_exception_vector(void)
1915 if (!secondaryTC) { 1907{
1916#endif /* CONFIG_MIPS_MT_SMTC */
1917
1918 if (cpu_has_veic || cpu_has_vint) { 1908 if (cpu_has_veic || cpu_has_vint) {
1919 unsigned long sr = set_c0_status(ST0_BEV); 1909 unsigned long sr = set_c0_status(ST0_BEV);
1920 write_c0_ebase(ebase); 1910 write_c0_ebase(ebase);
@@ -1930,6 +1920,34 @@ void per_cpu_trap_init(bool is_boot_cpu)
1930 } else 1920 } else
1931 set_c0_cause(CAUSEF_IV); 1921 set_c0_cause(CAUSEF_IV);
1932 } 1922 }
1923}
1924
1925void per_cpu_trap_init(bool is_boot_cpu)
1926{
1927 unsigned int cpu = smp_processor_id();
1928#ifdef CONFIG_MIPS_MT_SMTC
1929 int secondaryTC = 0;
1930 int bootTC = (cpu == 0);
1931
1932 /*
1933 * Only do per_cpu_trap_init() for first TC of Each VPE.
1934 * Note that this hack assumes that the SMTC init code
1935 * assigns TCs consecutively and in ascending order.
1936 */
1937
1938 if (((read_c0_tcbind() & TCBIND_CURTC) != 0) &&
1939 ((read_c0_tcbind() & TCBIND_CURVPE) == cpu_data[cpu - 1].vpe_id))
1940 secondaryTC = 1;
1941#endif /* CONFIG_MIPS_MT_SMTC */
1942
1943 configure_status();
1944 configure_hwrena();
1945
1946#ifdef CONFIG_MIPS_MT_SMTC
1947 if (!secondaryTC) {
1948#endif /* CONFIG_MIPS_MT_SMTC */
1949
1950 configure_exception_vector();
1933 1951
1934 /* 1952 /*
1935 * Before R2 both interrupt numbers were fixed to 7, so on R2 only: 1953 * Before R2 both interrupt numbers were fixed to 7, so on R2 only:
@@ -2185,3 +2203,32 @@ void __init trap_init(void)
2185 2203
2186 cu2_notifier(default_cu2_call, 0x80000000); /* Run last */ 2204 cu2_notifier(default_cu2_call, 0x80000000); /* Run last */
2187} 2205}
2206
2207static int trap_pm_notifier(struct notifier_block *self, unsigned long cmd,
2208 void *v)
2209{
2210 switch (cmd) {
2211 case CPU_PM_ENTER_FAILED:
2212 case CPU_PM_EXIT:
2213 configure_status();
2214 configure_hwrena();
2215 configure_exception_vector();
2216
2217 /* Restore register with CPU number for TLB handlers */
2218 TLBMISS_HANDLER_RESTORE();
2219
2220 break;
2221 }
2222
2223 return NOTIFY_OK;
2224}
2225
2226static struct notifier_block trap_pm_notifier_block = {
2227 .notifier_call = trap_pm_notifier,
2228};
2229
2230static int __init trap_pm_init(void)
2231{
2232 return cpu_pm_register_notifier(&trap_pm_notifier_block);
2233}
2234arch_initcall(trap_pm_init);