|
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 #include <e32cia.h> |
|
17 #include <arm_mem.h> |
|
18 |
|
19 #ifdef _DEBUG |
|
20 #define ASM_KILL_LINK(rp,rs) asm("mov "#rs", #0xdf ");\ |
|
21 asm("orr "#rs", "#rs", "#rs", lsl #8 ");\ |
|
22 asm("orr "#rs", "#rs", "#rs", lsl #16 ");\ |
|
23 asm("str "#rs", ["#rp"] ");\ |
|
24 asm("str "#rs", ["#rp", #4] "); |
|
25 #else |
|
26 #define ASM_KILL_LINK(rp,rs) |
|
27 #endif |
|
28 |
|
29 |
|
30 __NAKED__ TInt ThreadDoReadAndParseDesHeader(DThread* aThread, const TAny* aSrc, TUint32* aDest) |
|
31 { |
|
32 asm("stmdb sp!, {r4-r7, lr} "); // stack unaligned, but we only call assembler |
|
33 |
|
34 #ifdef __SMP__ |
|
35 GET_RWNO_TID(,r6); // r6->TSubScheduler - can't migrate since we hold system lock |
|
36 asm("ldr r3, [r0, #%a0]" : : "i" _FOFF(DThread,iOwningProcess)); // r3->target process |
|
37 asm("ldr r4, [r6, #%a0]" : : "i" _FOFF(TSubScheduler,iAddressSpace)); // r4->current process |
|
38 asm("ldr r5, [r6, #%a0]" : : "i" _FOFF(TSubScheduler,iCurrentThread)); // r5->current NThread |
|
39 #else |
|
40 asm("ldr r6, __TheScheduler "); // r6->TheScheduler |
|
41 asm("ldr r3, [r0, #%a0]" : : "i" _FOFF(DThread,iOwningProcess)); // r3->target process |
|
42 asm("ldr r4, [r6, #%a0]" : : "i" _FOFF(TScheduler,iAddressSpace)); // r4->current process |
|
43 asm("ldr r5, [r6, #%a0]" : : "i" _FOFF(TScheduler,iCurrentThread)); // r5->current NThread |
|
44 #endif |
|
45 |
|
46 // set TheCurrentThread->iIpcClient to this thread |
|
47 #ifdef _DEBUG |
|
48 asm("ldr r12, [r5, #%a0] " : : "i" (_FOFF(DThread, iIpcClient) - _FOFF(DThread, iNThread))); |
|
49 asm("teq r12, #0 "); |
|
50 asm("bne __FaultIpcClientNotNull "); |
|
51 #endif |
|
52 asm("str r0, [r5, #%a0] " : : "i" (_FOFF(DThread, iIpcClient) - _FOFF(DThread, iNThread))); |
|
53 |
|
54 // switch address space to process r3... |
|
55 asm("mrc p15, 0, r7, c2, c0, 0 "); // r7 = original TTBR0 |
|
56 asm("ldr r0, [r3, #%a0]" : : "i" _FOFF(DMemModelProcess,iLocalPageDir)); // r0->target process page directory |
|
57 asm("ldr r12, [r3, #%a0]" : : "i" _FOFF(DMemModelProcess,iOsAsid)); // r12 = target ASID |
|
58 #ifdef __SMP__ |
|
59 __ASM_CLI(); |
|
60 #else |
|
61 CPSIDIF; // disable all interrupts |
|
62 #endif |
|
63 asm("mcr p15, 0, r12, c7, c10, 4 "); // drain write buffer before changing MMU registers (see ARMv6 specs) |
|
64 asm("and lr, r7, #%a0" : : "i" ((TInt)KTTBRExtraBitsMask)); // lr = TTBR0 extra bits |
|
65 asm("orr lr, lr, r0 "); // target process page directory + extra bits |
|
66 UPDATE_PW_CACHING_ATTRIBUTES(,lr); // ERRATUM 1136_317041 |
|
67 asm("mcr p15, 0, lr, c2, c0, 0 "); // change TTBR0 |
|
68 asm("mcr p15, 0, r12, c13, c0, 1 "); // change ASID |
|
69 |
|
70 #if defined(__CPU_ARM11MP__) |
|
71 // On other platforms, tha ASID change above has already flushed the branch prediction buffers |
|
72 asm("mcr p15, 0, r12, c7, c5, 6 "); // flush BTAC |
|
73 #endif |
|
74 |
|
75 #ifdef __SMP__ |
|
76 asm("str r3, [r6, #%a0]" : : "i" _FOFF(TSubScheduler,iAddressSpace)); |
|
77 #else |
|
78 asm("str r3, [r6, #%a0]" : : "i" _FOFF(TScheduler,iAddressSpace)); |
|
79 #endif |
|
80 asm("str r3, [r5, #%a0]" : : "i" _FOFF(NThread,iAddressSpace)); |
|
81 #ifdef __SMP__ |
|
82 __ASM_STI(); |
|
83 #else |
|
84 CPSIEIF; // enable all interrupts |
|
85 #endif |
|
86 // read and parse the descriptor header |
|
87 asm("bl read_and_parse_des_header_local"); // defined in e32/kernel/arm/cipc.cia |
|
88 |
|
89 // restore address space to process r4... |
|
90 asm("ldr r12, [r4, #%a0]" : : "i" _FOFF(DMemModelProcess,iOsAsid)); // r12 = current process ASID |
|
91 #ifdef __SMP__ |
|
92 __ASM_CLI(); |
|
93 #else |
|
94 CPSIDIF; // disable all interrupts |
|
95 #endif |
|
96 asm("mcr p15, 0, r12, c7, c10, 4 "); // drain write buffer before changing MMU registers (see ARMv6 specs) |
|
97 UPDATE_PW_CACHING_ATTRIBUTES(,r7); // ERRATUM 1136_317041 |
|
98 asm("mcr p15, 0, r7, c2, c0, 0 "); // restore TTBR0 |
|
99 asm("mcr p15, 0, r12, c13, c0, 1 "); // restore ASID |
|
100 |
|
101 #if defined(__CPU_ARM11MP__) |
|
102 // On other platforms, the ASID change above has already flushed the branch prediction buffers |
|
103 asm("mcr p15, 0, r12, c7, c5, 6 "); // flush BTAC |
|
104 #endif |
|
105 |
|
106 #ifdef __SMP__ |
|
107 asm("str r4, [r6, #%a0]" : : "i" _FOFF(TSubScheduler,iAddressSpace)); |
|
108 #else |
|
109 asm("str r4, [r6, #%a0]" : : "i" _FOFF(TScheduler,iAddressSpace)); |
|
110 #endif |
|
111 asm("str r4, [r5, #%a0]" : : "i" _FOFF(NThread,iAddressSpace)); |
|
112 #ifdef __SMP__ |
|
113 __ASM_STI(); |
|
114 #else |
|
115 CPSIEIF; // enable all interrupts |
|
116 #endif |
|
117 |
|
118 // set TheCurrentThread->iIpcClient to NULL again |
|
119 asm("mov r12, #0 "); |
|
120 asm("str r12, [r5, #%a0] " : : "i" (_FOFF(DThread, iIpcClient) - _FOFF(DThread, iNThread))); |
|
121 |
|
122 // finished... |
|
123 __POPRET("r4-r7,"); |
|
124 |
|
125 #ifndef __SMP__ |
|
126 asm("__TheScheduler: "); |
|
127 asm(".word TheScheduler "); |
|
128 #endif |
|
129 } |
|
130 |