]> xenbits.xensource.com Git - people/royger/xen-test-framework.git/commitdiff
LDT/GDT infrastructure
authorAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 4 May 2015 16:52:45 +0000 (17:52 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 28 Sep 2015 13:54:44 +0000 (14:54 +0100)
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Doxyfile
arch/x86/desc.c [new file with mode: 0644]
config/files.mk
include/arch/x86/desc.h [new file with mode: 0644]
include/arch/x86/segment.h [new file with mode: 0644]
include/xtf/compiler.h
include/xtf/macro_magic.h [new file with mode: 0644]

index 9dd89be70626801ccdb9c7ac34fe2dbb4ac6da5f..016cb5a1dcb30e637907e0c2c925522bf387ef25 100644 (file)
--- a/Doxyfile
+++ b/Doxyfile
@@ -1987,6 +1987,7 @@ INCLUDE_FILE_PATTERNS  =
 
 PREDEFINED             = __aligned(x)= \
                          __attribute__(x)= \
+                         __packed \
                          __printf(x,y)= \
                          __noreturn \
 
diff --git a/arch/x86/desc.c b/arch/x86/desc.c
new file mode 100644 (file)
index 0000000..4dd02bf
--- /dev/null
@@ -0,0 +1,25 @@
+#include <arch/x86/desc.h>
+#include <arch/x86/segment.h>
+
+user_desc gdt[NR_GDT_ENTRIES] =
+{
+    [GDTE_CS64_DPL0] = INIT_GDTE_SYM(0, 0xfffff, COMMON, CODE, DPL0, R, L),
+    [GDTE_CS32_DPL0] = INIT_GDTE_SYM(0, 0xfffff, COMMON, CODE, DPL0, R, D),
+    [GDTE_DS32_DPL0] = INIT_GDTE_SYM(0, 0xfffff, COMMON, DATA, DPL0, B, W),
+};
+
+desc_ptr gdt_ptr =
+{
+    .limit = sizeof(gdt) - 1,
+    .base = (unsigned long)&gdt,
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index 0e4921ff64c2b7bed1a490f1d358689931f645f9..420508c5488ad571227760a57a9b8569126c1732 100644 (file)
@@ -10,6 +10,7 @@ obj-perarch += $(ROOT)/common/libc/string.o
 obj-perarch += $(ROOT)/common/libc/vsnprintf.o
 obj-perarch += $(ROOT)/common/setup.o
 
+obj-perenv += $(ROOT)/arch/x86/desc.o
 obj-perenv += $(ROOT)/arch/x86/setup.o
 obj-perenv += $(ROOT)/arch/x86/traps.o
 
diff --git a/include/arch/x86/desc.h b/include/arch/x86/desc.h
new file mode 100644 (file)
index 0000000..b52d685
--- /dev/null
@@ -0,0 +1,149 @@
+/**
+ * @file include/arch/x86/desc.h
+ *
+ * %x86 segment descriptor infrastructure.
+ */
+
+#ifndef XTF_X86_DESC_H
+#define XTF_X86_DESC_H
+
+#include <xtf/types.h>
+#include <xtf/compiler.h>
+#include <xtf/macro_magic.h>
+
+/** 8 byte user segment descriptor (GDT/LDT entries with .s = 1) */
+struct __packed seg_desc32 {
+    union {
+        /** Raw backing integers. */
+        struct {
+            uint32_t lo, hi;
+        };
+        /** Common named fields. */
+        struct {
+            uint16_t limit0;
+            uint16_t base0;
+            uint8_t  base1;
+            unsigned type: 4;
+            unsigned s: 1, dpl: 2, p: 1;
+            unsigned limit: 4;
+            unsigned avl: 1, l: 1, d: 1, g: 1;
+            uint8_t base2;
+        };
+        /** Code segment specific field names. */
+        struct {
+            uint16_t limit0;
+            uint16_t base0;
+            uint8_t  base1;
+            unsigned a: 1, r: 1, c: 1, x: 1;
+            unsigned s: 1, dpl: 2, p: 1;
+            unsigned limit: 4;
+            unsigned avl: 1, l: 1, d: 1, g: 1;
+            uint8_t base2;
+        } code;
+        /** Data segment specific field names. */
+        struct {
+            uint16_t limit0;
+            uint16_t base0;
+            uint8_t  base1;
+            unsigned a: 1, w: 1, e: 1, x: 1;
+            unsigned s: 1, dpl: 2, p: 1;
+            unsigned limit: 4;
+            unsigned avl: 1, _r0: 1, b: 1, g: 1;
+            uint8_t base2;
+        } data;
+    };
+};
+
+/* GDT/LDT attribute flags for user segments */
+
+/* Common */
+#define SEG_ATTR_G      0x8000 /**< Granularity of limit (0 = 1, 1 = 4K) */
+#define SEG_ATTR_AVL    0x1000 /**< Available for software use */
+#define SEG_ATTR_P      0x0080 /**< Present? */
+#define SEG_ATTR_S      0x0010 /**< !System desc (0 = system, 1 = user) */
+#define SEG_ATTR_A      0x0001 /**< Accessed? (set by hardware) */
+
+#define SEG_ATTR_COMMON 0x8091 /**< Commonly set bits (G P S A) */
+
+#define SEG_ATTR_DPL0   0x0000 /**< Descriptor privilege level 0 */
+#define SEG_ATTR_DPL1   0x0020 /**< Descriptor privilege level 1 */
+#define SEG_ATTR_DPL2   0x0040 /**< Descriptor privilege level 2 */
+#define SEG_ATTR_DPL3   0x0060 /**< Descriptor privilege level 3 */
+#define SEG_ATTR_CODE   0x0008 /**< Type (0 = data, 1 = code)    */
+#define SEG_ATTR_DATA   0x0000 /**< Type (0 = data, 1 = code)    */
+
+/* Code segments */
+#define SEG_ATTR_D      0x4000 /**< Default operand size (0 = 16bit, 1 = 32bit) */
+#define SEG_ATTR_L      0x2000 /**< Long segment? (1 = 64bit) */
+#define SEG_ATTR_C      0x0004 /**< Conforming? (0 = non, 1 = conforming) */
+#define SEG_ATTR_R      0x0002 /**< Readable? (0 = XO seg, 1 = RX seg) */
+
+/* Data segments */
+#define SEG_ATTR_B      0x4000 /**< 'Big' flag.
+                                *    - For %ss, default operand size.
+                                *    - For expand-down segment, sets upper bound. */
+#define SEG_ATTR_E      0x0004 /**< Expand-down? (0 = normal, 1 = expand-down) */
+#define SEG_ATTR_W      0x0002 /**< Writable? (0 = RO seg, 1 = RW seg) */
+
+/* Macro magic to expand symbolic SEG_ATTR names into a constant */
+#define _GDTE_ATTR0()       (0)
+#define _GDTE_ATTR1(x)      (SEG_ATTR_ ## x)
+#define _GDTE_ATTR2(x, ...) (SEG_ATTR_ ## x | _GDTE_ATTR1(__VA_ARGS__))
+#define _GDTE_ATTR3(x, ...) (SEG_ATTR_ ## x | _GDTE_ATTR2(__VA_ARGS__))
+#define _GDTE_ATTR4(x, ...) (SEG_ATTR_ ## x | _GDTE_ATTR3(__VA_ARGS__))
+#define _GDTE_ATTR5(x, ...) (SEG_ATTR_ ## x | _GDTE_ATTR4(__VA_ARGS__))
+#define _GDTE_ATTR6(x, ...) (SEG_ATTR_ ## x | _GDTE_ATTR5(__VA_ARGS__))
+#define _GDTE_ATTR7(x, ...) (SEG_ATTR_ ## x | _GDTE_ATTR6(__VA_ARGS__))
+#define _GDTE_ATTR8(x, ...) (SEG_ATTR_ ## x | _GDTE_ATTR7(__VA_ARGS__))
+
+#define GDTE_ATTR(...) VAR_MACRO(_GDTE_ATTR, __VA_ARGS__)
+
+
+#define _INIT_GDTE(base, limit, attr) { { {                           \
+     .lo = (((base) & 0xffff) << 16) | ((limit) & 0xffff),            \
+     .hi = ((base) & 0xff000000) | ((limit) & 0xf0000) |              \
+           (((attr) & 0xf0ff) << 8) | (((base) & 0xff0000) >> 16)     \
+     } } }
+
+/** Initialise an LDT/GDT entry using a raw attribute number. */
+#define INIT_GDTE_RAW(base, limit, attr) _INIT_GDTE(base, limit, attr)
+/** Initialise an LDT/GDT entry using symbol attributes. */
+#define INIT_GDTE_SYM(base, limit, ...)  _INIT_GDTE(base, limit, GDTE_ATTR(__VA_ARGS__))
+
+/** Long mode lgdt/lidt table pointer. */
+struct __packed desc_ptr64 {
+    uint16_t limit;
+    uint64_t base;
+};
+
+/** Protected mode lgdt/lidt table pointer. */
+struct __packed desc_ptr32 {
+    uint16_t limit;
+    uint32_t base;
+};
+
+#if defined(__x86_64__)
+
+typedef struct desc_ptr64 desc_ptr;
+typedef struct seg_desc32 user_desc;
+
+#elif defined(__i386__)
+
+typedef struct desc_ptr32 desc_ptr;
+typedef struct seg_desc32 user_desc;
+
+#else
+# error Bad architecture for descriptor infrastructure
+#endif
+
+#endif /* XTF_X86_DESC_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/arch/x86/segment.h b/include/arch/x86/segment.h
new file mode 100644 (file)
index 0000000..812adf2
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef XTF_X86_SEGMENT_H
+#define XTF_X86_SEGMENT_H
+
+/*
+ * GDT layout:
+ *
+ * For simplicitly, the gdt is shared as much as possible between different
+ * environments.
+ *
+ *  0 - null
+ *  1 - 64bit supervisor code
+ *  2 - 32bit supervisor code
+ *  3 - 32bit supervisor data
+ */
+
+#define GDTE_CS64_DPL0 1
+#define GDTE_CS32_DPL0 2
+#define GDTE_DS32_DPL0 3
+
+#define NR_GDT_ENTRIES 4
+
+#if defined(CONFIG_ENV_hvm64)
+
+#define __KERN_CS (GDTE_CS64_DPL0 * 8)
+#define __KERN_DS (0)
+
+#elif defined(CONFIG_ENV_hvm32)
+
+#define __KERN_CS (GDTE_CS32_DPL0 * 8)
+#define __KERN_DS (GDTE_DS32_DPL0 * 8)
+
+#endif
+
+#endif /* XTF_X86_SEGMENT_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index 9c3b05d9e015944bc1f47a7cac8876e6819016c2..6829273387dae58151b5b1d39b1007528e1879af 100644 (file)
@@ -2,6 +2,7 @@
 #define XTF_COMPILER_H
 
 #define __aligned(x)          __attribute__((aligned(x)))
