blob: 5aa6d24b79dfbbe22687d7388f701ded3ac5d429 [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
Ian Rogers9651f422011-09-19 20:26:07 -07009#include "asm_support.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070010#include "macros.h"
Ian Rogersb033c752011-07-20 12:22:35 -070011
12namespace art {
13
14void Thread::InitCpu() {
15 // Read LDT
16 CHECK_EQ((size_t)LDT_ENTRY_SIZE, sizeof(uint64_t));
Elliott Hughes7f40ffc2011-09-04 10:50:01 -070017 uint64_t ldt[LDT_ENTRIES];
18 memset(ldt, 0, sizeof(ldt));
19 syscall(SYS_modify_ldt, 0, ldt, sizeof(ldt));
Ian Rogersb033c752011-07-20 12:22:35 -070020 // Create empty slot to point at current Thread*
Elliott Hughes7f40ffc2011-09-04 10:50:01 -070021 user_desc ldt_entry;
22 memset(&ldt_entry, 0, sizeof(ldt_entry));
Ian Rogersb033c752011-07-20 12:22:35 -070023 ldt_entry.entry_number = -1;
24 ldt_entry.base_addr = (unsigned int)this;
Brian Carlstromb0460ea2011-07-29 10:08:05 -070025 ldt_entry.limit = kPageSize;
Ian Rogersb033c752011-07-20 12:22:35 -070026 ldt_entry.seg_32bit = 1;
27 ldt_entry.contents = MODIFY_LDT_CONTENTS_DATA;
28 ldt_entry.read_exec_only = 0;
29 ldt_entry.limit_in_pages = 0;
30 ldt_entry.seg_not_present = 0;
31 ldt_entry.useable = 1;
32 for (int i = 0; i < LDT_ENTRIES; i++) {
Elliott Hughes7f40ffc2011-09-04 10:50:01 -070033 if (ldt[i] == 0) {
Ian Rogersb033c752011-07-20 12:22:35 -070034 ldt_entry.entry_number = i;
35 break;
36 }
37 }
38 if (ldt_entry.entry_number >= LDT_ENTRIES) {
39 LOG(FATAL) << "Failed to find available LDT slot";
40 }
41 // Update LDT
42 CHECK_EQ(0, syscall(SYS_modify_ldt, 1, &ldt_entry, sizeof(ldt_entry)));
43 // Change FS to be new LDT entry
44 uint16_t table_indicator = 1 << 2; // LDT
45 uint16_t rpl = 3; // Requested privilege level
46 uint16_t selector = (ldt_entry.entry_number << 3) | table_indicator | rpl;
47 // TODO: use our assembler to generate code
Elliott Hughes7f40ffc2011-09-04 10:50:01 -070048 asm volatile("movw %w0, %%fs"
Ian Rogersb033c752011-07-20 12:22:35 -070049 : // output
50 : "q"(selector) // input
51 :); // clobber
52 // Allow easy indirection back to Thread*
53 self_ = this;
54 // Sanity check reads from FS goes to this Thread*
Ian Rogersb033c752011-07-20 12:22:35 -070055 Thread* self_check;
56 // TODO: use our assembler to generate code
Ian Rogers9651f422011-09-19 20:26:07 -070057 CHECK_EQ(THREAD_SELF_OFFSET, OFFSETOF_MEMBER(Thread, self_));
Elliott Hughes7f40ffc2011-09-04 10:50:01 -070058 asm volatile("movl %%fs:(%1), %0"
Ian Rogersb033c752011-07-20 12:22:35 -070059 : "=r"(self_check) // output
Ian Rogers9651f422011-09-19 20:26:07 -070060 : "r"(THREAD_SELF_OFFSET) // input
Ian Rogersb033c752011-07-20 12:22:35 -070061 :); // clobber
62 CHECK_EQ(self_check, this);
63}
64
65} // namespace art