11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved. 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met: 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * * Redistributions of source code must retain the above copyright 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer. 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * * Redistributions in binary form must reproduce the above copyright 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer in 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the documentation and/or other materials provided with the 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * distribution. 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE. 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 290d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes#include <limits.h> 300d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes#include <pthread.h> 3131e72bc3289acdd85b0b745fbf64c5949ca33432Jack Ren 320d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes#include <asm/ldt.h> 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 34b291d08af2a384d7468330dd35bfe3f612ab1b3fElliott Hughesextern "C" int __set_thread_area(user_desc*); 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 36b291d08af2a384d7468330dd35bfe3f612ab1b3fElliott Hughes__LIBC_HIDDEN__ void __init_user_desc(user_desc* result, bool allocate, void* base_addr) { 370d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes if (allocate) { 380d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes // Let the kernel choose. 390d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes result->entry_number = -1; 400d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes } else { 410d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes // Get the existing entry number from %gs. 420d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes uint32_t gs; 430d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes __asm__ __volatile__("movw %%gs, %w0" : "=q"(gs) /*output*/); 440d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes result->entry_number = (gs & 0xffff) >> 3; 450d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes } 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4701b85d5df3744449471b327d7afd6c1d5854bd11Elliott Hughes result->base_addr = reinterpret_cast<uintptr_t>(base_addr); 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4901b85d5df3744449471b327d7afd6c1d5854bd11Elliott Hughes result->limit = 0xfffff; 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 510d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes result->seg_32bit = 1; 520d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes result->contents = MODIFY_LDT_CONTENTS_DATA; 530d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes result->read_exec_only = 0; 540d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes result->limit_in_pages = 1; 550d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes result->seg_not_present = 0; 560d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes result->useable = 1; 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5901b85d5df3744449471b327d7afd6c1d5854bd11Elliott Hughesextern "C" __LIBC_HIDDEN__ int __set_tls(void* ptr) { 60b291d08af2a384d7468330dd35bfe3f612ab1b3fElliott Hughes user_desc tls_descriptor = {}; 610d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes __init_user_desc(&tls_descriptor, true, ptr); 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 630d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes int rc = __set_thread_area(&tls_descriptor); 640d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes if (rc != -1) { 650d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes // Change %gs to be new GDT entry. 660d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes uint16_t table_indicator = 0; // GDT 670d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes uint16_t rpl = 3; // Requested privilege level 680d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes uint16_t selector = (tls_descriptor.entry_number << 3) | table_indicator | rpl; 690d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes __asm__ __volatile__("movw %w0, %%gs" : /*output*/ : "q"(selector) /*input*/ : /*clobber*/); 700d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes } 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 720d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes return rc; 730d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes} 74