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