1 // overlay.h -- Overlay manager header file
2 // $Id$
3 
4 // Copyright (c) 2013 Tensilica Inc.
5 //
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:
13 //
14 // The above copyright notice and this permission notice shall be included
15 // in all copies or substantial portions of the Software.
16 //
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.
24 
25 
26 #ifndef OVERLAY_H
27 #define OVERLAY_H
28 
29 
30 #include <xtensa/xtruntime.h>
31 
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
37 
38 // Overlays not supported for CALL0 ABI
39 #if defined (__XTENSA_CALL0_ABI__)
40 #undef  XT_DISABLE_OVERLAYS
41 #define XT_DISABLE_OVERLAYS    1
42 #endif
43 
44 // Define this to turn off overlay support
45 #ifdef XT_DISABLE_OVERLAYS
46 
47 #define OVERLAY(n)
48 #define DECLARE_OVERLAY(n)
49 
50 #define xt_overlay_map(ov_id)
51 #define xt_overlay_map_async(ov_id)                 0
52 #define xt_overlay_map_in_progress()                0
53 #define xt_overlay_get_id()                         0
54 #define xt_overlay_get_state(pc)                    0
55 #define xt_overlay_check_map(pc,ps,ovstate,sp)      0
56 
57 #else
58 
59 // Shorthand for convenience and portability.
60 #define OVERLAY(n)  __attribute__((overlay(n)))
61 
62 // Structure of the overlay table required by gdb and the overlay
63 // manager. Should not be accessed by user code unless overriding
64 // the load process.
65 struct ovly_table {
66     void *        vma;    // The overlay's mapped address.
67     unsigned int  size;   // The size of the overlay, in bytes.
68     void *        lma;    // The overlay's load address.
69     unsigned int  mapped; // Non-zero if overlay is currently mapped; zero otherwise.
70 };
71 
72 // Constructed by the linker. Required for gdb and for the overlay
73 // manager. Should not be accessed by user code unless overriding
74 // the load process.
75 extern struct ovly_table _ovly_table[];
76 
77 // Functions.
78 void xt_overlay_map(int ov_id);
79 int  xt_overlay_map_async(int ov_id);
80 int  xt_overlay_map_in_progress(void);
81 unsigned int xt_overlay_get_state(unsigned int pc);
82 unsigned int xt_overlay_check_map(unsigned int * pc, unsigned int * ps,
83                                   unsigned int ovstate, unsigned int sp);
84 int  xt_overlay_start_map(void * dst, void * src, unsigned int len, int ov_id);
85 int  xt_overlay_is_mapping(int ov_id);
86 void xt_overlay_fatal_error(int ov_id);
87 
88 
89 // Returns the current overlay ID. If no overlay is mapped or an overlay
90 // is in the middle of being mapped, returns -1. Inlined to avoid calling
91 // out of overlay (wastes cycles, can end up reading wrong ID on interrupt
92 // activity).
93 //
94 static inline int __attribute__((always_inline)) xt_overlay_get_id(void)
95 {
96 extern short _mapping_id;
97 extern short _ovly_id;
98 
99     int ret;
100     unsigned int flags = XTOS_SET_INTLEVEL(15);
101 
102     if (_mapping_id >= 0) {
103         ret = -1;
104     }
105     else {
106         ret = _ovly_id;
107     }
108 
109     XTOS_RESTORE_INTLEVEL(flags);
110     return ret;
111 }
112 
113 
114 // The following macros are used to declare numbered overlays and generate
115 // the corresponding call stubs. Use as follows:
116 //
117 //    DECLARE_OVERLAY(n)
118 //
119 // See documentation for more details.
120 
121 //#include <xtensa/config/core-isa.h>
122 
123 // At this time overlays are not supported without windowing.
124 #if defined(__XTENSA_WINDOWED_ABI__)
125 
126 #define xstr(x)   str(x)
127 #define str(x)    #x
128 
129 // At entry, register a8 holds the return address and a9 holds the target
130 // function address. This stub saves a8 on the stack at (SP - 20) which
131 // is the only location that is safe for us to use. Then it allocates 32
132 // bytes on the stack for working storage, loads the overlay number into
133 // a8, and jumps to the common handler. The common handler will make sure
134 // that the called function is loaded into memory before calling it.
135 // NOTE: we are using the stack area normally reserved for nested functions.
136 // This means nested functions cannot be used when overlays are in use.
137 
138 #define CALL_IN(num) \
139     asm(".section .gnu.linkonce.t.overlay.call." xstr(num) ".text, \"ax\"\n" \
140         ".global  _overlay_call_in_" xstr(num)  "_\n" \
141         ".align   4\n" \
142         "_overlay_call_in_" xstr(num) "_:\n" \
143         "s32e    a8, a1, -20\n" \
144         "addi    a8, a1, -32\n" \
145         "movsp   a1, a8\n" \
146         "movi    a8, " xstr(num) "\n" \
147         "j       _overlay_call_in_common\n" \
148         ".size   _overlay_call_in_" xstr(num) "_, . - _overlay_call_in_" xstr(num) "_\n");
149 
150 // The call-out stub first calls the target function, then loads the overlay
151 // number into register a14 and jumps to the common handler. The handler will
152 // make sure that the caller function is present in memory before returning.
153 // Note that registers a10-a13 may contain return values so must be preserved.
154 //
155 // Because we came here via a call4, the return address is in a4, and the top
156 // 2 bits are set to the window increment. We'll restore the top 2 bits of
157 // the return address from the called function's address, assuming that both
158 // are in the same 1 GB segment. For now this is always true.
159 
160 #define CALL_OUT(num) \
161     asm(".section .gnu.linkonce.t.overlay.call." xstr(num) ".text, \"ax\"\n" \
162         ".global  _overlay_call_out_" xstr(num) "_\n" \
163         ".align   4\n" \
164         "_overlay_call_out_" xstr(num) "_:\n" \
165         "slli    a4, a4, 2\n" \
166         "srli    a4, a4, 2\n" \
167         "extui   a8, a9, 30, 2\n" \
168         "slli    a8, a8, 30\n" \
169         "or      a4, a4, a8\n" \
170         "callx8  a9\n" \
171         "movi    a14, " xstr(num) "\n" \
172         "j       _overlay_call_out_common\n" \
173         ".size   _overlay_call_out_" xstr(num) "_, . - _overlay_call_out_" xstr(num) "_\n");
174 
175 // Generate a call-in and a call-out stub for each overlay.
176 
177 #define DECLARE_OVERLAY(num) \
178     CALL_IN(num) \
179     CALL_OUT(num)
180 
181 #endif // defined(__XTENSA_WINDOWED_ABI__)
182 
183 #endif // XT_DISABLE_OVERLAYS
184 
185 #ifdef __cplusplus
186 }
187 #endif
188 
189 #endif // OVERLAY_H
190 
191