thread_x86.cc revision b033c75ebda80ac75f936366fe78d1edf5cec937
1// 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* 50 CHECK_EQ(0, OFFSETOF_MEMBER(Thread, self_)); 51 Thread* self_check; 52 // TODO: use our assembler to generate code 53 asm("movl %%fs:0, %0" 54 : "=r"(self_check) // output 55 : // input 56 :); // clobber 57 CHECK_EQ(self_check, this); 58} 59 60} // namespace art 61