]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
Generalize and fix read_descriptor
authorJan Kiszka <jan.kiszka@siemens.com>
Fri, 22 Nov 2013 06:56:40 +0000 (07:56 +0100)
committerJan Kiszka <jan.kiszka@siemens.com>
Fri, 22 Nov 2013 07:10:28 +0000 (08:10 +0100)
The current code used some improper bitmasks and still assumed to read a
task state segment. This rework allows to use it also for code and data
segments we will face when starting the hypervisor.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
hypervisor/arch/x86/include/asm/processor.h
hypervisor/arch/x86/setup.c

index 58e944eccc52d333c37aa1610815ec408963fbc8..75336e1214bb33126e9b5c41908dd8bcfbbfca4e 100644 (file)
 
 #define NMI_VECTOR                                     2
 
+#define DESC_PRESENT                                   (1UL << (15 + 32))
+#define DESC_CODE_DATA                                 (1UL << (12 + 32))
+#define DESC_PAGE_GRAN                                 (1UL << (23 + 32))
+
 #ifndef __ASSEMBLY__
 
 struct registers {
index d6e8848b815ff222ae33f9ceefebf1a2a4995f0f..2eafb59b770eba7ebe7e2c34b484e2ccf74934ff 100644 (file)
@@ -79,13 +79,25 @@ int arch_init_early(struct cell *linux_cell,
 
 static void read_descriptor(struct per_cpu *cpu_data, struct segment *seg)
 {
-       u64 *desc;
-
-       desc = (u64 *)(cpu_data->linux_gdtr.base + (seg->selector & 0xfff8));
-       seg->base = ((desc[0] >> 16) & 0xffffff) |
-               ((desc[0] >> 32) & 0xff000000) | (desc[1] << 32);
-       seg->limit = (desc[0] & 0xffff) | ((desc[0] >> 32) & 0xff0000);
-       seg->access_rights = (desc[0] >> 40) & 0xffff;
+       u64 *desc = (u64 *)(cpu_data->linux_gdtr.base +
+                           (seg->selector & 0xfff8));
+
+       if (desc[0] & DESC_PRESENT) {
+               seg->base = ((desc[0] >> 16) & 0xffffff) |
+                       ((desc[0] >> 32) & 0xff000000);
+               if (!(desc[0] & DESC_CODE_DATA))
+                       seg->base |= desc[1] << 32;
+
+               seg->limit = (desc[0] & 0xffff) | ((desc[0] >> 32) & 0xf0000);
+               if (desc[0] & DESC_PAGE_GRAN)
+                       seg->limit = (seg->limit << 12) | 0xfff;
+
+               seg->access_rights = (desc[0] >> 40) & 0xf0ff;
+       } else {
+               seg->base = 0;
+               seg->limit = 0;
+               seg->access_rights = 0x10000;
+       }
 }
 
 static void set_cs(u16 cs)