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