diff options
Diffstat (limited to 'arch/sparc64/kernel/traps.c')
| -rw-r--r-- | arch/sparc64/kernel/traps.c | 100 |
1 files changed, 47 insertions, 53 deletions
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index b280b2ef674f..5570e7bb22bb 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c | |||
| @@ -189,19 +189,18 @@ void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, un | |||
| 189 | 189 | ||
| 190 | if (regs->tstate & TSTATE_PRIV) { | 190 | if (regs->tstate & TSTATE_PRIV) { |
| 191 | /* Test if this comes from uaccess places. */ | 191 | /* Test if this comes from uaccess places. */ |
| 192 | unsigned long fixup; | 192 | const struct exception_table_entry *entry; |
| 193 | unsigned long g2 = regs->u_regs[UREG_G2]; | ||
| 194 | 193 | ||
| 195 | if ((fixup = search_extables_range(regs->tpc, &g2))) { | 194 | entry = search_exception_tables(regs->tpc); |
| 196 | /* Ouch, somebody is trying ugly VM hole tricks on us... */ | 195 | if (entry) { |
| 196 | /* Ouch, somebody is trying VM hole tricks on us... */ | ||
| 197 | #ifdef DEBUG_EXCEPTIONS | 197 | #ifdef DEBUG_EXCEPTIONS |
| 198 | printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc); | 198 | printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc); |
| 199 | printk("EX_TABLE: insn<%016lx> fixup<%016lx> " | 199 | printk("EX_TABLE: insn<%016lx> fixup<%016lx>\n", |
| 200 | "g2<%016lx>\n", regs->tpc, fixup, g2); | 200 | regs->tpc, entry->fixup); |
| 201 | #endif | 201 | #endif |
| 202 | regs->tpc = fixup; | 202 | regs->tpc = entry->fixup; |
| 203 | regs->tnpc = regs->tpc + 4; | 203 | regs->tnpc = regs->tpc + 4; |
| 204 | regs->u_regs[UREG_G2] = g2; | ||
| 205 | return; | 204 | return; |
| 206 | } | 205 | } |
| 207 | /* Shit... */ | 206 | /* Shit... */ |
| @@ -758,26 +757,12 @@ void __init cheetah_ecache_flush_init(void) | |||
| 758 | ecache_flush_size = (2 * largest_size); | 757 | ecache_flush_size = (2 * largest_size); |
| 759 | ecache_flush_linesize = smallest_linesize; | 758 | ecache_flush_linesize = smallest_linesize; |
| 760 | 759 | ||
| 761 | /* Discover a physically contiguous chunk of physical | 760 | ecache_flush_physbase = find_ecache_flush_span(ecache_flush_size); |
| 762 | * memory in 'sp_banks' of size ecache_flush_size calculated | ||
| 763 | * above. Store the physical base of this area at | ||
| 764 | * ecache_flush_physbase. | ||
| 765 | */ | ||
| 766 | for (node = 0; ; node++) { | ||
| 767 | if (sp_banks[node].num_bytes == 0) | ||
| 768 | break; | ||
| 769 | if (sp_banks[node].num_bytes >= ecache_flush_size) { | ||
| 770 | ecache_flush_physbase = sp_banks[node].base_addr; | ||
| 771 | break; | ||
| 772 | } | ||
| 773 | } | ||
| 774 | 761 | ||
| 775 | /* Note: Zero would be a valid value of ecache_flush_physbase so | 762 | if (ecache_flush_physbase == ~0UL) { |
| 776 | * don't use that as the success test. :-) | ||
| 777 | */ | ||
| 778 | if (sp_banks[node].num_bytes == 0) { | ||
| 779 | prom_printf("cheetah_ecache_flush_init: Cannot find %d byte " | 763 | prom_printf("cheetah_ecache_flush_init: Cannot find %d byte " |
| 780 | "contiguous physical memory.\n", ecache_flush_size); | 764 | "contiguous physical memory.\n", |
| 765 | ecache_flush_size); | ||
| 781 | prom_halt(); | 766 | prom_halt(); |
| 782 | } | 767 | } |
| 783 | 768 | ||
| @@ -869,14 +854,19 @@ static void cheetah_flush_ecache_line(unsigned long physaddr) | |||
| 869 | */ | 854 | */ |
| 870 | static void __cheetah_flush_icache(void) | 855 | static void __cheetah_flush_icache(void) |
| 871 | { | 856 | { |
| 872 | unsigned long i; | 857 | unsigned int icache_size, icache_line_size; |
| 858 | unsigned long addr; | ||
| 859 | |||
| 860 | icache_size = local_cpu_data().icache_size; | ||
| 861 | icache_line_size = local_cpu_data().icache_line_size; | ||
| 873 | 862 | ||
| 874 | /* Clear the valid bits in all the tags. */ | 863 | /* Clear the valid bits in all the tags. */ |
| 875 | for (i = 0; i < (1 << 15); i += (1 << 5)) { | 864 | for (addr = 0; addr < icache_size; addr += icache_line_size) { |
| 876 | __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" | 865 | __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" |
| 877 | "membar #Sync" | 866 | "membar #Sync" |
| 878 | : /* no outputs */ | 867 | : /* no outputs */ |
| 879 | : "r" (i | (2 << 3)), "i" (ASI_IC_TAG)); | 868 | : "r" (addr | (2 << 3)), |
| 869 | "i" (ASI_IC_TAG)); | ||
| 880 | } | 870 | } |
| 881 | } | 871 | } |
| 882 | 872 | ||
| @@ -904,13 +894,17 @@ static void cheetah_flush_icache(void) | |||
| 904 | 894 | ||
| 905 | static void cheetah_flush_dcache(void) | 895 | static void cheetah_flush_dcache(void) |
| 906 | { | 896 | { |
| 907 | unsigned long i; | 897 | unsigned int dcache_size, dcache_line_size; |
| 898 | unsigned long addr; | ||
| 908 | 899 | ||
| 909 | for (i = 0; i < (1 << 16); i += (1 << 5)) { | 900 | dcache_size = local_cpu_data().dcache_size; |
| 901 | dcache_line_size = local_cpu_data().dcache_line_size; | ||
| 902 | |||
| 903 | for (addr = 0; addr < dcache_size; addr += dcache_line_size) { | ||
| 910 | __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" | 904 | __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" |
| 911 | "membar #Sync" | 905 | "membar #Sync" |
| 912 | : /* no outputs */ | 906 | : /* no outputs */ |
| 913 | : "r" (i), "i" (ASI_DCACHE_TAG)); | 907 | : "r" (addr), "i" (ASI_DCACHE_TAG)); |
| 914 | } | 908 | } |
| 915 | } | 909 | } |
| 916 | 910 | ||
| @@ -921,24 +915,29 @@ static void cheetah_flush_dcache(void) | |||
| 921 | */ | 915 | */ |
| 922 | static void cheetah_plus_zap_dcache_parity(void) | 916 | static void cheetah_plus_zap_dcache_parity(void) |
| 923 | { | 917 | { |
| 924 | unsigned long i; | 918 | unsigned int dcache_size, dcache_line_size; |
| 919 | unsigned long addr; | ||
| 920 | |||
| 921 | dcache_size = local_cpu_data().dcache_size; | ||
| 922 | dcache_line_size = local_cpu_data().dcache_line_size; | ||
| 925 | 923 | ||
| 926 | for (i = 0; i < (1 << 16); i += (1 << 5)) { | 924 | for (addr = 0; addr < dcache_size; addr += dcache_line_size) { |
| 927 | unsigned long tag = (i >> 14); | 925 | unsigned long tag = (addr >> 14); |
| 928 | unsigned long j; | 926 | unsigned long line; |
| 929 | 927 | ||
| 930 | __asm__ __volatile__("membar #Sync\n\t" | 928 | __asm__ __volatile__("membar #Sync\n\t" |
| 931 | "stxa %0, [%1] %2\n\t" | 929 | "stxa %0, [%1] %2\n\t" |
| 932 | "membar #Sync" | 930 | "membar #Sync" |
| 933 | : /* no outputs */ | 931 | : /* no outputs */ |
| 934 | : "r" (tag), "r" (i), | 932 | : "r" (tag), "r" (addr), |
| 935 | "i" (ASI_DCACHE_UTAG)); | 933 | "i" (ASI_DCACHE_UTAG)); |
| 936 | for (j = i; j < i + (1 << 5); j += (1 << 3)) | 934 | for (line = addr; line < addr + dcache_line_size; line += 8) |
| 937 | __asm__ __volatile__("membar #Sync\n\t" | 935 | __asm__ __volatile__("membar #Sync\n\t" |
| 938 | "stxa %%g0, [%0] %1\n\t" | 936 | "stxa %%g0, [%0] %1\n\t" |
| 939 | "membar #Sync" | 937 | "membar #Sync" |
| 940 | : /* no outputs */ | 938 | : /* no outputs */ |
| 941 | : "r" (j), "i" (ASI_DCACHE_DATA)); | 939 | : "r" (line), |
| 940 | "i" (ASI_DCACHE_DATA)); | ||
| 942 | } | 941 | } |
| 943 | } | 942 | } |
| 944 | 943 | ||
| @@ -1332,16 +1331,12 @@ static int cheetah_fix_ce(unsigned long physaddr) | |||
| 1332 | /* Return non-zero if PADDR is a valid physical memory address. */ | 1331 | /* Return non-zero if PADDR is a valid physical memory address. */ |
| 1333 | static int cheetah_check_main_memory(unsigned long paddr) | 1332 | static int cheetah_check_main_memory(unsigned long paddr) |
| 1334 | { | 1333 | { |
| 1335 | int i; | 1334 | unsigned long vaddr = PAGE_OFFSET + paddr; |
| 1336 | 1335 | ||
| 1337 | for (i = 0; ; i++) { | 1336 | if (vaddr > (unsigned long) high_memory) |
| 1338 | if (sp_banks[i].num_bytes == 0) | 1337 | return 0; |
| 1339 | break; | 1338 | |
| 1340 | if (paddr >= sp_banks[i].base_addr && | 1339 | return kern_addr_valid(vaddr); |
| 1341 | paddr < (sp_banks[i].base_addr + sp_banks[i].num_bytes)) | ||
| 1342 | return 1; | ||
| 1343 | } | ||
| 1344 | return 0; | ||
| 1345 | } | 1340 | } |
| 1346 | 1341 | ||
| 1347 | void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar) | 1342 | void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar) |
| @@ -1596,10 +1591,10 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned | |||
| 1596 | /* OK, usermode access. */ | 1591 | /* OK, usermode access. */ |
| 1597 | recoverable = 1; | 1592 | recoverable = 1; |
| 1598 | } else { | 1593 | } else { |
| 1599 | unsigned long g2 = regs->u_regs[UREG_G2]; | 1594 | const struct exception_table_entry *entry; |
| 1600 | unsigned long fixup = search_extables_range(regs->tpc, &g2); | ||
| 1601 | 1595 | ||
| 1602 | if (fixup != 0UL) { | 1596 | entry = search_exception_tables(regs->tpc); |
| 1597 | if (entry) { | ||
| 1603 | /* OK, kernel access to userspace. */ | 1598 | /* OK, kernel access to userspace. */ |
| 1604 | recoverable = 1; | 1599 | recoverable = 1; |
| 1605 | 1600 | ||
| @@ -1618,9 +1613,8 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned | |||
| 1618 | * recoverable condition. | 1613 | * recoverable condition. |
| 1619 | */ | 1614 | */ |
| 1620 | if (recoverable) { | 1615 | if (recoverable) { |
| 1621 | regs->tpc = fixup; | 1616 | regs->tpc = entry->fixup; |
| 1622 | regs->tnpc = regs->tpc + 4; | 1617 | regs->tnpc = regs->tpc + 4; |
| 1623 | regs->u_regs[UREG_G2] = g2; | ||
| 1624 | } | 1618 | } |
| 1625 | } | 1619 | } |
| 1626 | } | 1620 | } |
