/* * Copyright (c) 2005 Martin Decky * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include .text FUNCTION_BEGIN(userspace_asm) /* * r3 = uspace_uarg * r4 = stack * r5 = entry */ /* Disable interrupts */ mfmsr r31 rlwinm r31, r31, 0, 17, 15 mtmsr r31 isync /* Set entry point */ mtsrr0 r5 /* Set privileged state, enable interrupts */ ori r31, r31, MSR_PR ori r31, r31, MSR_EE mtsrr1 r31 /* Set stack */ mr sp, r4 /* %r6 is defined to hold pcb_ptr - set it to 0 */ xor r6, r6, r6 /* Jump to userspace */ rfi FUNCTION_END(userspace_asm) SYMBOL(iret) /* Disable interrupts */ mfmsr r31 rlwinm r31, r31, 0, 17, 15 mtmsr r31 isync lwz r0, ISTATE_OFFSET_R0(sp) lwz r2, ISTATE_OFFSET_R2(sp) lwz r3, ISTATE_OFFSET_R3(sp) lwz r4, ISTATE_OFFSET_R4(sp) lwz r5, ISTATE_OFFSET_R5(sp) lwz r6, ISTATE_OFFSET_R6(sp) lwz r7, ISTATE_OFFSET_R7(sp) lwz r8, ISTATE_OFFSET_R8(sp) lwz r9, ISTATE_OFFSET_R9(sp) lwz r10, ISTATE_OFFSET_R10(sp) lwz r11, ISTATE_OFFSET_R11(sp) lwz r13, ISTATE_OFFSET_R13(sp) lwz r14, ISTATE_OFFSET_R14(sp) lwz r15, ISTATE_OFFSET_R15(sp) lwz r16, ISTATE_OFFSET_R16(sp) lwz r17, ISTATE_OFFSET_R17(sp) lwz r18, ISTATE_OFFSET_R18(sp) lwz r19, ISTATE_OFFSET_R19(sp) lwz r20, ISTATE_OFFSET_R20(sp) lwz r21, ISTATE_OFFSET_R21(sp) lwz r22, ISTATE_OFFSET_R22(sp) lwz r23, ISTATE_OFFSET_R23(sp) lwz r24, ISTATE_OFFSET_R24(sp) lwz r25, ISTATE_OFFSET_R25(sp) lwz r26, ISTATE_OFFSET_R26(sp) lwz r27, ISTATE_OFFSET_R27(sp) lwz r28, ISTATE_OFFSET_R28(sp) lwz r29, ISTATE_OFFSET_R29(sp) lwz r30, ISTATE_OFFSET_R30(sp) lwz r31, ISTATE_OFFSET_R31(sp) lwz r12, ISTATE_OFFSET_CR(sp) mtcr r12 lwz r12, ISTATE_OFFSET_PC(sp) mtsrr0 r12 lwz r12, ISTATE_OFFSET_SRR1(sp) mtsrr1 r12 lwz r12, ISTATE_OFFSET_LR(sp) mtlr r12 lwz r12, ISTATE_OFFSET_CTR(sp) mtctr r12 lwz r12, ISTATE_OFFSET_XER(sp) mtxer r12 lwz r12, ISTATE_OFFSET_R12(sp) lwz sp, ISTATE_OFFSET_SP(sp) rfi SYMBOL(iret_syscall) /* Disable interrupts */ mfmsr r31 rlwinm r31, r31, 0, 17, 15 mtmsr r31 isync lwz r0, ISTATE_OFFSET_R0(sp) lwz r2, ISTATE_OFFSET_R2(sp) lwz r4, ISTATE_OFFSET_R4(sp) lwz r5, ISTATE_OFFSET_R5(sp) lwz r6, ISTATE_OFFSET_R6(sp) lwz r7, ISTATE_OFFSET_R7(sp) lwz r8, ISTATE_OFFSET_R8(sp) lwz r9, ISTATE_OFFSET_R9(sp) lwz r10, ISTATE_OFFSET_R10(sp) lwz r11, ISTATE_OFFSET_R11(sp) lwz r13, ISTATE_OFFSET_R13(sp) lwz r14, ISTATE_OFFSET_R14(sp) lwz r15, ISTATE_OFFSET_R15(sp) lwz r16, ISTATE_OFFSET_R16(sp) lwz r17, ISTATE_OFFSET_R17(sp) lwz r18, ISTATE_OFFSET_R18(sp) lwz r19, ISTATE_OFFSET_R19(sp) lwz r20, ISTATE_OFFSET_R20(sp) lwz r21, ISTATE_OFFSET_R21(sp) lwz r22, ISTATE_OFFSET_R22(sp) lwz r23, ISTATE_OFFSET_R23(sp) lwz r24, ISTATE_OFFSET_R24(sp) lwz r25, ISTATE_OFFSET_R25(sp) lwz r26, ISTATE_OFFSET_R26(sp) lwz r27, ISTATE_OFFSET_R27(sp) lwz r28, ISTATE_OFFSET_R28(sp) lwz r29, ISTATE_OFFSET_R29(sp) lwz r30, ISTATE_OFFSET_R30(sp) lwz r31, ISTATE_OFFSET_R31(sp) lwz r12, ISTATE_OFFSET_CR(sp) mtcr r12 lwz r12, ISTATE_OFFSET_PC(sp) mtsrr0 r12 lwz r12, ISTATE_OFFSET_SRR1(sp) mtsrr1 r12 lwz r12, ISTATE_OFFSET_LR(sp) mtlr r12 lwz r12, ISTATE_OFFSET_CTR(sp) mtctr r12 lwz r12, ISTATE_OFFSET_XER(sp) mtxer r12 lwz r12, ISTATE_OFFSET_R12(sp) lwz sp, ISTATE_OFFSET_SP(sp) rfi FUNCTION_BEGIN(memcpy_from_uspace) FUNCTION_BEGIN(memcpy_to_uspace) srwi. r7, r5, 3 addi r6, r3, -4 addi r4, r4, -4 beq 2f andi. r0, r6, 3 mtctr r7 bne 5f 1: lwz r7, 4(r4) lwzu r8, 8(r4) stw r7, 4(r6) stwu r8, 8(r6) bdnz 1b andi. r5, r5, 7 2: cmplwi 0, r5, 4 blt 3f lwzu r0, 4(r4) addi r5, r5, -4 stwu r0, 4(r6) 3: cmpwi 0, r5, 0 beqlr mtctr r5 addi r4, r4, 3 addi r6, r6, 3 4: lbzu r0, 1(r4) stbu r0, 1(r6) bdnz 4b blr 5: subfic r0, r0, 4 mtctr r0 6: lbz r7, 4(r4) addi r4, r4, 1 stb r7, 4(r6) addi r6, r6, 1 bdnz 6b subf r5, r0, r5 rlwinm. r7, r5, 32-3, 3, 31 beq 2b mtctr r7 b 1b FUNCTION_END(memcpy_from_uspace) FUNCTION_END(memcpy_to_uspace) SYMBOL(memcpy_from_uspace_failover_address) SYMBOL(memcpy_to_uspace_failover_address) /* Return zero, failure */ xor r3, r3, r3 blr FUNCTION_BEGIN(early_putuchar) blr FUNCTION_END(early_putuchar)