blob: 718e9b8c7d6b7de6d5fd75d0511707c89572880b [file] [log] [blame]
Ian Rogersb033c752011-07-20 12:22:35 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#include "src/thread.h"
4#include <asm/ldt.h>
5#include <sys/syscall.h>
6#include <sys/types.h>
7#include "src/macros.h"
8
9namespace art {
10
11void Thread::InitCpu() {
12 // Read LDT
13 CHECK_EQ((size_t)LDT_ENTRY_SIZE, sizeof(uint64_t));
14 uint64_t ldt_[LDT_ENTRIES];
15 syscall(SYS_modify_ldt, 0, ldt_, sizeof(ldt_));
16 // Create empty slot to point at current Thread*
17 struct user_desc ldt_entry;
18 ldt_entry.entry_number = -1;
19 ldt_entry.base_addr = (unsigned int)this;
20 ldt_entry.limit = 4096;
21 ldt_entry.seg_32bit = 1;
22 ldt_entry.contents = MODIFY_LDT_CONTENTS_DATA;
23 ldt_entry.read_exec_only = 0;
24 ldt_entry.limit_in_pages = 0;
25 ldt_entry.seg_not_present = 0;
26 ldt_entry.useable = 1;
27 for (int i = 0; i < LDT_ENTRIES; i++) {
28 if (ldt_[i] == 0) {
29 ldt_entry.entry_number = i;
30 break;
31 }
32 }
33 if (ldt_entry.entry_number >= LDT_ENTRIES) {
34 LOG(FATAL) << "Failed to find available LDT slot";
35 }
36 // Update LDT
37 CHECK_EQ(0, syscall(SYS_modify_ldt, 1, &ldt_entry, sizeof(ldt_entry)));
38 // Change FS to be new LDT entry
39 uint16_t table_indicator = 1 << 2; // LDT
40 uint16_t rpl = 3; // Requested privilege level
41 uint16_t selector = (ldt_entry.entry_number << 3) | table_indicator | rpl;
42 // TODO: use our assembler to generate code
43 asm("movw %w0, %%fs"
44 : // output
45 : "q"(selector) // input
46 :); // clobber
47 // Allow easy indirection back to Thread*
48 self_ = this;
49 // Sanity check reads from FS goes to this Thread*
Ian Rogersb033c752011-07-20 12:22:35 -070050 Thread* self_check;
51 // TODO: use our assembler to generate code
Carl Shapiro69759ea2011-07-21 18:13:35 -070052 asm("movl %%fs:(%1), %0"
Ian Rogersb033c752011-07-20 12:22:35 -070053 : "=r"(self_check) // output
Carl Shapiro69759ea2011-07-21 18:13:35 -070054 : "r"(OFFSETOF_MEMBER(Thread, self_)) // input
Ian Rogersb033c752011-07-20 12:22:35 -070055 :); // clobber
56 CHECK_EQ(self_check, this);
57}
58
59} // namespace art