First public contribution.
1 // Copyright (c) 2006-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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\nkernsmp\x86\nccpu.cpp
22 const TLinAddr KWarmResetTrampolineAddr = 0x467;
24 TLinAddr ApTrampolinePage = 0; // overridden in multiple memory model with linear address
26 extern "C" void nanowait(TUint32 aNanoseconds);
27 void cmos_write(TUint32 val, TUint32 addr);
28 void SetupApInitInfo(volatile SApInitInfo&);
31 TInt WakeAP(TInt aAPICID)
33 __KTRACE_OPT(KBOOT,DEBUGPRINT("WakeAP %d", aAPICID));
35 write_apic_reg(ESR, 0);
38 __KTRACE_OPT(KBOOT,DEBUGPRINT("Asserting INIT"));
40 //Turn INIT on target chip
41 write_apic_reg(ICRH, aAPICID<<24);
44 write_apic_reg(ICRL, 0xC500);
46 __KTRACE_OPT(KBOOT,DEBUGPRINT("Waiting for send to finish..."));
49 TUint32 accept_status;
51 __KTRACE_OPT(KBOOT,DEBUGPRINT("+"));
53 send_status = read_apic_reg(ICRL) & 0x1000;
54 } while (send_status && (++timeout < 1000));
58 __KTRACE_OPT(KBOOT,DEBUGPRINT("Deasserting INIT"));
61 write_apic_reg(ICRH, aAPICID<<24);
64 write_apic_reg(ICRL, 0x8500);
66 __KTRACE_OPT(KBOOT,DEBUGPRINT("Waiting for send to finish..."));
69 __KTRACE_OPT(KBOOT,DEBUGPRINT("+"));
71 send_status = read_apic_reg(ICRL) & 0x1000;
72 } while (send_status && (++timeout < 1000));
75 * Should we send STARTUP IPIs ?
77 * Determine this based on the APIC version.
78 * If we don't have an integrated APIC, don't send the STARTUP IPIs.
80 // if (APIC_INTEGRATED(apic_version[phys_apicid]))
85 // Run STARTUP IPI loop.
86 // maxlvt = get_maxlvt();
89 for (j = 1; j <= num_starts; j++)
91 __KTRACE_OPT(KBOOT,DEBUGPRINT("Sending STARTUP %d",j));
93 write_apic_reg(ESR, 0);
97 write_apic_reg(ICRH, aAPICID<<24);
100 write_apic_reg(ICRL, (0x600 | (KApBootPage>>12)));
102 // give other CPU time to accept it
105 __KTRACE_OPT(KBOOT,DEBUGPRINT("Waiting for send to finish..."));
108 __KTRACE_OPT(KBOOT,DEBUGPRINT("+"));
110 send_status = read_apic_reg(ICRL) & 0x1000;
111 } while (send_status && (++timeout < 1000));
113 // give other CPU time to accept it
117 * Due to the Pentium erratum 3AP.
120 // read_apic_reg(APIC_SPIV);
121 // write_apic_reg(APIC_ESR, 0);
123 accept_status = (read_apic_reg(ESR) & 0xEF);
124 if (send_status || accept_status)
127 __KTRACE_OPT(KBOOT,DEBUGPRINT("After startup"));
130 __KTRACE_OPT(KBOOT,DEBUGPRINT("APIC never delivered???"));
132 __KTRACE_OPT(KBOOT,DEBUGPRINT("APIC delivery error %x", accept_status));
134 return (send_status | accept_status);
139 TInt NKern::BootAP(volatile SAPBootInfo* aInfo)
141 __KTRACE_OPT(KBOOT,DEBUGPRINT("NKern::BootAP %08x %08x+%x", aInfo->iCpu, aInfo->iInitStackBase, aInfo->iInitStackSize));
143 cmos_write(0xa, 0xf);
145 TUint8* t = (TUint8*)(KWarmResetTrampolineAddr + ApTrampolinePage);
146 TUint cs = KApBootPage>>4;
152 volatile SApInitInfo& a = *(volatile SApInitInfo*)KApBootPage;
153 TCpuPages& cp=X86::CpuPage();
155 memcpy((TAny*)a.iTempGdt, cp.iGdt, sizeof(cp.iGdt));
156 a.iTempGdtr = TUint64(KApBootPage + _FOFF(SApInitInfo,iTempGdt))<<16 | TUint64(KSmpGdtSize*sizeof(SX86Des)-1);
157 a.iRgs.iCs = RING0_CS;
158 a.iRgs.iEip = (TLinAddr)&_ApMain;
161 a.iLinAddr = (TLinAddr)&a;
163 a.iStackBase = aInfo->iInitStackBase;
164 a.iStackSize = aInfo->iInitStackSize;
165 a.iRgs.iEsp = a.iStackBase + a.iStackSize;
166 a.iExtra = (TAny*)aInfo;
168 TInt r = WakeAP(aInfo->iCpu);
176 if (a.iBootFlag == KBootFlagMagic-1)
180 __KTRACE_OPT(KBOOT, DEBUGPRINT("iBootFlag=%08x",a.iBootFlag));
184 __e32_atomic_add_ord32(&a.iBootFlag, TUint32(-1));
186 NKern::DisableAllInterrupts();
187 while (a.iBootFlag2==0)
189 __e32_io_completion_barrier();
191 __e32_io_completion_barrier();
192 a.iBPTimestamp = X86::Timestamp();
193 __e32_io_completion_barrier();
194 while (a.iBootFlag2==2)
196 __e32_io_completion_barrier();
197 NKern::EnableAllInterrupts();
202 void InitAPTimestamp(SNThreadCreateInfo&)
204 volatile SApInitInfo& a = *(volatile SApInitInfo*)KApBootPage;
205 NKern::DisableAllInterrupts();
207 __e32_io_completion_barrier();
208 while (a.iBootFlag2==1)
210 __e32_io_completion_barrier();
211 a.iAPTimestamp = X86::Timestamp();
212 __e32_io_completion_barrier();
213 TUint64 bpt = a.iBPTimestamp;
214 TUint64 apt = a.iAPTimestamp;
215 TUint64 delta = bpt - apt;
216 TSubScheduler& ss = SubScheduler();
217 ss.iLastTimestamp64 += delta;
218 *(TUint64*)&ss.i_TimestampOffset = delta;
219 __KTRACE_OPT(KBOOT,DEBUGPRINT("APT=0x%lx BPT=0x%lx Delta=0x%lx", apt, bpt, delta));
220 __e32_io_completion_barrier();
222 NKern::EnableAllInterrupts();