Contiki 3.x
prot-domains.h
1 /*
2  * Copyright (C) 2015, Intel Corporation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * 3. Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #ifndef CPU_X86_MM_PROT_DOMAINS_H_
32 #define CPU_X86_MM_PROT_DOMAINS_H_
33 
34 #if !__ASSEMBLER__
35 #include <stdint.h>
36 #include <stdlib.h>
37 #include <stdbool.h>
38 #include "helpers.h"
39 #endif
40 
41 #define X86_CONF_PROT_DOMAINS__NONE 0
42 #define X86_CONF_PROT_DOMAINS__PAGING 1
43 #define X86_CONF_PROT_DOMAINS__TSS 2
44 #define X86_CONF_PROT_DOMAINS__SWSEG 3
45 
46 #define X86_CONF_PROT_DOMAINS_MULTI_SEG \
47  ((X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS) || \
48  (X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG))
49 
50 /** Privilege level (ring) for exception handlers and other supervisory code */
51 #define PRIV_LVL_EXC 0
52 #if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE
53 /** Privilege level for interrupt handlers */
54 #define PRIV_LVL_INT 2
55 /** Default privilege level */
56 #define PRIV_LVL_USER 3
57 #else
58 #define PRIV_LVL_INT PRIV_LVL_EXC
59 #define PRIV_LVL_USER PRIV_LVL_EXC
60 #endif
61 
62 #define DOM_ID_kern 0
63 #define DOM_ID_app 1
64 
65 /** I/O Privilege Level */
66 #define EFLAGS_IOPL(pl) ((pl) << 12)
67 /** Interrupt Enable Flag */
68 #define EFLAGS_IF (1u << 9)
69 
70 #if !__ASSEMBLER__
71 
72 /** Protection domain ID */
73 typedef uint32_t dom_id_t;
74 
75 #if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING
76 #include "paging-prot-domains.h"
77 #elif X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS
78 #include "tss-prot-domains.h"
79 #elif X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG
80 #include "swseg-prot-domains.h"
81 #endif
82 
83 #ifndef ATTR_META_ADDR_SPACE
84 #define ATTR_META_ADDR_SPACE
85 #endif
86 #ifndef ATTR_MMIO_ADDR_SPACE
87 #define ATTR_MMIO_ADDR_SPACE
88 #endif
89 #ifndef ATTR_KERN_ADDR_SPACE
90 #define ATTR_KERN_ADDR_SPACE
91 #endif
92 
93 #ifndef MMIO_READL
94 #define MMIO_READL(dst, src) dst = (src)
95 #define MMIO_READW(dst, src) dst = (src)
96 #define MMIO_READB(dst, src) dst = (src)
97 #define MMIO_WRITEL(dst, src) MMIO_READL(dst, src)
98 #define MMIO_WRITEW(dst, src) MMIO_READW(dst, src)
99 #define MMIO_WRITEB(dst, src) MMIO_READB(dst, src)
100 #endif
101 #ifndef KERN_READL
102 #define KERN_READL(dst, src) dst = (src)
103 #define KERN_READW(dst, src) dst = (src)
104 #define KERN_READB(dst, src) dst = (src)
105 #define KERN_WRITEL(dst, src) KERN_READL(dst, src)
106 #define KERN_WRITEW(dst, src) KERN_READW(dst, src)
107 #define KERN_WRITEB(dst, src) KERN_READB(dst, src)
108 #endif
109 #ifndef META_READL
110 #define META_READL(dst, src) dst = (src)
111 #define META_READW(dst, src) dst = (src)
112 #define META_READB(dst, src) dst = (src)
113 #define META_WRITEL(dst, src) META_READL(dst, src)
114 #define META_WRITEW(dst, src) META_READw(dst, src)
115 #define META_WRITEB(dst, src) META_READB(dst, src)
116 #endif
117 
118 #ifndef MEMCPY_FROM_META
119 #define MEMCPY_FROM_META(dst, src, sz) \
120  memcpy((void *)(dst), (const void *)(src), (sz))
121 #define MEMCPY_TO_META(dst, src, sz) MEMCPY_FROM_META(dst, src, sz)
122 #endif
123 
124 /* The following symbols are defined in the linker script */
125 /** Bounds for .text section */
126 extern uint32_t _stext_addr, _etext_addr;
127 
128 #if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE
129 
130 /** Metadata that should not be DMA-accessible */
131 #define ATTR_BSS_META __attribute__((section(".meta_bss"))) ATTR_META_ADDR_SPACE
132 /** Kernel-owned data */
133 #define ATTR_BSS_KERN __attribute__((section(".kern_bss"))) ATTR_KERN_ADDR_SPACE
134 /** Code that should only be executable during bootup */
135 #define ATTR_CODE_BOOT __attribute__((section(".boot_text")))
136 
137 /**
138  * Domain-defined metadata must be page-aligned, which is implemented by the
139  * linker script for variables with this attribute.
140  */
141 #define ATTR_BSS_KERN_PAGE_ALIGNED \
142  __attribute__((section(".page_aligned_kern_bss")))
143 
144 /** Bounds for .kern_data, .syscall_data, and .prot_dom_data sections */
145 extern uint32_t _sbss_kern_addr, _ebss_kern_addr;
146 /** End of .syscall_data section */
147 extern uint32_t _ebss_syscall_addr;
148 /** Bounds for other data sections */
149 extern uint32_t _sdata_addr, _edata_addr;
150 
151 #ifndef SEG_KERN
152 #define SEG_KERN "d"
153 #endif
154 
155 /**
156  * If set, this protection domain is already in the call stack and is not
157  * available for nested invocations.
158  */
159 #define PROT_DOMAINS_FLAG_BUSY BIT(0)
160 /** If set, this protection domain requires port I/O access. */
161 #define PROT_DOMAINS_FLAG_PIO BIT(1)
162 /** If set, this protection domain is initialized. */
163 #define PROT_DOMAINS_FLAG_INITED BIT(2)
164 
165 /**
166  * Data associated with each protection domain that should be fully accessible
167  * only to the kernel, with limited accesses and modifications permitted from
168  * other domains. Includes storage for system data structures.
169  */
170 typedef struct dom_kern_data dom_kern_data_t;
171 
172 extern volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE prot_domains_kern_data[];
173 extern volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE prot_domains_kern_data_end[];
174 
175 #define PROT_DOMAINS_ACTUAL_CNT \
176  (prot_domains_kern_data_end - prot_domains_kern_data)
177 
178 #define PROT_DOMAINS_GET_DOM_ID(dkd) \
179  ((dom_id_t)((dkd) - prot_domains_kern_data))
180 
181 void prot_domains_syscall_dispatcher(void);
182 
183 #if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__TSS
184 /**
185  * Data associated with each protection domain that is owned by clients of that
186  * domain and used to identify the domain.
187  */
188 struct dom_client_data {
189  dom_id_t dom_id;
190 } __attribute__((packed));
191 #endif
192 
193 #ifndef PROT_DOMAINS_ALLOC_IMPL
194 #define PROT_DOMAINS_ALLOC_IMPL(nm)
195 #endif
196 
197 /** Allocate the client-owned protection domain data structure. */
198 #define PROT_DOMAINS_PDCS_NM(nm) _pdcs_##nm
199 #define PROT_DOMAINS_ALLOC(typ, nm) \
200  static dom_kern_data_t __attribute__((section(".prot_dom_bss"))) \
201  ATTR_KERN_ADDR_SPACE PROT_DOMAINS_PDCS_NM(nm); \
202  PROT_DOMAINS_ALLOC_IMPL(nm); \
203  static typ ATTR_BSS_KERN nm
204 #define PROT_DOMAINS_INIT_ID(nm) \
205  KERN_WRITEL((nm).dom_id, PROT_DOMAINS_GET_DOM_ID(&PROT_DOMAINS_PDCS_NM(nm)))
206 
207 /**
208  * Perform early initialization during boot stage 0 to prepare for boot stage 1
209  */
210 void prot_domains_gdt_init() ATTR_CODE_BOOT;
211 /**
212  * Perform initialization during boot stage 1 to prepare for kernel launch
213  */
214 void prot_domains_init();
215 void prot_domains_impl_init();
216 
217 /* Return from cpu_boot_stage1 will invoke prot_domains_launch_kernel due to
218  * that return address being pushed on the stack by cpu_boot_stage0.
219  */
220 #define prot_domains_leave_boot_stage1()
221 
222 /* Return from main will invoke prot_domains_launch_app due to that return
223  * address being pushed on the stack by cpu_boot_stage0.
224  */
225 #define prot_domains_leave_main()
226 
227 void prot_domains_launch_kernel(void);
228 
229 /* Whenever changing this, update syscalls-int-asm.S:prot_domains_launch_kernel
230  * to match:
231  */
232 #define PROT_DOMAINS_INIT_RET_ADDR_CNT 2
233 
234 #if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS
235 void prot_domains_launch_app(void);
236 #else
237 void app_main(void);
238 #define prot_domains_launch_app app_main
239 #endif
240 
241 #else
242 
243 #define ATTR_BSS_META
244 #define ATTR_BSS_KERN
245 #define ATTR_CODE_BOOT
246 
248  uintptr_t mmio; /**< MMIO range base address */
249  uintptr_t meta; /**< Domain-defined metadata base address */
250 };
251 
252 /** Retrieve the MMIO base address for the specified protection domain. */
253 #define PROT_DOMAINS_MMIO(dcd) ((dcd).mmio)
254 
255 /** Retrieve the metadata base address for the specified protection domain. */
256 #define PROT_DOMAINS_META(dcd) ((dcd).meta)
257 
258 #define PROT_DOMAINS_ALLOC(typ, nm) static typ nm
259 #define PROT_DOMAINS_INIT_ID(nm)
260 
261 #define prot_domains_gdt_init()
262 
263 #define prot_domains_init()
264 
265 int main(void);
266 #define prot_domains_leave_boot_stage1 main
267 #define prot_domains_leave_main ENABLE_IRQ(); app_main
268 
269 #define PROT_DOMAINS_INIT_RET_ADDR_CNT 0
270 
271 #endif
272 
273 /**
274  * Protection domain data readable by the client. It is used to control
275  * execution, so it should be protected from modifications by clients.
276  * Otherwise, there is a risk that one client could modify one of these
277  * structures used by another client to issue a system call, which could then
278  * cause the latter client to perform an unintended system call.
279  */
280 typedef struct dom_client_data dom_client_data_t;
281 
282 #if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE
283 #define prot_domains_reg(dcd, mmio_, mmio_sz, meta_, meta_sz, pio) \
284  (dcd)->mmio = (mmio_); \
285  (dcd)->meta = (meta_)
286 #else
287 /**
288  * \brief Register a protection domain, which involves creating the
289  * necessary system data structures for it.
290  *
291  * \param dcd Client-accessible domain information
292  * \param mmio Optional base address for per-domain memory-mapped IO region
293  * \param mmio_sz Size of MMIO region
294  * \param meta Optional base address for per-domain metadata
295  * \param meta_sz Size of metadata
296  * \param pio Set to true if protection domain requires port IO access
297  */
298 void prot_domains_reg(dom_client_data_t ATTR_KERN_ADDR_SPACE *dcd,
299  uintptr_t mmio,
300  size_t mmio_sz,
301  uintptr_t meta,
302  size_t meta_sz,
303  bool pio);
304 #endif
305 
306 #if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE
307 #define prot_domains_copy_dcd(dst, src) *(dst) = *(src)
308 #else
309 static inline void
310 /**
311  * It is necessary to make a local copy of a dom_client_data structure when a
312  * multi-segment protection domain implementation is in use, segment attributes
313  * are not supported by the compiler, and a dom_client_data structure needs to
314  * be passed by value into some function. Otherwise, the compiler will not know
315  * to access the non-default segment in which *src is stored and will attempt
316  * to copy it out of the default data segment.
317  */
318 prot_domains_copy_dcd(struct dom_client_data *dst,
319  struct dom_client_data ATTR_KERN_ADDR_SPACE *src)
320 {
321  KERN_READL(dst->dom_id, src->dom_id);
322 #if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS
323  KERN_READL(dst->tss_sel, src->tss_sel);
324 #endif
325 }
326 #endif
327 
328 #if !X86_CONF_PROT_DOMAINS_MULTI_SEG
329 #define prot_domains_enable_mmio()
330 #define prot_domains_disable_mmio()
331 
332 #define KERN_DATA_OFF_TO_PHYS_ADDR(x) ((uintptr_t)(x))
333 #define DATA_OFF_TO_PHYS_ADDR(x) ((uintptr_t)(x))
334 #endif
335 
336 #if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE
337 #define prot_domains_lookup_meta_phys_base(drv) 0
338 #else
339 /** Lookup base physical address of metadata region for specified domain */
340 uintptr_t prot_domains_lookup_meta_phys_base(dom_client_data_t ATTR_KERN_ADDR_SPACE *drv);
341 #endif
342 
343 #if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__PAGING
344 #define PROT_DOMAINS_META_OFF_TO_PHYS(off, meta_phys_base) \
345  ((meta_phys_base) + (off))
346 #endif
347 
348 #if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE
349 #define PROT_DOMAINS_ENTER_ISR(...)
350 #define PROT_DOMAINS_LEAVE_ISR(...)
351 #else
352 #define PROT_DOMAINS_ENTER_ISR_COMMON(exc) \
353  ".if !" #exc "\n\t" \
354  /* Save the current stack pointer into a callee-saved register. */ \
355  "mov %%esp, %%ebx\n\t" \
356  /* Pivot to the main stack of the interrupted context. */ \
357  /* Interrupts never have an error code, so the offset is always 44. */ \
358  /* No interrupt handlers use anything from the original interrupt stack, */ \
359  /* so there is no need to copy anything from it to the main stack. */ \
360  "mov 44(%%esp), %%esp\n\t" \
361  ".endif\n\t"
362 #define PROT_DOMAINS_LEAVE_ISR_COMMON(exc) \
363  /* Restore the interrupt/exception stack pointer. */ \
364  ".if !" #exc "\n\t" \
365  "mov %%ebx, %%esp\n\t" \
366  ".endif\n\t"
367 #endif
368 
369 #ifdef X86_CONF_PROT_DOMAINS_MULTI_SEG
370 /* include GDT section definitions used when allocating protection domains: */
371 #include "gdt.h"
372 #endif
373 
374 #endif /* !__ASSEMBLER__ */
375 
376 #endif /* CPU_X86_MM_PROT_DOMAINS_H_ */
#define __attribute__(nothing)
Define attribute to nothing since it isn't handled by IAR.
Definition: iar.h:194
uint32_t tss_sel
The selector is only 16 bits, but it is padded to 32 bits.
uintptr_t meta
Domain-defined metadata base address.
Definition: prot-domains.h:249
Data associated with each protection domain that is owned by clients of that domain and used to ident...
Definition: prot-domains.h:247
uintptr_t mmio
MMIO range base address.
Definition: prot-domains.h:248
int main(void)
This is main...
Definition: ethconfig.c:49