1 // Copyright 2016 The Fuchsia Authors
2 // Copyright (c) 2009 Corey Tabaka
3 // Copyright (c) 2014 Intel Corporation
4 //
5 // Use of this source code is governed by a MIT-style
6 // license that can be found in the LICENSE file or at
7 // https://opensource.org/licenses/MIT
8 
9 #pragma once
10 
11 /*
12  * System Selectors
13  */
14 #define NULL_SELECTOR           0x00
15 
16 /********* kernel selectors *********/
17 #define CODE_SELECTOR           0x08
18 #define CODE_64_SELECTOR        0x10
19 #define DATA_SELECTOR           0x18
20 
21 /********* user selectors *********/
22 #define USER_CODE_SELECTOR      (0x20 | 3)
23 #define USER_DATA_SELECTOR      (0x28 | 3)
24 #define USER_CODE_64_SELECTOR   (0x30 | 3)
25 
26 #define TSS_SELECTOR(i)            ((uint16_t)(0x38 + 16 * (i)))
27 /* 0x40 is used by the second half of the first TSS descriptor */
28 
29 /* selector priviledge level */
30 #define SELECTOR_PL(s) ((s) & 0x3)
31 
32 /*
33  * Descriptor Types
34  */
35 #define SEG_TYPE_TSS        0x9
36 #define SEG_TYPE_TSS_BUSY   0xb
37 #define SEG_TYPE_TASK_GATE  0x5
38 #define SEG_TYPE_INT_GATE   0xe     /* 32 bit */
39 #define SEG_TYPE_DATA_RW    0x2
40 #define SEG_TYPE_CODE_RW    0xa
41 
42 #ifndef __ASSEMBLER__
43 
44 #include <arch/aspace.h>
45 #include <zircon/compiler.h>
46 #include <reg.h>
47 #include <sys/types.h>
48 
49 #ifdef __cplusplus
50 #include <arch/x86/ioport.h>
51 
52 void x86_set_tss_io_bitmap(IoBitmap& bitmap);
53 void x86_clear_tss_io_bitmap(IoBitmap& bitmap);
54 void x86_reset_tss_io_bitmap(void);
55 #endif // __cplusplus
56 
57 __BEGIN_CDECLS
58 
59 typedef uint16_t seg_sel_t;
60 
61 /* fill in a descriptor in the GDT */
62 void set_global_desc_64(seg_sel_t sel, uint64_t base, uint32_t limit,
63                         uint8_t present, uint8_t ring, uint8_t sys,
64                         uint8_t type, uint8_t gran, uint8_t bits);
65 
66 /* tss stuff */
67 void x86_initialize_percpu_tss(void);
68 
69 void x86_set_tss_sp(vaddr_t sp);
70 void x86_clear_tss_busy(seg_sel_t sel);
71 
gdt_load(uintptr_t base)72 static inline void gdt_load(uintptr_t base) {
73     struct gdtr {
74         uint16_t limit;
75         uintptr_t address;
76     } __PACKED;
77     // During VM exit GDTR limit is always set to 0xffff and instead of
78     // trying to maintain the limit aligned with the actual GDT size we
79     // decided to just keep it 0xffff all the time and instead of relying
80     // on the limit just map GDT in the way that accesses beyond GDT cause
81     // page faults. This allows us to avoid calling LGDT on every VM exit.
82     struct gdtr gdtr = { .limit = 0xffff, .address = base };
83     x86_lgdt((uintptr_t)&gdtr);
84 }
85 
86 void gdt_setup(void);
87 uintptr_t gdt_get(void);
88 
89 __END_CDECLS
90 
91 #endif
92