summaryrefslogtreecommitdiffstats
path: root/arch/sparc64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64')
-rw-r--r--arch/sparc64/kernel/entry.S14
-rw-r--r--arch/sparc64/kernel/head.S13
-rw-r--r--arch/sparc64/kernel/setup.c10
-rw-r--r--arch/sparc64/kernel/smp.c12
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c28
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c26
-rw-r--r--arch/sparc64/lib/blockops.S38
-rw-r--r--arch/sparc64/mm/init.c86
-rw-r--r--arch/sparc64/mm/ultra.S56
9 files changed, 224 insertions, 59 deletions
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index df636ec6f..2ab8b70d4 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.112 2000/01/14 07:12:31 davem Exp $
+/* $Id: entry.S,v 1.113 2000/03/06 22:33:42 davem Exp $
* arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points.
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -927,7 +927,17 @@ ret_from_syscall:
nop
ldx [%g6 + AOFF_task_thread + AOFF_thread_pcr_reg], %o7
wr %g0, %o7, %pcr
- wr %g0, %g0, %pic
+
+ /* Blackbird errata workaround. See commentary in
+ * smp.c:smp_percpu_timer_interrupt() for more
+ * information.
+ */
+ ba,pt %xcc, 99f
+ nop
+ .align 64
+99: wr %g0, %g0, %pic
+ rd %pic, %g0
+
1: b,pt %xcc, ret_sys_call
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0
sparc_exit: rdpr %otherwin, %g1
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 47a170f54..7eefa9f65 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.63 1999/11/19 05:52:49 davem Exp $
+/* $Id: head.S,v 1.64 2000/03/06 22:33:42 davem Exp $
* head.S: Initial boot code for the Sparc64 port of Linux.
*
* Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -262,7 +262,16 @@ sun4u_init:
/* Setup "Linux Current Register", thanks Sun 8-) */
wr %g0, 0x1, %pcr
- wr %g6, 0x0, %pic
+
+ /* Blackbird errata workaround. See commentary in
+ * smp.c:smp_percpu_timer_interrupt() for more
+ * information.
+ */
+ ba,pt %xcc, 99f
+ nop
+ .align 64
+99: wr %g6, %g0, %pic
+ rd %pic, %g0
#endif
wr %g0, ASI_P, %asi
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index ed2e8bd81..0d1b968fa 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.51 2000/02/26 04:24:32 davem Exp $
+/* $Id: setup.c,v 1.52 2000/03/03 23:48:41 davem Exp $
* linux/arch/sparc64/kernel/setup.c
*
* Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
@@ -164,9 +164,17 @@ int prom_callback(long *args)
}
if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) {
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
/*
* Locked down tlb entry 63.
*/
+
tte = spitfire_get_dtlb_data(63);
res = PROM_TRUE;
goto done;
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 175372877..96360b010 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -312,6 +312,13 @@ static inline void xcall_deliver(u64 data0, u64 data1, u64 data2, u64 pstate, un
smp_processor_id(), data0, data1, data2, target);
#endif
again:
+ /* Ok, this is the real Spitfire Errata #54.
+ * One must read back from a UDB internal register
+ * after writes to the UDB interrupt dispatch, but
+ * before the membar Sync for that write.
+ * So we use the high UDB control register (ASI 0x7f,
+ * ADDR 0x20) for the dummy read. -DaveM
+ */
tmp = 0x40;
__asm__ __volatile__("
wrpr %1, %2, %%pstate
@@ -321,10 +328,13 @@ again:
stxa %6, [%0+%8] %3
membar #Sync
stxa %%g0, [%7] %3
+ mov 0x20, %%g1
+ ldxa [%%g1] 0x7f, %%g0
membar #Sync"
: "=r" (tmp)
: "r" (pstate), "i" (PSTATE_IE), "i" (ASI_UDB_INTR_W),
- "r" (data0), "r" (data1), "r" (data2), "r" (target), "r" (0x10), "0" (tmp));
+ "r" (data0), "r" (data1), "r" (data2), "r" (target), "r" (0x10), "0" (tmp)
+ : "g1");
/* NOTE: PSTATE_IE is still clear. */
stuck = 100000;
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 6e2d566b2..d3f02ae54 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1257,10 +1257,8 @@ asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent,
{
int error = -EBADF;
struct file * file;
- struct inode * inode;
struct readdir_callback32 buf;
- lock_kernel();
file = fget(fd);
if (!file)
goto out;
@@ -1268,22 +1266,16 @@ asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent,
buf.count = 0;
buf.dirent = dirent;
- error = -ENOTDIR;
- if (!file->f_op || !file->f_op->readdir)
- goto out_putf;
-
- inode = file->f_dentry->d_inode;
- down(&inode->i_sem);
- error = file->f_op->readdir(file, &buf, fillonedir);
- up(&inode->i_sem);
+ lock_kernel();
+ error = vfs_readdir(file, fillonedir, &buf);
if (error < 0)
goto out_putf;
error = buf.count;
out_putf:
+ unlock_kernel();
fput(file);
out:
- unlock_kernel();
return error;
}
@@ -1328,12 +1320,10 @@ static int filldir(void * __buf, const char * name, int namlen, off_t offset, in
asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count)
{
struct file * file;
- struct inode * inode;
struct linux_dirent32 * lastdirent;
struct getdents_callback32 buf;
int error = -EBADF;
- lock_kernel();
file = fget(fd);
if (!file)
goto out;
@@ -1343,14 +1333,8 @@ asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, un
buf.count = count;
buf.error = 0;
- error = -ENOTDIR;
- if (!file->f_op || !file->f_op->readdir)
- goto out_putf;
-
- inode = file->f_dentry->d_inode;
- down(&inode->i_sem);
- error = file->f_op->readdir(file, &buf, filldir);
- up(&inode->i_sem);
+ lock_kernel();
+ error = vfs_readdir(file, filldir, &buf);
if (error < 0)
goto out_putf;
lastdirent = buf.previous;
@@ -1360,9 +1344,9 @@ asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, un
error = count - buf.count;
}
out_putf:
+ unlock_kernel();
fput(file);
out:
- unlock_kernel();
return error;
}
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index c5101248a..d977c7952 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -388,13 +388,11 @@ static int sunos_filldir(void * __buf, const char * name, int namlen,
asmlinkage int sunos_getdents(unsigned int fd, u32 u_dirent, int cnt)
{
struct file * file;
- struct inode * inode;
struct sunos_dirent * lastdirent;
struct sunos_dirent_callback buf;
int error = -EBADF;
void *dirent = (void *)A(u_dirent);
- lock_kernel();
if(fd >= SUNOS_NR_OPEN)
goto out;
@@ -402,9 +400,7 @@ asmlinkage int sunos_getdents(unsigned int fd, u32 u_dirent, int cnt)
if(!file)
goto out;
- error = -ENOTDIR;
- if (!file->f_op || !file->f_op->readdir)
- goto out_putf;
+ lock_kernel();
error = -EINVAL;
if(cnt < (sizeof(struct sunos_dirent) + 255))
@@ -415,10 +411,7 @@ asmlinkage int sunos_getdents(unsigned int fd, u32 u_dirent, int cnt)
buf.count = cnt;
buf.error = 0;
- inode = file->f_dentry->d_inode;
- down(&inode->i_sem);
- error = file->f_op->readdir(file, &buf, sunos_filldir);
- up(&inode->i_sem);
+ error = vfs_readdir(file, sunos_filldir, &buf);
if (error < 0)
goto out_putf;
@@ -430,9 +423,9 @@ asmlinkage int sunos_getdents(unsigned int fd, u32 u_dirent, int cnt)
}
out_putf:
+ unlock_kernel();
fput(file);
out:
- unlock_kernel();
return error;
}
@@ -481,12 +474,10 @@ asmlinkage int sunos_getdirentries(unsigned int fd, u32 u_dirent,
void *dirent = (void *) A(u_dirent);
unsigned int *basep = (unsigned int *)A(u_basep);
struct file * file;
- struct inode * inode;
struct sunos_direntry * lastdirent;
int error = -EBADF;
struct sunos_direntry_callback buf;
- lock_kernel();
if(fd >= SUNOS_NR_OPEN)
goto out;
@@ -494,9 +485,7 @@ asmlinkage int sunos_getdirentries(unsigned int fd, u32 u_dirent,
if(!file)
goto out;
- error = -ENOTDIR;
- if (!file->f_op || !file->f_op->readdir)
- goto out_putf;
+ lock_kernel();
error = -EINVAL;
if(cnt < (sizeof(struct sunos_direntry) + 255))
@@ -507,10 +496,7 @@ asmlinkage int sunos_getdirentries(unsigned int fd, u32 u_dirent,
buf.count = cnt;
buf.error = 0;
- inode = file->f_dentry->d_inode;
- down(&inode->i_sem);
- error = file->f_op->readdir(file, &buf, sunos_filldirentry);
- up(&inode->i_sem);
+ error = vfs_readdir(file, sunos_filldirentry, &buf);
if (error < 0)
goto out_putf;
@@ -522,9 +508,9 @@ asmlinkage int sunos_getdirentries(unsigned int fd, u32 u_dirent,
}
out_putf:
+ unlock_kernel();
fput(file);
out:
- unlock_kernel();
return error;
}
diff --git a/arch/sparc64/lib/blockops.S b/arch/sparc64/lib/blockops.S
index 1aa48643c..1cdbf09da 100644
--- a/arch/sparc64/lib/blockops.S
+++ b/arch/sparc64/lib/blockops.S
@@ -1,4 +1,4 @@
-/* $Id: blockops.S,v 1.19 1999/11/19 05:52:45 davem Exp $
+/* $Id: blockops.S,v 1.20 2000/03/03 23:48:38 davem Exp $
* blockops.S: UltraSparc block zero optimized routines.
*
* Copyright (C) 1996,1998 David S. Miller (davem@caip.rutgers.edu)
@@ -46,13 +46,37 @@ copy_page: /* %o0=dest, %o1=src */
sethi %hi(TLBTEMP_ENT1), %o3
rdpr %pstate, %g3
wrpr %g3, PSTATE_IE, %pstate
+
+ /* Spitfire Errata #32 workaround */
+ mov 0x8, %o4
+ stxa %g0, [%o4] ASI_DMMU
+ flush %g6
+
ldxa [%o3] ASI_DTLB_TAG_READ, %o4
+
+ /* Spitfire Errata #32 workaround */
+ mov 0x8, %o5
+ stxa %g0, [%o5] ASI_DMMU
+ flush %g6
+
ldxa [%o3] ASI_DTLB_DATA_ACCESS, %o5
stxa %o0, [%o2] ASI_DMMU
stxa %g1, [%o3] ASI_DTLB_DATA_ACCESS
membar #Sync
add %o3, (TLBTEMP_ENTSZ), %o3
+
+ /* Spitfire Errata #32 workaround */
+ mov 0x8, %g5
+ stxa %g0, [%g5] ASI_DMMU
+ flush %g6
+
ldxa [%o3] ASI_DTLB_TAG_READ, %g5
+
+ /* Spitfire Errata #32 workaround */
+ mov 0x8, %g7
+ stxa %g0, [%g7] ASI_DMMU
+ flush %g6
+
ldxa [%o3] ASI_DTLB_DATA_ACCESS, %g7
stxa %o1, [%o2] ASI_DMMU
stxa %g2, [%o3] ASI_DTLB_DATA_ACCESS
@@ -120,7 +144,19 @@ clear_page: /* %o0=dest */
sethi %hi(TLBTEMP_ENT2), %o3
rdpr %pstate, %g3
wrpr %g3, PSTATE_IE, %pstate
+
+ /* Spitfire Errata #32 workaround */
+ mov 0x8, %g5
+ stxa %g0, [%g5] ASI_DMMU
+ flush %g6
+
ldxa [%o3] ASI_DTLB_TAG_READ, %g5
+
+ /* Spitfire Errata #32 workaround */
+ mov 0x8, %g7
+ stxa %g0, [%g7] ASI_DMMU
+ flush %g6
+
ldxa [%o3] ASI_DTLB_DATA_ACCESS, %g7
stxa %o0, [%o2] ASI_DMMU
stxa %g1, [%o3] ASI_DTLB_DATA_ACCESS
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 58dc224f9..68147d4d4 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.146 2000/02/09 21:11:09 davem Exp $
+/* $Id: init.c,v 1.147 2000/03/03 23:48:44 davem Exp $
* arch/sparc64/mm/init.c
*
* Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -230,6 +230,14 @@ static void inherit_prom_mappings(void)
/* Now fixup OBP's idea about where we really are mapped. */
prom_printf("Remapping the kernel... ");
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
phys_page = spitfire_get_dtlb_data(63) & _PAGE_PADDR;
phys_page += ((unsigned long)&prom_boot_page -
(unsigned long)&empty_zero_page);
@@ -252,11 +260,27 @@ static void inherit_prom_mappings(void)
: "memory");
tte_vaddr = (unsigned long) &empty_zero_page;
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
kern_locked_tte_data = tte_data = spitfire_get_dtlb_data(63);
remap_func = (void *) ((unsigned long) &prom_remap -
(unsigned long) &prom_boot_page);
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
remap_func(spitfire_get_dtlb_data(63) & _PAGE_PADDR,
(unsigned long) &empty_zero_page,
prom_get_mmu_ihandle());
@@ -319,8 +343,16 @@ static void __flush_nucleus_vptes(void)
/* Only DTLB must be checked for VPTE entries. */
for(i = 0; i < 63; i++) {
- unsigned long tag = spitfire_get_dtlb_tag(i);
+ unsigned long tag;
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
+ tag = spitfire_get_dtlb_tag(i);
if(((tag & ~(PAGE_MASK)) == 0) &&
((tag & (PAGE_MASK)) >= prom_reserved_base)) {
__asm__ __volatile__("stxa %%g0, [%0] %1"
@@ -436,10 +468,26 @@ void inherit_locked_prom_mappings(int save_p)
for(i = 0; i < 63; i++) {
unsigned long data;
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
data = spitfire_get_dtlb_data(i);
if((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
- unsigned long tag = spitfire_get_dtlb_tag(i);
+ unsigned long tag;
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+ tag = spitfire_get_dtlb_tag(i);
if(save_p) {
prom_dtlb[dtlb_seen].tlb_ent = i;
prom_dtlb[dtlb_seen].tlb_tag = tag;
@@ -459,10 +507,25 @@ void inherit_locked_prom_mappings(int save_p)
for(i = 0; i < 63; i++) {
unsigned long data;
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
data = spitfire_get_itlb_data(i);
if((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
- unsigned long tag = spitfire_get_itlb_tag(i);
+ unsigned long tag;
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+ tag = spitfire_get_itlb_tag(i);
if(save_p) {
prom_itlb[itlb_seen].tlb_ent = i;
prom_itlb[itlb_seen].tlb_tag = tag;
@@ -544,6 +607,13 @@ void __flush_tlb_all(void)
: "=r" (pstate)
: "i" (PSTATE_IE));
for(i = 0; i < 64; i++) {
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
if(!(spitfire_get_dtlb_data(i) & _PAGE_L)) {
__asm__ __volatile__("stxa %%g0, [%0] %1"
: /* no outputs */
@@ -552,6 +622,14 @@ void __flush_tlb_all(void)
spitfire_put_dtlb_data(i, 0x0UL);
membar("#Sync");
}
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
if(!(spitfire_get_itlb_data(i) & _PAGE_L)) {
__asm__ __volatile__("stxa %%g0, [%0] %1"
: /* no outputs */
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
index 0825b0585..210db79e6 100644
--- a/arch/sparc64/mm/ultra.S
+++ b/arch/sparc64/mm/ultra.S
@@ -1,4 +1,4 @@
-/* $Id: ultra.S,v 1.37 2000/02/14 02:52:04 davem Exp $
+/* $Id: ultra.S,v 1.38 2000/03/03 23:48:44 davem Exp $
* ultra.S: Don't expand these all over the place...
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -35,7 +35,7 @@ __flush_tlb_mm: /* %o0=(ctx & 0x3ff), %o1=SECONDARY_CONTEXT */
__flush_tlb_range: /* %o0=(ctx&0x3ff), %o1=start&PAGE_MASK, %o2=SECONDARY_CONTEXT,
* %o3=end&PAGE_MASK, %o4=PAGE_SIZE, %o5=(end - start)
*/
-#define TLB_MAGIC 206 /* Students, do you know how I calculated this? -DaveM */
+#define TLB_MAGIC 207 /* Students, do you know how I calculated this? -DaveM */
/*IC3*/ cmp %o5, %o4
be,pt %xcc, __flush_tlb_page
srlx %o5, 13, %g5
@@ -58,6 +58,12 @@ __flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
wrpr %g1, PSTATE_IE, %pstate
mov TLB_TAG_ACCESS, %g3
mov (62 << 3), %g2
+
+ /* Spitfire Errata #32 workaround. */
+ mov 0x8, %o4
+ stxa %g0, [%o4] ASI_DMMU
+ flush %g6
+
1: ldxa [%g2] ASI_ITLB_TAG_READ, %o4
and %o4, 0x3ff, %o5
cmp %o5, %o0
@@ -83,12 +89,27 @@ __flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
wrpr %g1, 0x0, %pstate
4: stxa %g0, [%g3] ASI_IMMU
stxa %g0, [%g2] ASI_ITLB_DATA_ACCESS
+ flush %g6
+
+ /* Spitfire Errata #32 workaround. */
+ mov 0x8, %o4
+ stxa %g0, [%o4] ASI_DMMU
+ flush %g6
+
ba,pt %xcc, 2b
- flush %g6
+ nop
+
5: stxa %g0, [%g3] ASI_DMMU
/*IC9*/ stxa %g0, [%g2] ASI_DTLB_DATA_ACCESS
+ flush %g6
+
+ /* Spitfire Errata #32 workaround. */
+ mov 0x8, %o4
+ stxa %g0, [%o4] ASI_DMMU
+ flush %g6
+
ba,pt %xcc, 3b
- flush %g6
+ nop
.align 32
__flush_tlb_mm_slow:
@@ -293,28 +314,51 @@ xcall_receive_signal:
clr %l6
99: retry
+ .data
+
+errata32_hwbug:
+ .xword 0
+
+ .text
+
/* These two are not performance critical... */
.globl xcall_flush_tlb_all
xcall_flush_tlb_all:
+
+ /* Spitfire Errata #32 workaround. */
+ sethi %hi(errata32_hwbug), %g4
+ stx %g0, [%g4 + %lo(errata32_hwbug)]
+
clr %g2
clr %g3
1: ldxa [%g3] ASI_DTLB_DATA_ACCESS, %g4
and %g4, _PAGE_L, %g5
brnz,pn %g5, 2f
mov TLB_TAG_ACCESS, %g7
+
stxa %g0, [%g7] ASI_DMMU
membar #Sync
-
stxa %g0, [%g3] ASI_DTLB_DATA_ACCESS
membar #Sync
+
+ /* Spitfire Errata #32 workaround. */
+ sethi %hi(errata32_hwbug), %g4
+ stx %g0, [%g4 + %lo(errata32_hwbug)]
+
2: ldxa [%g3] ASI_ITLB_DATA_ACCESS, %g4
and %g4, _PAGE_L, %g5
brnz,pn %g5, 2f
mov TLB_TAG_ACCESS, %g7
+
stxa %g0, [%g7] ASI_IMMU
membar #Sync
-
stxa %g0, [%g3] ASI_ITLB_DATA_ACCESS
+ membar #Sync
+
+ /* Spitfire Errata #32 workaround. */
+ sethi %hi(errata32_hwbug), %g4
+ stx %g0, [%g4 + %lo(errata32_hwbug)]
+
2: add %g2, 1, %g2
cmp %g2, 63
ble,pt %icc, 1b