Contiki 3.x
tss-prot-domains.c
1 /*
2  * Copyright (C) 2015-2016, 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 #include <stdint.h>
32 #include <string.h>
33 #include "gdt.h"
34 #include "helpers.h"
35 #include "idt.h"
36 #include "prot-domains.h"
37 #include "stacks.h"
38 #include "syscalls.h"
39 #include "tss.h"
40 
41 uint32_t prot_domains_main_esp;
42 syscalls_entrypoint_t ATTR_KERN_ADDR_SPACE *prot_domains_syscall;
43 
44 /*---------------------------------------------------------------------------*/
45 void app_main(void);
46 void
47 prot_domains_reg(dom_client_data_t ATTR_KERN_ADDR_SPACE *dcd,
48  uintptr_t mmio, size_t mmio_sz,
49  uintptr_t meta, size_t meta_sz,
50  bool pio)
51 {
52  segment_desc_t desc;
53  uint32_t eflags;
54  dom_id_t dom_id;
55  volatile struct dom_kern_data ATTR_KERN_ADDR_SPACE *dkd;
56 
57  KERN_READL(dom_id, dcd->dom_id);
58 
59  dkd = prot_domains_kern_data + dom_id;
60 
61  prot_domains_reg_multi_seg(dkd, mmio, mmio_sz, meta, meta_sz);
62 
63  /* Only the kernel protection domain requires port I/O access outside of the
64  * interrupt handlers.
65  */
66  eflags = EFLAGS_IOPL(pio ? PRIV_LVL_USER : PRIV_LVL_INT);
67  if(dom_id == DOM_ID_app) {
68  eflags |= EFLAGS_IF;
69  }
70 
71  /* Keep this initialization in sync with the register definitions in
72  * tss-prot-domains-asm.S.
73  */
74  KERN_WRITEL(dkd->tss.ebp, 0);
75  KERN_WRITEL(dkd->tss.ebx, 0);
76  KERN_WRITEL(dkd->tss.esi, BIT(dom_id));
77  KERN_WRITEL(dkd->tss.eip,
78  (dom_id == DOM_ID_app) ?
79  (uint32_t)app_main :
80  (uint32_t)prot_domains_syscall_dispatcher);
81  KERN_WRITEL(dkd->tss.cs, GDT_SEL_CODE);
82  KERN_WRITEL(dkd->tss.ds, GDT_SEL_DATA);
83  KERN_WRITEL(dkd->tss.es, GDT_SEL_DATA);
84  KERN_WRITEL(dkd->tss.fs, LDT_SEL_KERN);
85  KERN_WRITEL(dkd->tss.gs,
86  (meta_sz == 0) ? GDT_SEL_NULL : LDT_SEL_META);
87  KERN_WRITEL(dkd->tss.ss, GDT_SEL_STK);
88  /* This stack pointer is only actually used in application protection domain.
89  * Other domains enter at system call dispatcher, which switches to main
90  * stack.
91  */
92  KERN_WRITEL(dkd->tss.esp,
93  /* Two return addresses have been consumed: */
94  STACKS_INIT_TOP + (2 * sizeof(uintptr_t)));
95  KERN_WRITEL(dkd->tss.eflags, eflags);
96  KERN_WRITEL(dkd->tss.ldt, GDT_SEL_LDT(dom_id));
97  KERN_WRITEL(dkd->tss.esp2, STACKS_SIZE_MAIN + STACKS_SIZE_INT);
98  KERN_WRITEL(dkd->tss.ss2, GDT_SEL_STK_INT);
99  KERN_WRITEL(dkd->tss.esp0,
100  STACKS_SIZE_MAIN + STACKS_SIZE_INT + STACKS_SIZE_EXC);
101  KERN_WRITEL(dkd->tss.ss0, GDT_SEL_STK_EXC);
102  KERN_WRITEW(dkd->tss.t, 0);
103  KERN_WRITEW(dkd->tss.iomap_base, sizeof(tss_t));
104  KERN_WRITEL(dkd->tss.cr3, 0);
105 
106  segment_desc_init(&desc,
107  KERN_DATA_OFF_TO_PHYS_ADDR((uint32_t)&(dkd->tss)),
108  sizeof(dkd->tss),
109  /* It should be possible for code at any privilege level to invoke the task's
110  * system call dispatcher.
111  */
112  SEG_FLAG(DPL, PRIV_LVL_USER) | SEG_TYPE_TSS32_AVAIL);
113 
114  gdt_insert(GDT_IDX_TSS(dom_id), desc);
115 
116  KERN_WRITEW(dcd->tss_sel, GDT_SEL(GDT_IDX_TSS(dom_id), PRIV_LVL_USER));
117 }
118 /*---------------------------------------------------------------------------*/
119 void dev_not_avail_isr(void);
120 void
121 prot_domains_impl_init(void)
122 {
123  __asm__ __volatile__ ("ltr %0" :: "r" ((uint16_t)GDT_SEL_TSS(DOM_ID_kern)));
124  __asm__ __volatile__ ("lldt %0" :: "r" ((uint16_t)GDT_SEL_LDT(DOM_ID_kern)));
125 
126  idt_set_intr_gate_desc(7,
127  (uint32_t)dev_not_avail_isr,
128  GDT_SEL_CODE_EXC, PRIV_LVL_EXC);
129 }
130 /*---------------------------------------------------------------------------*/
131 int main();
132 void
133 prot_domains_launch_kernel(void)
134 {
135  multi_segment_launch_kernel();
136 
137  /* Activate kernel protection domain, entering the kernel at main. */
138  __asm__ __volatile__ (
139  "pushl %[_ss_]\n\t"
140  "pushl %[_top_of_stk_]\n\t"
141  "pushl %[_eflags_]\n\t"
142  "pushl %[_cs_]\n\t"
143  "pushl %[_kern_start_]\n\t"
144  "iretl\n\t"
145  :
146  : [_ss_] "g" (GDT_SEL_STK),
147  [_eflags_] "g" (EFLAGS_IOPL(PRIV_LVL_USER)),
148  [_cs_] "g" (GDT_SEL_CODE),
149  [_kern_start_] "g" (main),
150  /* one address has already been consumed */
151  [_top_of_stk_] "g" (STACKS_INIT_TOP + sizeof(uint32_t))
152  );
153 }
154 /*---------------------------------------------------------------------------*/
155 void
156 prot_domains_launch_app()
157 {
158  far_pointer_t app_ptr = { 0, GDT_SEL_TSS(DOM_ID_app) };
159  __asm__ __volatile__ ("ljmp *%0" :: "m" (app_ptr));
160 }
161 /*---------------------------------------------------------------------------*/
#define BIT(x)
Useful to reference a single bit of a byte.
Segment descriptor.
Definition: segmentation.h:89
Task State Segment.
Definition: tss.h:45
Data associated with each protection domain that is owned by clients of that domain and used to ident...
Definition: prot-domains.h:247
int main()
This is main...
Definition: ethconfig.c:49