3 * Emulation Code for some processor internals (registers, instructions)
9 #include "mem_layout.h"
13 struct Ldt_user_desc // work around glibc naming mess
15 unsigned int entry_number;
16 unsigned long base_addr;
18 unsigned int seg_32bit:1;
19 unsigned int contents:2;
20 unsigned int read_exec_only:1;
21 unsigned int limit_in_pages:1;
22 unsigned int seg_not_present:1;
23 unsigned int useable:1;
26 class Pseudo_descriptor;
31 static Address _page_dir_addr asm ("PAGE_DIR_ADDR");
32 static Address _page_fault_addr asm ("PAGE_FAULT_ADDR");
33 static Idt_entry const *_idt_base;
34 static unsigned short _idt_limit;
35 static unsigned _host_tls_base;
41 #include <asm/unistd.h>
45 Address Emulation::_page_dir_addr;
46 Address Emulation::_page_fault_addr;
47 Idt_entry const *Emulation::_idt_base;
48 unsigned short Emulation::_idt_limit;
49 unsigned Emulation::_host_tls_base;
52 * Return page directory base address (register cr3)
53 * @return Page Directory Base Address
57 Emulation::pdir_addr()
59 return _page_dir_addr;
63 * Set page directory base address (register cr3)
64 * @param addr New Page Directory Base Address
68 Emulation::set_pdir_addr (Address addr)
70 _page_dir_addr = addr;
74 * Set page fault address (register cr2)
75 * @param addr Page Fault Address
79 Emulation::set_page_fault_addr (Address addr)
81 _page_fault_addr = addr;
85 * Emulate LIDT instruction
86 * @param desc IDT pseudo descriptor
88 PUBLIC static inline NEEDS["x86desc.h"]
90 Emulation::lidt (Pseudo_descriptor *desc)
92 _idt_base = reinterpret_cast<Idt_entry const *>(desc->base());
93 _idt_limit = desc->limit();
97 * Emulate SIDT instruction
98 * @param desc IDT pseudo descriptor
100 PUBLIC static inline NEEDS["x86desc.h"]
102 Emulation::sidt (Pseudo_descriptor *desc)
104 *desc = Pseudo_descriptor((Address)_idt_base, _idt_limit);
107 PUBLIC static inline NEEDS["x86desc.h"]
109 Emulation::idt_vector (Mword trap, bool user)
111 Idt_entry const *gate = _idt_base + trap;
114 if (gate >= (_idt_base + _idt_limit))
117 // Gate permission check
118 if (user && !(gate->access() & X86desc::Access_user))
121 assert(gate->present());
123 return gate->offset();
126 PUBLIC static inline NEEDS["x86desc.h"]
128 Emulation::idt_vector_present (Mword vector)
130 Idt_entry const *gate = _idt_base + vector;
132 if (gate >= (_idt_base + _idt_limit))
135 return gate->present();
140 Emulation::kernel_cs()
143 asm volatile ("movw %%cs, %0" : "=g" (cs));
149 Emulation::kernel_ss()
152 asm volatile ("movw %%ss, %0" : "=g" (ss));
156 PUBLIC static inline NEEDS [<asm/unistd.h>]
158 Emulation::modify_ldt (unsigned entry, unsigned long base_addr, unsigned limit)
162 ldt.entry_number = entry;
163 ldt.base_addr = base_addr;
167 ldt.read_exec_only = 0;
168 ldt.limit_in_pages = 0;
169 ldt.seg_not_present = 0;
172 asm volatile ("int $0x80" : : "a" (__NR_modify_ldt),
174 "c" (&ldt), "m" (ldt),
180 Emulation::set_host_tls_base(unsigned b)
187 Emulation::host_tls_base()
188 { return _host_tls_base; }
192 Emulation::get_thread_area(Ldt_user_desc *desc, unsigned entry_number)
195 desc->entry_number = entry_number;
197 #ifndef __NR_get_thread_area
198 #define __NR_get_thread_area 244
200 asm volatile ("int $0x80" : "=a" (result)
201 : "0" (__NR_get_thread_area),
202 "b" (desc), "m" (*desc));
204 if (EXPECT_FALSE(result == -38)) // -ENOSYS
205 printf("Your kernel does not support the get/set_thread_area system calls!\n"
206 "The requested feature will not work.\n");
210 PUBLIC static inline NEEDS [<asm/unistd.h>, <cassert>]
212 Emulation::thread_area_host (unsigned entry)
216 enum { NUM_TLS = 3 };
217 static int called[NUM_TLS];
219 #ifndef __NR_set_thread_area
220 #define __NR_set_thread_area 243
223 assert(_host_tls_base <= entry && entry < (_host_tls_base + NUM_TLS));
225 if (called[entry - _host_tls_base])
228 called[entry - _host_tls_base] = 1;
230 result = get_thread_area(&desc, entry);
233 if (!desc.base_addr || !desc.limit)
239 desc.read_exec_only = 0;
240 desc.limit_in_pages = 0;
241 desc.seg_not_present = 0;
245 asm volatile ("int $0x80" : "=a" (result)
246 : "0" (__NR_set_thread_area),
247 "b" (&desc), "m" (desc));
252 // ------------------------------------------------------------------------
253 IMPLEMENTATION[ux && mp]:
260 asm volatile("int $0x80" : "=a" (tid) : "0" (__NR_gettid) : "memory");
266 Emulation::spawn_cpu_thread(Address ip)
270 asm volatile ("int $0x80 \t\n"
277 "b" (CLONE_VM | CLONE_FILES),