+#define __packed              __attribute__((packed))
 
 #define __noreturn            __attribute__((noreturn))
 #define unreachable()         __builtin_unreachable()
diff --git a/include/xtf/macro_magic.h b/include/xtf/macro_magic.h
new file mode 100644 (file)
index 0000000..9bff470
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef XTF_MACRO_MAGIC_H
+#define XTF_MACRO_MAGIC_H
+
+/* Here be many dragons */
+
+/*
+ * VA_NRARGS(...) will count the number of provided arguments.
+ *
+ * - VA_NRARGS()  => 0
+ * - VA_NRARGS(x) => 1
+ *
+ * Currently functions for 0 to 11 arguments.
+ */
+#define VA_NARGS_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) N
+#define VA_NARGS(...) \
+    VA_NARGS_(X,##__VA_ARGS__, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+
+/*
+ * VAR_MACRO(macro, ...) will construct a macro which counts its arguments and
+ * calls a evaluates a varient of its first parameter.
+ *
+ * - VAR_MACRO(x)       => x0()
+ * - VAR_MACRO(x, y)    => x1(y)
+ * - VAR_MACRO(x, y, x) => x2(y, z)
+ */
+#define VAR_MACRO__(macro, count, ...) macro##count(__VA_ARGS__)
+#define VAR_MACRO_(macro, count, ...)  VAR_MACRO__(macro, count, __VA_ARGS__)
+#define VAR_MACRO(macro, ...) \
+    VAR_MACRO_(macro, VA_NARGS(__VA_ARGS__), __VA_ARGS__)
+
+#endif /* XTF_MACRO_MAGIC_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */