Как регистры fs / gs используются в Linux AMD64? - PullRequest
35 голосов
/ 07 июля 2011

В архитектуре x86-64 два регистра имеют специальное назначение: FS и GS. В linux 2.6. * Регистр FS, кажется, используется для хранения локальной информации о потоке.

  • Это правильно?
  • Что хранится в фс: 0? Есть ли какая-либо структура C, которая описывает это содержание?
  • Какая польза от GS?

Ответы [ 3 ]

37 голосов
/ 08 июля 2011

В x86-64 есть 3 записей TLS , две из них доступны через FS и GS , FS используется внутренне для glibc (в IA32, по-видимому, FS используетсяby Wine и GS by glibc ).

Glibc делает свою точку входа TLS в struct pthread, которая содержит некоторые внутренние структуры для потоков.Glibc обычно ссылается на переменную struct pthread как pd, предположительно для дескриптора pthread .

На x86-64, struct pthread начинается с tcbhead_t (это зависит от архитектуры, см. макросы TLS_DTV_AT_TP и TLS_TCB_AT_TP).Этот заголовок блока управления потоками, AFAIU, содержит некоторые поля, которые необходимы, даже если существует один поток.DTV является вектором динамического потока и содержит указатели на блоки TLS для DSO, загружаемых через dlopen().До или после TCB существует статический блок TLS для исполняемого файла и DSO, связанных во время загрузки (программы).TCB и DTV довольно хорошо объяснены в документе TLS Ульриха Дреппера (см. Схемы в главе 3).

16 голосов
/ 20 ноября 2015

Чтобы на самом деле ответить на ваш fs:0 вопрос: ABI x86_64 требует, чтобы fs:0 содержал адрес, «указанный» самим fs.То есть fs:-4 загружает значение, хранящееся в fs:0 - 4.Эта функция необходима, потому что вы не можете легко получить адрес, на который указывает fs, не пройдя код ядра.Таким образом, хранение адреса в fs:0 делает работу с локальным хранилищем потока более эффективной.

Это можно увидеть в действии, когда вы берете адрес локальной переменной потока:

static __thread int test = 0;

int *f(void) {
    return &test;
}

int g(void) {
    return test;
}

компилируется в

f:
    movq    %fs:0, %rax
    leaq    -4(%rax), %rax
    retq

g:
    movl    %fs:-4, %eax
    retq

i686 делает то же самое, но с %gs.На aarch64 это не обязательно, потому что адрес можно прочитать из самого регистра tls.

2 голосов
/ 18 сентября 2018

Какая польза от GS?

x86_64 Ядро Linux использует регистр GS в качестве эффективного способа получения стека пространства ядра для системных вызовов.

В регистре GS хранится базовый адрес для области процессора. Чтобы получить стек пространства ядра, в entry_SYSCALL_64

movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp

После расширения PER_CPU_VAR мы получаем следующее:

movq    %gs:cpu_current_top_of_stack, %rsp
...