os/kernelhwsrv/kernel/eka/memmodel/epoc/flexible/arm/xipc.cia
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #define INCLUDED_FROM_ASM
    17 
    18 #include <e32cia.h>
    19 #include <arm_mem.h>
    20 #include "xdefs.h"
    21 
    22 #ifdef _DEBUG
    23 #define ASM_KILL_LINK(rp,rs)	asm("mov "#rs", #0xdf ");\
    24 								asm("orr "#rs", "#rs", "#rs", lsl #8 ");\
    25 								asm("orr "#rs", "#rs", "#rs", lsl #16 ");\
    26 								asm("str "#rs", ["#rp"] ");\
    27 								asm("str "#rs", ["#rp", #4] ");
    28 #else
    29 #define ASM_KILL_LINK(rp,rs)
    30 #endif
    31 
    32 #ifdef _DEBUG
    33 extern "C" void __FaultIpcClientNotNull();  // defined in ckernel.cpp
    34 #endif
    35 
    36 
    37 __NAKED__ TInt DThread::ReadAndParseDesHeader(const TAny* aSrc, TDesHeader& aDest)
    38 	{
    39 	ASM_ASSERT_PAGING_SAFE;
    40 	// save state including 'this', aSrc and sDest. Double word aligns the stack 
    41 	// which is required to call c++ functions.
    42 	asm("stmdb sp!, {r0-r2, r4-r8, r10, lr} ");
    43 
    44 	// Register use this method:
    45 	// r0 = 'this' until iIpcClient set.
    46 	// r1 = aSrc until read_and_parse_des_header_local.
    47 	// r2 = aDest until read_and_parse_des_header_local.
    48 	// r4 = target process
    49 	// r5 = current nthread
    50 	// r6 = scheduler.
    51 	// r7 = current process 
    52 	// r8 = orig ttbr0
    53 	// r10 = os asid of current process.
    54 
    55 	// Open a reference on the target process's os asid as we will be switching to
    56 	// it so it can't be allowed to be freed and/or reused.
    57 	asm("ldr r4, [r0, #%a0]" : : "i" _FOFF(DThread,iOwningProcess));		// r4->target process
    58 	asm("bl " CSM_ZN5NKern13ThreadEnterCSEv);	// First enter a critical section so can't leak os asid reference.
    59 	asm("mov r0, r4");		// r0 = target process ('this' for TryOpenOsAsid() below).
    60 	asm("bl " CSM_ZN16DMemModelProcess13TryOpenOsAsidEv);
    61 	// Check a reference could be opened on target process's os asid, failed if r0 < 0.
    62 	asm("cmp r0, #0");
    63 	asm("bmi readParseDesHeader_ExitErr");
    64 
    65 	asm("mov r10, r0");			// r10 = os asid of current process
    66 	asm("ldmia sp!, {r0-r2}");	// r0 = this, r1 = aSrc, r2 = aDest
    67 	
    68 	__ASM_CLI(); // disable all interrupts
    69 #ifdef __SMP__
    70 	GET_RWNO_TID(,r6);														// r6->TSubScheduler
    71 	asm("ldr r7, [r6, #%a0]" : : "i" _FOFF(TSubScheduler,iAddressSpace));	// r7->current process
    72 	asm("ldr r5, [r6, #%a0]" : : "i" _FOFF(TSubScheduler,iCurrentThread));	// r5->current NThreadBase
    73 #else
    74 	asm("ldr r6, __TheScheduler ");											// r6->TheScheduler
    75 	asm("ldr r7, [r6, #%a0]" : : "i" _FOFF(TScheduler,iAddressSpace));		// r7->current process
    76 	asm("ldr r5, [r6, #%a0]" : : "i" _FOFF(TScheduler,iCurrentThread));		// r5->current NThreadBase
    77 #endif
    78 
    79 	// set TheCurrentThread->iIpcClient to this (r0) thread
    80 #ifdef _DEBUG
    81 	asm("ldr r12, [r5, #%a0] " : : "i" (_FOFF(DThread, iIpcClient) - _FOFF(DThread, iNThread)));
    82 	asm("teq r12, #0 ");
    83 	asm("bne __FaultIpcClientNotNull ");
    84 #endif
    85 	asm("str r0, [r5, #%a0] " : : "i" (_FOFF(DThread, iIpcClient) - _FOFF(DThread, iNThread)));
    86 
    87 	// switch address space to process r4...
    88 	asm("mrc p15, 0, r8, c2, c0, 0 ");		// r8 = original TTBR0
    89 	asm("ldr r0, [r4, #%a0]" : : "i" _FOFF(DMemModelProcess,iPageDir));		// r0->target process page directory
    90 	asm("and lr, r8, #%a0" : : "i" ((TInt)KTTBRExtraBitsMask));	// lr = TTBR0 extra bits
    91 	asm("orr r0, r0, lr ");					// r0 = target process page directory + extra bits
    92 
    93 	__ASM_SET_ADDRESS_SPACE(r10,r0,lr);
    94 #ifdef __SMP__
    95 	asm("str r4, [r6, #%a0]" : : "i" _FOFF(TSubScheduler,iAddressSpace));
    96 #else
    97 	asm("str r4, [r6, #%a0]" : : "i" _FOFF(TScheduler,iAddressSpace));
    98 #endif
    99 	asm("str r4, [r5, #%a0]" : : "i" _FOFF(NThread,iAddressSpace));
   100 	__ASM_STI(); // enable all interrupts
   101 
   102 	// read and parse descriptor header, r1=aSrc, r2=aDest
   103 	asm("bl read_and_parse_des_header_local");	// defined in e32/kernel/arm/cipc.cia
   104 		
   105 	// restore address space to process r7...
   106 	asm("ldr r12, [r7, #%a0]" : : "i" _FOFF(DMemModelProcess,iOsAsid));		// r12 = current process ASID
   107 
   108 	__ASM_CLI(); // disable all interrupts
   109 	__ASM_SET_ADDRESS_SPACE(r12,r8,lr);
   110 #ifdef __SMP__
   111 	GET_RWNO_TID(,r6);														// r6->TSubScheduler
   112 	asm("str r7, [r6, #%a0]" : : "i" _FOFF(TSubScheduler,iAddressSpace));
   113 #else
   114 	asm("str r7, [r6, #%a0]" : : "i" _FOFF(TScheduler,iAddressSpace));
   115 #endif
   116 	asm("str r7, [r5, #%a0]" : : "i" _FOFF(NThread,iAddressSpace));
   117 	__ASM_STI(); // enable all interrupts
   118 
   119 	// set TheCurrentThread->iIpcClient to NULL again
   120 	asm("mov r12, #0 ");
   121 	asm("str r12, [r5, #%a0] " : : "i" (_FOFF(DThread, iIpcClient) - _FOFF(DThread, iNThread)));
   122 
   123 	// close the reference on the target process's os asid.
   124 	asm("mov r6, r0");	// r6 = return value from read_and_parse_des_header_local
   125 	asm("mov r0, r4");	// r0 = target process
   126 	asm("bl " CSM_ZN16DMemModelProcess11CloseOsAsidEv);
   127 	
   128 	// finished...
   129 	asm("bl " CSM_ZN5NKern13ThreadLeaveCSEv);	// Os asid reference closed so leave critical section.
   130 	asm("mov r0, r6");			// r0 = return value from read_and_parse_des_header_local.
   131 	__POPRET("r4-r8, r10, ");	// Restore the state and return.
   132 
   133 	// exit with error...
   134 	asm("readParseDesHeader_ExitErr:");
   135 	asm("bl " CSM_ZN5NKern13ThreadLeaveCSEv);	// Os asid reference not open so leave critical section.
   136 	asm("mov r0, #%a0" : : "i" ((TInt)KErrBadDescriptor));
   137 	asm("add sp, sp, #12");	// pop r0-r2 off the stack.
   138 	__POPRET("r4-r8, r10, ");	// Restore the state and return.
   139 
   140 #ifndef __SMP__
   141 	asm("__TheScheduler: ");
   142 	asm(".word TheScheduler ");
   143 #endif
   144 	}
   145