Contiki 3.x
gdt.c
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 #include <stdint.h>
32 #include "gdt.h"
33 #include "gdt-layout.h"
34 #include "helpers.h"
35 #include "prot-domains.h"
36 #include "segmentation.h"
37 
38 #define GDT_MEM_PL0 (SEG_DESCTYPE_NSYS | SEG_GRAN_PAGE)
39 #define GDT_CODE_PL0 (GDT_MEM_PL0 | SEG_TYPE_CODE_EXRD)
40 #define GDT_DATA_PL0 (GDT_MEM_PL0 | SEG_TYPE_DATA_RDWR)
41 
42 typedef struct gdtr
43 {
44  uint16_t limit;
45  uint32_t base;
46 } __attribute__((packed)) gdtr_t;
47 
48 /* From Intel Combined Manual, Vol. 3 , Section 3.5.1: The base addresses of
49  * the GDT should be aligned on an eight-byte boundary to yield the best
50  * processor performance.
51  */
52 segment_desc_t __attribute__ ((aligned(8))) ATTR_BSS_GDT_START
53  gdt[GDT_NUM_FIXED_DESC];
54 
55 #define GDT_LEN \
56  ((((uintptr_t)&_ebss_gdt_addr) - \
57  (uintptr_t)gdt)/sizeof(segment_desc_t))
58 
59 /*---------------------------------------------------------------------------*/
60 static void ATTR_CODE_BOOT
61 set_descriptor(unsigned int index,
62  uint32_t base,
63  uint32_t len,
64  uint16_t flag)
65 {
66  segment_desc_t descriptor;
67 
68  if(GDT_LEN <= index) {
69  halt();
70  }
71 
72  segment_desc_init(&descriptor, base, len, flag);
73 
74  /* Save descriptor into gdt */
75  gdt_insert_boot(index, descriptor);
76 }
77 /*---------------------------------------------------------------------------*/
78 void
79 gdt_copy_desc_change_dpl(unsigned int dest_idx,
80  unsigned int src_idx,
81  unsigned dpl)
82 {
83  segment_desc_t desc;
84 
85  if((GDT_LEN <= dest_idx) || (GDT_LEN <= src_idx)) {
86  halt();
87  }
88 
89  gdt_lookup(src_idx, &desc);
90  SEG_SET_FLAG(desc, DPL, dpl);
91  gdt_insert(dest_idx, desc);
92 }
93 /*---------------------------------------------------------------------------*/
94 /* This function initializes the Global Descriptor Table. For simplicity, the
95  * memory is initially organized following the flat model. Thus, memory appears
96  * to Contiki as a single continuous address space. Code, data, and stack
97  * are all contained in this address space (so called linear address space).
98  * Certain protection domain implementations switch to a multi-segment memory
99  * model later during boot.
100  */
101 void
102 gdt_init(void)
103 {
104  gdtr_t gdtr;
105 
106  /* Initialize gdtr structure */
107  gdtr.limit = sizeof(segment_desc_t) * GDT_LEN - 1;
108  gdtr.base = KERN_DATA_OFF_TO_PHYS_ADDR(gdt);
109 
110  /* Initialize descriptors */
111  set_descriptor(GDT_IDX_NULL, 0, 0, 0);
112  set_descriptor(GDT_IDX_CODE_FLAT, 0, 0x100000, GDT_CODE_PL0);
113  set_descriptor(GDT_IDX_DATA_FLAT, 0, 0x100000, GDT_DATA_PL0);
114 
115  /* Load GDTR */
116  __asm__ __volatile__ ("lgdt %0" :: "m" (gdtr));
117 }
118 /*---------------------------------------------------------------------------*/
119 void
120 gdt_insert_boot(unsigned int idx, segment_desc_t desc)
121 {
122  ((segment_desc_t *)KERN_DATA_OFF_TO_PHYS_ADDR(gdt))[idx] = desc;
123 }
124 /*---------------------------------------------------------------------------*/
125 void
126 gdt_insert(unsigned int idx, segment_desc_t desc)
127 {
128  if(GDT_LEN <= idx) {
129  halt();
130  }
131 
132  KERN_WRITEL(gdt[idx].raw_lo, desc.raw_lo);
133  KERN_WRITEL(gdt[idx].raw_hi, desc.raw_hi);
134 }
135 /*---------------------------------------------------------------------------*/
136 void
137 gdt_lookup(unsigned int idx, segment_desc_t *desc)
138 {
139  if((GDT_LEN <= idx) || (desc == NULL)) {
140  halt();
141  }
142 
143  KERN_READL(desc->raw_lo, gdt[idx].raw_lo);
144  KERN_READL(desc->raw_hi, gdt[idx].raw_hi);
145 }
146 /*---------------------------------------------------------------------------*/
#define __attribute__(nothing)
Define attribute to nothing since it isn't handled by IAR.
Definition: iar.h:194
Segment descriptor.
Definition: segmentation.h:89
#define NULL
The null pointer.