thread_x86.cc revision 578bbdc684db8ed68e9fedbc678669d27fa68b6e
1// Copyright 2011 Google Inc. All Rights Reserved. 2 3#include "thread.h" 4 5#include <asm/ldt.h> 6#include <sys/syscall.h> 7#include <sys/types.h> 8 9#include "macros.h" 10 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; 22 ldt_entry.limit = 4096; 23 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* 52 Thread* self_check; 53 // TODO: use our assembler to generate code 54 asm("movl %%fs:(%1), %0" 55 : "=r"(self_check) // output 56 : "r"(OFFSETOF_MEMBER(Thread, self_)) // input 57 :); // clobber 58 CHECK_EQ(self_check, this); 59} 60 61} // namespace art 62