• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // For GDT details see arch/x86/include/asm/segment.h
6 
7 use kvm_sys::kvm_segment;
8 
9 /// Constructor for a conventional segment GDT (or LDT) entry. Derived from the kernel's segment.h.
gdt_entry(flags: u16, base: u32, limit: u32) -> u6410 pub fn gdt_entry(flags: u16, base: u32, limit: u32) -> u64 {
11     ((((base as u64) & 0xff000000u64) << (56 - 24))
12         | (((flags as u64) & 0x0000f0ffu64) << 40)
13         | (((limit as u64) & 0x000f0000u64) << (48 - 16))
14         | (((base as u64) & 0x00ffffffu64) << 16)
15         | ((limit as u64) & 0x0000ffffu64))
16 }
17 
get_base(entry: u64) -> u6418 fn get_base(entry: u64) -> u64 {
19     ((((entry) & 0xFF00000000000000) >> 32)
20         | (((entry) & 0x000000FF00000000) >> 16)
21         | (((entry) & 0x00000000FFFF0000) >> 16))
22 }
23 
get_limit(entry: u64) -> u3224 fn get_limit(entry: u64) -> u32 {
25     ((((entry) & 0x000F000000000000) >> 32) | ((entry) & 0x000000000000FFFF)) as u32
26 }
27 
get_g(entry: u64) -> u828 fn get_g(entry: u64) -> u8 {
29     ((entry & 0x0080000000000000) >> 55) as u8
30 }
31 
get_db(entry: u64) -> u832 fn get_db(entry: u64) -> u8 {
33     ((entry & 0x0040000000000000) >> 54) as u8
34 }
35 
get_l(entry: u64) -> u836 fn get_l(entry: u64) -> u8 {
37     ((entry & 0x0020000000000000) >> 53) as u8
38 }
39 
get_avl(entry: u64) -> u840 fn get_avl(entry: u64) -> u8 {
41     ((entry & 0x0010000000000000) >> 52) as u8
42 }
43 
get_p(entry: u64) -> u844 fn get_p(entry: u64) -> u8 {
45     ((entry & 0x0000800000000000) >> 47) as u8
46 }
47 
get_dpl(entry: u64) -> u848 fn get_dpl(entry: u64) -> u8 {
49     ((entry & 0x0000600000000000) >> 45) as u8
50 }
51 
get_s(entry: u64) -> u852 fn get_s(entry: u64) -> u8 {
53     ((entry & 0x0000100000000000) >> 44) as u8
54 }
55 
get_type(entry: u64) -> u856 fn get_type(entry: u64) -> u8 {
57     ((entry & 0x00000F0000000000) >> 40) as u8
58 }
59 
60 /// Automatically build the kvm struct for SET_SREGS from the kernel bit fields.
61 ///
62 /// # Arguments
63 ///
64 /// * `entry` - The gdt entry.
65 /// * `table_index` - Index of the entry in the gdt table.
kvm_segment_from_gdt(entry: u64, table_index: u8) -> kvm_segment66 pub fn kvm_segment_from_gdt(entry: u64, table_index: u8) -> kvm_segment {
67     kvm_segment {
68         base: get_base(entry),
69         limit: get_limit(entry),
70         selector: (table_index * 8) as u16,
71         type_: get_type(entry),
72         present: get_p(entry),
73         dpl: get_dpl(entry),
74         db: get_db(entry),
75         s: get_s(entry),
76         l: get_l(entry),
77         g: get_g(entry),
78         avl: get_avl(entry),
79         padding: 0,
80         unusable: match get_p(entry) {
81             0 => 1,
82             _ => 0,
83         },
84     }
85 }
86 
87 #[cfg(test)]
88 mod test {
89     use super::*;
90 
91     #[test]
field_parse()92     fn field_parse() {
93         let gdt = gdt_entry(0xA09B, 0x100000, 0xfffff);
94         let seg = kvm_segment_from_gdt(gdt, 0);
95         // 0xA09B
96         // 'A'
97         assert_eq!(0x1, seg.g);
98         assert_eq!(0x0, seg.db);
99         assert_eq!(0x1, seg.l);
100         assert_eq!(0x0, seg.avl);
101         // '9'
102         assert_eq!(0x1, seg.present);
103         assert_eq!(0x0, seg.dpl);
104         assert_eq!(0x1, seg.s);
105         // 'B'
106         assert_eq!(0xB, seg.type_);
107         // base and limit
108         assert_eq!(0x100000, seg.base);
109         assert_eq!(0xfffff, seg.limit);
110         assert_eq!(0x0, seg.unusable);
111     }
112 }
113