Commit bd59127c authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/home/davem/BK/sparc-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 633afd73 482cf40c
...@@ -625,7 +625,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, ...@@ -625,7 +625,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
* Does the userspace VM want the TID cleared on mm_release()? * Does the userspace VM want the TID cleared on mm_release()?
*/ */
if (clone_flags & CLONE_CLEARTID) if (clone_flags & CLONE_CLEARTID)
p->user_tid = (long *) childregs->edx; p->user_tid = (int *) childregs->edx;
return 0; return 0;
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/sched.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/linkage.h> #include <linux/linkage.h>
......
...@@ -508,6 +508,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, ...@@ -508,6 +508,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
#endif #endif
} }
p->user_tid = NULL;
/* Calculate offset to stack_frame & pt_regs */ /* Calculate offset to stack_frame & pt_regs */
stack_offset = THREAD_SIZE - TRACEREG_SZ; stack_offset = THREAD_SIZE - TRACEREG_SZ;
...@@ -581,6 +583,16 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, ...@@ -581,6 +583,16 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
/* Set the return value for the parent. */ /* Set the return value for the parent. */
regs->u_regs[UREG_I1] = 0; regs->u_regs[UREG_I1] = 0;
if (!(clone_flags & (CLONE_SETTID | CLONE_CLEARTID)))
return 0;
if (clone_flags & CLONE_SETTID)
if (put_user(p->pid, (int *)childregs->u_regs[UREG_G2]))
return -EFAULT;
if (clone_flags & CLONE_CLEARTID)
p->user_tid = (int *) childregs->u_regs[UREG_G2];
return 0; return 0;
} }
...@@ -681,6 +693,8 @@ asmlinkage int sparc_execve(struct pt_regs *regs) ...@@ -681,6 +693,8 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
error = do_execve(filename, (char **) regs->u_regs[base + UREG_I1], error = do_execve(filename, (char **) regs->u_regs[base + UREG_I1],
(char **) regs->u_regs[base + UREG_I2], regs); (char **) regs->u_regs[base + UREG_I2], regs);
putname(filename); putname(filename);
if (error == 0)
current->ptrace &= ~PT_DTRACE;
out: out:
return error; return error;
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/user.h> #include <linux/user.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/security.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -283,11 +284,19 @@ asmlinkage void do_ptrace(struct pt_regs *regs) ...@@ -283,11 +284,19 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
} }
#endif #endif
if(request == PTRACE_TRACEME) { if(request == PTRACE_TRACEME) {
int ret;
/* are we already being traced? */ /* are we already being traced? */
if (current->ptrace & PT_PTRACED) { if (current->ptrace & PT_PTRACED) {
pt_error_return(regs, EPERM); pt_error_return(regs, EPERM);
goto out; goto out;
} }
ret = security_ops->ptrace(current->parent, current);
if (ret) {
pt_error_return(regs, -ret);
goto out;
}
/* set the ptrace bit in the process flags. */ /* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED; current->ptrace |= PT_PTRACED;
pt_succ_return(regs, 0); pt_succ_return(regs, 0);
......
...@@ -10,12 +10,12 @@ ...@@ -10,12 +10,12 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/ptrace.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -7,12 +7,12 @@ ...@@ -7,12 +7,12 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/ptrace.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/random.h> #include <linux/random.h>
......
...@@ -10,12 +10,12 @@ ...@@ -10,12 +10,12 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/ptrace.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/slab.h> #include <linux/slab.h>
......
...@@ -49,7 +49,7 @@ sys_call_table: ...@@ -49,7 +49,7 @@ sys_call_table:
/*140*/ .long sys_sendfile64, sys_nis_syscall, sys_futex, sys_gettid, sys_getrlimit /*140*/ .long sys_sendfile64, sys_nis_syscall, sys_futex, sys_gettid, sys_getrlimit
/*145*/ .long sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write /*145*/ .long sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
/*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 /*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
/*155*/ .long sys_fcntl64, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount /*155*/ .long sys_fcntl64, sys_security, sys_statfs, sys_fstatfs, sys_oldumount
/*160*/ .long sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall /*160*/ .long sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall
/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr /*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
/*170*/ .long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents /*170*/ .long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/sched.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/mman.h> #include <linux/mman.h>
#include <linux/threads.h> #include <linux/threads.h>
......
...@@ -95,7 +95,9 @@ CONFIG_DUMMY_CONSOLE=y ...@@ -95,7 +95,9 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_FB_CYBER2000 is not set # CONFIG_FB_CYBER2000 is not set
# CONFIG_FB_RIVA is not set # CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set # CONFIG_FB_MATROX is not set
# CONFIG_FB_ATY is not set CONFIG_FB_ATY=y
CONFIG_FB_ATY_GX=y
CONFIG_FB_ATY_CT=y
# CONFIG_FB_RADEON is not set # CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set # CONFIG_FB_ATY128 is not set
# CONFIG_FB_SIS is not set # CONFIG_FB_SIS is not set
...@@ -111,9 +113,12 @@ CONFIG_FB_CGSIX=y ...@@ -111,9 +113,12 @@ CONFIG_FB_CGSIX=y
# CONFIG_FB_CGTHREE is not set # CONFIG_FB_CGTHREE is not set
# CONFIG_FB_LEO is not set # CONFIG_FB_LEO is not set
CONFIG_FB_PCI=y CONFIG_FB_PCI=y
# CONFIG_FB_ATY is not set CONFIG_FB_ATY=y
CONFIG_FB_ATY_CT=y
# CONFIG_FB_VIRTUAL is not set # CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set # CONFIG_FBCON_ADVANCED is not set
CONFIG_FBCON_CFB24=y
CONFIG_FBCON_ACCEL=y
CONFIG_FBCON_FONTWIDTH8_ONLY=y CONFIG_FBCON_FONTWIDTH8_ONLY=y
CONFIG_FONT_SUN8x16=y CONFIG_FONT_SUN8x16=y
# CONFIG_FBCON_FONTS is not set # CONFIG_FBCON_FONTS is not set
...@@ -185,79 +190,6 @@ CONFIG_MD_RAID1=m ...@@ -185,79 +190,6 @@ CONFIG_MD_RAID1=m
# CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set # CONFIG_BLK_DEV_INITRD is not set
#
# Networking options
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_NETLINK_DEV=y
# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
CONFIG_ARPD=y
CONFIG_INET_ECN=y
# CONFIG_SYN_COOKIES is not set
CONFIG_IPV6=m
# CONFIG_ATM is not set
CONFIG_VLAN_8021Q=m
#
#
#
CONFIG_IPX=m
# CONFIG_IPX_INTERN is not set
CONFIG_ATALK=m
#
# Appletalk devices
#
# CONFIG_DEV_APPLETALK is not set
CONFIG_DECNET=m
CONFIG_DECNET_SIOCGIFCONF=y
# CONFIG_DECNET_ROUTER is not set
# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
CONFIG_LLC=m
CONFIG_LLC_UI=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
CONFIG_NET_SCH_CSZ=m
CONFIG_NET_SCH_PRIO=m
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFQ=m
CONFIG_NET_SCH_TEQL=m
CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_QOS=y
CONFIG_NET_ESTIMATOR=y
CONFIG_NET_CLS=y
CONFIG_NET_CLS_TCINDEX=m
CONFIG_NET_CLS_ROUTE4=m
CONFIG_NET_CLS_ROUTE=y
CONFIG_NET_CLS_FW=m
CONFIG_NET_CLS_U32=m
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
CONFIG_NET_CLS_POLICE=y
# #
# ATA/ATAPI/MFM/RLL device support # ATA/ATAPI/MFM/RLL device support
# #
...@@ -421,6 +353,71 @@ CONFIG_IEEE1394_CMP=m ...@@ -421,6 +353,71 @@ CONFIG_IEEE1394_CMP=m
CONFIG_IEEE1394_AMDTP=m CONFIG_IEEE1394_AMDTP=m
# CONFIG_IEEE1394_VERBOSEDEBUG is not set # CONFIG_IEEE1394_VERBOSEDEBUG is not set
#
# Networking options
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_NETLINK_DEV=y
# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
CONFIG_ARPD=y
CONFIG_INET_ECN=y
# CONFIG_SYN_COOKIES is not set
CONFIG_IPV6=m
# CONFIG_ATM is not set
CONFIG_VLAN_8021Q=m
CONFIG_LLC=m
CONFIG_LLC_UI=y
CONFIG_IPX=m
# CONFIG_IPX_INTERN is not set
CONFIG_ATALK=m
# CONFIG_DEV_APPLETALK is not set
CONFIG_DECNET=m
CONFIG_DECNET_SIOCGIFCONF=y
# CONFIG_DECNET_ROUTER is not set
# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
CONFIG_NET_SCH_CSZ=m
CONFIG_NET_SCH_PRIO=m
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFQ=m
CONFIG_NET_SCH_TEQL=m
CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_QOS=y
CONFIG_NET_ESTIMATOR=y
CONFIG_NET_CLS=y
CONFIG_NET_CLS_TCINDEX=m
CONFIG_NET_CLS_ROUTE4=m
CONFIG_NET_CLS_ROUTE=y
CONFIG_NET_CLS_FW=m
CONFIG_NET_CLS_U32=m
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
CONFIG_NET_CLS_POLICE=y
# #
# Network device support # Network device support
# #
......
...@@ -424,7 +424,7 @@ static int __init chmc_init(void) ...@@ -424,7 +424,7 @@ static int __init chmc_init(void)
int index; int index;
/* This driver is only for cheetah platforms. */ /* This driver is only for cheetah platforms. */
if (tlb_type != cheetah) if (tlb_type != cheetah && tlb_type != cheetah_plus)
return -ENODEV; return -ENODEV;
index = probe_for_string("memory-controller", 0); index = probe_for_string("memory-controller", 0);
......
...@@ -33,6 +33,7 @@ struct cpu_fp_info linux_sparc_fpu[] = { ...@@ -33,6 +33,7 @@ struct cpu_fp_info linux_sparc_fpu[] = {
{ 0x17, 0x12, 0, "UltraSparc IIi integrated FPU"}, { 0x17, 0x12, 0, "UltraSparc IIi integrated FPU"},
{ 0x17, 0x13, 0, "UltraSparc IIe integrated FPU"}, { 0x17, 0x13, 0, "UltraSparc IIe integrated FPU"},
{ 0x3e, 0x14, 0, "UltraSparc III integrated FPU"}, { 0x3e, 0x14, 0, "UltraSparc III integrated FPU"},
{ 0x3e, 0x15, 0, "UltraSparc III+ integrated FPU"},
}; };
#define NSPARCFPU (sizeof(linux_sparc_fpu)/sizeof(struct cpu_fp_info)) #define NSPARCFPU (sizeof(linux_sparc_fpu)/sizeof(struct cpu_fp_info))
...@@ -44,6 +45,7 @@ struct cpu_iu_info linux_sparc_chips[] = { ...@@ -44,6 +45,7 @@ struct cpu_iu_info linux_sparc_chips[] = {
{ 0x17, 0x12, "TI UltraSparc IIi"}, { 0x17, 0x12, "TI UltraSparc IIi"},
{ 0x17, 0x13, "TI UltraSparc IIe"}, { 0x17, 0x13, "TI UltraSparc IIe"},
{ 0x3e, 0x14, "TI UltraSparc III (Cheetah)"}, { 0x3e, 0x14, "TI UltraSparc III (Cheetah)"},
{ 0x3e, 0x15, "TI UltraSparc III+ (Cheetah+)"},
}; };
#define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info)) #define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info))
......
...@@ -63,7 +63,8 @@ void __init device_scan(void) ...@@ -63,7 +63,8 @@ void __init device_scan(void)
if (tlb_type == spitfire) { if (tlb_type == spitfire) {
prom_getproperty(scan, "upa-portid", prom_getproperty(scan, "upa-portid",
(char *) &thismid, sizeof(thismid)); (char *) &thismid, sizeof(thismid));
} else if (tlb_type == cheetah) { } else if (tlb_type == cheetah ||
tlb_type == cheetah_plus) {
prom_getproperty(scan, "portid", prom_getproperty(scan, "portid",
(char *) &thismid, sizeof(thismid)); (char *) &thismid, sizeof(thismid));
} }
......
...@@ -73,7 +73,7 @@ from_tl1_trap: ...@@ -73,7 +73,7 @@ from_tl1_trap:
CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset
be,pn %xcc, 3f ! Yep, special processing be,pn %xcc, 3f ! Yep, special processing
CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset
cmp %g5, 3 ! Last trap level? cmp %g5, 4 ! Last trap level?
be,pn %xcc, longpath ! Yep, cannot risk VPTE miss be,pn %xcc, longpath ! Yep, cannot risk VPTE miss
nop ! delay slot nop ! delay slot
......
...@@ -774,7 +774,14 @@ __do_instruction_access_exception_tl1: ...@@ -774,7 +774,14 @@ __do_instruction_access_exception_tl1:
membar #Sync membar #Sync
sethi %hi(109f), %g7 sethi %hi(109f), %g7
ba,pt %xcc, etraptl1 ba,pt %xcc, etraptl1
or %g7, %lo(109f), %g7 ! Merge in below 109: or %g7, %lo(109b), %g7
mov %l4, %o1
mov %l5, %o2
call instruction_access_exception_tl1
add %sp, STACK_BIAS + REGWIN_SZ, %o0
ba,pt %xcc, rtrap
clr %l6
__do_instruction_access_exception: __do_instruction_access_exception:
rdpr %pstate, %g4 rdpr %pstate, %g4
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
...@@ -1074,6 +1081,181 @@ cheetah_deferred_trap_vector_tl1: ...@@ -1074,6 +1081,181 @@ cheetah_deferred_trap_vector_tl1:
jmpl %g2 + %lo(cheetah_deferred_trap), %g0 jmpl %g2 + %lo(cheetah_deferred_trap), %g0
mov 1, %g1 mov 1, %g1
/* Cheetah+ specific traps. These are for the new I/D cache parity
* error traps. The first argument to cheetah_plus_parity_handler
* is encoded as follows:
*
* Bit0: 0=dcache,1=icache
* Bit1: 0=recoverable,1=unrecoverable
*/
.globl cheetah_plus_dcpe_trap_vector, cheetah_plus_dcpe_trap_vector_tl1
cheetah_plus_dcpe_trap_vector:
membar #Sync
sethi %hi(do_cheetah_plus_data_parity), %g7
jmpl %g7 + %lo(do_cheetah_plus_data_parity), %g0
nop
nop
nop
nop
nop
do_cheetah_plus_data_parity:
ba,pt %xcc, etrap
rd %pc, %g7
mov 0x0, %o0
call cheetah_plus_parity_error
add %sp, STACK_BIAS + REGWIN_SZ, %o1
ba,pt %xcc, rtrap
clr %l6
cheetah_plus_dcpe_trap_vector_tl1:
membar #Sync
wrpr PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
sethi %hi(do_dcpe_tl1), %g3
jmpl %g3 + %lo(do_dcpe_tl1), %g0
nop
nop
nop
nop
.globl cheetah_plus_icpe_trap_vector, cheetah_plus_icpe_trap_vector_tl1
cheetah_plus_icpe_trap_vector:
membar #Sync
sethi %hi(do_cheetah_plus_insn_parity), %g7
jmpl %g7 + %lo(do_cheetah_plus_insn_parity), %g0
nop
nop
nop
nop
nop
do_cheetah_plus_insn_parity:
ba,pt %xcc, etrap
rd %pc, %g7
mov 0x1, %o0
call cheetah_plus_parity_error
add %sp, STACK_BIAS + REGWIN_SZ, %o1
ba,pt %xcc, rtrap
clr %l6
cheetah_plus_icpe_trap_vector_tl1:
membar #Sync
wrpr PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
sethi %hi(do_icpe_tl1), %g3
jmpl %g3 + %lo(do_icpe_tl1), %g0
nop
nop
nop
nop
/* If we take one of these traps when tl >= 1, then we
* jump to interrupt globals. If some trap level above us
* was also using interrupt globals, we cannot recover.
* We may use all interrupt global registers except %g6.
*/
.globl do_dcpe_tl1, do_icpe_tl1
do_dcpe_tl1:
rdpr %tl, %g1 ! Save original trap level
mov 1, %g2 ! Setup TSTATE checking loop
sethi %hi(TSTATE_IG), %g3 ! TSTATE mask bit
1: wrpr %g2, %tl ! Set trap level to check
rdpr %tstate, %g4 ! Read TSTATE for this level
andcc %g4, %g3, %g0 ! Interrupt globals in use?
bne,a,pn %xcc, do_dcpe_tl1_fatal ! Yep, irrecoverable
wrpr %g1, %tl ! Restore original trap level
add %g2, 1, %g2 ! Next trap level
cmp %g2, %g1 ! Hit them all yet?
ble,pt %icc, 1b ! Not yet
nop
wrpr %g1, %tl ! Restore original trap level
do_dcpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */
/* Reset D-cache parity */
sethi %hi(1 << 16), %g1 ! D-cache size
mov (1 << 5), %g2 ! D-cache line size
sub %g1, %g2, %g1 ! Move down 1 cacheline
1: srl %g1, 14, %g3 ! Compute UTAG
membar #Sync
stxa %g3, [%g1] ASI_DCACHE_UTAG
membar #Sync
sub %g2, 8, %g3 ! 64-bit data word within line
2: membar #Sync
stxa %g0, [%g1 + %g3] ASI_DCACHE_DATA
membar #Sync
subcc %g3, 8, %g3 ! Next 64-bit data word
bge,pt %icc, 2b
nop
subcc %g1, %g2, %g1 ! Next cacheline
bge,pt %icc, 1b
nop
ba,pt %xcc, dcpe_icpe_tl1_common
nop
do_dcpe_tl1_fatal:
sethi %hi(1f), %g7
ba,pt %xcc, etraptl1
1: or %g7, %lo(1b), %g7
mov 0x2, %o0
call cheetah_plus_parity_error
add %sp, STACK_BIAS + REGWIN_SZ, %o1
ba,pt %xcc, rtrap
clr %l6
do_icpe_tl1:
rdpr %tl, %g1 ! Save original trap level
mov 1, %g2 ! Setup TSTATE checking loop
sethi %hi(TSTATE_IG), %g3 ! TSTATE mask bit
1: wrpr %g2, %tl ! Set trap level to check
rdpr %tstate, %g4 ! Read TSTATE for this level
andcc %g4, %g3, %g0 ! Interrupt globals in use?
bne,a,pn %xcc, do_icpe_tl1_fatal ! Yep, irrecoverable
wrpr %g1, %tl ! Restore original trap level
add %g2, 1, %g2 ! Next trap level
cmp %g2, %g1 ! Hit them all yet?
ble,pt %icc, 1b ! Not yet
nop
wrpr %g1, %tl ! Restore original trap level
do_icpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */
/* Flush I-cache */
sethi %hi(1 << 15), %g1 ! I-cache size
mov (1 << 5), %g2 ! I-cache line size
sub %g1, %g2, %g1
1: or %g1, (2 << 3), %g3
stxa %g0, [%g3] ASI_IC_TAG
membar #Sync
subcc %g1, %g2, %g1
bge,pt %icc, 1b
nop
ba,pt %xcc, dcpe_icpe_tl1_common
nop
do_icpe_tl1_fatal:
sethi %hi(1f), %g7
ba,pt %xcc, etraptl1
1: or %g7, %lo(1b), %g7
mov 0x3, %o0
call cheetah_plus_parity_error
add %sp, STACK_BIAS + REGWIN_SZ, %o1
ba,pt %xcc, rtrap
clr %l6
dcpe_icpe_tl1_common:
/* Flush D-cache, re-enable D/I caches in DCU and finally
* retry the trapping instruction.
*/
sethi %hi(1 << 16), %g1 ! D-cache size
mov (1 << 5), %g2 ! D-cache line size
sub %g1, %g2, %g1
1: stxa %g0, [%g1] ASI_DCACHE_TAG
membar #Sync
subcc %g1, %g2, %g1
bge,pt %icc, 1b
nop
ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
or %g1, (DCU_DC | DCU_IC), %g1
stxa %g1, [%g0] ASI_DCU_CONTROL_REG
membar #Sync
retry
/* Cheetah FECC trap handling, we get here from tl{0,1}_fecc /* Cheetah FECC trap handling, we get here from tl{0,1}_fecc
* in the trap table. That code has done a memory barrier * in the trap table. That code has done a memory barrier
* and has disabled both the I-cache and D-cache in the DCU * and has disabled both the I-cache and D-cache in the DCU
...@@ -1639,12 +1821,17 @@ do_gettimeofday: /* %o0 = timevalp */ ...@@ -1639,12 +1821,17 @@ do_gettimeofday: /* %o0 = timevalp */
or %g2, %lo(xtime), %g2 or %g2, %lo(xtime), %g2
or %g1, %lo(timer_tick_compare), %g1 or %g1, %lo(timer_tick_compare), %g1
1: rdpr %ver, %o2 1: rdpr %ver, %o2
sethi %hi(0x003e0014), %o1 sethi %hi(CHEETAH_ID), %o1
srlx %o2, 32, %o2 srlx %o2, 32, %o2
or %o1, %lo(0x003e0014), %o1 or %o1, %lo(CHEETAH_ID), %o1
membar #Sync membar #Sync
ldda [%g2] ASI_NUCLEUS_QUAD_LDD, %o4 ldda [%g2] ASI_NUCLEUS_QUAD_LDD, %o4
cmp %o2, %o1 cmp %o2, %o1
be,a,pn %xcc, 3f
rd %asr24, %o1
sethi %hi(CHEETAH_PLUS_ID), %o1
or %o1, %lo(CHEETAH_PLUS_ID), %o1
cmp %o2, %o1
bne,pt %xcc, 2f bne,pt %xcc, 2f
nop nop
ba,pt %xcc, 3f ba,pt %xcc, 3f
......
...@@ -109,8 +109,56 @@ etrap_irq: ...@@ -109,8 +109,56 @@ etrap_irq:
stb %g0, [%l4 + %l3] ! Store Group stb %g0, [%l4 + %l3] ! Store Group
nop nop
etraptl1: rdpr %tstate, %g1 ! Single Group+4bubbles etraptl1: /* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself.
sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ! IEU1 * We place this right after pt_regs on the trap stack. The layout
* is:
* 0x00 TL1's TSTATE
* 0x08 TL1's TPC
* 0x10 TL1's TNPC
* ...
* 0x58 TL4's TNPC
* 0x60 TL
*/
sub %sp, (24 * 8) + 8, %g2
rdpr %tl, %g1
wrpr %g0, 1, %tl
rdpr %tstate, %g3
stx %g3, [%g2 + STACK_BIAS + 0x00]
rdpr %tpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x08]
rdpr %tnpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x10]
wrpr %g0, 2, %tl
rdpr %tstate, %g3
stx %g3, [%g2 + STACK_BIAS + 0x18]
rdpr %tpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x20]
rdpr %tnpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x28]
wrpr %g0, 3, %tl
rdpr %tstate, %g3
stx %g3, [%g2 + STACK_BIAS + 0x30]
rdpr %tpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x38]
rdpr %tnpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x40]
wrpr %g0, 4, %tl
rdpr %tstate, %g3
stx %g3, [%g2 + STACK_BIAS + 0x48]
rdpr %tpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x50]
rdpr %tnpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x58]
wrpr %g1, %tl
stx %g1, [%g2 + STACK_BIAS + 0x60]
rdpr %tstate, %g1 ! Single Group+4bubbles
sub %g2, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ! IEU1
ba,pt %xcc, 1b ! CTI Group ba,pt %xcc, 1b ! CTI Group
andcc %g1, TSTATE_PRIV, %g0 ! IEU0 andcc %g1, TSTATE_PRIV, %g0 ! IEU0
......
...@@ -79,24 +79,34 @@ sparc_ramdisk_size: ...@@ -79,24 +79,34 @@ sparc_ramdisk_size:
*/ */
sparc64_boot: sparc64_boot:
rdpr %ver, %g1 rdpr %ver, %g1
sethi %hi(0x003e0014), %g5 sethi %hi(CHEETAH_ID), %g5
srlx %g1, 32, %g1 srlx %g1, 32, %g1
or %g5, %lo(0x003e0014), %g5 or %g5, %lo(CHEETAH_ID), %g5
cmp %g1, %g5
be,pn %icc, cheetah_boot
sethi %hi(CHEETAH_PLUS_ID), %g5
or %g5, %lo(CHEETAH_PLUS_ID), %g5
cmp %g1, %g5 cmp %g1, %g5
bne,pt %icc, spitfire_boot bne,pt %icc, spitfire_boot
nop nop
cheetah_plus_boot:
/* Preserve OBP choosen DCU and DCR register settings. */
ba,pt %xcc, cheetah_generic_boot
nop
cheetah_boot: cheetah_boot:
mov DCR_BPE | DCR_RPE | DCR_SI | DCR_IFPOE | DCR_MS, %g1 mov DCR_BPE | DCR_RPE | DCR_SI | DCR_IFPOE | DCR_MS, %g1
wr %g1, %asr18 wr %g1, %asr18
sethi %uhi(DCU_ME | DCU_RE | /*DCU_PE |*/ DCU_HPE | DCU_SPE | DCU_SL | DCU_WE), %g5 sethi %uhi(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g5
or %g5, %ulo(DCU_ME | DCU_RE | /*DCU_PE |*/ DCU_HPE | DCU_SPE | DCU_SL | DCU_WE), %g5 or %g5, %ulo(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g5
sllx %g5, 32, %g5 sllx %g5, 32, %g5
or %g5, DCU_DM | DCU_IM | DCU_DC | DCU_IC, %g5 or %g5, DCU_DM | DCU_IM | DCU_DC | DCU_IC, %g5
stxa %g5, [%g0] ASI_DCU_CONTROL_REG stxa %g5, [%g0] ASI_DCU_CONTROL_REG
membar #Sync membar #Sync
cheetah_generic_boot:
mov TSB_EXTENSION_P, %g3 mov TSB_EXTENSION_P, %g3
stxa %g0, [%g3] ASI_DMMU stxa %g0, [%g3] ASI_DMMU
stxa %g0, [%g3] ASI_IMMU stxa %g0, [%g3] ASI_IMMU
...@@ -149,6 +159,7 @@ cheetah_boot: ...@@ -149,6 +159,7 @@ cheetah_boot:
add %l0, (1 << 3), %l0 add %l0, (1 << 3), %l0
cheetah_got_tlbentry: cheetah_got_tlbentry:
ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g0
ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1 ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1
membar #Sync membar #Sync
and %g1, %g3, %g1 and %g1, %g3, %g1
...@@ -200,6 +211,36 @@ cheetah_got_tlbentry: ...@@ -200,6 +211,36 @@ cheetah_got_tlbentry:
blu,pt %xcc, 1b blu,pt %xcc, 1b
add %l0, (1 << 3), %l0 add %l0, (1 << 3), %l0
/* On Cheetah+, have to check second DTLB. */
rdpr %ver, %g1
srlx %g1, 32, %g1
sethi %hi(CHEETAH_PLUS_ID), %l0
or %l0, %lo(CHEETAH_PLUS_ID), %l0
cmp %g1, %l0
bne,pt %icc, 9f
nop
set 3 << 16, %l0
1: ldxa [%l0] ASI_DTLB_TAG_READ, %g1
membar #Sync
andn %g1, %l2, %g1
cmp %g1, %g3
blu,pn %xcc, 2f
cmp %g1, %g7
bgeu,pn %xcc, 2f
nop
stxa %g0, [%l7] ASI_DMMU
membar #Sync
stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS
membar #Sync
2: and %l0, (511 << 3), %g1
cmp %g1, (511 << 3)
blu,pt %xcc, 1b
add %l0, (1 << 3), %l0
9:
/* Now lock the TTE we created into ITLB-0 and DTLB-0, /* Now lock the TTE we created into ITLB-0 and DTLB-0,
* entry 15 (and maybe 14 too). * entry 15 (and maybe 14 too).
*/ */
...@@ -429,20 +470,26 @@ sun4u_init: ...@@ -429,20 +470,26 @@ sun4u_init:
membar #Sync membar #Sync
rdpr %ver, %g1 rdpr %ver, %g1
sethi %hi(0x003e0014), %g5 sethi %hi(CHEETAH_ID), %g5
srlx %g1, 32, %g1 srlx %g1, 32, %g1
or %g5, %lo(0x003e0014), %g5 or %g5, %lo(CHEETAH_ID), %g5
cmp %g1, %g5
be,pn %icc, cheetah_tlb_fixup
sethi %hi(CHEETAH_PLUS_ID), %g5
or %g5, %lo(CHEETAH_PLUS_ID), %g5
cmp %g1, %g5 cmp %g1, %g5
bne,pt %icc, spitfire_tlb_fixup bne,pt %icc, spitfire_tlb_fixup
nop nop
cheetah_tlb_fixup: cheetah_tlb_fixup:
set (0 << 16) | (15 << 3), %g7 set (0 << 16) | (15 << 3), %g7
ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g0
ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1 ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1
andn %g1, (_PAGE_G), %g1 andn %g1, (_PAGE_G), %g1
stxa %g1, [%g7] ASI_ITLB_DATA_ACCESS stxa %g1, [%g7] ASI_ITLB_DATA_ACCESS
membar #Sync membar #Sync
ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g0
ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g1 ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g1
andn %g1, (_PAGE_G), %g1 andn %g1, (_PAGE_G), %g1
stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS
...@@ -452,9 +499,17 @@ cheetah_tlb_fixup: ...@@ -452,9 +499,17 @@ cheetah_tlb_fixup:
flush %g3 flush %g3
membar #Sync membar #Sync
/* Set TLB type to cheetah. */ sethi %hi(CHEETAH_PLUS_ID), %g5
mov 1, %g2 or %g5, %lo(CHEETAH_PLUS_ID), %g5
sethi %hi(tlb_type), %g5 rdpr %ver, %g2
srlx %g2, 32, %g2
cmp %g2, %g5
bne,a,pt %icc, 1f
mov 1, %g2 /* Set TLB type to cheetah. */
mov 2, %g2 /* Set TLB type to cheetah+. */
1: sethi %hi(tlb_type), %g5
stw %g2, [%g5 + %lo(tlb_type)] stw %g2, [%g5 + %lo(tlb_type)]
/* Patch copy/page operations to cheetah optimized versions. */ /* Patch copy/page operations to cheetah optimized versions. */
...@@ -462,6 +517,8 @@ cheetah_tlb_fixup: ...@@ -462,6 +517,8 @@ cheetah_tlb_fixup:
nop nop
call cheetah_patch_pgcopyops call cheetah_patch_pgcopyops
nop nop
call cheetah_patch_cachetlbops
nop
ba,pt %xcc, tlb_fixup_done ba,pt %xcc, tlb_fixup_done
nop nop
...@@ -575,18 +632,23 @@ setup_tba: /* i0 = is_starfire */ ...@@ -575,18 +632,23 @@ setup_tba: /* i0 = is_starfire */
or %g2, KERN_LOWBITS, %g2 or %g2, KERN_LOWBITS, %g2
rdpr %ver, %g3 rdpr %ver, %g3
sethi %hi(0x003e0014), %g7 sethi %hi(CHEETAH_ID), %g7
srlx %g3, 32, %g3 srlx %g3, 32, %g3
or %g7, %lo(0x003e0014), %g7 or %g7, %lo(CHEETAH_ID), %g7
cmp %g3, %g7
be,pn %icc, cheetah_vpte_base
sethi %hi(CHEETAH_PLUS_ID), %g7
or %g7, %lo(CHEETAH_PLUS_ID), %g7
cmp %g3, %g7 cmp %g3, %g7
bne,pt %icc, 1f bne,pt %icc, spitfire_vpte_base
nop nop
cheetah_vpte_base:
sethi %uhi(VPTE_BASE_CHEETAH), %g3 sethi %uhi(VPTE_BASE_CHEETAH), %g3
or %g3, %ulo(VPTE_BASE_CHEETAH), %g3 or %g3, %ulo(VPTE_BASE_CHEETAH), %g3
ba,pt %xcc, 2f ba,pt %xcc, 2f
sllx %g3, 32, %g3 sllx %g3, 32, %g3
1: spitfire_vpte_base:
sethi %uhi(VPTE_BASE_SPITFIRE), %g3 sethi %uhi(VPTE_BASE_SPITFIRE), %g3
or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3 or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3
sllx %g3, 32, %g3 sllx %g3, 32, %g3
...@@ -614,13 +676,18 @@ setup_tba: /* i0 = is_starfire */ ...@@ -614,13 +676,18 @@ setup_tba: /* i0 = is_starfire */
not_starfire: not_starfire:
rdpr %ver, %g1 rdpr %ver, %g1
sethi %hi(0x003e0014), %g5 sethi %hi(CHEETAH_ID), %g5
srlx %g1, 32, %g1 srlx %g1, 32, %g1
or %g7, %lo(0x003e0014), %g5 or %g5, %lo(CHEETAH_ID), %g5
cmp %g1, %g5
be,pn %icc, is_cheetah
sethi %hi(CHEETAH_PLUS_ID), %g5
or %g5, %lo(CHEETAH_PLUS_ID), %g5
cmp %g1, %g5 cmp %g1, %g5
bne,pt %icc, not_cheetah bne,pt %icc, not_cheetah
nop nop
is_cheetah:
ldxa [%g0] ASI_SAFARI_CONFIG, %g1 ldxa [%g0] ASI_SAFARI_CONFIG, %g1
srlx %g1, 17, %g1 srlx %g1, 17, %g1
ba,pt %xcc, set_worklist ba,pt %xcc, set_worklist
...@@ -644,14 +711,19 @@ set_worklist: ...@@ -644,14 +711,19 @@ set_worklist:
wr %g0, 0, %tick_cmpr wr %g0, 0, %tick_cmpr
rdpr %ver, %g1 rdpr %ver, %g1
sethi %hi(0x003e0014), %g5 sethi %hi(CHEETAH_ID), %g5
srlx %g1, 32, %g1 srlx %g1, 32, %g1
or %g7, %lo(0x003e0014), %g5 or %g5, %lo(CHEETAH_ID), %g5
cmp %g1, %g5 cmp %g1, %g5
bne,pt %icc, 1f be,pn %icc, 1f
sethi %hi(CHEETAH_PLUS_ID), %g5
or %g5, %lo(CHEETAH_PLUS_ID), %g5
cmp %g1, %g5
bne,pt %icc, 2f
nop nop
/* Disable STICK_INT interrupts. */ /* Disable STICK_INT interrupts. */
1:
sethi %hi(0x80000000), %g1 sethi %hi(0x80000000), %g1
sllx %g1, 32, %g1 sllx %g1, 32, %g1
wr %g1, %asr25 wr %g1, %asr25
...@@ -659,7 +731,7 @@ set_worklist: ...@@ -659,7 +731,7 @@ set_worklist:
/* Ok, we're done setting up all the state our trap mechanims needs, /* Ok, we're done setting up all the state our trap mechanims needs,
* now get back into normal globals and let the PROM know what is up. * now get back into normal globals and let the PROM know what is up.
*/ */
1: 2:
wrpr %g0, %g0, %wstate wrpr %g0, %g0, %wstate
wrpr %o1, PSTATE_IE, %pstate wrpr %o1, PSTATE_IE, %pstate
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/sched.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
...@@ -162,7 +163,7 @@ void enable_irq(unsigned int irq) ...@@ -162,7 +163,7 @@ void enable_irq(unsigned int irq)
if (imap == 0UL) if (imap == 0UL)
return; return;
if (tlb_type == cheetah) { if (tlb_type == cheetah || tlb_type == cheetah_plus) {
/* We set it to our Safari AID. */ /* We set it to our Safari AID. */
__asm__ __volatile__("ldxa [%%g0] %1, %0" __asm__ __volatile__("ldxa [%%g0] %1, %0"
: "=r" (tid) : "=r" (tid)
...@@ -1068,7 +1069,7 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu) ...@@ -1068,7 +1069,7 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu)
goal_cpu = 0; goal_cpu = 0;
} }
if (tlb_type == cheetah) { if (tlb_type == cheetah || tlb_type == cheetah_plus) {
tid = goal_cpu << 26; tid = goal_cpu << 26;
tid &= IMAP_AID_SAFARI; tid &= IMAP_AID_SAFARI;
} else if (this_is_starfire == 0) { } else if (this_is_starfire == 0) {
......
...@@ -591,6 +591,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, ...@@ -591,6 +591,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
p->thread.smp_lock_pc = 0; p->thread.smp_lock_pc = 0;
#endif #endif
p->user_tid = NULL;
/* Calculate offset to stack_frame & pt_regs */ /* Calculate offset to stack_frame & pt_regs */
child_trap_frame = ((char *)t) + (THREAD_SIZE - (TRACEREG_SZ+REGWIN_SZ)); child_trap_frame = ((char *)t) + (THREAD_SIZE - (TRACEREG_SZ+REGWIN_SZ));
memcpy(child_trap_frame, (((struct reg_window *)regs)-1), (TRACEREG_SZ+REGWIN_SZ)); memcpy(child_trap_frame, (((struct reg_window *)regs)-1), (TRACEREG_SZ+REGWIN_SZ));
...@@ -647,6 +649,19 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, ...@@ -647,6 +649,19 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
/* Set the second return value for the parent. */ /* Set the second return value for the parent. */
regs->u_regs[UREG_I1] = 0; regs->u_regs[UREG_I1] = 0;
if (!(clone_flags & (CLONE_SETTID | CLONE_CLEARTID)))
return 0;
if (t->flags & _TIF_32BIT)
t->kregs->u_regs[UREG_G2] &= 0xffffffff;
if (clone_flags & CLONE_SETTID)
if (put_user(p->pid, (int *)t->kregs->u_regs[UREG_G2]))
return -EFAULT;
if (clone_flags & CLONE_CLEARTID)
p->user_tid = (int *) t->kregs->u_regs[UREG_G2];
return 0; return 0;
} }
...@@ -791,6 +806,7 @@ asmlinkage int sparc_execve(struct pt_regs *regs) ...@@ -791,6 +806,7 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
current_thread_info()->xfsr[0] = 0; current_thread_info()->xfsr[0] = 0;
current_thread_info()->fpsaved[0] = 0; current_thread_info()->fpsaved[0] = 0;
regs->tstate &= ~TSTATE_PEF; regs->tstate &= ~TSTATE_PEF;
current->ptrace &= ~PT_DTRACE;
} }
out: out:
return error; return error;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/user.h> #include <linux/user.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/security.h>
#include <asm/asi.h> #include <asm/asi.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
...@@ -132,11 +133,19 @@ asmlinkage void do_ptrace(struct pt_regs *regs) ...@@ -132,11 +133,19 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
} }
#endif #endif
if (request == PTRACE_TRACEME) { if (request == PTRACE_TRACEME) {
int ret;
/* are we already being traced? */ /* are we already being traced? */
if (current->ptrace & PT_PTRACED) { if (current->ptrace & PT_PTRACED) {
pt_error_return(regs, EPERM); pt_error_return(regs, EPERM);
goto out; goto out;
} }
ret = security_ops->ptrace(current->parent, current);
if (ret) {
pt_error_return(regs, -ret);
goto out;
}
/* set the ptrace bit in the process flags. */ /* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED; current->ptrace |= PT_PTRACED;
pt_succ_return(regs, 0); pt_succ_return(regs, 0);
...@@ -570,7 +579,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) ...@@ -570,7 +579,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
{ {
unsigned long va; unsigned long va;
if (tlb_type == cheetah) { if (tlb_type == cheetah || tlb_type == cheetah_plus) {
for (va = 0; va < (1 << 16); va += (1 << 5)) for (va = 0; va < (1 << 16); va += (1 << 5))
spitfire_put_dcache_tag(va, 0x0); spitfire_put_dcache_tag(va, 0x0);
/* No need to mess with I-cache on Cheetah. */ /* No need to mess with I-cache on Cheetah. */
......
...@@ -193,7 +193,7 @@ int prom_callback(long *args) ...@@ -193,7 +193,7 @@ int prom_callback(long *args)
if (tlb_type == spitfire) if (tlb_type == spitfire)
tte = spitfire_get_dtlb_data(SPITFIRE_HIGHEST_LOCKED_TLBENT); tte = spitfire_get_dtlb_data(SPITFIRE_HIGHEST_LOCKED_TLBENT);
else if (tlb_type == cheetah) else if (tlb_type == cheetah || tlb_type == cheetah_plus)
tte = cheetah_get_ldtlb_data(CHEETAH_HIGHEST_LOCKED_TLBENT); tte = cheetah_get_ldtlb_data(CHEETAH_HIGHEST_LOCKED_TLBENT);
res = PROM_TRUE; res = PROM_TRUE;
...@@ -506,7 +506,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -506,7 +506,7 @@ void __init setup_arch(char **cmdline_p)
extern unsigned int irqsz_patchme[1]; extern unsigned int irqsz_patchme[1];
irqsz_patchme[0] |= ((i == SMP_CACHE_BYTES) ? SMP_CACHE_BYTES_SHIFT : \ irqsz_patchme[0] |= ((i == SMP_CACHE_BYTES) ? SMP_CACHE_BYTES_SHIFT : \
SMP_CACHE_BYTES_SHIFT + 1); SMP_CACHE_BYTES_SHIFT + 1);
flushi((long)&irqsz_patchme[1]); flushi((long)&irqsz_patchme[0]);
} else { } else {
prom_printf("Unexpected size of irq_stat[] elements\n"); prom_printf("Unexpected size of irq_stat[] elements\n");
prom_halt(); prom_halt();
......
...@@ -558,9 +558,9 @@ extern unsigned long xcall_flush_tlb_page; ...@@ -558,9 +558,9 @@ extern unsigned long xcall_flush_tlb_page;
extern unsigned long xcall_flush_tlb_mm; extern unsigned long xcall_flush_tlb_mm;
extern unsigned long xcall_flush_tlb_range; extern unsigned long xcall_flush_tlb_range;
extern unsigned long xcall_flush_tlb_kernel_range; extern unsigned long xcall_flush_tlb_kernel_range;
extern unsigned long xcall_flush_tlb_all; extern unsigned long xcall_flush_tlb_all_spitfire;
extern unsigned long xcall_tlbcachesync; extern unsigned long xcall_flush_tlb_all_cheetah;
extern unsigned long xcall_flush_cache_all; extern unsigned long xcall_flush_cache_all_spitfire;
extern unsigned long xcall_report_regs; extern unsigned long xcall_report_regs;
extern unsigned long xcall_receive_signal; extern unsigned long xcall_receive_signal;
extern unsigned long xcall_flush_dcache_page_cheetah; extern unsigned long xcall_flush_dcache_page_cheetah;
...@@ -676,13 +676,19 @@ void smp_report_regs(void) ...@@ -676,13 +676,19 @@ void smp_report_regs(void)
void smp_flush_cache_all(void) void smp_flush_cache_all(void)
{ {
smp_cross_call(&xcall_flush_cache_all, 0, 0, 0); /* Cheetah need do nothing. */
__flush_cache_all(); if (tlb_type == spitfire) {
smp_cross_call(&xcall_flush_cache_all_spitfire, 0, 0, 0);
__flush_cache_all();
}
} }
void smp_flush_tlb_all(void) void smp_flush_tlb_all(void)
{ {
smp_cross_call(&xcall_flush_tlb_all, 0, 0, 0); if (tlb_type == spitfire)
smp_cross_call(&xcall_flush_tlb_all_spitfire, 0, 0, 0);
else
smp_cross_call(&xcall_flush_tlb_all_cheetah, 0, 0, 0);
__flush_tlb_all(); __flush_tlb_all();
} }
...@@ -1115,7 +1121,7 @@ static void __init smp_tune_scheduling(void) ...@@ -1115,7 +1121,7 @@ static void __init smp_tune_scheduling(void)
* of moving a process from one cpu to another). * of moving a process from one cpu to another).
*/ */
printk("SMP: Calibrating ecache flush... "); printk("SMP: Calibrating ecache flush... ");
if (tlb_type == cheetah) { if (tlb_type == cheetah || tlb_type == cheetah_plus) {
cacheflush_time = cheetah_tune_scheduling(); cacheflush_time = cheetah_tune_scheduling();
goto report; goto report;
} }
......
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/fpumacro.h> #include <asm/fpumacro.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <asm/mmu_context.h>
#include <net/scm.h> #include <net/scm.h>
...@@ -2873,26 +2874,30 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) ...@@ -2873,26 +2874,30 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
int retval; int retval;
int i; int i;
bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
file = open_exec(filename); file = open_exec(filename);
retval = PTR_ERR(file); retval = PTR_ERR(file);
if (IS_ERR(file)) if (IS_ERR(file))
return retval; return retval;
bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
bprm.file = file; bprm.file = file;
bprm.filename = filename; bprm.filename = filename;
bprm.sh_bang = 0; bprm.sh_bang = 0;
bprm.loader = 0; bprm.loader = 0;
bprm.exec = 0; bprm.exec = 0;
bprm.security = NULL;
bprm.mm = mm_alloc(); bprm.mm = mm_alloc();
retval = -ENOMEM; retval = -ENOMEM;
if (!bprm.mm) if (!bprm.mm)
goto out_file; goto out_file;
retval = init_new_context(current, bprm.mm);
if (retval < 0)
goto out_mm;
bprm.argc = count32(argv, bprm.p / sizeof(u32)); bprm.argc = count32(argv, bprm.p / sizeof(u32));
if ((retval = bprm.argc) < 0) if ((retval = bprm.argc) < 0)
goto out_mm; goto out_mm;
...@@ -2901,6 +2906,10 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) ...@@ -2901,6 +2906,10 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
if ((retval = bprm.envc) < 0) if ((retval = bprm.envc) < 0)
goto out_mm; goto out_mm;
retval = security_ops->bprm_alloc_security(&bprm);
if (retval)
goto out;
retval = prepare_binprm(&bprm); retval = prepare_binprm(&bprm);
if (retval < 0) if (retval < 0)
goto out; goto out;
...@@ -2919,9 +2928,11 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) ...@@ -2919,9 +2928,11 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
goto out; goto out;
retval = search_binary_handler(&bprm, regs); retval = search_binary_handler(&bprm, regs);
if (retval >= 0) if (retval >= 0) {
/* execve success */ /* execve success */
security_ops->bprm_free_security(&bprm);
return retval; return retval;
}
out: out:
/* Something went wrong, return the inode and free the argument pages*/ /* Something went wrong, return the inode and free the argument pages*/
...@@ -2931,6 +2942,9 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) ...@@ -2931,6 +2942,9 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
__free_page(page); __free_page(page);
} }
if (bprm.security)
security_ops->bprm_free_security(&bprm);
out_mm: out_mm:
mmdrop(bprm.mm); mmdrop(bprm.mm);
...@@ -2971,6 +2985,7 @@ asmlinkage int sparc32_execve(struct pt_regs *regs) ...@@ -2971,6 +2985,7 @@ asmlinkage int sparc32_execve(struct pt_regs *regs)
current_thread_info()->xfsr[0] = 0; current_thread_info()->xfsr[0] = 0;
current_thread_info()->fpsaved[0] = 0; current_thread_info()->fpsaved[0] = 0;
regs->tstate &= ~TSTATE_PEF; regs->tstate &= ~TSTATE_PEF;
current->ptrace &= ~PT_DTRACE;
} }
out: out:
return error; return error;
......
...@@ -50,7 +50,7 @@ sys_call_table32: ...@@ -50,7 +50,7 @@ sys_call_table32:
/*140*/ .word sys32_sendfile64, sys_nis_syscall, sys_futex, sys_gettid, sys32_getrlimit /*140*/ .word sys32_sendfile64, sys_nis_syscall, sys_futex, sys_gettid, sys32_getrlimit
.word sys32_setrlimit, sys_pivot_root, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write .word sys32_setrlimit, sys_pivot_root, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write
/*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
.word sys32_fcntl64, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount .word sys32_fcntl64, sys_security, sys32_statfs, sys32_fstatfs, sys_oldumount
/*160*/ .word sys32_sched_setaffinity, sys32_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall /*160*/ .word sys32_sched_setaffinity, sys32_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall
.word sys_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_setxattr .word sys_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_setxattr
/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents
...@@ -109,7 +109,7 @@ sys_call_table: ...@@ -109,7 +109,7 @@ sys_call_table:
/*140*/ .word sys_sendfile64, sys_getpeername, sys_futex, sys_gettid, sys_getrlimit /*140*/ .word sys_sendfile64, sys_getpeername, sys_futex, sys_gettid, sys_getrlimit
.word sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write .word sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
/*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 /*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
.word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount .word sys_nis_syscall, sys_security, sys_statfs, sys_fstatfs, sys_oldumount
/*160*/ .word sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_utrap_install /*160*/ .word sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_utrap_install
.word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
......
...@@ -34,13 +34,22 @@ sparc64_cpu_startup: ...@@ -34,13 +34,22 @@ sparc64_cpu_startup:
flushw flushw
rdpr %ver, %g1 rdpr %ver, %g1
sethi %hi(0x003e0014), %g5 sethi %hi(CHEETAH_ID), %g5
srlx %g1, 32, %g1 srlx %g1, 32, %g1
or %g5, %lo(0x003e0014), %g5 or %g5, %lo(CHEETAH_ID), %g5
cmp %g1, %g5
be,pn %icc, cheetah_startup
sethi %hi(CHEETAH_PLUS_ID), %g5
or %g5, %lo(CHEETAH_PLUS_ID), %g5
cmp %g1, %g5 cmp %g1, %g5
bne,pt %icc, spitfire_startup bne,pt %icc, spitfire_startup
nop nop
cheetah_plus_startup:
/* Preserve OBP choosen DCU and DCR register settings. */
ba,pt %xcc, cheetah_generic_startup
nop
cheetah_startup: cheetah_startup:
mov DCR_BPE | DCR_RPE | DCR_SI | DCR_IFPOE | DCR_MS, %g1 mov DCR_BPE | DCR_RPE | DCR_SI | DCR_IFPOE | DCR_MS, %g1
wr %g1, %asr18 wr %g1, %asr18
...@@ -52,6 +61,7 @@ cheetah_startup: ...@@ -52,6 +61,7 @@ cheetah_startup:
stxa %g5, [%g0] ASI_DCU_CONTROL_REG stxa %g5, [%g0] ASI_DCU_CONTROL_REG
membar #Sync membar #Sync
cheetah_generic_startup:
mov TSB_EXTENSION_P, %g3 mov TSB_EXTENSION_P, %g3
stxa %g0, [%g3] ASI_DMMU stxa %g0, [%g3] ASI_DMMU
stxa %g0, [%g3] ASI_IMMU stxa %g0, [%g3] ASI_IMMU
...@@ -118,9 +128,14 @@ startup_continue: ...@@ -118,9 +128,14 @@ startup_continue:
stx %g2, [%sp + 2047 + 128 + 0x30] stx %g2, [%sp + 2047 + 128 + 0x30]
rdpr %ver, %g1 rdpr %ver, %g1
sethi %hi(0x003e0014), %g5 sethi %hi(CHEETAH_ID), %g5
srlx %g1, 32, %g1 srlx %g1, 32, %g1
or %g5, %lo(0x003e0014), %g5 or %g5, %lo(CHEETAH_ID), %g5
cmp %g1, %g5
be,a,pn %icc, 1f
mov 15, %g2
sethi %hi(CHEETAH_PLUS_ID), %g5
or %g5, %lo(CHEETAH_PLUS_ID), %g5
cmp %g1, %g5 cmp %g1, %g5
bne,a,pt %icc, 1f bne,a,pt %icc, 1f
mov 63, %g2 mov 63, %g2
...@@ -153,9 +168,14 @@ startup_continue: ...@@ -153,9 +168,14 @@ startup_continue:
stx %g2, [%sp + 2047 + 128 + 0x30] stx %g2, [%sp + 2047 + 128 + 0x30]
rdpr %ver, %g1 rdpr %ver, %g1
sethi %hi(0x003e0014), %g5 sethi %hi(CHEETAH_ID), %g5
srlx %g1, 32, %g1 srlx %g1, 32, %g1
or %g5, %lo(0x003e0014), %g5 or %g5, %lo(CHEETAH_ID), %g5
cmp %g1, %g5
be,a,pn %icc, 1f
mov 15, %g2
sethi %hi(CHEETAH_PLUS_ID), %g5
or %g5, %lo(CHEETAH_PLUS_ID), %g5
cmp %g1, %g5 cmp %g1, %g5
bne,a,pt %icc, 1f bne,a,pt %icc, 1f
mov 63, %g2 mov 63, %g2
...@@ -225,13 +245,18 @@ startup_continue: ...@@ -225,13 +245,18 @@ startup_continue:
or %g2, KERN_LOWBITS, %g2 or %g2, KERN_LOWBITS, %g2
rdpr %ver, %g3 rdpr %ver, %g3
sethi %hi(0x003e0014), %g7 sethi %hi(CHEETAH_ID), %g7
srlx %g3, 32, %g3 srlx %g3, 32, %g3
or %g7, %lo(0x003e0014), %g7 or %g7, %lo(CHEETAH_ID), %g7
cmp %g3, %g7
be,pn %icc, 9f
sethi %hi(CHEETAH_PLUS_ID), %g7
or %g7, %lo(CHEETAH_PLUS_ID), %g7
cmp %g3, %g7 cmp %g3, %g7
bne,pt %icc, 1f bne,pt %icc, 1f
nop nop
9:
sethi %uhi(VPTE_BASE_CHEETAH), %g3 sethi %uhi(VPTE_BASE_CHEETAH), %g3
or %g3, %ulo(VPTE_BASE_CHEETAH), %g3 or %g3, %ulo(VPTE_BASE_CHEETAH), %g3
ba,pt %xcc, 2f ba,pt %xcc, 2f
......
...@@ -37,6 +37,33 @@ ...@@ -37,6 +37,33 @@
#include <linux/kmod.h> #include <linux/kmod.h>
#endif #endif
/* When an irrecoverable trap occurs at tl > 0, the trap entry
* code logs the trap state registers at every level in the trap
* stack. It is found at (pt_regs + sizeof(pt_regs)) and the layout
* is as follows:
*/
struct tl1_traplog {
struct {
unsigned long tstate;
unsigned long tpc;
unsigned long tnpc;
} trapstack[4];
unsigned long tl;
};
static void dump_tl1_traplog(struct tl1_traplog *p)
{
int i;
printk("TRAPLOG: Error at trap level 0x%lx, dumping track stack.\n",
p->tl);
for (i = 0; i < 4; i++) {
printk("TRAPLOG: Trap level %d TSTATE[%016lx] TPC[%016lx] TNPC[%016lx]\n",
i + 1,
p->trapstack[i].tstate, p->trapstack[i].tpc, p->trapstack[i].tnpc);
}
}
void bad_trap (struct pt_regs *regs, long lvl) void bad_trap (struct pt_regs *regs, long lvl)
{ {
char buffer[32]; char buffer[32];
...@@ -66,8 +93,10 @@ void bad_trap (struct pt_regs *regs, long lvl) ...@@ -66,8 +93,10 @@ void bad_trap (struct pt_regs *regs, long lvl)
void bad_trap_tl1 (struct pt_regs *regs, long lvl) void bad_trap_tl1 (struct pt_regs *regs, long lvl)
{ {
char buffer[24]; char buffer[32];
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
sprintf (buffer, "Bad trap %lx at tl>0", lvl); sprintf (buffer, "Bad trap %lx at tl>0", lvl);
die_if_kernel (buffer, regs); die_if_kernel (buffer, regs);
} }
...@@ -80,8 +109,8 @@ void do_BUG(const char *file, int line) ...@@ -80,8 +109,8 @@ void do_BUG(const char *file, int line)
} }
#endif #endif
void instruction_access_exception (struct pt_regs *regs, void instruction_access_exception(struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar) unsigned long sfsr, unsigned long sfar)
{ {
siginfo_t info; siginfo_t info;
...@@ -102,6 +131,13 @@ void instruction_access_exception (struct pt_regs *regs, ...@@ -102,6 +131,13 @@ void instruction_access_exception (struct pt_regs *regs,
force_sig_info(SIGSEGV, &info, current); force_sig_info(SIGSEGV, &info, current);
} }
void instruction_access_exception_tl1(struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
instruction_access_exception(regs, sfsr, sfar);
}
void data_access_exception (struct pt_regs *regs, void data_access_exception (struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar) unsigned long sfsr, unsigned long sfar)
{ {
...@@ -167,7 +203,7 @@ static void clean_and_reenable_l1_caches(void) ...@@ -167,7 +203,7 @@ static void clean_and_reenable_l1_caches(void)
LSU_CONTROL_IM | LSU_CONTROL_DM), LSU_CONTROL_IM | LSU_CONTROL_DM),
"i" (ASI_LSU_CONTROL) "i" (ASI_LSU_CONTROL)
: "memory"); : "memory");
} else if (tlb_type == cheetah) { } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
/* Flush D-cache */ /* Flush D-cache */
for (va = 0; va < (1 << 16); va += (1 << 5)) { for (va = 0; va < (1 << 16); va += (1 << 5)) {
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t" __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
...@@ -201,7 +237,7 @@ void do_dae(struct pt_regs *regs) ...@@ -201,7 +237,7 @@ void do_dae(struct pt_regs *regs)
pci_poke_faulted = 1; pci_poke_faulted = 1;
/* Why the fuck did they have to change this? */ /* Why the fuck did they have to change this? */
if (tlb_type == cheetah) if (tlb_type == cheetah || tlb_type == cheetah_plus)
regs->tpc += 4; regs->tpc += 4;
regs->tnpc = regs->tpc + 4; regs->tnpc = regs->tpc + 4;
...@@ -390,10 +426,14 @@ static __inline__ struct cheetah_err_info *cheetah_get_error_log(unsigned long a ...@@ -390,10 +426,14 @@ static __inline__ struct cheetah_err_info *cheetah_get_error_log(unsigned long a
return p; return p;
} }
extern unsigned int tl0_icpe[], tl1_icpe[];
extern unsigned int tl0_dcpe[], tl1_dcpe[];
extern unsigned int tl0_fecc[], tl1_fecc[]; extern unsigned int tl0_fecc[], tl1_fecc[];
extern unsigned int tl0_cee[], tl1_cee[]; extern unsigned int tl0_cee[], tl1_cee[];
extern unsigned int tl0_iae[], tl1_iae[]; extern unsigned int tl0_iae[], tl1_iae[];
extern unsigned int tl0_dae[], tl1_dae[]; extern unsigned int tl0_dae[], tl1_dae[];
extern unsigned int cheetah_plus_icpe_trap_vector[], cheetah_plus_icpe_trap_vector_tl1[];
extern unsigned int cheetah_plus_dcpe_trap_vector[], cheetah_plus_dcpe_trap_vector_tl1[];
extern unsigned int cheetah_fecc_trap_vector[], cheetah_fecc_trap_vector_tl1[]; extern unsigned int cheetah_fecc_trap_vector[], cheetah_fecc_trap_vector_tl1[];
extern unsigned int cheetah_cee_trap_vector[], cheetah_cee_trap_vector_tl1[]; extern unsigned int cheetah_cee_trap_vector[], cheetah_cee_trap_vector_tl1[];
extern unsigned int cheetah_deferred_trap_vector[], cheetah_deferred_trap_vector_tl1[]; extern unsigned int cheetah_deferred_trap_vector[], cheetah_deferred_trap_vector_tl1[];
...@@ -487,6 +527,12 @@ void __init cheetah_ecache_flush_init(void) ...@@ -487,6 +527,12 @@ void __init cheetah_ecache_flush_init(void)
memcpy(tl1_iae, cheetah_deferred_trap_vector_tl1, (8 * 4)); memcpy(tl1_iae, cheetah_deferred_trap_vector_tl1, (8 * 4));
memcpy(tl0_dae, cheetah_deferred_trap_vector, (8 * 4)); memcpy(tl0_dae, cheetah_deferred_trap_vector, (8 * 4));
memcpy(tl1_dae, cheetah_deferred_trap_vector_tl1, (8 * 4)); memcpy(tl1_dae, cheetah_deferred_trap_vector_tl1, (8 * 4));
if (tlb_type == cheetah_plus) {
memcpy(tl0_dcpe, cheetah_plus_dcpe_trap_vector, (8 * 4));
memcpy(tl1_dcpe, cheetah_plus_dcpe_trap_vector_tl1, (8 * 4));
memcpy(tl0_icpe, cheetah_plus_icpe_trap_vector, (8 * 4));
memcpy(tl1_icpe, cheetah_plus_icpe_trap_vector_tl1, (8 * 4));
}
flushi(PAGE_OFFSET); flushi(PAGE_OFFSET);
} }
...@@ -567,9 +613,22 @@ unsigned long __init cheetah_tune_scheduling(void) ...@@ -567,9 +613,22 @@ unsigned long __init cheetah_tune_scheduling(void)
* *
* So we must only flush the I-cache when it is disabled. * So we must only flush the I-cache when it is disabled.
*/ */
static void __cheetah_flush_icache(void)
{
unsigned long i;
/* Clear the valid bits in all the tags. */
for (i = 0; i < (1 << 15); i += (1 << 5)) {
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
"membar #Sync"
: /* no outputs */
: "r" (i | (2 << 3)), "i" (ASI_IC_TAG));
}
}
static void cheetah_flush_icache(void) static void cheetah_flush_icache(void)
{ {
unsigned long dcu_save, i; unsigned long dcu_save;
/* Save current DCU, disable I-cache. */ /* Save current DCU, disable I-cache. */
__asm__ __volatile__("ldxa [%%g0] %1, %0\n\t" __asm__ __volatile__("ldxa [%%g0] %1, %0\n\t"
...@@ -580,13 +639,7 @@ static void cheetah_flush_icache(void) ...@@ -580,13 +639,7 @@ static void cheetah_flush_icache(void)
: "i" (ASI_DCU_CONTROL_REG), "i" (DCU_IC) : "i" (ASI_DCU_CONTROL_REG), "i" (DCU_IC)
: "g1"); : "g1");
/* Clear the valid bits in all the tags. */ __cheetah_flush_icache();
for (i = 0; i < (1 << 16); i += (1 << 5)) {
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
"membar #Sync"
: /* no outputs */
: "r" (i | (2 << 3)), "i" (ASI_IC_TAG));
}
/* Restore DCU register */ /* Restore DCU register */
__asm__ __volatile__("stxa %0, [%%g0] %1\n\t" __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
...@@ -607,6 +660,34 @@ static void cheetah_flush_dcache(void) ...@@ -607,6 +660,34 @@ static void cheetah_flush_dcache(void)
} }
} }
/* In order to make the even parity correct we must do two things.
* First, we clear DC_data_parity and set DC_utag to an appropriate value.
* Next, we clear out all 32-bytes of data for that line. Data of
* all-zero + tag parity value of zero == correct parity.
*/
static void cheetah_plus_zap_dcache_parity(void)
{
unsigned long i;
for (i = 0; i < (1 << 16); i += (1 << 5)) {
unsigned long tag = (i >> 14);
unsigned long j;
__asm__ __volatile__("membar #Sync\n\t"
"stxa %0, [%1] %2\n\t"
"membar #Sync"
: /* no outputs */
: "r" (tag), "r" (i),
"i" (ASI_DCACHE_UTAG));
for (j = i; j < i + (1 << 5); j += (1 << 3))
__asm__ __volatile__("membar #Sync\n\t"
"stxa %%g0, [%0] %1\n\t"
"membar #Sync"
: /* no outputs */
: "r" (j), "i" (ASI_DCACHE_DATA));
}
}
/* Conversion tables used to frob Cheetah AFSR syndrome values into /* Conversion tables used to frob Cheetah AFSR syndrome values into
* something palatable to the memory controller driver get_unumber * something palatable to the memory controller driver get_unumber
* routine. * routine.
...@@ -1327,6 +1408,46 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned ...@@ -1327,6 +1408,46 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned
panic("Irrecoverable deferred error trap.\n"); panic("Irrecoverable deferred error trap.\n");
} }
/* Handle a D/I cache parity error trap. TYPE is encoded as:
*
* Bit0: 0=dcache,1=icache
* Bit1: 0=recoverable,1=unrecoverable
*
* The hardware has disabled both the I-cache and D-cache in
* the %dcr register.
*/
void cheetah_plus_parity_error(int type, struct pt_regs *regs)
{
if (type & 0x1)
__cheetah_flush_icache();
else
cheetah_plus_zap_dcache_parity();
cheetah_flush_dcache();
/* Re-enable I-cache/D-cache */
__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
"or %%g1, %1, %%g1\n\t"
"stxa %%g1, [%%g0] %0\n\t"
"membar #Sync"
: /* no outputs */
: "i" (ASI_DCU_CONTROL_REG),
"i" (DCU_DC | DCU_IC)
: "g1");
if (type & 0x2) {
printk(KERN_EMERG "CPU[%d]: Cheetah+ %c-cache parity error at TPC[%016lx]\n",
smp_processor_id(),
(type & 0x1) ? 'I' : 'D',
regs->tpc);
panic("Irrecoverable Cheetah+ parity error.");
}
printk(KERN_WARNING "CPU[%d]: Cheetah+ %c-cache parity error at TPC[%016lx]\n",
smp_processor_id(),
(type & 0x1) ? 'I' : 'D',
regs->tpc);
}
void do_fpe_common(struct pt_regs *regs) void do_fpe_common(struct pt_regs *regs)
{ {
if (regs->tstate & TSTATE_PRIV) { if (regs->tstate & TSTATE_PRIV) {
...@@ -1604,56 +1725,67 @@ void do_cee(struct pt_regs *regs) ...@@ -1604,56 +1725,67 @@ void do_cee(struct pt_regs *regs)
void do_cee_tl1(struct pt_regs *regs) void do_cee_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Cache Error Exception", regs); die_if_kernel("TL1: Cache Error Exception", regs);
} }
void do_dae_tl1(struct pt_regs *regs) void do_dae_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Data Access Exception", regs); die_if_kernel("TL1: Data Access Exception", regs);
} }
void do_iae_tl1(struct pt_regs *regs) void do_iae_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Instruction Access Exception", regs); die_if_kernel("TL1: Instruction Access Exception", regs);
} }
void do_div0_tl1(struct pt_regs *regs) void do_div0_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: DIV0 Exception", regs); die_if_kernel("TL1: DIV0 Exception", regs);
} }
void do_fpdis_tl1(struct pt_regs *regs) void do_fpdis_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: FPU Disabled", regs); die_if_kernel("TL1: FPU Disabled", regs);
} }
void do_fpieee_tl1(struct pt_regs *regs) void do_fpieee_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: FPU IEEE Exception", regs); die_if_kernel("TL1: FPU IEEE Exception", regs);
} }
void do_fpother_tl1(struct pt_regs *regs) void do_fpother_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: FPU Other Exception", regs); die_if_kernel("TL1: FPU Other Exception", regs);
} }
void do_ill_tl1(struct pt_regs *regs) void do_ill_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Illegal Instruction Exception", regs); die_if_kernel("TL1: Illegal Instruction Exception", regs);
} }
void do_irq_tl1(struct pt_regs *regs) void do_irq_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: IRQ Exception", regs); die_if_kernel("TL1: IRQ Exception", regs);
} }
void do_lddfmna_tl1(struct pt_regs *regs) void do_lddfmna_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: LDDF Exception", regs); die_if_kernel("TL1: LDDF Exception", regs);
} }
void do_stdfmna_tl1(struct pt_regs *regs) void do_stdfmna_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: STDF Exception", regs); die_if_kernel("TL1: STDF Exception", regs);
} }
...@@ -1664,6 +1796,7 @@ void do_paw(struct pt_regs *regs) ...@@ -1664,6 +1796,7 @@ void do_paw(struct pt_regs *regs)
void do_paw_tl1(struct pt_regs *regs) void do_paw_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Phys Watchpoint Exception", regs); die_if_kernel("TL1: Phys Watchpoint Exception", regs);
} }
...@@ -1674,11 +1807,13 @@ void do_vaw(struct pt_regs *regs) ...@@ -1674,11 +1807,13 @@ void do_vaw(struct pt_regs *regs)
void do_vaw_tl1(struct pt_regs *regs) void do_vaw_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Virt Watchpoint Exception", regs); die_if_kernel("TL1: Virt Watchpoint Exception", regs);
} }
void do_tof_tl1(struct pt_regs *regs) void do_tof_tl1(struct pt_regs *regs)
{ {
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Tag Overflow Exception", regs); die_if_kernel("TL1: Tag Overflow Exception", regs);
} }
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <linux/config.h> #include <linux/config.h>
.globl sparc64_ttable_tl0, sparc64_ttable_tl1 .globl sparc64_ttable_tl0, sparc64_ttable_tl1
.globl tl0_icpe, tl1_icpe
.globl tl0_dcpe, tl1_dcpe
.globl tl0_fecc, tl1_fecc .globl tl0_fecc, tl1_fecc
.globl tl0_cee, tl1_cee .globl tl0_cee, tl1_cee
.globl tl0_iae, tl1_iae .globl tl0_iae, tl1_iae
...@@ -79,7 +81,9 @@ tl0_damiss: ...@@ -79,7 +81,9 @@ tl0_damiss:
tl0_daprot: tl0_daprot:
#include "dtlb_prot.S" #include "dtlb_prot.S"
tl0_fecc: BTRAP(0x70) /* Fast-ECC on Cheetah */ tl0_fecc: BTRAP(0x70) /* Fast-ECC on Cheetah */
tl0_resv071: BTRAP(0x71) BTRAP(0x72) BTRAP(0x73) BTRAP(0x74) BTRAP(0x75) tl0_dcpe: BTRAP(0x71) /* D-cache Parity Error on Cheetah+ */
tl0_icpe: BTRAP(0x72) /* I-cache Parity Error on Cheetah+ */
tl0_resv073: BTRAP(0x73) BTRAP(0x74) BTRAP(0x75)
tl0_resv076: BTRAP(0x76) BTRAP(0x77) BTRAP(0x78) BTRAP(0x79) BTRAP(0x7a) BTRAP(0x7b) tl0_resv076: BTRAP(0x76) BTRAP(0x77) BTRAP(0x78) BTRAP(0x79) BTRAP(0x7a) BTRAP(0x7b)
tl0_resv07c: BTRAP(0x7c) BTRAP(0x7d) BTRAP(0x7e) BTRAP(0x7f) tl0_resv07c: BTRAP(0x7c) BTRAP(0x7d) BTRAP(0x7e) BTRAP(0x7f)
tl0_s0n: SPILL_0_NORMAL tl0_s0n: SPILL_0_NORMAL
...@@ -235,8 +239,10 @@ tl1_damiss: ...@@ -235,8 +239,10 @@ tl1_damiss:
#include "dtlb_backend.S" #include "dtlb_backend.S"
tl1_daprot: tl1_daprot:
#include "dtlb_prot.S" #include "dtlb_prot.S"
tl1_fecc: BTRAP(0x70) /* Fast-ECC on Cheetah */ tl1_fecc: BTRAPTL1(0x70) /* Fast-ECC on Cheetah */
tl1_resc071: BTRAPTL1(0x71) BTRAPTL1(0x72) BTRAPTL1(0x73) tl1_dcpe: BTRAPTL1(0x71) /* D-cache Parity Error on Cheetah+ */
tl1_icpe: BTRAPTL1(0x72) /* I-cache Parity Error on Cheetah+ */
tl1_resv073: BTRAPTL1(0x73)
tl1_resv074: BTRAPTL1(0x74) BTRAPTL1(0x75) BTRAPTL1(0x76) BTRAPTL1(0x77) tl1_resv074: BTRAPTL1(0x74) BTRAPTL1(0x75) BTRAPTL1(0x76) BTRAPTL1(0x77)
tl1_resv078: BTRAPTL1(0x78) BTRAPTL1(0x79) BTRAPTL1(0x7a) BTRAPTL1(0x7b) tl1_resv078: BTRAPTL1(0x78) BTRAPTL1(0x79) BTRAPTL1(0x7a) BTRAPTL1(0x7b)
tl1_resv07c: BTRAPTL1(0x7c) BTRAPTL1(0x7d) BTRAPTL1(0x7e) BTRAPTL1(0x7f) tl1_resv07c: BTRAPTL1(0x7c) BTRAPTL1(0x7d) BTRAPTL1(0x7e) BTRAPTL1(0x7f)
......
...@@ -66,14 +66,14 @@ cheetah_patch_1: ...@@ -66,14 +66,14 @@ cheetah_patch_1:
ldx [%g6 + TI_FLAGS], %g3 ldx [%g6 + TI_FLAGS], %g3
/* Spitfire Errata #32 workaround */ /* Spitfire Errata #32 workaround */
mov 0x8, %o4 mov PRIMARY_CONTEXT, %o4
stxa %g0, [%o4] ASI_DMMU stxa %g0, [%o4] ASI_DMMU
membar #Sync membar #Sync
ldxa [%o3] ASI_DTLB_TAG_READ, %o4 ldxa [%o3] ASI_DTLB_TAG_READ, %o4
/* Spitfire Errata #32 workaround */ /* Spitfire Errata #32 workaround */
mov 0x8, %o5 mov PRIMARY_CONTEXT, %o5
stxa %g0, [%o5] ASI_DMMU stxa %g0, [%o5] ASI_DMMU
membar #Sync membar #Sync
...@@ -85,14 +85,14 @@ cheetah_patch_1: ...@@ -85,14 +85,14 @@ cheetah_patch_1:
add %o3, (TLBTEMP_ENTSZ), %o3 add %o3, (TLBTEMP_ENTSZ), %o3
/* Spitfire Errata #32 workaround */ /* Spitfire Errata #32 workaround */
mov 0x8, %g5 mov PRIMARY_CONTEXT, %g5
stxa %g0, [%g5] ASI_DMMU stxa %g0, [%g5] ASI_DMMU
membar #Sync membar #Sync
ldxa [%o3] ASI_DTLB_TAG_READ, %g5 ldxa [%o3] ASI_DTLB_TAG_READ, %g5
/* Spitfire Errata #32 workaround */ /* Spitfire Errata #32 workaround */
mov 0x8, %g7 mov PRIMARY_CONTEXT, %g7
stxa %g0, [%g7] ASI_DMMU stxa %g0, [%g7] ASI_DMMU
membar #Sync membar #Sync
...@@ -109,7 +109,9 @@ cheetah_patch_1: ...@@ -109,7 +109,9 @@ cheetah_patch_1:
rdpr %ver, %g3 rdpr %ver, %g3
sllx %g3, 16, %g3 sllx %g3, 16, %g3
srlx %g3, 32 + 16, %g3 srlx %g3, 32 + 16, %g3
cmp %g3, 0x14 cmp %g3, 0x14 ! CHEETAH_ID
be,pn %icc, cheetah_copy_user_page
cmp %g3, 0x15 ! CHEETAH_PLUS_ID
bne,pt %icc, spitfire_copy_user_page bne,pt %icc, spitfire_copy_user_page
nop nop
...@@ -357,14 +359,14 @@ cheetah_patch_2: ...@@ -357,14 +359,14 @@ cheetah_patch_2:
wrpr %g3, PSTATE_IE, %pstate wrpr %g3, PSTATE_IE, %pstate
/* Spitfire Errata #32 workaround */ /* Spitfire Errata #32 workaround */
mov 0x8, %g5 mov PRIMARY_CONTEXT, %g5
stxa %g0, [%g5] ASI_DMMU stxa %g0, [%g5] ASI_DMMU
membar #Sync membar #Sync
ldxa [%o3] ASI_DTLB_TAG_READ, %g5 ldxa [%o3] ASI_DTLB_TAG_READ, %g5
/* Spitfire Errata #32 workaround */ /* Spitfire Errata #32 workaround */
mov 0x8, %g7 mov PRIMARY_CONTEXT, %g7
stxa %g0, [%g7] ASI_DMMU stxa %g0, [%g7] ASI_DMMU
membar #Sync membar #Sync
...@@ -409,7 +411,8 @@ clear_page_common: ...@@ -409,7 +411,8 @@ clear_page_common:
retl retl
nop nop
1: stxa %g5, [%o2] ASI_DMMU 1:
stxa %g5, [%o2] ASI_DMMU
stxa %g7, [%o3] ASI_DTLB_DATA_ACCESS stxa %g7, [%o3] ASI_DTLB_DATA_ACCESS
membar #Sync membar #Sync
jmpl %o7 + 0x8, %g0 jmpl %o7 + 0x8, %g0
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/sched.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/mman.h> #include <linux/mman.h>
#include <linux/signal.h> #include <linux/signal.h>
......
...@@ -345,6 +345,8 @@ void mmu_info(struct seq_file *m) ...@@ -345,6 +345,8 @@ void mmu_info(struct seq_file *m)
{ {
if (tlb_type == cheetah) if (tlb_type == cheetah)
seq_printf(m, "MMU Type\t: Cheetah\n"); seq_printf(m, "MMU Type\t: Cheetah\n");
else if (tlb_type == cheetah_plus)
seq_printf(m, "MMU Type\t: Cheetah+\n");
else if (tlb_type == spitfire) else if (tlb_type == spitfire)
seq_printf(m, "MMU Type\t: Spitfire\n"); seq_printf(m, "MMU Type\t: Spitfire\n");
else else
...@@ -514,6 +516,7 @@ static void inherit_prom_mappings(void) ...@@ -514,6 +516,7 @@ static void inherit_prom_mappings(void)
break; break;
case cheetah: case cheetah:
case cheetah_plus:
phys_page = cheetah_get_litlb_data(sparc64_highest_locked_tlbent()); phys_page = cheetah_get_litlb_data(sparc64_highest_locked_tlbent());
break; break;
}; };
...@@ -539,7 +542,7 @@ static void inherit_prom_mappings(void) ...@@ -539,7 +542,7 @@ static void inherit_prom_mappings(void)
"i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS),
"i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS) "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS)
: "memory"); : "memory");
} else if (tlb_type == cheetah) { } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
/* Lock this into i/d tlb-0 entry 11 */ /* Lock this into i/d tlb-0 entry 11 */
__asm__ __volatile__( __asm__ __volatile__(
"stxa %%g0, [%2] %3\n\t" "stxa %%g0, [%2] %3\n\t"
...@@ -684,9 +687,9 @@ static void __flush_nucleus_vptes(void) ...@@ -684,9 +687,9 @@ static void __flush_nucleus_vptes(void)
spitfire_put_dtlb_data(i, 0x0UL); spitfire_put_dtlb_data(i, 0x0UL);
} }
} }
} else if (tlb_type == cheetah) { } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
for (i = 0; i < 512; i++) { for (i = 0; i < 512; i++) {
unsigned long tag = cheetah_get_dtlb_tag(i); unsigned long tag = cheetah_get_dtlb_tag(i, 2);
if ((tag & ~PAGE_MASK) == 0 && if ((tag & ~PAGE_MASK) == 0 &&
(tag & PAGE_MASK) >= prom_reserved_base) { (tag & PAGE_MASK) >= prom_reserved_base) {
...@@ -694,7 +697,21 @@ static void __flush_nucleus_vptes(void) ...@@ -694,7 +697,21 @@ static void __flush_nucleus_vptes(void)
"membar #Sync" "membar #Sync"
: /* no outputs */ : /* no outputs */
: "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
cheetah_put_dtlb_data(i, 0x0UL); cheetah_put_dtlb_data(i, 0x0UL, 2);
}
if (tlb_type != cheetah_plus)
continue;
tag = cheetah_get_dtlb_tag(i, 3);
if ((tag & ~PAGE_MASK) == 0 &&
(tag & PAGE_MASK) >= prom_reserved_base) {
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
"membar #Sync"
: /* no outputs */
: "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
cheetah_put_dtlb_data(i, 0x0UL, 3);
} }
} }
} else { } else {
...@@ -743,7 +760,7 @@ void prom_world(int enter) ...@@ -743,7 +760,7 @@ void prom_world(int enter)
if (tlb_type == spitfire) if (tlb_type == spitfire)
spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent, spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent,
prom_dtlb[i].tlb_data); prom_dtlb[i].tlb_data);
else if (tlb_type == cheetah) else if (tlb_type == cheetah || tlb_type == cheetah_plus)
cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent, cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent,
prom_dtlb[i].tlb_data); prom_dtlb[i].tlb_data);
} }
...@@ -756,7 +773,7 @@ void prom_world(int enter) ...@@ -756,7 +773,7 @@ void prom_world(int enter)
if (tlb_type == spitfire) if (tlb_type == spitfire)
spitfire_put_itlb_data(prom_itlb[i].tlb_ent, spitfire_put_itlb_data(prom_itlb[i].tlb_ent,
prom_itlb[i].tlb_data); prom_itlb[i].tlb_data);
else if (tlb_type == cheetah) else if (tlb_type == cheetah || tlb_type == cheetah_plus)
cheetah_put_litlb_data(prom_itlb[i].tlb_ent, cheetah_put_litlb_data(prom_itlb[i].tlb_ent,
prom_itlb[i].tlb_data); prom_itlb[i].tlb_data);
} }
...@@ -891,7 +908,7 @@ void inherit_locked_prom_mappings(int save_p) ...@@ -891,7 +908,7 @@ void inherit_locked_prom_mappings(int save_p)
break; break;
} }
} }
} else if (tlb_type == cheetah) { } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
int high = CHEETAH_HIGHEST_LOCKED_TLBENT - bigkernel; int high = CHEETAH_HIGHEST_LOCKED_TLBENT - bigkernel;
for (i = 0; i < high; i++) { for (i = 0; i < high; i++) {
...@@ -963,7 +980,7 @@ void prom_reload_locked(void) ...@@ -963,7 +980,7 @@ void prom_reload_locked(void)
if (tlb_type == spitfire) if (tlb_type == spitfire)
spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent, spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent,
prom_dtlb[i].tlb_data); prom_dtlb[i].tlb_data);
else if (tlb_type == cheetah) else if (tlb_type == cheetah || tlb_type == cheetah_plus)
cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent, cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent,
prom_dtlb[i].tlb_data); prom_dtlb[i].tlb_data);
} }
...@@ -1064,7 +1081,7 @@ void __flush_tlb_all(void) ...@@ -1064,7 +1081,7 @@ void __flush_tlb_all(void)
spitfire_put_itlb_data(i, 0x0UL); spitfire_put_itlb_data(i, 0x0UL);
} }
} }
} else if (tlb_type == cheetah) { } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
cheetah_flush_dtlb_all(); cheetah_flush_dtlb_all();
cheetah_flush_itlb_all(); cheetah_flush_itlb_all();
} }
...@@ -1208,7 +1225,7 @@ void sparc_ultra_dump_itlb(void) ...@@ -1208,7 +1225,7 @@ void sparc_ultra_dump_itlb(void)
slot+2, slot+2,
spitfire_get_itlb_tag(slot+2), spitfire_get_itlb_data(slot+2)); spitfire_get_itlb_tag(slot+2), spitfire_get_itlb_data(slot+2));
} }
} else if (tlb_type == cheetah) { } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
printk ("Contents of itlb0:\n"); printk ("Contents of itlb0:\n");
for (slot = 0; slot < 16; slot+=2) { for (slot = 0; slot < 16; slot+=2) {
printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n", printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
...@@ -1246,7 +1263,7 @@ void sparc_ultra_dump_dtlb(void) ...@@ -1246,7 +1263,7 @@ void sparc_ultra_dump_dtlb(void)
slot+2, slot+2,
spitfire_get_dtlb_tag(slot+2), spitfire_get_dtlb_data(slot+2)); spitfire_get_dtlb_tag(slot+2), spitfire_get_dtlb_data(slot+2));
} }
} else if (tlb_type == cheetah) { } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
printk ("Contents of dtlb0:\n"); printk ("Contents of dtlb0:\n");
for (slot = 0; slot < 16; slot+=2) { for (slot = 0; slot < 16; slot+=2) {
printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n", printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
...@@ -1259,9 +1276,19 @@ void sparc_ultra_dump_dtlb(void) ...@@ -1259,9 +1276,19 @@ void sparc_ultra_dump_dtlb(void)
for (slot = 0; slot < 512; slot+=2) { for (slot = 0; slot < 512; slot+=2) {
printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n", printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
slot, slot,
cheetah_get_dtlb_tag(slot), cheetah_get_dtlb_data(slot), cheetah_get_dtlb_tag(slot, 2), cheetah_get_dtlb_data(slot, 2),
slot+1, slot+1,
cheetah_get_dtlb_tag(slot+1), cheetah_get_dtlb_data(slot+1)); cheetah_get_dtlb_tag(slot+1, 2), cheetah_get_dtlb_data(slot+1, 2));
}
if (tlb_type == cheetah_plus) {
printk ("Contents of dtlb3:\n");
for (slot = 0; slot < 512; slot+=2) {
printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
slot,
cheetah_get_dtlb_tag(slot, 3), cheetah_get_dtlb_data(slot, 3),
slot+1,
cheetah_get_dtlb_tag(slot+1, 3), cheetah_get_dtlb_data(slot+1, 3));
}
} }
} }
} }
...@@ -1439,7 +1466,7 @@ void __init paging_init(void) ...@@ -1439,7 +1466,7 @@ void __init paging_init(void)
"i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (60 << 3) "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (60 << 3)
: "memory"); : "memory");
} }
} else if (tlb_type == cheetah) { } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
__asm__ __volatile__( __asm__ __volatile__(
" stxa %1, [%0] %3\n" " stxa %1, [%0] %3\n"
" stxa %2, [%5] %4\n" " stxa %2, [%5] %4\n"
...@@ -1745,7 +1772,7 @@ void __init mem_init(void) ...@@ -1745,7 +1772,7 @@ void __init mem_init(void)
initpages << (PAGE_SHIFT-10), initpages << (PAGE_SHIFT-10),
PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT)); PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT));
if (tlb_type == cheetah) if (tlb_type == cheetah || tlb_type == cheetah_plus)
cheetah_ecache_flush_init(); cheetah_ecache_flush_init();
} }
......
...@@ -5,10 +5,9 @@ ...@@ -5,10 +5,9 @@
* Based upon code written by Linus Torvalds and others. * Based upon code written by Linus Torvalds and others.
*/ */
#warning "major untested changes to this file --hch (2002/08/05)"
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/mm.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -30,13 +29,13 @@ void module_unmap (void * addr) ...@@ -30,13 +29,13 @@ void module_unmap (void * addr)
for (p = &modvmlist ; (tmp = *p) ; p = &tmp->next) { for (p = &modvmlist ; (tmp = *p) ; p = &tmp->next) {
if (tmp->addr == addr) { if (tmp->addr == addr) {
*p = tmp->next; *p = tmp->next;
goto found;
} }
} }
printk("Trying to unmap nonexistent module vm area (%p)\n", addr); printk("Trying to unmap nonexistent module vm area (%p)\n", addr);
return; return;
found: found:
unmap_vm_area(tmp); unmap_vm_area(tmp);
for (i = 0; i < tmp->nr_pages; i++) { for (i = 0; i < tmp->nr_pages; i++) {
...@@ -53,14 +52,13 @@ void module_unmap (void * addr) ...@@ -53,14 +52,13 @@ void module_unmap (void * addr)
void * module_map (unsigned long size) void * module_map (unsigned long size)
{ {
struct vm_struct **p, *tmp, *area; struct vm_struct **p, *tmp, *area;
struct vm_struct *area;
struct page **pages; struct page **pages;
void * addr; void * addr;
unsigned int nr_pages, array_size, i; unsigned int nr_pages, array_size, i;
size = PAGE_ALIGN(size); size = PAGE_ALIGN(size);
if (!size || size > MODULES_LEN) return NULL; if (!size || size > MODULES_LEN)
return NULL;
addr = (void *) MODULES_VADDR; addr = (void *) MODULES_VADDR;
for (p = &modvmlist; (tmp = *p) ; p = &tmp->next) { for (p = &modvmlist; (tmp = *p) ; p = &tmp->next) {
...@@ -68,10 +66,12 @@ void * module_map (unsigned long size) ...@@ -68,10 +66,12 @@ void * module_map (unsigned long size)
break; break;
addr = (void *) (tmp->size + (unsigned long) tmp->addr); addr = (void *) (tmp->size + (unsigned long) tmp->addr);
} }
if ((unsigned long) addr + size >= MODULES_END) return NULL; if ((unsigned long) addr + size >= MODULES_END)
return NULL;
area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL); area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
if (!area) return NULL; if (!area)
return NULL;
area->size = size + PAGE_SIZE; area->size = size + PAGE_SIZE;
area->addr = addr; area->addr = addr;
area->next = *p; area->next = *p;
...@@ -80,27 +80,38 @@ void * module_map (unsigned long size) ...@@ -80,27 +80,38 @@ void * module_map (unsigned long size)
area->phys_addr = 0; area->phys_addr = 0;
*p = area; *p = area;
nr_pages = (size+PAGE_SIZE) >> PAGE_SHIFT; nr_pages = size >> PAGE_SHIFT;
array_size = (nr_pages * sizeof(struct page *)); array_size = (nr_pages * sizeof(struct page *));
area->nr_pages = nr_pages; area->nr_pages = nr_pages;
area->pages = pages = kmalloc(array_size, (gfp_mask & ~__GFP_HIGHMEM)); area->pages = pages = kmalloc(array_size, GFP_KERNEL);
if (!area->pages) if (!area->pages)
return NULL; goto fail;
memset(area->pages, 0, array_size); memset(area->pages, 0, array_size);
for (i = 0; i < area->nr_pages; i++) { for (i = 0; i < area->nr_pages; i++) {
area->pages[i] = alloc_page(gfp_mask); area->pages[i] = alloc_page(GFP_KERNEL);
if (unlikely(!area->pages[i])) if (unlikely(!area->pages[i]))
goto fail; goto fail;
} }
if (map_vm_area(area, prot, &pages)) if (map_vm_area(area, PAGE_KERNEL, &pages)) {
unmap_vm_area(area);
goto fail; goto fail;
}
return area->addr; return area->addr;
fail: fail:
vfree(area->addr); if (area->pages) {
for (i = 0; i < area->nr_pages; i++) {
if (area->pages[i])
__free_page(area->pages[i]);
}
kfree(area->pages);
}
kfree(area);
return NULL; return NULL;
} }
}
...@@ -14,21 +14,12 @@ ...@@ -14,21 +14,12 @@
#include <asm/head.h> #include <asm/head.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
/* Basically, all this madness has to do with the /* Basically, most of the Spitfire vs. Cheetah madness
* fact that Cheetah does not support IMMU flushes * has to do with the fact that Cheetah does not support
* out of the secondary context. Someone needs to * IMMU flushes out of the secondary context. Someone needs
* throw a south lake birthday party for the folks * to throw a south lake birthday party for the folks
* in Microelectronics who refused to fix this shit. * in Microelectronics who refused to fix this shit.
*/ */
#define BRANCH_IF_CHEETAH(tmp1, tmp2, label) \
rdpr %ver, %tmp1; \
sethi %hi(0x003e0014), %tmp2; \
srlx %tmp1, 32, %tmp1; \
or %tmp2, %lo(0x003e0014), %tmp2; \
cmp %tmp1, %tmp2; \
be,pn %icc, label; \
nop; \
nop;
/* This file is meant to be read efficiently by the CPU, not humans. /* This file is meant to be read efficiently by the CPU, not humans.
* Staraj sie tego nikomu nie pierdolnac... * Staraj sie tego nikomu nie pierdolnac...
...@@ -37,9 +28,7 @@ ...@@ -37,9 +28,7 @@
.align 32 .align 32
.globl __flush_tlb_page, __flush_tlb_mm, __flush_tlb_range .globl __flush_tlb_page, __flush_tlb_mm, __flush_tlb_range
__flush_tlb_page: /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=page&PAGE_MASK, %o2=SECONDARY_CONTEXT */ __flush_tlb_page: /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=page&PAGE_MASK, %o2=SECONDARY_CONTEXT */
/*IC1*/ BRANCH_IF_CHEETAH(g2, g3, __cheetah_flush_tlb_page) ldxa [%o2] ASI_DMMU, %g2
__spitfire_flush_tlb_page:
/*IC2*/ ldxa [%o2] ASI_DMMU, %g2
cmp %g2, %o0 cmp %g2, %o0
bne,pn %icc, __spitfire_flush_tlb_page_slow bne,pn %icc, __spitfire_flush_tlb_page_slow
or %o1, 0x10, %g3 or %o1, 0x10, %g3
...@@ -47,27 +36,17 @@ __spitfire_flush_tlb_page: ...@@ -47,27 +36,17 @@ __spitfire_flush_tlb_page:
stxa %g0, [%g3] ASI_IMMU_DEMAP stxa %g0, [%g3] ASI_IMMU_DEMAP
retl retl
flush %g6 flush %g6
__cheetah_flush_tlb_page:
/*IC3*/ rdpr %pstate, %g5
andn %g5, PSTATE_IE, %g2
wrpr %g2, 0x0, %pstate
wrpr %g0, 1, %tl
mov PRIMARY_CONTEXT, %o2
ldxa [%o2] ASI_DMMU, %g2
stxa %o0, [%o2] ASI_DMMU
stxa %g0, [%o1] ASI_DMMU_DEMAP
/*IC4*/ stxa %g0, [%o1] ASI_IMMU_DEMAP
stxa %g2, [%o2] ASI_DMMU
flush %g6
wrpr %g0, 0, %tl
retl
wrpr %g5, 0x0, %pstate
nop nop
nop nop
nop
nop
nop
nop
nop
nop
__flush_tlb_mm: /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=SECONDARY_CONTEXT */ __flush_tlb_mm: /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=SECONDARY_CONTEXT */
/*IC5*/ BRANCH_IF_CHEETAH(g2, g3, __cheetah_flush_tlb_mm) ldxa [%o1] ASI_DMMU, %g2
__spitfire_flush_tlb_mm:
/*IC6*/ ldxa [%o1] ASI_DMMU, %g2
cmp %g2, %o0 cmp %g2, %o0
bne,pn %icc, __spitfire_flush_tlb_mm_slow bne,pn %icc, __spitfire_flush_tlb_mm_slow
mov 0x50, %g3 mov 0x50, %g3
...@@ -75,30 +54,20 @@ __spitfire_flush_tlb_mm: ...@@ -75,30 +54,20 @@ __spitfire_flush_tlb_mm:
stxa %g0, [%g3] ASI_IMMU_DEMAP stxa %g0, [%g3] ASI_IMMU_DEMAP
retl retl
flush %g6 flush %g6
__cheetah_flush_tlb_mm:
/*IC7*/ rdpr %pstate, %g5
andn %g5, PSTATE_IE, %g2
wrpr %g2, 0x0, %pstate
wrpr %g0, 1, %tl
mov PRIMARY_CONTEXT, %o2
mov 0x40, %g3
ldxa [%o2] ASI_DMMU, %g2
stxa %o0, [%o2] ASI_DMMU
/*IC8*/ stxa %g0, [%g3] ASI_DMMU_DEMAP
stxa %g0, [%g3] ASI_IMMU_DEMAP
stxa %g2, [%o2] ASI_DMMU
flush %g6
wrpr %g0, 0, %tl
retl
wrpr %g5, 0x0, %pstate
nop nop
nop
nop
nop
nop
nop
nop
nop
__flush_tlb_range: /* %o0=(ctx&TAG_CONTEXT_BITS), %o1=start&PAGE_MASK, %o2=SECONDARY_CONTEXT, __flush_tlb_range: /* %o0=(ctx&TAG_CONTEXT_BITS), %o1=start&PAGE_MASK, %o2=SECONDARY_CONTEXT,
* %o3=end&PAGE_MASK, %o4=PAGE_SIZE, %o5=(end - start) * %o3=end&PAGE_MASK, %o4=PAGE_SIZE, %o5=(end - start)
*/ */
/*IC9*/ BRANCH_IF_CHEETAH(g2, g3, __cheetah_flush_tlb_range)
__spitfire_flush_tlb_range:
#define TLB_MAGIC 207 /* Students, do you know how I calculated this? -DaveM */ #define TLB_MAGIC 207 /* Students, do you know how I calculated this? -DaveM */
/*IC10*/cmp %o5, %o4 cmp %o5, %o4
bleu,pt %xcc, __flush_tlb_page bleu,pt %xcc, __flush_tlb_page
srlx %o5, PAGE_SHIFT, %g5 srlx %o5, PAGE_SHIFT, %g5
cmp %g5, TLB_MAGIC cmp %g5, TLB_MAGIC
...@@ -107,7 +76,7 @@ __spitfire_flush_tlb_range: ...@@ -107,7 +76,7 @@ __spitfire_flush_tlb_range:
ldxa [%o2] ASI_DMMU, %g2 ldxa [%o2] ASI_DMMU, %g2
cmp %g2, %o0 cmp %g2, %o0
__spitfire_flush_tlb_range_page_by_page: __spitfire_flush_tlb_range_page_by_page:
/*IC11*/bne,pn %icc, __spitfire_flush_tlb_range_pbp_slow bne,pn %icc, __spitfire_flush_tlb_range_pbp_slow
sub %o5, %o4, %o5 sub %o5, %o4, %o5
1: stxa %g0, [%g5 + %o5] ASI_DMMU_DEMAP 1: stxa %g0, [%g5 + %o5] ASI_DMMU_DEMAP
stxa %g0, [%g5 + %o5] ASI_IMMU_DEMAP stxa %g0, [%g5 + %o5] ASI_IMMU_DEMAP
...@@ -116,10 +85,9 @@ __spitfire_flush_tlb_range_page_by_page: ...@@ -116,10 +85,9 @@ __spitfire_flush_tlb_range_page_by_page:
retl retl
flush %g6 flush %g6
__spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */ __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
/*IC12*/rdpr %pstate, %g1 rdpr %pstate, %g1
wrpr %g1, PSTATE_IE, %pstate wrpr %g1, PSTATE_IE, %pstate
mov TLB_TAG_ACCESS, %g3 mov TLB_TAG_ACCESS, %g3
/* XXX Spitfire dependency... */
mov ((SPITFIRE_HIGHEST_LOCKED_TLBENT-1) << 3), %g2 mov ((SPITFIRE_HIGHEST_LOCKED_TLBENT-1) << 3), %g2
/* Spitfire Errata #32 workaround. */ /* Spitfire Errata #32 workaround. */
...@@ -131,7 +99,7 @@ __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */ ...@@ -131,7 +99,7 @@ __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
and %o4, TAG_CONTEXT_BITS, %o5 and %o4, TAG_CONTEXT_BITS, %o5
cmp %o5, %o0 cmp %o5, %o0
bne,pt %icc, 2f bne,pt %icc, 2f
/*IC13*/ andn %o4, TAG_CONTEXT_BITS, %o4 andn %o4, TAG_CONTEXT_BITS, %o4
cmp %o4, %o1 cmp %o4, %o1
blu,pt %xcc, 2f blu,pt %xcc, 2f
cmp %o4, %o3 cmp %o4, %o3
...@@ -139,7 +107,7 @@ __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */ ...@@ -139,7 +107,7 @@ __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
2: ldxa [%g2] ASI_DTLB_TAG_READ, %o4 2: ldxa [%g2] ASI_DTLB_TAG_READ, %o4
and %o4, TAG_CONTEXT_BITS, %o5 and %o4, TAG_CONTEXT_BITS, %o5
cmp %o5, %o0 cmp %o5, %o0
/*IC14*/andn %o4, TAG_CONTEXT_BITS, %o4 andn %o4, TAG_CONTEXT_BITS, %o4
bne,pt %icc, 3f bne,pt %icc, 3f
cmp %o4, %o1 cmp %o4, %o1
blu,pt %xcc, 3f blu,pt %xcc, 3f
...@@ -147,7 +115,7 @@ __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */ ...@@ -147,7 +115,7 @@ __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
blu,pn %xcc, 5f blu,pn %xcc, 5f
nop nop
3: brnz,pt %g2, 1b 3: brnz,pt %g2, 1b
/*IC15*/ sub %g2, (1 << 3), %g2 sub %g2, (1 << 3), %g2
retl retl
wrpr %g1, 0x0, %pstate wrpr %g1, 0x0, %pstate
4: stxa %g0, [%g3] ASI_IMMU 4: stxa %g0, [%g3] ASI_IMMU
...@@ -163,7 +131,7 @@ __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */ ...@@ -163,7 +131,7 @@ __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
nop nop
5: stxa %g0, [%g3] ASI_DMMU 5: stxa %g0, [%g3] ASI_DMMU
/*IC16*/stxa %g0, [%g2] ASI_DTLB_DATA_ACCESS stxa %g0, [%g2] ASI_DTLB_DATA_ACCESS
flush %g6 flush %g6
/* Spitfire Errata #32 workaround. */ /* Spitfire Errata #32 workaround. */
...@@ -175,33 +143,6 @@ __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */ ...@@ -175,33 +143,6 @@ __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
nop nop
.align 32 .align 32
__cheetah_flush_tlb_range:
cmp %o5, %o4
bleu,pt %xcc, __cheetah_flush_tlb_page
nop
/*IC17*/rdpr %pstate, %g5
andn %g5, PSTATE_IE, %g2
wrpr %g2, 0x0, %pstate
wrpr %g0, 1, %tl
mov PRIMARY_CONTEXT, %o2
sub %o5, %o4, %o5
ldxa [%o2] ASI_DMMU, %g2
stxa %o0, [%o2] ASI_DMMU
/*IC18*/
1: stxa %g0, [%o1 + %o5] ASI_DMMU_DEMAP
stxa %g0, [%o1 + %o5] ASI_IMMU_DEMAP
membar #Sync
brnz,pt %o5, 1b
sub %o5, %o4, %o5
stxa %g2, [%o2] ASI_DMMU
flush %g6
wrpr %g0, 0, %tl
retl
/*IC19*/ wrpr %g5, 0x0, %pstate
.align 32
.globl __flush_tlb_kernel_range .globl __flush_tlb_kernel_range
__flush_tlb_kernel_range: /* %o0=start, %o1=end */ __flush_tlb_kernel_range: /* %o0=start, %o1=end */
cmp %o0, %o1 cmp %o0, %o1
...@@ -226,7 +167,7 @@ __spitfire_flush_tlb_mm_slow: ...@@ -226,7 +167,7 @@ __spitfire_flush_tlb_mm_slow:
stxa %g0, [%g3] ASI_IMMU_DEMAP stxa %g0, [%g3] ASI_IMMU_DEMAP
flush %g6 flush %g6
stxa %g2, [%o1] ASI_DMMU stxa %g2, [%o1] ASI_DMMU
/*IC18*/flush %g6 flush %g6
retl retl
wrpr %g1, 0, %pstate wrpr %g1, 0, %pstate
...@@ -236,7 +177,7 @@ __spitfire_flush_tlb_page_slow: ...@@ -236,7 +177,7 @@ __spitfire_flush_tlb_page_slow:
stxa %o0, [%o2] ASI_DMMU stxa %o0, [%o2] ASI_DMMU
stxa %g0, [%g3] ASI_DMMU_DEMAP stxa %g0, [%g3] ASI_DMMU_DEMAP
stxa %g0, [%g3] ASI_IMMU_DEMAP stxa %g0, [%g3] ASI_IMMU_DEMAP
/*IC20*/flush %g6 flush %g6
stxa %g2, [%o2] ASI_DMMU stxa %g2, [%o2] ASI_DMMU
flush %g6 flush %g6
retl retl
...@@ -246,7 +187,7 @@ __spitfire_flush_tlb_range_pbp_slow: ...@@ -246,7 +187,7 @@ __spitfire_flush_tlb_range_pbp_slow:
rdpr %pstate, %g1 rdpr %pstate, %g1
wrpr %g1, PSTATE_IE, %pstate wrpr %g1, PSTATE_IE, %pstate
stxa %o0, [%o2] ASI_DMMU stxa %o0, [%o2] ASI_DMMU
/*IC21*/
2: stxa %g0, [%g5 + %o5] ASI_DMMU_DEMAP 2: stxa %g0, [%g5 + %o5] ASI_DMMU_DEMAP
stxa %g0, [%g5 + %o5] ASI_IMMU_DEMAP stxa %g0, [%g5 + %o5] ASI_IMMU_DEMAP
brnz,pt %o5, 2b brnz,pt %o5, 2b
...@@ -255,7 +196,7 @@ __spitfire_flush_tlb_range_pbp_slow: ...@@ -255,7 +196,7 @@ __spitfire_flush_tlb_range_pbp_slow:
stxa %g2, [%o2] ASI_DMMU stxa %g2, [%o2] ASI_DMMU
flush %g6 flush %g6
retl retl
/*IC22*/ wrpr %g1, 0x0, %pstate wrpr %g1, 0x0, %pstate
/* /*
* The following code flushes one page_size worth. * The following code flushes one page_size worth.
...@@ -318,32 +259,6 @@ iflush2:sub %o1, 0x20, %g3 ...@@ -318,32 +259,6 @@ iflush2:sub %o1, 0x20, %g3
flush %g6 flush %g6
ba,a,pt %xcc, 3b ba,a,pt %xcc, 3b
.align 64
.globl __flush_dcache_page
__flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */
sethi %uhi(PAGE_OFFSET), %g1
sllx %g1, 32, %g1
sub %o0, %g1, %o0
rdpr %ver, %g1
sethi %hi(0x003e0014), %g2
srlx %g1, 32, %g1
or %g2, %lo(0x003e0014), %g2
cmp %g1, %g2
bne,pt %icc, flush_dcpage_spitfire
nop
flush_dcpage_cheetah:
sethi %hi(PAGE_SIZE), %o4
1: subcc %o4, (1 << 5), %o4
stxa %g0, [%o0 + %o4] ASI_DCACHE_INVALIDATE
bne,pt %icc, 1b
nop
membar #Sync
/* I-cache flush never needed on Cheetah, see callers. */
retl
nop
#if (PAGE_SHIFT == 13) #if (PAGE_SHIFT == 13)
#define DTAG_MASK 0x3 #define DTAG_MASK 0x3
#elif (PAGE_SHIFT == 16) #elif (PAGE_SHIFT == 16)
...@@ -354,7 +269,12 @@ flush_dcpage_cheetah: ...@@ -354,7 +269,12 @@ flush_dcpage_cheetah:
#define DTAG_MASK 0x3ff #define DTAG_MASK 0x3ff
#endif #endif
flush_dcpage_spitfire: .align 64
.globl __flush_dcache_page
__flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */
sethi %uhi(PAGE_OFFSET), %g1
sllx %g1, 32, %g1
sub %o0, %g1, %o0
clr %o4 clr %o4
srlx %o0, 11, %o0 srlx %o0, 11, %o0
sethi %hi(1 << 14), %o2 sethi %hi(1 << 14), %o2
...@@ -435,6 +355,121 @@ __update_mmu_cache: /* %o0=hw_context, %o1=address, %o2=pte, %o3=fault_code */ ...@@ -435,6 +355,121 @@ __update_mmu_cache: /* %o0=hw_context, %o1=address, %o2=pte, %o3=fault_code */
or %o5, %o0, %o5 or %o5, %o0, %o5
ba,a,pt %xcc, __prefill_itlb ba,a,pt %xcc, __prefill_itlb
/* Cheetah specific versions, patched at boot time. */
__cheetah_flush_tlb_page: /* 14 insns */
rdpr %pstate, %g5
andn %g5, PSTATE_IE, %g2
wrpr %g2, 0x0, %pstate
wrpr %g0, 1, %tl
mov PRIMARY_CONTEXT, %o2
ldxa [%o2] ASI_DMMU, %g2
stxa %o0, [%o2] ASI_DMMU
stxa %g0, [%o1] ASI_DMMU_DEMAP
stxa %g0, [%o1] ASI_IMMU_DEMAP
stxa %g2, [%o2] ASI_DMMU
flush %g6
wrpr %g0, 0, %tl
retl
wrpr %g5, 0x0, %pstate
__cheetah_flush_tlb_mm: /* 15 insns */
rdpr %pstate, %g5
andn %g5, PSTATE_IE, %g2
wrpr %g2, 0x0, %pstate
wrpr %g0, 1, %tl
mov PRIMARY_CONTEXT, %o2
mov 0x40, %g3
ldxa [%o2] ASI_DMMU, %g2
stxa %o0, [%o2] ASI_DMMU
stxa %g0, [%g3] ASI_DMMU_DEMAP
stxa %g0, [%g3] ASI_IMMU_DEMAP
stxa %g2, [%o2] ASI_DMMU
flush %g6
wrpr %g0, 0, %tl
retl
wrpr %g5, 0x0, %pstate
__cheetah_flush_tlb_range: /* 20 insns */
cmp %o5, %o4
blu,pt %xcc, 9f
rdpr %pstate, %g5
andn %g5, PSTATE_IE, %g2
wrpr %g2, 0x0, %pstate
wrpr %g0, 1, %tl
mov PRIMARY_CONTEXT, %o2
sub %o5, %o4, %o5
ldxa [%o2] ASI_DMMU, %g2
stxa %o0, [%o2] ASI_DMMU
1: stxa %g0, [%o1 + %o5] ASI_DMMU_DEMAP
stxa %g0, [%o1 + %o5] ASI_IMMU_DEMAP
membar #Sync
brnz,pt %o5, 1b
sub %o5, %o4, %o5
stxa %g2, [%o2] ASI_DMMU
flush %g6
wrpr %g0, 0, %tl
9: retl
wrpr %g5, 0x0, %pstate
flush_dcpage_cheetah: /* 11 insns */
sethi %uhi(PAGE_OFFSET), %g1
sllx %g1, 32, %g1
sub %o0, %g1, %o0
sethi %hi(PAGE_SIZE), %o4
1: subcc %o4, (1 << 5), %o4
stxa %g0, [%o0 + %o4] ASI_DCACHE_INVALIDATE
membar #Sync
bne,pt %icc, 1b
nop
retl /* I-cache flush never needed on Cheetah, see callers. */
nop
cheetah_patch_one:
1: lduw [%o1], %g1
stw %g1, [%o0]
flush %o0
subcc %o2, 1, %o2
add %o1, 4, %o1
bne,pt %icc, 1b
add %o0, 4, %o0
retl
nop
.globl cheetah_patch_cachetlbops
cheetah_patch_cachetlbops:
save %sp, -128, %sp
sethi %hi(__flush_tlb_page), %o0
or %o0, %lo(__flush_tlb_page), %o0
sethi %hi(__cheetah_flush_tlb_page), %o1
or %o1, %lo(__cheetah_flush_tlb_page), %o1
call cheetah_patch_one
mov 14, %o2
sethi %hi(__flush_tlb_mm), %o0
or %o0, %lo(__flush_tlb_mm), %o0
sethi %hi(__cheetah_flush_tlb_mm), %o1
or %o1, %lo(__cheetah_flush_tlb_mm), %o1
call cheetah_patch_one
mov 15, %o2
sethi %hi(__flush_tlb_range), %o0
or %o0, %lo(__flush_tlb_range), %o0
sethi %hi(__cheetah_flush_tlb_range), %o1
or %o1, %lo(__cheetah_flush_tlb_range), %o1
call cheetah_patch_one
mov 20, %o2
sethi %hi(__flush_dcache_page), %o0
or %o0, %lo(__flush_dcache_page), %o0
sethi %hi(flush_dcpage_cheetah), %o1
or %o1, %lo(flush_dcpage_cheetah), %o1
call cheetah_patch_one
mov 11, %o2
ret
restore
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* These are all called by the slaves of a cross call, at /* These are all called by the slaves of a cross call, at
* trap level 1, with interrupts fully disabled. * trap level 1, with interrupts fully disabled.
...@@ -538,7 +573,7 @@ xcall_report_regs: ...@@ -538,7 +573,7 @@ xcall_report_regs:
rdpr %pil, %g2 rdpr %pil, %g2
wrpr %g0, 15, %pil wrpr %g0, 15, %pil
sethi %hi(109f), %g7 sethi %hi(109f), %g7
b,pt %xcc, etrap b,pt %xcc, etrap_irq
109: or %g7, %lo(109b), %g7 109: or %g7, %lo(109b), %g7
call __show_regs call __show_regs
add %sp, STACK_BIAS + REGWIN_SZ, %o0 add %sp, STACK_BIAS + REGWIN_SZ, %o0
...@@ -553,9 +588,9 @@ xcall_flush_dcache_page_cheetah: /* %g1 == physical page address */ ...@@ -553,9 +588,9 @@ xcall_flush_dcache_page_cheetah: /* %g1 == physical page address */
sethi %hi(PAGE_SIZE), %g3 sethi %hi(PAGE_SIZE), %g3
1: subcc %g3, (1 << 5), %g3 1: subcc %g3, (1 << 5), %g3
stxa %g0, [%g1 + %g3] ASI_DCACHE_INVALIDATE stxa %g0, [%g1 + %g3] ASI_DCACHE_INVALIDATE
membar #Sync
bne,pt %icc, 1b bne,pt %icc, 1b
nop nop
membar #Sync
retry retry
nop nop
...@@ -601,7 +636,7 @@ xcall_promstop: ...@@ -601,7 +636,7 @@ xcall_promstop:
rdpr %pil, %g2 rdpr %pil, %g2
wrpr %g0, 15, %pil wrpr %g0, 15, %pil
sethi %hi(109f), %g7 sethi %hi(109f), %g7
b,pt %xcc, etrap b,pt %xcc, etrap_irq
109: or %g7, %lo(109b), %g7 109: or %g7, %lo(109b), %g7
flushw flushw
call prom_stopself call prom_stopself
...@@ -618,10 +653,8 @@ errata32_hwbug: ...@@ -618,10 +653,8 @@ errata32_hwbug:
.text .text
/* These two are not performance critical... */ /* These two are not performance critical... */
.globl xcall_flush_tlb_all .globl xcall_flush_tlb_all_spitfire
xcall_flush_tlb_all: xcall_flush_tlb_all_spitfire:
BRANCH_IF_CHEETAH(g2, g3, __cheetah_xcall_flush_tlb_all)
__spitfire_xcall_flush_tlb_all:
/* Spitfire Errata #32 workaround. */ /* Spitfire Errata #32 workaround. */
sethi %hi(errata32_hwbug), %g4 sethi %hi(errata32_hwbug), %g4
stx %g0, [%g4 + %lo(errata32_hwbug)] stx %g0, [%g4 + %lo(errata32_hwbug)]
...@@ -663,16 +696,15 @@ __spitfire_xcall_flush_tlb_all: ...@@ -663,16 +696,15 @@ __spitfire_xcall_flush_tlb_all:
flush %g6 flush %g6
retry retry
__cheetah_xcall_flush_tlb_all: .globl xcall_flush_tlb_all_cheetah
xcall_flush_tlb_all_cheetah:
mov 0x80, %g2 mov 0x80, %g2
stxa %g0, [%g2] ASI_DMMU_DEMAP stxa %g0, [%g2] ASI_DMMU_DEMAP
stxa %g0, [%g2] ASI_IMMU_DEMAP stxa %g0, [%g2] ASI_IMMU_DEMAP
retry retry
.globl xcall_flush_cache_all .globl xcall_flush_cache_all_spitfire
xcall_flush_cache_all: xcall_flush_cache_all_spitfire:
BRANCH_IF_CHEETAH(g2, g3, __cheetah_xcall_flush_cache_all)
__spitfire_xcall_flush_cache_all:
sethi %hi(16383), %g2 sethi %hi(16383), %g2
or %g2, %lo(16383), %g2 or %g2, %lo(16383), %g2
clr %g3 clr %g3
...@@ -685,13 +717,6 @@ __spitfire_xcall_flush_cache_all: ...@@ -685,13 +717,6 @@ __spitfire_xcall_flush_cache_all:
flush %g6 flush %g6
retry retry
/* Cheetah's caches are fully coherent in the sense that
* caches are flushed here. We need to verify this and
* really just not even send out the xcall at the top level.
*/
__cheetah_xcall_flush_cache_all:
retry
/* These just get rescheduled to PIL vectors. */ /* These just get rescheduled to PIL vectors. */
.globl xcall_call_function .globl xcall_call_function
xcall_call_function: xcall_call_function:
......
...@@ -252,7 +252,7 @@ struct aty_cursor *__init aty_init_cursor(struct fb_info *info) ...@@ -252,7 +252,7 @@ struct aty_cursor *__init aty_init_cursor(struct fb_info *info)
cursor->offset = info->fix.smem_len; cursor->offset = info->fix.smem_len;
#ifdef __sparc__ #ifdef __sparc__
addr = info->screen_base - 0x800000 + cursor->offset; addr = (unsigned long) info->screen_base - 0x800000 + cursor->offset;
cursor->ram = (u8 *) addr; cursor->ram = (u8 *) addr;
#else #else
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
......
...@@ -203,7 +203,7 @@ static void cg14_margins (struct fb_info_sbusfb *fb, struct display *p, ...@@ -203,7 +203,7 @@ static void cg14_margins (struct fb_info_sbusfb *fb, struct display *p,
int x_margin, int y_margin) int x_margin, int y_margin)
{ {
fb->info.screen_base += (y_margin - fb->y_margin) * fb->info.screen_base += (y_margin - fb->y_margin) *
p->line_length + (x_margin - fb->x_margin); fb->info.fix.line_length + (x_margin - fb->x_margin);
} }
static void cg14_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) static void cg14_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
......
...@@ -673,7 +673,7 @@ static void cg6_reset (struct fb_info_sbusfb *fb) ...@@ -673,7 +673,7 @@ static void cg6_reset (struct fb_info_sbusfb *fb)
static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
{ {
fb->info.screen_base += (y_margin - fb->y_margin) * fb->info.screen_base += (y_margin - fb->y_margin) *
p->line_length + (x_margin - fb->x_margin); fb->info.fix.line_length + (x_margin - fb->x_margin);
} }
static int __init cg6_rasterimg (struct fb_info *info, int start) static int __init cg6_rasterimg (struct fb_info *info, int start)
......
...@@ -140,7 +140,7 @@ static void cg3_margins (struct fb_info_sbusfb *fb, struct display *p, ...@@ -140,7 +140,7 @@ static void cg3_margins (struct fb_info_sbusfb *fb, struct display *p,
int x_margin, int y_margin) int x_margin, int y_margin)
{ {
fb->info.screen_base += (y_margin - fb->y_margin) * fb->info.screen_base += (y_margin - fb->y_margin) *
p->line_length + (x_margin - fb->x_margin); fb->info.fix.line_length + (x_margin - fb->x_margin);
} }
static u8 cg3regvals_66hz[] __initdata = { /* 1152 x 900, 66 Hz */ static u8 cg3regvals_66hz[] __initdata = { /* 1152 x 900, 66 Hz */
......
...@@ -78,10 +78,6 @@ static int sbusfb_open(struct fb_info *info, int user); ...@@ -78,10 +78,6 @@ static int sbusfb_open(struct fb_info *info, int user);
static int sbusfb_release(struct fb_info *info, int user); static int sbusfb_release(struct fb_info *info, int user);
static int sbusfb_mmap(struct fb_info *info, struct file *file, static int sbusfb_mmap(struct fb_info *info, struct file *file,
struct vm_area_struct *vma); struct vm_area_struct *vma);
static int sbusfb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int sbusfb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int sbusfb_set_var(struct fb_var_screeninfo *var, int con, static int sbusfb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info); struct fb_info *info);
static int sbusfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, static int sbusfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
...@@ -115,8 +111,6 @@ static struct fb_ops sbusfb_ops = { ...@@ -115,8 +111,6 @@ static struct fb_ops sbusfb_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_open = sbusfb_open, .fb_open = sbusfb_open,
.fb_release = sbusfb_release, .fb_release = sbusfb_release,
.fb_get_fix = sbusfb_get_fix,
.fb_get_var = sbusfb_get_var,
.fb_set_var = sbusfb_set_var, .fb_set_var = sbusfb_set_var,
.fb_get_cmap = sbusfb_get_cmap, .fb_get_cmap = sbusfb_get_cmap,
.fb_set_cmap = sbusfb_set_cmap, .fb_set_cmap = sbusfb_set_cmap,
...@@ -303,31 +297,6 @@ static void sbusfb_disp_setup(struct display *p) ...@@ -303,31 +297,6 @@ static void sbusfb_disp_setup(struct display *p)
sbusfb_clear_margin(p, 0); sbusfb_clear_margin(p, 0);
} }
/*
* Get the Fixed Part of the Display
*/
static int sbusfb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{
struct fb_info_sbusfb *fb = sbusfbinfo(info);
memcpy(fix, &fb->fix, sizeof(struct fb_fix_screeninfo));
return 0;
}
/*
* Get the User Defined Part of the Display
*/
static int sbusfb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
struct fb_info_sbusfb *fb = sbusfbinfo(info);
memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));
return 0;
}
/* /*
* Set the User Defined Part of the Display * Set the User Defined Part of the Display
...@@ -1084,10 +1053,6 @@ static void __init sbusfb_init_fb(int node, int parent, int fbtype, ...@@ -1084,10 +1053,6 @@ static void __init sbusfb_init_fb(int node, int parent, int fbtype,
fb->dispsw.clear_margins = NULL; fb->dispsw.clear_margins = NULL;
disp->var = *var; disp->var = *var;
disp->visual = fix->visual;
disp->type = fix->type;
disp->type_aux = fix->type_aux;
disp->line_length = fix->line_length;
if (fb->blank) if (fb->blank)
disp->can_soft_blank = 1; disp->can_soft_blank = 1;
......
...@@ -66,16 +66,24 @@ static __inline__ void ide_init_default_hwifs(void) ...@@ -66,16 +66,24 @@ static __inline__ void ide_init_default_hwifs(void)
for (index = 0; index < MAX_HWIFS; index++) { for (index = 0; index < MAX_HWIFS; index++) {
ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL); ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
hw.irq = ide_default_irq(ide_default_io_base(index)); hw.irq = ide_default_irq(ide_default_io_base(index));
ide_register_hw(&hw); ide_register_hw(&hw, NULL);
} }
#endif #endif
} }
#undef SUPPORT_SLOW_DATA_PORTS #define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id))
#define SUPPORT_SLOW_DATA_PORTS 0 #define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id))
#define ide_check_region(from,extent) check_region((from), (extent))
#define ide_request_region(from,extent,name) request_region((from), (extent), (name))
#define ide_release_region(from,extent) release_region((from), (extent))
#undef HD_DATA /*
#define HD_DATA ((ide_ioreg_t)0) * The following are not needed for the non-m68k ports
*/
#define ide_ack_intr(hwif) (1)
#define ide_fix_driveid(id) do {} while (0)
#define ide_release_lock(lock) do {} while (0)
#define ide_get_lock(lock, hdlr, data) do {} while (0)
/* From m68k code... */ /* From m68k code... */
......
...@@ -181,7 +181,7 @@ extern unsigned long empty_zero_page; ...@@ -181,7 +181,7 @@ extern unsigned long empty_zero_page;
#define BAD_PAGETABLE __bad_pagetable() #define BAD_PAGETABLE __bad_pagetable()
#define BAD_PAGE __bad_page() #define BAD_PAGE __bad_page()
#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) #define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
/* /*
*/ */
......
...@@ -171,7 +171,7 @@ ...@@ -171,7 +171,7 @@
#define __NR_poll 153 /* Common */ #define __NR_poll 153 /* Common */
#define __NR_getdents64 154 /* Linux specific */ #define __NR_getdents64 154 /* Linux specific */
#define __NR_fcntl64 155 /* Linux sparc32 Specific */ #define __NR_fcntl64 155 /* Linux sparc32 Specific */
/* #define __NR_getdirentries 156 SunOS Specific */ #define __NR_security 156 /* getdirentries under SunOS */
#define __NR_statfs 157 /* Common */ #define __NR_statfs 157 /* Common */
#define __NR_fstatfs 158 /* Common */ #define __NR_fstatfs 158 /* Common */
#define __NR_umount 159 /* Common */ #define __NR_umount 159 /* Common */
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#define ASI_WCACHE_DATA 0x39 /* (III) WCache data RAM diag */ #define ASI_WCACHE_DATA 0x39 /* (III) WCache data RAM diag */
#define ASI_WCACHE_TAG 0x3a /* (III) WCache tag RAM diag */ #define ASI_WCACHE_TAG 0x3a /* (III) WCache tag RAM diag */
#define ASI_WCACHE_SNOOP_TAG 0x3b /* (III) WCache snoop tag RAM diag */ #define ASI_WCACHE_SNOOP_TAG 0x3b /* (III) WCache snoop tag RAM diag */
#define ASI_SRAM_FAST_INIT 0x40 /* (III+) Fast SRAM init */
#define ASI_DCACHE_INVALIDATE 0x42 /* (III) DCache Invalidate diag */ #define ASI_DCACHE_INVALIDATE 0x42 /* (III) DCache Invalidate diag */
#define ASI_DCACHE_UTAG 0x43 /* (III) DCache uTag diag */ #define ASI_DCACHE_UTAG 0x43 /* (III) DCache uTag diag */
#define ASI_DCACHE_SNOOP_TAG 0x44 /* (III) DCache snoop tag RAM diag */ #define ASI_DCACHE_SNOOP_TAG 0x44 /* (III) DCache snoop tag RAM diag */
......
...@@ -2,11 +2,13 @@ ...@@ -2,11 +2,13 @@
#ifndef _SPARC64_DCR_H #ifndef _SPARC64_DCR_H
#define _SPARC64_DCR_H #define _SPARC64_DCR_H
/* UltraSparc-III Dispatch Control Register, ASR 0x12 */ /* UltraSparc-III/III+ Dispatch Control Register, ASR 0x12 */
#define DCR_DPE 0x0000000000001000 /* III+: D$ Parity Error Enable */
#define DCR_OBS 0x0000000000000fc0 /* Observability Bus Controls */ #define DCR_OBS 0x0000000000000fc0 /* Observability Bus Controls */
#define DCR_BPE 0x0000000000000020 /* Branch Predict Enable */ #define DCR_BPE 0x0000000000000020 /* Branch Predict Enable */
#define DCR_RPE 0x0000000000000010 /* Return Address Prediction Enable */ #define DCR_RPE 0x0000000000000010 /* Return Address Prediction Enable */
#define DCR_SI 0x0000000000000008 /* Single Instruction Disable */ #define DCR_SI 0x0000000000000008 /* Single Instruction Disable */
#define DCR_IPE 0x0000000000000004 /* III+: I$ Parity Error Enable */
#define DCR_IFPOE 0x0000000000000002 /* IRQ FP Operation Enable */ #define DCR_IFPOE 0x0000000000000002 /* IRQ FP Operation Enable */
#define DCR_MS 0x0000000000000001 /* Multi-Scalar dispatch */ #define DCR_MS 0x0000000000000001 /* Multi-Scalar dispatch */
......
...@@ -89,7 +89,8 @@ typedef struct { ...@@ -89,7 +89,8 @@ typedef struct {
#define ELF_HWCAP ((HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \ #define ELF_HWCAP ((HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \
HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV | \ HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV | \
HWCAP_SPARC_V9) | \ HWCAP_SPARC_V9) | \
((tlb_type == cheetah) ? HWCAP_SPARC_ULTRA3 : 0)) ((tlb_type == cheetah || tlb_type == cheetah_plus) ? \
HWCAP_SPARC_ULTRA3 : 0))
/* This yields a string that ld.so will use to load implementation /* This yields a string that ld.so will use to load implementation
specific libraries for optimization. This is more specific in specific libraries for optimization. This is more specific in
......
...@@ -8,4 +8,7 @@ ...@@ -8,4 +8,7 @@
#define PTREGS_OFF (STACK_BIAS + REGWIN_SZ) #define PTREGS_OFF (STACK_BIAS + REGWIN_SZ)
#define CHEETAH_ID 0x003e0014
#define CHEETAH_PLUS_ID 0x003e0015
#endif /* !(_SPARC64_HEAD_H) */ #endif /* !(_SPARC64_HEAD_H) */
...@@ -62,16 +62,25 @@ static __inline__ void ide_init_default_hwifs(void) ...@@ -62,16 +62,25 @@ static __inline__ void ide_init_default_hwifs(void)
for (index = 0; index < MAX_HWIFS; index++) { for (index = 0; index < MAX_HWIFS; index++) {
ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL); ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
hw.irq = ide_default_irq(ide_default_io_base(index)); hw.irq = ide_default_irq(ide_default_io_base(index));
ide_register_hw(&hw); ide_register_hw(&hw, NULL);
} }
#endif #endif
} }
#undef SUPPORT_SLOW_DATA_PORTS
#define SUPPORT_SLOW_DATA_PORTS 0
#undef HD_DATA #define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id))
#define HD_DATA ((ide_ioreg_t)0) #define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id))
#define ide_check_region(from,extent) check_region((from), (extent))
#define ide_request_region(from,extent,name) request_region((from), (extent), (name))
#define ide_release_region(from,extent) release_region((from), (extent))
/*
* The following are not needed for the non-m68k ports
*/
#define ide_ack_intr(hwif) (1)
#define ide_fix_driveid(id) do {} while (0)
#define ide_release_lock(lock) do {} while (0)
#define ide_get_lock(lock, hdlr, data) do {} while (0)
/* From m68k code... */ /* From m68k code... */
......
...@@ -91,7 +91,7 @@ static inline int any_online_cpu(unsigned long mask) ...@@ -91,7 +91,7 @@ static inline int any_online_cpu(unsigned long mask)
extern __inline__ int hard_smp_processor_id(void) extern __inline__ int hard_smp_processor_id(void)
{ {
if (tlb_type == cheetah) { if (tlb_type == cheetah || tlb_type == cheetah_plus) {
unsigned long safari_config; unsigned long safari_config;
__asm__ __volatile__("ldxa [%%g0] %1, %0" __asm__ __volatile__("ldxa [%%g0] %1, %0"
: "=r" (safari_config) : "=r" (safari_config)
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#define TSB_EXTENSION_P 0x0000000000000048 /* Ultra-III and later */ #define TSB_EXTENSION_P 0x0000000000000048 /* Ultra-III and later */
#define TSB_EXTENSION_S 0x0000000000000050 /* Ultra-III and later, D-TLB only */ #define TSB_EXTENSION_S 0x0000000000000050 /* Ultra-III and later, D-TLB only */
#define TSB_EXTENSION_N 0x0000000000000058 /* Ultra-III and later */ #define TSB_EXTENSION_N 0x0000000000000058 /* Ultra-III and later */
#define TLB_TAG_ACCESS_EXT 0x0000000000000060 /* Ultra-III+ and later */
/* These registers only exist as one entity, and are accessed /* These registers only exist as one entity, and are accessed
* via ASI_DMMU only. * via ASI_DMMU only.
...@@ -38,12 +39,13 @@ ...@@ -38,12 +39,13 @@
enum ultra_tlb_layout { enum ultra_tlb_layout {
spitfire = 0, spitfire = 0,
cheetah = 1 cheetah = 1,
cheetah_plus = 2,
}; };
extern enum ultra_tlb_layout tlb_type; extern enum ultra_tlb_layout tlb_type;
#define SPARC64_USE_STICK (tlb_type == cheetah) #define SPARC64_USE_STICK (tlb_type != spitfire)
#define CHEETAH_HIGHEST_LOCKED_TLBENT (16 - 1) #define CHEETAH_HIGHEST_LOCKED_TLBENT (16 - 1)
...@@ -433,35 +435,35 @@ extern __inline__ void cheetah_put_litlb_data(int entry, unsigned long data) ...@@ -433,35 +435,35 @@ extern __inline__ void cheetah_put_litlb_data(int entry, unsigned long data)
"i" (ASI_ITLB_DATA_ACCESS)); "i" (ASI_ITLB_DATA_ACCESS));
} }
extern __inline__ unsigned long cheetah_get_dtlb_data(int entry) extern __inline__ unsigned long cheetah_get_dtlb_data(int entry, int tlb)
{ {
unsigned long data; unsigned long data;
__asm__ __volatile__("ldxa [%1] %2, %%g0\n\t" __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t"
"ldxa [%1] %2, %0" "ldxa [%1] %2, %0"
: "=r" (data) : "=r" (data)
: "r" ((2 << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS)); : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS));
return data; return data;
} }
extern __inline__ unsigned long cheetah_get_dtlb_tag(int entry) extern __inline__ unsigned long cheetah_get_dtlb_tag(int entry, int tlb)
{ {
unsigned long tag; unsigned long tag;
__asm__ __volatile__("ldxa [%1] %2, %0" __asm__ __volatile__("ldxa [%1] %2, %0"
: "=r" (tag) : "=r" (tag)
: "r" ((2 << 16) | (entry << 3)), "i" (ASI_DTLB_TAG_READ)); : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_TAG_READ));
return tag; return tag;
} }
extern __inline__ void cheetah_put_dtlb_data(int entry, unsigned long data) extern __inline__ void cheetah_put_dtlb_data(int entry, unsigned long data, int tlb)
{ {
__asm__ __volatile__("stxa %0, [%1] %2\n\t" __asm__ __volatile__("stxa %0, [%1] %2\n\t"
"membar #Sync" "membar #Sync"
: /* No outputs */ : /* No outputs */
: "r" (data), : "r" (data),
"r" ((2 << 16) | (entry << 3)), "r" ((tlb << 16) | (entry << 3)),
"i" (ASI_DTLB_DATA_ACCESS)); "i" (ASI_DTLB_DATA_ACCESS));
} }
......
...@@ -171,7 +171,7 @@ ...@@ -171,7 +171,7 @@
#define __NR_poll 153 /* Common */ #define __NR_poll 153 /* Common */
#define __NR_getdents64 154 /* Linux specific */ #define __NR_getdents64 154 /* Linux specific */
/* #define __NR_fcntl64 155 Linux sparc32 Specific */ /* #define __NR_fcntl64 155 Linux sparc32 Specific */
/* #define __NR_getdirentries 156 SunOS Specific */ #define __NR_security 156 /* getdirentries under SunOS */
#define __NR_statfs 157 /* Common */ #define __NR_statfs 157 /* Common */
#define __NR_fstatfs 158 /* Common */ #define __NR_fstatfs 158 /* Common */
#define __NR_umount 159 /* Common */ #define __NR_umount 159 /* Common */
......
...@@ -409,6 +409,7 @@ extern void cfb_imageblit(struct fb_info *info, struct fb_image *image); ...@@ -409,6 +409,7 @@ extern void cfb_imageblit(struct fb_info *info, struct fb_image *image);
* Helper functions * Helper functions
*/ */
extern void do_install_cmap(int con, struct fb_info *info);
extern int gen_update_var(int con, struct fb_info *info); extern int gen_update_var(int con, struct fb_info *info);
extern int fb_blank(int blank, struct fb_info *info); extern int fb_blank(int blank, struct fb_info *info);
extern int gen_switch(int con, struct fb_info *info); extern int gen_switch(int con, struct fb_info *info);
......
...@@ -309,7 +309,7 @@ struct task_struct { ...@@ -309,7 +309,7 @@ struct task_struct {
wait_queue_head_t wait_chldexit; /* for wait4() */ wait_queue_head_t wait_chldexit; /* for wait4() */
struct completion *vfork_done; /* for vfork() */ struct completion *vfork_done; /* for vfork() */
long *user_tid; /* for CLONE_CLEARTID */ int *user_tid; /* for CLONE_CLEARTID */
unsigned long rt_priority; unsigned long rt_priority;
unsigned long it_real_value, it_prof_value, it_virt_value; unsigned long it_real_value, it_prof_value, it_virt_value;
......
...@@ -377,7 +377,7 @@ void mm_release(void) ...@@ -377,7 +377,7 @@ void mm_release(void)
* We dont check the error code - if userspace has * We dont check the error code - if userspace has
* not set up a proper pointer then tough luck. * not set up a proper pointer then tough luck.
*/ */
put_user(0UL, tsk->user_tid); put_user(0, tsk->user_tid);
sys_futex(tsk->user_tid, FUTEX_WAKE, 1, NULL); sys_futex(tsk->user_tid, FUTEX_WAKE, 1, NULL);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment