Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
iakovlev.org

Gdt

В интеловской архитектуре для защищенного режима контроль за памятью осуществляется с помощью специальных дескрипторных таблиц . Дескриптор может хранить информацию о каком-то обьекте - задаче , программе и т.д. Перед тем как вы каждый раз делаете запись в сегментный регистр , процессор должен проверить корректность такой записи .

Intel определяет 3 типа таблиц : таблица прерываний - IDT, глобальная таблица дескрипторов - GDT , и локальная таблица дескрипторов - LDT. Таблицы инициализируются с помощью инчструкций lidt, lgdt, lldt. Положение этих таблиц фиксируется еще на этапе загрузки и последующий доступ к ним осуществляется с помощью указателей .

Glossary

Segment
область памяти с заданными свойствами
Segment Register
регистр , ссылающийся на такой сегмент ( ss, cs, ds ...)
Selector
ссылка на дескриптор , загружаемый в сегментный регистр .
Descriptor
структура (строка в таблице)

Что можно сохранить в GDT ?

  • null descriptor
  • code segment descriptor (type=0x9A)
  • data segment descriptor (type=0x92)
  • TSS segment descriptor

GDT имеет следующую структуру :

  • null descriptor
  • dpl 0 code segment descriptor
  • dpl 0 data segment descriptor
  • dpl 3 code segment
  • dpl 3 data segment
  • остальной произвольный набор дескрипторов

dpl 0 code segment загружается в MSR. Остальные вычисляются на его базе . (See the intel instruction reference for SYSENTER and SYSEXIT for more information.)

Flat Setup

Если вам нужны 4GB памяти :

GDT[0]={.base=0, .limit=0, .type=0};              // selector 0 cannot be used
 GDT[1]={.base=0, .limit=0xffffffff, .type=0x9A};  // selector 8 will be our code
 GDT[2]={.base=0, .limit=0xffffffff, .type=0x92};  // selector 0x10 will be our data
 GDT[3]={.base=&myTss, .limit=sizeof(myTss), .type=0x89}; // you can use LTR(0x18)

В данной модели код не очень-то и защищен , потому-что он перекрывается с сегментом данных.

Small Kernel Setup

Если сегменты кода и данных нужно разделить и каждому выделить допустим по 4 метра:

GDT[0]={.base=0, .limit=0, .type=0};              // selector 0 cannot be used
 GDT[1]={.base=0x04000000, .limit=0x03ffffff, .type=0x9A};  // selector 8 will be our code
 GDT[2]={.base=0x08000000, .limit=0x03ffffff, .type=0x92};  // selector 0x10 will be our data
 GDT[3]={.base=&myTss, .limit=sizeof(myTss), .type=0x89}; // you can use LTR(0x18)

Начало кодового сегмента будет начинаться с отметки 4 метров иметь адрес совпадающий с cs:0 , сегмент данных будет начинаться с 8 метров и совпадать с адресом ds:0.

0. Отключение прерываний

Прерывания нужно отключать дабы не было проблем.

1. Заполнение таблиц

Базовый адрес в таблице GDT[] состоит из 3-х частей плюс флаг для установки свойств.

encodeGdtEntry(unsigned char target[8], struct MTGDT source)
 {
    if ((source.limit>64K) && (source.limit&0xfff)!=0xfff))
      kerror("you can't do that!");
    if (source.limit>64K) {
      // adjust granularity if required
      source.limit=source.limit/4096;
      target[6]=0xC0;
    } else target[6]=0x40;
 
    target[0]=source.limit&0xff;
    target[1]=(source.limit>>8)&0xff;
    target[6]|=(source.limit>>16)&0xf;
 
    target[2]=source.base&0xff;
    target[3]=(source.base>>8)&0xff;
    target[4]=(source.base>>16)&0xff;
    target[7]=(source.base>>24)&0xff;
 
    target[5]=source.type;
 }

2. Инициализация таблиц

Это можно сделать с помощью команд lgdt и lidt

real mode

линейный адрес может быть вычислен кака segment*16+offset.

gdtr dw 0 ; for limit storage
      dd 0 ; for base storage
 
 setGdt:
    xor eax,eax
    mov ax, ds
    shl eax, 4
    add eax, GDT
    mov [gdtr+2],eax
    mov eax, GDT_end
    sub eax, GDT
    mov [gdtr],ax
    lgdt [gdtr]
    ret

flat protected mode

gdtr dw 0   ; for limit storage
      dd 0   ; for base storage
 
 setGdt:
    mov eax,[esp+4]
    mov [gdtr+2],eax
    mov ax,[esp+8]
    mov [gdtr],ax
    ldgt [gdtr]
    ret

3. Reload segment registers

Для работы с GDT нужно использовать сегментные регистры

reloadSegments:
    jmp 0x08:here
 .here:
    mov ax,0x10
    mov ds,ax
    mov es,ax
    mov fs,ax
    mov gs,ax
    mov ss,ax
    ret

LDT

Аналогично GDT (global descriptor table), LDT (local descriptor table) состоит из дескрипторов . Каждый процесс имеет свою собственную LDT .

               GDTR (base+limit)
               +-- GDT -----------+
               |                  |
 SELECTOR ---> [LDT descriptor    ]----> LDTR (base+limit)
               |                  |     +---LDT-------------+
               |                  |     |                   |
               ..                 ..    ..                  ..
               +------------------+     +-------------------+

Сегменты

Real mode

В RealMode адрес имеет форму A:B :

Physical address = (A * 0x10) + B

Регистры в real-mode при адресации ограничены 16 битами. 16 бит - это число в диапазоне от 0 до 64k. Эти 64К и называются сегментом.

A = A 64k сегмент
B = смещение внутри сегмента

Базовые адреса сегментов - это чила типа (A * 0x10) .

Т.е. сегмент 0x1000 имеет базовый адрес 0x10000. Этот сегмент простирается в диапазоне 0x10000 -> 0x1FFFF, соответственно сегмент 0x1010 имеет базовый адрес 0x10100 и занимает диапазон физических алресов 0x10100 -> 0x200FF

Имеются 6 сегментных регистров : (CS, DS, ES, FS, GS, SS).

CS = Code Segment DS = Data Segment SS = Stack Segment ES = Extra Segment FS/GS = General Purpose Segments

DS,ES,FS,GS,SS можно смело использовать для работы с памятью .

MOV [SI], AX - базовым сегментным регистром по умолчанию является DS

MOV ES:[DI], AX - здесь базовым сегментным регистром является es

Операции с сегментными регистрами

Кроме CS, сегментные регистры можно загружать из AX (mov ds, ax) или из стека (pop ds).

CS нельзя изменить командой. Его можно изменить при переключении на другой сегментный регистр.

Far Jump
Например JMP 0x10:0x100 грузит CS сегментом 0x10 и IP = 0x100. CS:IP - это логический адрес для инструкции.
INT
Новое значение CS/IP читается из таблицы Interrupt Vector Table .

Protected Mode

Здесь логический адрес используется в форме A:B. Регистры в этом режиме ограничены 32 битами , что дает доступ к 4 гигам памяти.

Отличие защищенного режима от реального в том , что А - это не абсолютное значение , это - selector, который есть смещение в таблице Global Descriptor Table(GDT). GDT состоит из набора таких дескрипторов .

Каждый дескриптор включает в себя следующую информацию :

  • Базовый адрес сегмента
  • Тип сегмента (16-bit/32-bit)
  • Привилегия (Ring 0 -> Ring 3)
  • Байтовое ограничение (Segment limit is in byte/4kb units)
  • Сегментное ограничение (The maximum legal offset within the segment)
  • Тип дескриптора (0 = system; 1 = code/data)
  • Еще один тип(Code/Data/Read/Write/Accessed/Conforming/Non-Conforming/Expand-Up/Expand-Down)

Диапазон физических адресов в сегменте:

Segment Base -> Segment Base + Segment Limit
Physical address = Segment Base (Found from the descriptor GDT[A]) + B
Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье
Ольга
  Всё в этой статье вроде и не плохо,но я,задав в поисковой строке idt,не обнаружила того,что меня интересует. 
2006-03-30 11:40:27
Яковлев Се�
  Если набрать в поисковой строке "idt", то будет выведен список из 30 страниц.
В том числе и эта страница.
.

2006-03-30 19:33:19