diff options
-rw-r--r-- | arch/mips/include/asm/mmu_context.h | 15 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 93 |
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 | */ |
48 | extern unsigned long pgd_current[]; | 52 | extern 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 | ||
1868 | void per_cpu_trap_init(bool is_boot_cpu) | 1869 | /* configure STATUS register */ |
1870 | static 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 */ | ||
1892 | static 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 | 1906 | static 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 | |||
1925 | void 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 | |||
2207 | static 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 | |||
2226 | static struct notifier_block trap_pm_notifier_block = { | ||
2227 | .notifier_call = trap_pm_notifier, | ||
2228 | }; | ||
2229 | |||
2230 | static int __init trap_pm_init(void) | ||
2231 | { | ||
2232 | return cpu_pm_register_notifier(&trap_pm_notifier_block); | ||
2233 | } | ||
2234 | arch_initcall(trap_pm_init); | ||