diff options
Diffstat (limited to 'arch/sparc64/kernel/traps.c')
-rw-r--r-- | arch/sparc64/kernel/traps.c | 403 |
1 files changed, 388 insertions, 15 deletions
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 8d44ae5a15e3..7f7dba0ca96a 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/processor.h> | 38 | #include <asm/processor.h> |
39 | #include <asm/timer.h> | 39 | #include <asm/timer.h> |
40 | #include <asm/kdebug.h> | 40 | #include <asm/kdebug.h> |
41 | #include <asm/head.h> | ||
41 | #ifdef CONFIG_KMOD | 42 | #ifdef CONFIG_KMOD |
42 | #include <linux/kmod.h> | 43 | #include <linux/kmod.h> |
43 | #endif | 44 | #endif |
@@ -72,12 +73,14 @@ struct tl1_traplog { | |||
72 | 73 | ||
73 | static void dump_tl1_traplog(struct tl1_traplog *p) | 74 | static void dump_tl1_traplog(struct tl1_traplog *p) |
74 | { | 75 | { |
75 | int i; | 76 | int i, limit; |
77 | |||
78 | printk(KERN_EMERG "TRAPLOG: Error at trap level 0x%lx, " | ||
79 | "dumping track stack.\n", p->tl); | ||
76 | 80 | ||
77 | printk("TRAPLOG: Error at trap level 0x%lx, dumping track stack.\n", | 81 | limit = (tlb_type == hypervisor) ? 2 : 4; |
78 | p->tl); | 82 | for (i = 0; i < limit; i++) { |
79 | for (i = 0; i < 4; i++) { | 83 | printk(KERN_EMERG |
80 | printk(KERN_CRIT | ||
81 | "TRAPLOG: Trap level %d TSTATE[%016lx] TPC[%016lx] " | 84 | "TRAPLOG: Trap level %d TSTATE[%016lx] TPC[%016lx] " |
82 | "TNPC[%016lx] TT[%lx]\n", | 85 | "TNPC[%016lx] TT[%lx]\n", |
83 | i + 1, | 86 | i + 1, |
@@ -179,6 +182,45 @@ void spitfire_insn_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr | |||
179 | spitfire_insn_access_exception(regs, sfsr, sfar); | 182 | spitfire_insn_access_exception(regs, sfsr, sfar); |
180 | } | 183 | } |
181 | 184 | ||
185 | void sun4v_insn_access_exception(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx) | ||
186 | { | ||
187 | unsigned short type = (type_ctx >> 16); | ||
188 | unsigned short ctx = (type_ctx & 0xffff); | ||
189 | siginfo_t info; | ||
190 | |||
191 | if (notify_die(DIE_TRAP, "instruction access exception", regs, | ||
192 | 0, 0x8, SIGTRAP) == NOTIFY_STOP) | ||
193 | return; | ||
194 | |||
195 | if (regs->tstate & TSTATE_PRIV) { | ||
196 | printk("sun4v_insn_access_exception: ADDR[%016lx] " | ||
197 | "CTX[%04x] TYPE[%04x], going.\n", | ||
198 | addr, ctx, type); | ||
199 | die_if_kernel("Iax", regs); | ||
200 | } | ||
201 | |||
202 | if (test_thread_flag(TIF_32BIT)) { | ||
203 | regs->tpc &= 0xffffffff; | ||
204 | regs->tnpc &= 0xffffffff; | ||
205 | } | ||
206 | info.si_signo = SIGSEGV; | ||
207 | info.si_errno = 0; | ||
208 | info.si_code = SEGV_MAPERR; | ||
209 | info.si_addr = (void __user *) addr; | ||
210 | info.si_trapno = 0; | ||
211 | force_sig_info(SIGSEGV, &info, current); | ||
212 | } | ||
213 | |||
214 | void sun4v_insn_access_exception_tl1(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx) | ||
215 | { | ||
216 | if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs, | ||
217 | 0, 0x8, SIGTRAP) == NOTIFY_STOP) | ||
218 | return; | ||
219 | |||
220 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | ||
221 | sun4v_insn_access_exception(regs, addr, type_ctx); | ||
222 | } | ||
223 | |||
182 | void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) | 224 | void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) |
183 | { | 225 | { |
184 | siginfo_t info; | 226 | siginfo_t info; |
@@ -227,6 +269,45 @@ void spitfire_data_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr | |||
227 | spitfire_data_access_exception(regs, sfsr, sfar); | 269 | spitfire_data_access_exception(regs, sfsr, sfar); |
228 | } | 270 | } |
229 | 271 | ||
272 | void sun4v_data_access_exception(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx) | ||
273 | { | ||
274 | unsigned short type = (type_ctx >> 16); | ||
275 | unsigned short ctx = (type_ctx & 0xffff); | ||
276 | siginfo_t info; | ||
277 | |||
278 | if (notify_die(DIE_TRAP, "data access exception", regs, | ||
279 | 0, 0x8, SIGTRAP) == NOTIFY_STOP) | ||
280 | return; | ||
281 | |||
282 | if (regs->tstate & TSTATE_PRIV) { | ||
283 | printk("sun4v_data_access_exception: ADDR[%016lx] " | ||
284 | "CTX[%04x] TYPE[%04x], going.\n", | ||
285 | addr, ctx, type); | ||
286 | die_if_kernel("Dax", regs); | ||
287 | } | ||
288 | |||
289 | if (test_thread_flag(TIF_32BIT)) { | ||
290 | regs->tpc &= 0xffffffff; | ||
291 | regs->tnpc &= 0xffffffff; | ||
292 | } | ||
293 | info.si_signo = SIGSEGV; | ||
294 | info.si_errno = 0; | ||
295 | info.si_code = SEGV_MAPERR; | ||
296 | info.si_addr = (void __user *) addr; | ||
297 | info.si_trapno = 0; | ||
298 | force_sig_info(SIGSEGV, &info, current); | ||
299 | } | ||
300 | |||
301 | void sun4v_data_access_exception_tl1(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx) | ||
302 | { | ||
303 | if (notify_die(DIE_TRAP_TL1, "data access exception tl1", regs, | ||
304 | 0, 0x8, SIGTRAP) == NOTIFY_STOP) | ||
305 | return; | ||
306 | |||
307 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | ||
308 | sun4v_data_access_exception(regs, addr, type_ctx); | ||
309 | } | ||
310 | |||
230 | #ifdef CONFIG_PCI | 311 | #ifdef CONFIG_PCI |
231 | /* This is really pathetic... */ | 312 | /* This is really pathetic... */ |
232 | extern volatile int pci_poke_in_progress; | 313 | extern volatile int pci_poke_in_progress; |
@@ -788,7 +869,8 @@ void __init cheetah_ecache_flush_init(void) | |||
788 | cheetah_error_log[i].afsr = CHAFSR_INVALID; | 869 | cheetah_error_log[i].afsr = CHAFSR_INVALID; |
789 | 870 | ||
790 | __asm__ ("rdpr %%ver, %0" : "=r" (ver)); | 871 | __asm__ ("rdpr %%ver, %0" : "=r" (ver)); |
791 | if ((ver >> 32) == 0x003e0016) { | 872 | if ((ver >> 32) == __JALAPENO_ID || |
873 | (ver >> 32) == __SERRANO_ID) { | ||
792 | cheetah_error_table = &__jalapeno_error_table[0]; | 874 | cheetah_error_table = &__jalapeno_error_table[0]; |
793 | cheetah_afsr_errors = JPAFSR_ERRORS; | 875 | cheetah_afsr_errors = JPAFSR_ERRORS; |
794 | } else if ((ver >> 32) == 0x003e0015) { | 876 | } else if ((ver >> 32) == 0x003e0015) { |
@@ -1666,6 +1748,238 @@ void cheetah_plus_parity_error(int type, struct pt_regs *regs) | |||
1666 | regs->tpc); | 1748 | regs->tpc); |
1667 | } | 1749 | } |
1668 | 1750 | ||
1751 | struct sun4v_error_entry { | ||
1752 | u64 err_handle; | ||
1753 | u64 err_stick; | ||
1754 | |||
1755 | u32 err_type; | ||
1756 | #define SUN4V_ERR_TYPE_UNDEFINED 0 | ||
1757 | #define SUN4V_ERR_TYPE_UNCORRECTED_RES 1 | ||
1758 | #define SUN4V_ERR_TYPE_PRECISE_NONRES 2 | ||
1759 | #define SUN4V_ERR_TYPE_DEFERRED_NONRES 3 | ||
1760 | #define SUN4V_ERR_TYPE_WARNING_RES 4 | ||
1761 | |||
1762 | u32 err_attrs; | ||
1763 | #define SUN4V_ERR_ATTRS_PROCESSOR 0x00000001 | ||
1764 | #define SUN4V_ERR_ATTRS_MEMORY 0x00000002 | ||
1765 | #define SUN4V_ERR_ATTRS_PIO 0x00000004 | ||
1766 | #define SUN4V_ERR_ATTRS_INT_REGISTERS 0x00000008 | ||
1767 | #define SUN4V_ERR_ATTRS_FPU_REGISTERS 0x00000010 | ||
1768 | #define SUN4V_ERR_ATTRS_USER_MODE 0x01000000 | ||
1769 | #define SUN4V_ERR_ATTRS_PRIV_MODE 0x02000000 | ||
1770 | #define SUN4V_ERR_ATTRS_RES_QUEUE_FULL 0x80000000 | ||
1771 | |||
1772 | u64 err_raddr; | ||
1773 | u32 err_size; | ||
1774 | u16 err_cpu; | ||
1775 | u16 err_pad; | ||
1776 | }; | ||
1777 | |||
1778 | static atomic_t sun4v_resum_oflow_cnt = ATOMIC_INIT(0); | ||
1779 | static atomic_t sun4v_nonresum_oflow_cnt = ATOMIC_INIT(0); | ||
1780 | |||
1781 | static const char *sun4v_err_type_to_str(u32 type) | ||
1782 | { | ||
1783 | switch (type) { | ||
1784 | case SUN4V_ERR_TYPE_UNDEFINED: | ||
1785 | return "undefined"; | ||
1786 | case SUN4V_ERR_TYPE_UNCORRECTED_RES: | ||
1787 | return "uncorrected resumable"; | ||
1788 | case SUN4V_ERR_TYPE_PRECISE_NONRES: | ||
1789 | return "precise nonresumable"; | ||
1790 | case SUN4V_ERR_TYPE_DEFERRED_NONRES: | ||
1791 | return "deferred nonresumable"; | ||
1792 | case SUN4V_ERR_TYPE_WARNING_RES: | ||
1793 | return "warning resumable"; | ||
1794 | default: | ||
1795 | return "unknown"; | ||
1796 | }; | ||
1797 | } | ||
1798 | |||
1799 | static void sun4v_log_error(struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt) | ||
1800 | { | ||
1801 | int cnt; | ||
1802 | |||
1803 | printk("%s: Reporting on cpu %d\n", pfx, cpu); | ||
1804 | printk("%s: err_handle[%lx] err_stick[%lx] err_type[%08x:%s]\n", | ||
1805 | pfx, | ||
1806 | ent->err_handle, ent->err_stick, | ||
1807 | ent->err_type, | ||
1808 | sun4v_err_type_to_str(ent->err_type)); | ||
1809 | printk("%s: err_attrs[%08x:%s %s %s %s %s %s %s %s]\n", | ||
1810 | pfx, | ||
1811 | ent->err_attrs, | ||
1812 | ((ent->err_attrs & SUN4V_ERR_ATTRS_PROCESSOR) ? | ||
1813 | "processor" : ""), | ||
1814 | ((ent->err_attrs & SUN4V_ERR_ATTRS_MEMORY) ? | ||
1815 | "memory" : ""), | ||
1816 | ((ent->err_attrs & SUN4V_ERR_ATTRS_PIO) ? | ||
1817 | "pio" : ""), | ||
1818 | ((ent->err_attrs & SUN4V_ERR_ATTRS_INT_REGISTERS) ? | ||
1819 | "integer-regs" : ""), | ||
1820 | ((ent->err_attrs & SUN4V_ERR_ATTRS_FPU_REGISTERS) ? | ||
1821 | "fpu-regs" : ""), | ||
1822 | ((ent->err_attrs & SUN4V_ERR_ATTRS_USER_MODE) ? | ||
1823 | "user" : ""), | ||
1824 | ((ent->err_attrs & SUN4V_ERR_ATTRS_PRIV_MODE) ? | ||
1825 | "privileged" : ""), | ||
1826 | ((ent->err_attrs & SUN4V_ERR_ATTRS_RES_QUEUE_FULL) ? | ||
1827 | "queue-full" : "")); | ||
1828 | printk("%s: err_raddr[%016lx] err_size[%u] err_cpu[%u]\n", | ||
1829 | pfx, | ||
1830 | ent->err_raddr, ent->err_size, ent->err_cpu); | ||
1831 | |||
1832 | if ((cnt = atomic_read(ocnt)) != 0) { | ||
1833 | atomic_set(ocnt, 0); | ||
1834 | wmb(); | ||
1835 | printk("%s: Queue overflowed %d times.\n", | ||
1836 | pfx, cnt); | ||
1837 | } | ||
1838 | } | ||
1839 | |||
1840 | /* We run with %pil set to 15 and PSTATE_IE enabled in %pstate. | ||
1841 | * Log the event and clear the first word of the entry. | ||
1842 | */ | ||
1843 | void sun4v_resum_error(struct pt_regs *regs, unsigned long offset) | ||
1844 | { | ||
1845 | struct sun4v_error_entry *ent, local_copy; | ||
1846 | struct trap_per_cpu *tb; | ||
1847 | unsigned long paddr; | ||
1848 | int cpu; | ||
1849 | |||
1850 | cpu = get_cpu(); | ||
1851 | |||
1852 | tb = &trap_block[cpu]; | ||
1853 | paddr = tb->resum_kernel_buf_pa + offset; | ||
1854 | ent = __va(paddr); | ||
1855 | |||
1856 | memcpy(&local_copy, ent, sizeof(struct sun4v_error_entry)); | ||
1857 | |||
1858 | /* We have a local copy now, so release the entry. */ | ||
1859 | ent->err_handle = 0; | ||
1860 | wmb(); | ||
1861 | |||
1862 | put_cpu(); | ||
1863 | |||
1864 | sun4v_log_error(&local_copy, cpu, | ||
1865 | KERN_ERR "RESUMABLE ERROR", | ||
1866 | &sun4v_resum_oflow_cnt); | ||
1867 | } | ||
1868 | |||
1869 | /* If we try to printk() we'll probably make matters worse, by trying | ||
1870 | * to retake locks this cpu already holds or causing more errors. So | ||
1871 | * just bump a counter, and we'll report these counter bumps above. | ||
1872 | */ | ||
1873 | void sun4v_resum_overflow(struct pt_regs *regs) | ||
1874 | { | ||
1875 | atomic_inc(&sun4v_resum_oflow_cnt); | ||
1876 | } | ||
1877 | |||
1878 | /* We run with %pil set to 15 and PSTATE_IE enabled in %pstate. | ||
1879 | * Log the event, clear the first word of the entry, and die. | ||
1880 | */ | ||
1881 | void sun4v_nonresum_error(struct pt_regs *regs, unsigned long offset) | ||
1882 | { | ||
1883 | struct sun4v_error_entry *ent, local_copy; | ||
1884 | struct trap_per_cpu *tb; | ||
1885 | unsigned long paddr; | ||
1886 | int cpu; | ||
1887 | |||
1888 | cpu = get_cpu(); | ||
1889 | |||
1890 | tb = &trap_block[cpu]; | ||
1891 | paddr = tb->nonresum_kernel_buf_pa + offset; | ||
1892 | ent = __va(paddr); | ||
1893 | |||
1894 | memcpy(&local_copy, ent, sizeof(struct sun4v_error_entry)); | ||
1895 | |||
1896 | /* We have a local copy now, so release the entry. */ | ||
1897 | ent->err_handle = 0; | ||
1898 | wmb(); | ||
1899 | |||
1900 | put_cpu(); | ||
1901 | |||
1902 | #ifdef CONFIG_PCI | ||
1903 | /* Check for the special PCI poke sequence. */ | ||
1904 | if (pci_poke_in_progress && pci_poke_cpu == cpu) { | ||
1905 | pci_poke_faulted = 1; | ||
1906 | regs->tpc += 4; | ||
1907 | regs->tnpc = regs->tpc + 4; | ||
1908 | return; | ||
1909 | } | ||
1910 | #endif | ||
1911 | |||
1912 | sun4v_log_error(&local_copy, cpu, | ||
1913 | KERN_EMERG "NON-RESUMABLE ERROR", | ||
1914 | &sun4v_nonresum_oflow_cnt); | ||
1915 | |||
1916 | panic("Non-resumable error."); | ||
1917 | } | ||
1918 | |||
1919 | /* If we try to printk() we'll probably make matters worse, by trying | ||
1920 | * to retake locks this cpu already holds or causing more errors. So | ||
1921 | * just bump a counter, and we'll report these counter bumps above. | ||
1922 | */ | ||
1923 | void sun4v_nonresum_overflow(struct pt_regs *regs) | ||
1924 | { | ||
1925 | /* XXX Actually even this can make not that much sense. Perhaps | ||
1926 | * XXX we should just pull the plug and panic directly from here? | ||
1927 | */ | ||
1928 | atomic_inc(&sun4v_nonresum_oflow_cnt); | ||
1929 | } | ||
1930 | |||
1931 | unsigned long sun4v_err_itlb_vaddr; | ||
1932 | unsigned long sun4v_err_itlb_ctx; | ||
1933 | unsigned long sun4v_err_itlb_pte; | ||
1934 | unsigned long sun4v_err_itlb_error; | ||
1935 | |||
1936 | void sun4v_itlb_error_report(struct pt_regs *regs, int tl) | ||
1937 | { | ||
1938 | if (tl > 1) | ||
1939 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | ||
1940 | |||
1941 | printk(KERN_EMERG "SUN4V-ITLB: Error at TPC[%lx], tl %d\n", | ||
1942 | regs->tpc, tl); | ||
1943 | printk(KERN_EMERG "SUN4V-ITLB: vaddr[%lx] ctx[%lx] " | ||
1944 | "pte[%lx] error[%lx]\n", | ||
1945 | sun4v_err_itlb_vaddr, sun4v_err_itlb_ctx, | ||
1946 | sun4v_err_itlb_pte, sun4v_err_itlb_error); | ||
1947 | |||
1948 | prom_halt(); | ||
1949 | } | ||
1950 | |||
1951 | unsigned long sun4v_err_dtlb_vaddr; | ||
1952 | unsigned long sun4v_err_dtlb_ctx; | ||
1953 | unsigned long sun4v_err_dtlb_pte; | ||
1954 | unsigned long sun4v_err_dtlb_error; | ||
1955 | |||
1956 | void sun4v_dtlb_error_report(struct pt_regs *regs, int tl) | ||
1957 | { | ||
1958 | if (tl > 1) | ||
1959 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | ||
1960 | |||
1961 | printk(KERN_EMERG "SUN4V-DTLB: Error at TPC[%lx], tl %d\n", | ||
1962 | regs->tpc, tl); | ||
1963 | printk(KERN_EMERG "SUN4V-DTLB: vaddr[%lx] ctx[%lx] " | ||
1964 | "pte[%lx] error[%lx]\n", | ||
1965 | sun4v_err_dtlb_vaddr, sun4v_err_dtlb_ctx, | ||
1966 | sun4v_err_dtlb_pte, sun4v_err_dtlb_error); | ||
1967 | |||
1968 | prom_halt(); | ||
1969 | } | ||
1970 | |||
1971 | void hypervisor_tlbop_error(unsigned long err, unsigned long op) | ||
1972 | { | ||
1973 | printk(KERN_CRIT "SUN4V: TLB hv call error %lu for op %lu\n", | ||
1974 | err, op); | ||
1975 | } | ||
1976 | |||
1977 | void hypervisor_tlbop_error_xcall(unsigned long err, unsigned long op) | ||
1978 | { | ||
1979 | printk(KERN_CRIT "SUN4V: XCALL TLB hv call error %lu for op %lu\n", | ||
1980 | err, op); | ||
1981 | } | ||
1982 | |||
1669 | void do_fpe_common(struct pt_regs *regs) | 1983 | void do_fpe_common(struct pt_regs *regs) |
1670 | { | 1984 | { |
1671 | if (regs->tstate & TSTATE_PRIV) { | 1985 | if (regs->tstate & TSTATE_PRIV) { |
@@ -1924,10 +2238,11 @@ void die_if_kernel(char *str, struct pt_regs *regs) | |||
1924 | } | 2238 | } |
1925 | user_instruction_dump ((unsigned int __user *) regs->tpc); | 2239 | user_instruction_dump ((unsigned int __user *) regs->tpc); |
1926 | } | 2240 | } |
2241 | #if 0 | ||
1927 | #ifdef CONFIG_SMP | 2242 | #ifdef CONFIG_SMP |
1928 | smp_report_regs(); | 2243 | smp_report_regs(); |
1929 | #endif | 2244 | #endif |
1930 | 2245 | #endif | |
1931 | if (regs->tstate & TSTATE_PRIV) | 2246 | if (regs->tstate & TSTATE_PRIV) |
1932 | do_exit(SIGKILL); | 2247 | do_exit(SIGKILL); |
1933 | do_exit(SIGSEGV); | 2248 | do_exit(SIGSEGV); |
@@ -1958,6 +2273,11 @@ void do_illegal_instruction(struct pt_regs *regs) | |||
1958 | } else if ((insn & 0xc1580000) == 0xc1100000) /* LDQ/STQ */ { | 2273 | } else if ((insn & 0xc1580000) == 0xc1100000) /* LDQ/STQ */ { |
1959 | if (handle_ldf_stq(insn, regs)) | 2274 | if (handle_ldf_stq(insn, regs)) |
1960 | return; | 2275 | return; |
2276 | } else if (tlb_type == hypervisor) { | ||
2277 | extern int vis_emul(struct pt_regs *, unsigned int); | ||
2278 | |||
2279 | if (!vis_emul(regs, insn)) | ||
2280 | return; | ||
1961 | } | 2281 | } |
1962 | } | 2282 | } |
1963 | info.si_signo = SIGILL; | 2283 | info.si_signo = SIGILL; |
@@ -1968,6 +2288,8 @@ void do_illegal_instruction(struct pt_regs *regs) | |||
1968 | force_sig_info(SIGILL, &info, current); | 2288 | force_sig_info(SIGILL, &info, current); |
1969 | } | 2289 | } |
1970 | 2290 | ||
2291 | extern void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn); | ||
2292 | |||
1971 | void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) | 2293 | void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) |
1972 | { | 2294 | { |
1973 | siginfo_t info; | 2295 | siginfo_t info; |
@@ -1977,13 +2299,7 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo | |||
1977 | return; | 2299 | return; |
1978 | 2300 | ||
1979 | if (regs->tstate & TSTATE_PRIV) { | 2301 | if (regs->tstate & TSTATE_PRIV) { |
1980 | extern void kernel_unaligned_trap(struct pt_regs *regs, | 2302 | kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc)); |
1981 | unsigned int insn, | ||
1982 | unsigned long sfar, | ||
1983 | unsigned long sfsr); | ||
1984 | |||
1985 | kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc), | ||
1986 | sfar, sfsr); | ||
1987 | return; | 2303 | return; |
1988 | } | 2304 | } |
1989 | info.si_signo = SIGBUS; | 2305 | info.si_signo = SIGBUS; |
@@ -1994,6 +2310,26 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo | |||
1994 | force_sig_info(SIGBUS, &info, current); | 2310 | force_sig_info(SIGBUS, &info, current); |
1995 | } | 2311 | } |
1996 | 2312 | ||
2313 | void sun4v_do_mna(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx) | ||
2314 | { | ||
2315 | siginfo_t info; | ||
2316 | |||
2317 | if (notify_die(DIE_TRAP, "memory address unaligned", regs, | ||
2318 | 0, 0x34, SIGSEGV) == NOTIFY_STOP) | ||
2319 | return; | ||
2320 | |||
2321 | if (regs->tstate & TSTATE_PRIV) { | ||
2322 | kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc)); | ||
2323 | return; | ||
2324 | } | ||
2325 | info.si_signo = SIGBUS; | ||
2326 | info.si_errno = 0; | ||
2327 | info.si_code = BUS_ADRALN; | ||
2328 | info.si_addr = (void __user *) addr; | ||
2329 | info.si_trapno = 0; | ||
2330 | force_sig_info(SIGBUS, &info, current); | ||
2331 | } | ||
2332 | |||
1997 | void do_privop(struct pt_regs *regs) | 2333 | void do_privop(struct pt_regs *regs) |
1998 | { | 2334 | { |
1999 | siginfo_t info; | 2335 | siginfo_t info; |
@@ -2130,7 +2466,22 @@ void do_getpsr(struct pt_regs *regs) | |||
2130 | } | 2466 | } |
2131 | } | 2467 | } |
2132 | 2468 | ||
2469 | struct trap_per_cpu trap_block[NR_CPUS]; | ||
2470 | |||
2471 | /* This can get invoked before sched_init() so play it super safe | ||
2472 | * and use hard_smp_processor_id(). | ||
2473 | */ | ||
2474 | void init_cur_cpu_trap(struct thread_info *t) | ||
2475 | { | ||
2476 | int cpu = hard_smp_processor_id(); | ||
2477 | struct trap_per_cpu *p = &trap_block[cpu]; | ||
2478 | |||
2479 | p->thread = t; | ||
2480 | p->pgd_paddr = 0; | ||
2481 | } | ||
2482 | |||
2133 | extern void thread_info_offsets_are_bolixed_dave(void); | 2483 | extern void thread_info_offsets_are_bolixed_dave(void); |
2484 | extern void trap_per_cpu_offsets_are_bolixed_dave(void); | ||
2134 | 2485 | ||
2135 | /* Only invoked on boot processor. */ | 2486 | /* Only invoked on boot processor. */ |
2136 | void __init trap_init(void) | 2487 | void __init trap_init(void) |
@@ -2154,7 +2505,6 @@ void __init trap_init(void) | |||
2154 | TI_KERN_CNTD0 != offsetof(struct thread_info, kernel_cntd0) || | 2505 | TI_KERN_CNTD0 != offsetof(struct thread_info, kernel_cntd0) || |
2155 | TI_KERN_CNTD1 != offsetof(struct thread_info, kernel_cntd1) || | 2506 | TI_KERN_CNTD1 != offsetof(struct thread_info, kernel_cntd1) || |
2156 | TI_PCR != offsetof(struct thread_info, pcr_reg) || | 2507 | TI_PCR != offsetof(struct thread_info, pcr_reg) || |
2157 | TI_CEE_STUFF != offsetof(struct thread_info, cee_stuff) || | ||
2158 | TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) || | 2508 | TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) || |
2159 | TI_NEW_CHILD != offsetof(struct thread_info, new_child) || | 2509 | TI_NEW_CHILD != offsetof(struct thread_info, new_child) || |
2160 | TI_SYS_NOERROR != offsetof(struct thread_info, syscall_noerror) || | 2510 | TI_SYS_NOERROR != offsetof(struct thread_info, syscall_noerror) || |
@@ -2165,6 +2515,29 @@ void __init trap_init(void) | |||
2165 | (TI_FPREGS & (64 - 1))) | 2515 | (TI_FPREGS & (64 - 1))) |
2166 | thread_info_offsets_are_bolixed_dave(); | 2516 | thread_info_offsets_are_bolixed_dave(); |
2167 | 2517 | ||
2518 | if (TRAP_PER_CPU_THREAD != offsetof(struct trap_per_cpu, thread) || | ||
2519 | (TRAP_PER_CPU_PGD_PADDR != | ||
2520 | offsetof(struct trap_per_cpu, pgd_paddr)) || | ||
2521 | (TRAP_PER_CPU_CPU_MONDO_PA != | ||
2522 | offsetof(struct trap_per_cpu, cpu_mondo_pa)) || | ||
2523 | (TRAP_PER_CPU_DEV_MONDO_PA != | ||
2524 | offsetof(struct trap_per_cpu, dev_mondo_pa)) || | ||
2525 | (TRAP_PER_CPU_RESUM_MONDO_PA != | ||
2526 | offsetof(struct trap_per_cpu, resum_mondo_pa)) || | ||
2527 | (TRAP_PER_CPU_RESUM_KBUF_PA != | ||
2528 | offsetof(struct trap_per_cpu, resum_kernel_buf_pa)) || | ||
2529 | (TRAP_PER_CPU_NONRESUM_MONDO_PA != | ||
2530 | offsetof(struct trap_per_cpu, nonresum_mondo_pa)) || | ||
2531 | (TRAP_PER_CPU_NONRESUM_KBUF_PA != | ||
2532 | offsetof(struct trap_per_cpu, nonresum_kernel_buf_pa)) || | ||
2533 | (TRAP_PER_CPU_FAULT_INFO != | ||
2534 | offsetof(struct trap_per_cpu, fault_info)) || | ||
2535 | (TRAP_PER_CPU_CPU_MONDO_BLOCK_PA != | ||
2536 | offsetof(struct trap_per_cpu, cpu_mondo_block_pa)) || | ||
2537 | (TRAP_PER_CPU_CPU_LIST_PA != | ||
2538 | offsetof(struct trap_per_cpu, cpu_list_pa))) | ||
2539 | trap_per_cpu_offsets_are_bolixed_dave(); | ||
2540 | |||
2168 | /* Attach to the address space of init_task. On SMP we | 2541 | /* Attach to the address space of init_task. On SMP we |
2169 | * do this in smp.c:smp_callin for other cpus. | 2542 | * do this in smp.c:smp_callin for other cpus. |
2170 | */ | 2543 | */ |