|
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 |