diff options
Diffstat (limited to 'arch/sparc64')
-rw-r--r-- | arch/sparc64/kernel/entry.S | 14 | ||||
-rw-r--r-- | arch/sparc64/kernel/head.S | 13 | ||||
-rw-r--r-- | arch/sparc64/kernel/setup.c | 10 | ||||
-rw-r--r-- | arch/sparc64/kernel/smp.c | 12 | ||||
-rw-r--r-- | arch/sparc64/kernel/sys_sparc32.c | 28 | ||||
-rw-r--r-- | arch/sparc64/kernel/sys_sunos32.c | 26 | ||||
-rw-r--r-- | arch/sparc64/lib/blockops.S | 38 | ||||
-rw-r--r-- | arch/sparc64/mm/init.c | 86 | ||||
-rw-r--r-- | arch/sparc64/mm/ultra.S | 56 |
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 |