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