This patch implements a fast entry for syscalls.
Syscalls don't have to preserve non volatile registers except LR.
This patch then implement a fast entry for syscalls, where
volatile registers get clobbered.
As this entry is dedicated to syscall it always sets MSR_EE
and warns in case MSR_EE was previously off
It also assumes that the call is always from user, system calls are
unexpected from kernel.
Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/kernel/entry_32.S | 7 ---
arch/powerpc/kernel/head_44x.S | 3 +-
arch/powerpc/kernel/head_booke.h | 103 +++++++++++++++++++++++++++++++++--
arch/powerpc/kernel/head_fsl_booke.S | 3 +-
4 files changed, 100 insertions(+), 16 deletions(-)
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 184cc1de2f37..dc58fec51ed6 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -342,7 +342,6 @@ stack_ovf:
SYNC
RFI
-#ifndef CONFIG_BOOKE /* to be removed once BOOKE uses fast syscall entry */
#ifdef CONFIG_TRACE_IRQFLAGS
trace_syscall_entry_irq_off:
/*
@@ -369,7 +368,6 @@ transfer_to_syscall:
andi. r12,r9,MSR_EE
beq- trace_syscall_entry_irq_off
#endif /* CONFIG_TRACE_IRQFLAGS */
-#endif /* !CONFIG_BOOKE */
/*
* Handle a system call.
@@ -382,11 +380,6 @@ _GLOBAL(DoSyscall)
stw r3,ORIG_GPR3(r1)
li r12,0
stw r12,RESULT(r1)
-#ifdef CONFIG_BOOKE /* to be removed once BOOKE uses fast syscall entry */
- lwz r11,_CCR(r1) /* Clear SO bit in CR */
- rlwinm r11,r11,0,4,2
- stw r11,_CCR(r1)
-#endif
#ifdef CONFIG_TRACE_IRQFLAGS
/* Make sure interrupts are enabled */
mfmsr r11
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index e06cb1c84951..7d73c7e39afe 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -282,8 +282,7 @@ interrupt_base:
#endif
/* System Call Interrupt */
START_EXCEPTION(SystemCall)
- NORMAL_EXCEPTION_PROLOG(BOOKE_INTERRUPT_SYSCALL)
- EXC_XFER_SYS(0x0c00, DoSyscall)
+ SYSCALL_ENTRY 0xc00 BOOKE_INTERRUPT_SYSCALL
/* Auxiliary Processor Unavailable Interrupt */
EXCEPTION(0x2020, BOOKE_INTERRUPT_AP_UNAVAIL, \
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h
index 56dd1341eb3d..bfeb469e8106 100644
--- a/arch/powerpc/kernel/head_booke.h
+++ b/arch/powerpc/kernel/head_booke.h
@@ -6,6 +6,8 @@
#include <asm/kvm_asm.h>
#include <asm/kvm_booke_hv_asm.h>
+#ifdef __ASSEMBLY__
+
/*
* Macros used for common Book-e exception handling
*/
@@ -81,6 +83,101 @@ END_BTB_FLUSH_SECTION
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
+.macro SYSCALL_ENTRY trapno intno
+ mfspr r10, SPRN_SPRG_THREAD
+#ifdef CONFIG_KVM_BOOKE_HV
+BEGIN_FTR_SECTION
+ mtspr SPRN_SPRG_WSCRATCH0, r10
+ stw r11, THREAD_NORMSAVE(0)(r10)
+ stw r13, THREAD_NORMSAVE(2)(r10)
+ mfcr r13 /* save CR in r13 for now */
+ mfspr r11, SPRN_SRR1
+ mtocrf 0x80, r11 /* check MSR[GS] without clobbering reg */
+ bf 3, 1975f
+ b kvmppc_handler_BOOKE_INTERRUPT_\intno\()_SPRN_SRR1
+1975:
+ mr r12, r13
+ lwz r13, THREAD_NORMSAVE(2)(r10)
+FTR_SECTION_ELSE
+#endif
+ mfcr r12
+#ifdef CONFIG_KVM_BOOKE_HV
+ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
+#endif
+ BOOKE_CLEAR_BTB(r11)
+ lwz r11, TASK_STACK - THREAD(r10)
+ rlwinm r12,r12,0,4,2 /* Clear SO bit in CR */
+ ALLOC_STACK_FRAME(r11, THREAD_SIZE - INT_FRAME_SIZE)
+ stw r12, _CCR(r11) /* save various registers */
+ mflr r12
+ stw r12,_LINK(r11)
+ mfspr r12,SPRN_SRR0
+ stw r1, GPR1(r11)
+ mfspr r9,SPRN_SRR1
+ stw r1, 0(r11)
+ mr r1, r11
+ stw r12,_NIP(r11)
+ rlwinm r9,r9,0,14,12 /* clear MSR_WE (necessary?) */
+ lis r12, STACK_FRAME_REGS_MARKER@ha /* exception frame marker */
+ stw r2,GPR2(r11)
+ addi r12, r12, STACK_FRAME_REGS_MARKER@l
+ stw r9,_MSR(r11)
+ li r2, \trapno + 1
+ stw r12, 8(r11)
+ stw r2,_TRAP(r11)
+ SAVE_GPR(0, r11)
+ SAVE_4GPRS(3, r11)
+ SAVE_2GPRS(7, r11)
+
+ addi r11,r1,STACK_FRAME_OVERHEAD
+ addi r2,r10,-THREAD
+ stw r11,PT_REGS(r10)
+ /* Check to see if the dbcr0 register is set up to debug. Use the
+ internal debug mode bit to do this. */
+ lwz r12,THREAD_DBCR0(r10)
+ andis. r12,r12,DBCR0_IDM@h
+ ACCOUNT_CPU_USER_ENTRY(r2, r11, r12)
+ beq+ 3f
+ /* From user and task is ptraced - load up global dbcr0 */
+ li r12,-1 /* clear all pending debug events */
+ mtspr SPRN_DBSR,r12
+ lis r11,global_dbcr0@ha
+ tophys(r11,r11)
+ addi r11,r11,global_dbcr0@l
+#ifdef CONFIG_SMP
+ lwz r9,TASK_CPU(r2)
+ slwi r9,r9,3
+ add r11,r11,r9
+#endif
+ lwz r12,0(r11)
+ mtspr SPRN_DBCR0,r12
+ lwz r12,4(r11)
+ addi r12,r12,-1
+ stw r12,4(r11)
+
+3:
+ tovirt(r2, r2) /* set r2 to current */
+ lis r11, transfer_to_syscall@h
+ ori r11, r11, transfer_to_syscall@l
+#ifdef CONFIG_TRACE_IRQFLAGS
+ /*
+ * If MSR is changing we need to keep interrupts disabled at this point
+ * otherwise we might risk taking an interrupt before we tell lockdep
+ * they are enabled.
+ */
+ lis r10, MSR_KERNEL@h
+ ori r10, r10, MSR_KERNEL@l
+ rlwimi r10, r9, 0, MSR_EE
+#else
+ lis r10, (MSR_KERNEL | MSR_EE)@h
+ ori r10, r10, (MSR_KERNEL | MSR_EE)@l
+#endif
+ mtspr SPRN_SRR1,r10
+ mtspr SPRN_SRR0,r11
+ SYNC
+ RFI /* jump to handler, enable MMU */
+.endm
+
/* To handle the additional exception priority levels on 40x and Book-E
* processors we allocate a stack per additional priority level.
*
@@ -245,10 +342,6 @@ END_BTB_FLUSH_SECTION
EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, transfer_to_handler, \
ret_from_except)
-#define EXC_XFER_SYS(n, hdlr) \
- EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL | MSR_EE, transfer_to_handler, \
- ret_from_except)
-
/* Check for a single step debug exception while in an exception
* handler before state has been saved. This is to catch the case
* where an instruction that we are trying to single step causes
@@ -418,7 +511,7 @@ END_BTB_FLUSH_SECTION
1: addi r3,r1,STACK_FRAME_OVERHEAD; \
EXC_XFER_STD(0x800, kernel_fp_unavailable_exception)
-#ifndef __ASSEMBLY__
+#else /* __ASSEMBLY__ */
struct exception_regs {
unsigned long mas0;
unsigned long mas1;
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index b351851dc73d..a757be4f1cb5 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -410,8 +410,7 @@ interrupt_base:
/* System Call Interrupt */
START_EXCEPTION(SystemCall)
- NORMAL_EXCEPTION_PROLOG(SYSCALL)
- EXC_XFER_SYS(0x0c00, DoSyscall)
+ SYSCALL_ENTRY 0xc00 SYSCALL
/* Auxiliary Processor Unavailable Interrupt */
EXCEPTION(0x2900, AP_UNAVAIL, AuxillaryProcessorUnavailable, \
--
2.13.3
On Tue, Apr 30, 2019 at 12:39:03PM +0000, Christophe Leroy wrote:
> This patch implements a fast entry for syscalls.
>
> Syscalls don't have to preserve non volatile registers except LR.
>
> This patch then implement a fast entry for syscalls, where
> volatile registers get clobbered.
>
> As this entry is dedicated to syscall it always sets MSR_EE
> and warns in case MSR_EE was previously off
>
> It also assumes that the call is always from user, system calls are
> unexpected from kernel.
This is now upstream as commit 1a4b739bbb4f. On the e500mc test
config that I use, I'm getting this build failure:
arch/powerpc/kernel/head_fsl_booke.o: In function `SystemCall':
arch/powerpc/kernel/head_fsl_booke.S:416: undefined reference to `kvmppc_handler_BOOKE_INTERRUPT_SYSCALL_SPRN_SRR1'
Makefile:1052: recipe for target 'vmlinux' failed
> +.macro SYSCALL_ENTRY trapno intno
> + mfspr r10, SPRN_SPRG_THREAD
> +#ifdef CONFIG_KVM_BOOKE_HV
> +BEGIN_FTR_SECTION
> + mtspr SPRN_SPRG_WSCRATCH0, r10
> + stw r11, THREAD_NORMSAVE(0)(r10)
> + stw r13, THREAD_NORMSAVE(2)(r10)
> + mfcr r13 /* save CR in r13 for now */
> + mfspr r11, SPRN_SRR1
> + mtocrf 0x80, r11 /* check MSR[GS] without clobbering reg */
> + bf 3, 1975f
> + b kvmppc_handler_BOOKE_INTERRUPT_\intno\()_SPRN_SRR1
It seems to me that the "_SPRN_SRR1" on the end of this line
isn't meant to be there... However, it still fails to link with that
removed.
Paul.
Le 23/05/2019 à 08:14, Paul Mackerras a écrit :
> On Tue, Apr 30, 2019 at 12:39:03PM +0000, Christophe Leroy wrote:
>> This patch implements a fast entry for syscalls.
>>
>> Syscalls don't have to preserve non volatile registers except LR.
>>
>> This patch then implement a fast entry for syscalls, where
>> volatile registers get clobbered.
>>
>> As this entry is dedicated to syscall it always sets MSR_EE
>> and warns in case MSR_EE was previously off
>>
>> It also assumes that the call is always from user, system calls are
>> unexpected from kernel.
>
> This is now upstream as commit 1a4b739bbb4f. On the e500mc test
> config that I use, I'm getting this build failure:
Is that a standard defconfig ? If not, can you provide your .config ?
>
> arch/powerpc/kernel/head_fsl_booke.o: In function `SystemCall':
> arch/powerpc/kernel/head_fsl_booke.S:416: undefined reference to `kvmppc_handler_BOOKE_INTERRUPT_SYSCALL_SPRN_SRR1'
> Makefile:1052: recipe for target 'vmlinux' failed
>
>> +.macro SYSCALL_ENTRY trapno intno
>> + mfspr r10, SPRN_SPRG_THREAD
>> +#ifdef CONFIG_KVM_BOOKE_HV
>> +BEGIN_FTR_SECTION
>> + mtspr SPRN_SPRG_WSCRATCH0, r10
>> + stw r11, THREAD_NORMSAVE(0)(r10)
>> + stw r13, THREAD_NORMSAVE(2)(r10)
>> + mfcr r13 /* save CR in r13 for now */
>> + mfspr r11, SPRN_SRR1
>> + mtocrf 0x80, r11 /* check MSR[GS] without clobbering reg */
>> + bf 3, 1975f
>> + b kvmppc_handler_BOOKE_INTERRUPT_\intno\()_SPRN_SRR1
>
> It seems to me that the "_SPRN_SRR1" on the end of this line
> isn't meant to be there... However, it still fails to link with that
> removed.
This SYSCALL_ENTRY macro is a slimmed version of NORMAL_EXCEPTION_PROLOG()
In NORMAL_EXCEPTION_PROLOG(), we have:
DO_KVM BOOKE_INTERRUPT_##intno SPRN_SRR1;
The _SPRN_SRR1 comes from there
Then in /arch/powerpc/include/asm/kvm_booke_hv_asm.h:
.macro DO_KVM intno srr1
#ifdef CONFIG_KVM_BOOKE_HV
BEGIN_FTR_SECTION
mtocrf 0x80, r11 /* check MSR[GS] without clobbering reg */
bf 3, 1975f
b kvmppc_handler_\intno\()_\srr1
1975:
END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
#endif
.endm
Christophe
Le 23/05/2019 à 09:00, Christophe Leroy a écrit :
[...]
>
>>
>> arch/powerpc/kernel/head_fsl_booke.o: In function `SystemCall':
>> arch/powerpc/kernel/head_fsl_booke.S:416: undefined reference to
>> `kvmppc_handler_BOOKE_INTERRUPT_SYSCALL_SPRN_SRR1'
>> Makefile:1052: recipe for target 'vmlinux' failed
>>
>>> +.macro SYSCALL_ENTRY trapno intno
>>> + mfspr r10, SPRN_SPRG_THREAD
>>> +#ifdef CONFIG_KVM_BOOKE_HV
>>> +BEGIN_FTR_SECTION
>>> + mtspr SPRN_SPRG_WSCRATCH0, r10
>>> + stw r11, THREAD_NORMSAVE(0)(r10)
>>> + stw r13, THREAD_NORMSAVE(2)(r10)
>>> + mfcr r13 /* save CR in r13 for now */
>>> + mfspr r11, SPRN_SRR1
>>> + mtocrf 0x80, r11 /* check MSR[GS] without clobbering reg */
>>> + bf 3, 1975f
>>> + b kvmppc_handler_BOOKE_INTERRUPT_\intno\()_SPRN_SRR1
>>
>> It seems to me that the "_SPRN_SRR1" on the end of this line
>> isn't meant to be there... However, it still fails to link with that
>> removed.
It looks like I missed the macro expansion.
The called function should be kvmppc_handler_8_0x01B
Seems like kisskb doesn't build any config like this.
Christophe
>
> This SYSCALL_ENTRY macro is a slimmed version of NORMAL_EXCEPTION_PROLOG()
>
> In NORMAL_EXCEPTION_PROLOG(), we have:
> DO_KVM BOOKE_INTERRUPT_##intno SPRN_SRR1;
>
> The _SPRN_SRR1 comes from there
>
>
> Then in /arch/powerpc/include/asm/kvm_booke_hv_asm.h:
>
> .macro DO_KVM intno srr1
> #ifdef CONFIG_KVM_BOOKE_HV
> BEGIN_FTR_SECTION
> mtocrf 0x80, r11 /* check MSR[GS] without clobbering reg */
> bf 3, 1975f
> b kvmppc_handler_\intno\()_\srr1
> 1975:
> END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
> #endif
> .endm
>
>
> Christophe
Christophe Leroy <[email protected]> writes:
> Le 23/05/2019 à 09:00, Christophe Leroy a écrit :
>
> [...]
>
>>> arch/powerpc/kernel/head_fsl_booke.o: In function `SystemCall':
>>> arch/powerpc/kernel/head_fsl_booke.S:416: undefined reference to
>>> `kvmppc_handler_BOOKE_INTERRUPT_SYSCALL_SPRN_SRR1'
>>> Makefile:1052: recipe for target 'vmlinux' failed
>>>
>>>> +.macro SYSCALL_ENTRY trapno intno
>>>> + mfspr r10, SPRN_SPRG_THREAD
>>>> +#ifdef CONFIG_KVM_BOOKE_HV
>>>> +BEGIN_FTR_SECTION
>>>> + mtspr SPRN_SPRG_WSCRATCH0, r10
>>>> + stw r11, THREAD_NORMSAVE(0)(r10)
>>>> + stw r13, THREAD_NORMSAVE(2)(r10)
>>>> + mfcr r13 /* save CR in r13 for now */
>>>> + mfspr r11, SPRN_SRR1
>>>> + mtocrf 0x80, r11 /* check MSR[GS] without clobbering reg */
>>>> + bf 3, 1975f
>>>> + b kvmppc_handler_BOOKE_INTERRUPT_\intno\()_SPRN_SRR1
>>>
>>> It seems to me that the "_SPRN_SRR1" on the end of this line
>>> isn't meant to be there... However, it still fails to link with that
>>> removed.
>
> It looks like I missed the macro expansion.
>
> The called function should be kvmppc_handler_8_0x01B
>
> Seems like kisskb doesn't build any config like this.
I thought we did, ie:
http://kisskb.ellerman.id.au/kisskb/buildresult/13817941/
But clearly something is missing to trigger the bug.
cheers
Michael Ellerman <[email protected]> a écrit :
> Christophe Leroy <[email protected]> writes:
>> Le 23/05/2019 à 09:00, Christophe Leroy a écrit :
>>
>> [...]
>>
>>>> arch/powerpc/kernel/head_fsl_booke.o: In function `SystemCall':
>>>> arch/powerpc/kernel/head_fsl_booke.S:416: undefined reference to
>>>> `kvmppc_handler_BOOKE_INTERRUPT_SYSCALL_SPRN_SRR1'
>>>> Makefile:1052: recipe for target 'vmlinux' failed
>>>>
>>>>> +.macro SYSCALL_ENTRY trapno intno
>>>>> + mfspr r10, SPRN_SPRG_THREAD
>>>>> +#ifdef CONFIG_KVM_BOOKE_HV
>>>>> +BEGIN_FTR_SECTION
>>>>> + mtspr SPRN_SPRG_WSCRATCH0, r10
>>>>> + stw r11, THREAD_NORMSAVE(0)(r10)
>>>>> + stw r13, THREAD_NORMSAVE(2)(r10)
>>>>> + mfcr r13 /* save CR in r13 for now */
>>>>> + mfspr r11, SPRN_SRR1
>>>>> + mtocrf 0x80, r11 /* check MSR[GS] without clobbering reg */
>>>>> + bf 3, 1975f
>>>>> + b kvmppc_handler_BOOKE_INTERRUPT_\intno\()_SPRN_SRR1
>>>>
>>>> It seems to me that the "_SPRN_SRR1" on the end of this line
>>>> isn't meant to be there... However, it still fails to link with that
>>>> removed.
>>
>> It looks like I missed the macro expansion.
>>
>> The called function should be kvmppc_handler_8_0x01B
>>
>> Seems like kisskb doesn't build any config like this.
>
> I thought we did, ie:
>
> http://kisskb.ellerman.id.au/kisskb/buildresult/13817941/
That's a ppc64 config it seems. The problem was on booke32.
Christophe
>
> But clearly something is missing to trigger the bug.
>
> cheers
On 05/28/2019 05:03 PM, Christophe Leroy wrote:
> Michael Ellerman <[email protected]> a écrit :
>
>> Christophe Leroy <[email protected]> writes:
>>> Le 23/05/2019 à 09:00, Christophe Leroy a écrit :
>>>
>>> [...]
>>>
>>>>> arch/powerpc/kernel/head_fsl_booke.o: In function `SystemCall':
>>>>> arch/powerpc/kernel/head_fsl_booke.S:416: undefined reference to
>>>>> `kvmppc_handler_BOOKE_INTERRUPT_SYSCALL_SPRN_SRR1'
>>>>> Makefile:1052: recipe for target 'vmlinux' failed
>>>>>
>>>>>> +.macro SYSCALL_ENTRY trapno intno
>>>>>> + mfspr r10, SPRN_SPRG_THREAD
>>>>>> +#ifdef CONFIG_KVM_BOOKE_HV
>>>>>> +BEGIN_FTR_SECTION
>>>>>> + mtspr SPRN_SPRG_WSCRATCH0, r10
>>>>>> + stw r11, THREAD_NORMSAVE(0)(r10)
>>>>>> + stw r13, THREAD_NORMSAVE(2)(r10)
>>>>>> + mfcr r13 /* save CR in r13 for now */
>>>>>> + mfspr r11, SPRN_SRR1
>>>>>> + mtocrf 0x80, r11 /* check MSR[GS] without clobbering
>>>>>> reg */
>>>>>> + bf 3, 1975f
>>>>>> + b kvmppc_handler_BOOKE_INTERRUPT_\intno\()_SPRN_SRR1
>>>>>
>>>>> It seems to me that the "_SPRN_SRR1" on the end of this line
>>>>> isn't meant to be there... However, it still fails to link with that
>>>>> removed.
>>>
>>> It looks like I missed the macro expansion.
>>>
>>> The called function should be kvmppc_handler_8_0x01B
>>>
>>> Seems like kisskb doesn't build any config like this.
>>
>> I thought we did, ie:
>>
>> http://kisskb.ellerman.id.au/kisskb/buildresult/13817941/
>
> That's a ppc64 config it seems. The problem was on booke32.
>
> Christophe
>
>>
>> But clearly something is missing to trigger the bug.
I was able to trigger the bug with mpc85xx_defconfig +
CONFIG_VIRTUALIZATION + CONFIG_PPC_E500MC
The bug pops up when CONFIG_KVM_BOOKE_HV is set.
Christophe
>>
>> cheers
>
>
Paul,
Le 23/05/2019 à 08:14, Paul Mackerras a écrit :
> On Tue, Apr 30, 2019 at 12:39:03PM +0000, Christophe Leroy wrote:
>> This patch implements a fast entry for syscalls.
>>
>> Syscalls don't have to preserve non volatile registers except LR.
>>
>> This patch then implement a fast entry for syscalls, where
>> volatile registers get clobbered.
>>
>> As this entry is dedicated to syscall it always sets MSR_EE
>> and warns in case MSR_EE was previously off
>>
>> It also assumes that the call is always from user, system calls are
>> unexpected from kernel.
>
> This is now upstream as commit 1a4b739bbb4f. On the e500mc test
> config that I use, I'm getting this build failure:
>
> arch/powerpc/kernel/head_fsl_booke.o: In function `SystemCall':
> arch/powerpc/kernel/head_fsl_booke.S:416: undefined reference to `kvmppc_handler_BOOKE_INTERRUPT_SYSCALL_SPRN_SRR1'
> Makefile:1052: recipe for target 'vmlinux' failed
Does my patch (https://patchwork.ozlabs.org/patch/1103909/) fixes the
issue for you ?
Thanks
Christophe
>
>> +.macro SYSCALL_ENTRY trapno intno
>> + mfspr r10, SPRN_SPRG_THREAD
>> +#ifdef CONFIG_KVM_BOOKE_HV
>> +BEGIN_FTR_SECTION
>> + mtspr SPRN_SPRG_WSCRATCH0, r10
>> + stw r11, THREAD_NORMSAVE(0)(r10)
>> + stw r13, THREAD_NORMSAVE(2)(r10)
>> + mfcr r13 /* save CR in r13 for now */
>> + mfspr r11, SPRN_SRR1
>> + mtocrf 0x80, r11 /* check MSR[GS] without clobbering reg */
>> + bf 3, 1975f
>> + b kvmppc_handler_BOOKE_INTERRUPT_\intno\()_SPRN_SRR1
>
> It seems to me that the "_SPRN_SRR1" on the end of this line
> isn't meant to be there... However, it still fails to link with that
> removed.
>
> Paul.
>