blob: 57eeffdb0270530dd1e9e9c69dc0a497c16b8ba9 [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
9#include "macros.h"
Ian Rogersb033c752011-07-20 12:22:35 -070010
11namespace art {
12
13void Thread::InitCpu() {
14 // Read LDT
15 CHECK_EQ((size_t)LDT_ENTRY_SIZE, sizeof(uint64_t));
Elliott Hughes7f40ffc2011-09-04 10:50:01 -070016 uint64_t ldt[LDT_ENTRIES];
17 memset(ldt, 0, sizeof(ldt));
18 syscall(SYS_modify_ldt, 0, ldt, sizeof(ldt));
Ian Rogersb033c752011-07-20 12:22:35 -070019 // Create empty slot to point at current Thread*
Elliott Hughes7f40ffc2011-09-04 10:50:01 -070020 user_desc ldt_entry;
21 memset(&ldt_entry, 0, sizeof(ldt_entry));
Ian Rogersb033c752011-07-20 12:22:35 -070022 ldt_entry.entry_number = -1;
23 ldt_entry.base_addr = (unsigned int)this;
Brian Carlstromb0460ea2011-07-29 10:08:05 -070024 ldt_entry.limit = kPageSize;
Ian Rogersb033c752011-07-20 12:22:35 -070025 ldt_entry.seg_32bit = 1;
26 ldt_entry.contents = MODIFY_LDT_CONTENTS_DATA;
27 ldt_entry.read_exec_only = 0;
28 ldt_entry.limit_in_pages = 0;
29 ldt_entry.seg_not_present = 0;
30 ldt_entry.useable = 1;
31 for (int i = 0; i < LDT_ENTRIES; i++) {
Elliott Hughes7f40ffc2011-09-04 10:50:01 -070032 if (ldt[i] == 0) {
Ian Rogersb033c752011-07-20 12:22:35 -070033 ldt_entry.entry_number = i;
34 break;
35 }
36 }
37 if (ldt_entry.entry_number >= LDT_ENTRIES) {
38 LOG(FATAL) << "Failed to find available LDT slot";
39 }
40 // Update LDT
41 CHECK_EQ(0, syscall(SYS_modify_ldt, 1, &ldt_entry, sizeof(ldt_entry)));
42 // Change FS to be new LDT entry
43 uint16_t table_indicator = 1 << 2; // LDT
44 uint16_t rpl = 3; // Requested privilege level
45 uint16_t selector = (ldt_entry.entry_number << 3) | table_indicator | rpl;
46 // TODO: use our assembler to generate code
Elliott Hughes7f40ffc2011-09-04 10:50:01 -070047 asm volatile("movw %w0, %%fs"
Ian Rogersb033c752011-07-20 12:22:35 -070048 : // output
49 : "q"(selector) // input
50 :); // clobber
51 // Allow easy indirection back to Thread*
52 self_ = this;
53 // Sanity check reads from FS goes to this Thread*
Ian Rogersb033c752011-07-20 12:22:35 -070054 Thread* self_check;
55 // TODO: use our assembler to generate code
Elliott Hughes7f40ffc2011-09-04 10:50:01 -070056 asm volatile("movl %%fs:(%1), %0"
Ian Rogersb033c752011-07-20 12:22:35 -070057 : "=r"(self_check) // output
Carl Shapiro69759ea2011-07-21 18:13:35 -070058 : "r"(OFFSETOF_MEMBER(Thread, self_)) // input
Ian Rogersb033c752011-07-20 12:22:35 -070059 :); // clobber
60 CHECK_EQ(self_check, this);
61}
62
63} // namespace art