1 // reset-vector.S -- Xtensa Reset Vector
2 // $Id: //depot/rel/Cottonwood/Xtensa/OS/xtos/reset-vector.S#4 $
4 // Copyright (c) 1999-2010 Tensilica Inc.
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
14 // The above copyright notice and this permission notice shall be included
15 // in all copies or substantial portions of the Software.
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include <xtensa/coreasm.h>
26 #include <xtensa/cacheasm.h>
27 #include <xtensa/cacheattrasm.h>
28 #include <xtensa/xtensa-xer.h>
29 #include <xtensa/config/specreg.h>
30 #include <xtensa/config/system.h> /* for XSHAL_USE_ABSOLUTE_LITERALS only */
31 #include "xtos-internal.h"
33 // The following reset vector avoids initializing certain registers already
34 // initialized by processor reset.
35 // Some of the registers reset by the processor include:
36 // CACHEATTR or relevant TLB state
43 // VECBASE Relocatable vectors
44 // (and various others, depending on hardware version)
47 .begin literal_prefix .ResetVector
48 .section .ResetVector.text, "ax"
54 # if 0 /* if XCHAL_HAVE_HALT */
55 // In theory, minimal reset vector for Xtensa TX (assuming bootloader to clear BSS).
56 // In practice we let crt*.S decide whether to do more (e.g. for sim LSP)
57 // and we might unpack below for ROMing LSPs.
58 movi sp, __stack // setup the stack
59 call0 main // assume declared as "void main(void)" (no args)
63 #if (!XCHAL_HAVE_HALT || defined(XTOS_UNPACK)) && XCHAL_HAVE_IMEM_LOADSTORE
66 // IMPORTANT: If you move the _ResetHandler portion to a section
67 // other than .ResetVector.text that is outside the range of
68 // the reset vector's 'j' instruction, the _ResetHandler symbol
69 // and a more elaborate j/movi/jx sequence are needed in
70 // .ResetVector.text to dispatch to the new location.
74 .size _ResetVector, . - _ResetVector
77 // Xtensa TX: reset vector segment is only 4 bytes, so must place the
78 // unpacker code elsewhere in the memory that contains the reset vector.
79 # if XCHAL_RESET_VECTOR_VADDR == XCHAL_INSTRAM0_VADDR
80 .section .iram0.text, "ax"
81 # elif XCHAL_RESET_VECTOR_VADDR == XCHAL_INSTROM0_VADDR
82 .section .irom0.text, "ax"
83 # elif XCHAL_RESET_VECTOR_VADDR == XCHAL_URAM0_VADDR
84 .section .uram0.text, "ax"
86 # warning "Xtensa TX reset vector not at start of iram0, irom0, or uram0 -- ROMing LSPs may not work"
92 .literal_position // tells the assembler/linker to place literals here
102 * Even if the processor supports the non-PC-relative L32R option,
103 * it will always start up in PC-relative mode. We take advantage of
104 * this, and use PC-relative mode at least until we're sure the .lit4
105 * section is in place (which is sometimes only after unpacking).
107 .begin no-absolute-literals
110 movi a0, 0 // a0 is always 0 in this code, used to initialize lots of things
112 #if XCHAL_HAVE_INTERRUPTS // technically this should be under !FULL_RESET, assuming hard reset
113 wsr a0, INTENABLE // make sure that interrupts are shut off (*before* we lower PS.INTLEVEL and PS.EXCM!)
116 #if !XCHAL_HAVE_FULL_RESET
118 #if XCHAL_HAVE_CCOUNT && (XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RB_2006_0) /* pre-LX2 cores only */
119 wsr a0, CCOUNT // not really necessary, but nice; best done very early
122 // For full MMU configs, put page table at an unmapped virtual address.
123 // This ensures that accesses outside the static maps result
124 // in miss exceptions rather than random behaviour.
125 // Assumes XCHAL_SEG_MAPPABLE_VADDR == 0 (true in released MMU).
126 #if XCHAL_ITLB_ARF_WAYS > 0 || XCHAL_DTLB_ARF_WAYS > 0
130 // Debug initialization
132 // NOTE: DBREAKCn must be initialized before the combination of these two things:
133 // any load/store, and a lowering of PS.INTLEVEL below DEBUG_LEVEL.
134 // The processor already resets IBREAKENABLE appropriately.
137 # if XCHAL_NUM_DBREAK
138 # if XCHAL_NUM_DBREAK >= 2
142 dsync // wait for WSRs to DBREAKCn to complete
145 # if XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RA_2004_1 /* pre-LX cores only */
146 // Starting in Xtensa LX, ICOUNTLEVEL resets to zero (not 15), so no need to initialize it.
147 // Prior to that we do, otherwise we get an ICOUNT exception, 2^32 instructions after reset.
148 rsr a2, ICOUNTLEVEL // are we being debugged? (detected by ICOUNTLEVEL not 15, or dropped below 12)
149 bltui a2, 12, 1f // if so, avoid initializing ICOUNTLEVEL which drops single-steps through here
150 wsr a0, ICOUNTLEVEL // avoid ICOUNT exceptions
151 isync // wait for WSR to ICOUNTLEVEL to complete
156 #endif /* !XCHAL_HAVE_FULL_RESET */
158 #if XCHAL_HAVE_ABSOLUTE_LITERALS
159 // Technically, this only needs to be done under !FULL_RESET, assuming hard reset:
164 #if XCHAL_HAVE_PRID && XCHAL_HAVE_S32C1I
165 /* Core 0 initializes the XMP synchronization variable, if present. This operation needs to
166 happen as early as possible in the startup sequence so that the other cores can be released
169 movi a2, _ResetSync // address of sync variable
170 rsr.prid a3 // core and multiprocessor ID
171 extui a3, a3, 0, 8 // extract core ID (FIXME: need proper constants for PRID bits to extract)
172 beqz a2, 1f // skip if no sync variable
173 bnez a3, 1f // only do this on core 0
174 s32i a0, a2, 0 // clear sync variable
177 #if XCHAL_HAVE_EXTERN_REGS && XCHAL_HAVE_MP_RUNSTALL
178 /* On core 0, this releases other cores. On other cores this has no effect, because
179 runstall control is unconnected. */
185 * For processors with relocatable vectors, apply any alternate
186 * vector base given to xt-genldscripts, which sets the
187 * _memmap_vecbase_reset symbol accordingly.
189 #if XCHAL_HAVE_VECBASE
190 movi a2, _memmap_vecbase_reset /* note: absolute symbol, not a ptr */
194 #if XCHAL_HAVE_S32C1I && (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0) /* have ATOMCTL ? */
195 # if XCHAL_DCACHE_IS_COHERENT
196 movi a3, 0x25 /* MX -- internal for writeback, RCW otherwise */
198 movi a3, 0x15 /* non-MX -- always RCW */
203 #if XCHAL_HAVE_INTERRUPTS && XCHAL_HAVE_DEBUG
204 rsil a2, 1 // lower PS.INTLEVEL here to make reset vector easier to debug
208 * Initialize the caches.
209 * We do this very early because performance can increase by
210 * an order of magnitude when we enable the caches, which
211 * greatly affects start up time, including the mini-loader below.
212 * This is also required before we jump into any cacheable region.
213 * Without caches, these macros expand to nothing (see cacheasm.h).
218 #if XCHAL_HAVE_PREFETCH
219 /* Enable cache prefetch if present. */
220 movi a2, XCHAL_CACHE_PREFCTL_DEFAULT
225 * Now "enable" the caches, for unpacking to occur a bit more
226 * efficiently. Only relevant for region protection and XEA1.
228 * The _memmap_cacheattr_reset symbol's value (address) is defined
229 * by the LSP's linker script, as generated by xt-genldscripts.
231 * (NOTE: for configs that don't have CACHEATTR or region protection,
232 * ie. for full MMUs, there is no equivalent cache attribute layout,
233 * and the following code has no effect. We assume for now that the
234 * application restricts itself to the static TLB entries, i.e. to
235 * virtual addresses 0xD0000000 thru 0xFFFFFFFF.)
237 #if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR \
238 || (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY)
239 movi a2, _memmap_cacheattr_reset /* note: absolute symbol, not a ptr */
240 cacheattr_set /* set CACHEATTR from a2 (clobbers a3-a8) */
243 #if XCHAL_HAVE_EXTERN_REGS && XCHAL_DCACHE_IS_COHERENT
244 /* Opt into coherence if present. */
250 #endif /* !XCHAL_HAVE_HALT */
253 * Unpack code and data (eg. copy ROMed segments to RAM, vectors into
254 * their proper location, etc).
257 #if defined(XTOS_UNPACK)
258 movi a2, _rom_store_table
260 unpack: l32i a3, a2, 0 // start vaddr
261 l32i a4, a2, 4 // end vaddr
262 l32i a5, a2, 8 // store vaddr
264 bgeu a3, a4, upnext // skip unless start < end
265 uploop: l32i a6, a5, 0
271 upnext: bnez a3, unpack
273 #endif /* XTOS_UNPACK */
277 #if defined(XTOS_UNPACK) || defined(XTOS_MP)
279 * If writeback caches are configured and enabled, unpacked data must be
280 * written out to memory before trying to execute it:
282 dcache_writeback_all a2, a3, 0
283 icache_sync a2 // ensure data written back is visible to i-fetch
285 * Note: no need to invalidate the i-cache after the above, because we
286 * already invalidated it further above and did not execute anything within
287 * unpacked regions afterwards. [Strictly speaking, if an unpacked region
288 * follows this code very closely, it's possible for cache-ahead to have
289 * cached a bit of that unpacked region, so in the future we may need to
290 * invalidate the entire i-cache here again anyway.]
295 #if !XCHAL_HAVE_HALT /* skip for TX */
298 * Now that we know the .lit4 section is present (if got unpacked)
299 * (and if absolute literals are used), initialize LITBASE to use it.
301 #if XCHAL_HAVE_ABSOLUTE_LITERALS && XSHAL_USE_ABSOLUTE_LITERALS
303 * Switch from PC-relative to absolute (litbase-relative) L32R mode.
304 * Set LITBASE to 256 kB beyond the start of the literals in .lit4
305 * (aligns to the nearest 4 kB boundary, LITBASE does not have bits 1..11)
306 * and set the enable bit (_lit4_start is assumed 4-byte aligned).
308 movi a2, _lit4_start + 0x40001
311 #endif /* have and use absolute literals */
312 .end no-absolute-literals // we can now start using absolute literals
315 // Technically, this only needs to be done pre-LX2, assuming hard reset:
316 # if XCHAL_HAVE_WINDOWED && defined(__XTENSA_WINDOWED_ABI__)
317 // Windowed register init, so we can call windowed code (eg. C code).
320 // The processor always clears WINDOWBASE at reset, so no need to clear it here.
321 // It resets WINDOWSTART to 1 starting with LX2.0/X7.0 (RB-2006.0).
322 // However, assuming hard reset is not yet always practical, so do this anyway:
325 movi a0, 0 // possibly a different a0, clear it
328 #if XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RB_2006_0 /* only pre-LX2 needs this */
329 // Coprocessor option initialization
331 //movi a2, XCHAL_CP_MASK // enable existing CPs
332 // To allow creating new coprocessors using TC that are not known
333 // at GUI build time without having to explicitly enable them,
334 // all CPENABLE bits must be set, even though they may not always
335 // correspond to a coprocessor.
336 movi a2, 0xFF // enable *all* bits, to allow dynamic TIE
340 // Floating point coprocessor option initialization (at least
341 // rounding mode, so that floating point ops give predictable results)
342 # if XCHAL_HAVE_FP && !XCHAL_HAVE_VECTORFPU2005
343 # define FCR 232 /* floating-point control register (user register number) */
344 # define FSR 233 /* floating-point status register (user register number) */
345 rsync /* wait for WSR to CPENABLE to complete before accessing FP coproc state */
346 wur a0, FCR /* clear FCR (default rounding mode, round-nearest) */
347 wur a0, FSR /* clear FSR */
353 * Initialize medium and high priority interrupt dispatchers:
357 /* For asm macros; works for positive a,b smaller than 1000: */
358 # define GREATERTHAN(a,b) (((b)-(a)) & ~0xFFF)
360 # ifndef XCHAL_DEBUGLEVEL /* debug option not selected? */
361 # define XCHAL_DEBUGLEVEL 99 /* bogus value outside 2..6 */
364 .macro init_vector level
365 .if GREATERTHAN(XCHAL_NUM_INTLEVELS+1,\level)
366 .if XCHAL_DEBUGLEVEL-\level
367 .weak _Level&level&FromVector
368 movi a4, _Level&level&FromVector
369 wsr a4, EXCSAVE+\level
370 .if GREATERTHAN(\level,XCHAL_EXCM_LEVEL)
371 movi a5, _Pri_&level&_HandlerAddress
373 /* If user provides their own handler, that handler might
374 * not provide its own _Pri_<n>_HandlerAddress variable for
375 * linking handlers. In that case, the reference below
376 * would pull in the XTOS handler anyway, causing a conflict.
377 * To avoid that, provide a weak version of it here:
379 .pushsection .data, "aw"
380 .global _Pri_&level&_HandlerAddress
381 .weak _Pri_&level&_HandlerAddress
383 _Pri_&level&_HandlerAddress: .space 4
400 * Complete reset initialization outside the vector,
401 * to avoid requiring a vector that is larger than necessary.
402 * This 2nd-stage startup code sets up the C Run-Time (CRT) and calls main().
404 * Here we use call0 not because we expect any return, but
405 * because the assembler/linker dynamically sizes call0 as
406 * needed (with -mlongcalls) which it doesn't with j or jx.
407 * Note: This needs to be call0 regardless of the selected ABI.
409 call0 _start // jump to _start (in crt1-*.S)
410 /* does not return */
412 #else /* XCHAL_HAVE_HALT */
414 j _start // jump to _start (in crt1-*.S)
415 // (TX has max 64kB IRAM, so J always in range)
417 // Paranoia -- double-check requirements / assumptions of this Xtensa TX code:
418 # if !defined(__XTENSA_CALL0_ABI__) || !XCHAL_HAVE_FULL_RESET || XCHAL_HAVE_INTERRUPTS || XCHAL_HAVE_CCOUNT || XCHAL_DTLB_ARF_WAYS || XCHAL_HAVE_DEBUG || XCHAL_HAVE_S32C1I || XCHAL_HAVE_ABSOLUTE_LITERALS || XCHAL_DCACHE_SIZE || XCHAL_ICACHE_SIZE || XCHAL_HAVE_PIF || XCHAL_HAVE_WINDOWED
419 # error "Halt architecture (Xtensa TX) requires: call0 ABI, all flops reset, no exceptions or interrupts, no TLBs, no debug, no S32C1I, no LITBASE, no cache, no PIF, no windowed regs"
422 #endif /* XCHAL_HAVE_HALT */
425 #if (!XCHAL_HAVE_HALT || defined(XTOS_UNPACK)) && XCHAL_HAVE_IMEM_LOADSTORE
426 .size _ResetHandler, . - _ResetHandler
428 .size _ResetVector, . - _ResetVector
432 .global xthals_hw_configid0, xthals_hw_configid1
433 .global xthals_release_major, xthals_release_minor