Към съдържанието

Въпроси и задачи — отговори

Въпросите са от Ръководство за лабораторни упражнения по Микропроцесорни системи, Рускова Н., ТУ-Варна, 1999 г. Следват реда им в документа.


Лабораторно упражнение 4 — Суперскаларна архитектура на P6

Въпрос 1

Какви са предимствата на динамичната микроархитектура на семейството P6? Какво се печели от динамичното предсказване на преходите?

Динамичната микроархитектура на P6 (Pentium Pro/II/III) се основава на три основни механизма: извличане и декодиране извън ред, OoO изпълнение чрез ROB (Reorder Buffer) и завършване по реда на програмата. Предимствата са:

  • Скриване на латентности: докато инструкция чака операнд от паметта (кеш пропуск), изпълнителните устройства не стоят празни — ROB съдържа независими µops, готови за изпълнение.
  • Паралелизъм на ниво инструкции (ILP): до 5 µops на такт се изпращат към 5 изпълнителни порта, а до 3 µops завършват за такт — независимо от програмния ред.
  • Преобразуване CISC → RISC: сложните x86 инструкции се разлагат до прости, фиксирана дължина µops, удобни за тръбопровод с фиксирана латентност.

Печалба от динамичното предсказване на преходите (BTB):
При условен преход процесорът не може да знае следващата инструкция преди изпълнението. BTB (512 елемента) предсказва най-вероятния адрес и спекулативно зарежда и декодира инструкции по предсказания път — без да изчаква верификацията. При правилно предсказване (>90% при добри алгоритми) не се губи нито един такт. При грешно предсказване конвейерът се изчиства (около 10–20 такта наказание), но алтернативата — спиране при всеки преход — е несравнимо по-скъпа.


Въпрос 2

Обяснете ползата от устройството за динамично предсказване на преходите за повишаване ефективността на процесорите.

Устройството за динамично предсказване (BTB + RSB) повишава ефективността по два начина:

  1. Предсказване на условни преходи (BTB): Всеки условен преход се записва в Branch Target Buffer с адрес и история (взет/невзет). При повторно срещане на прехода BTB директно подава предсказания адрес на IFU, без да изчаква пресмятането на условието. Алгоритмите с 2-bit saturating counter се приближават до 95% точност при типични цикли.

  2. Предсказване на адреса при RET (RSB — Return Stack Buffer): При CALL адресът на следващата инструкция се записва в RSB (стеков буфер). При RET RSB директно връща предсказания адрес, без да го чете от стека в паметта. Точността е практически 100% при правилно вложени извиквания.

Без предсказване всеки преход би означавал спиране на конвейера за 7–20 такта (колкото степени заема устройството за извличане/декодиране). При типично разпределение от 15–20% преходи в кода и 90%+ точност на предсказването, ефективното ускорение е 2–4 пъти спрямо статичен конвейер.


Въпрос 3

Какви са особеностите на спекулативното извличане на инструкциите в динамичната архитектура на P6?

Спекулативното извличане в P6 означава, че IFU зарежда инструкции преди да е известно дали те наистина ще се изпълнят. Особености:

  • Управление от BTB: Веднага щом декодерите срещнат условен преход, BTB подава предсказания адрес. IFU продължава да зарежда по предсказания път — дори преди RS да е изпратил прехода за изпълнение.
  • Маркиране в ROB: Спекулативно извлечените µops се маркират като такива в ROB. Те могат да се изпълняват, но не могат да завършат (т.е. да запишат резултатите в архитектурните регистри или паметта) преди верификацията на прехода.
  • Отмяна при грешка: Ако JPU (Jump Prediction Unit) открие несъвпадение, сигнализира BTB и всички спекулативни µops след прехода се изхвърлят от ROB. Конвейерът се рестартира от правилния адрес. Резултатите от спекулативното изпълнение не достигат до архитектурното състояние.
  • Спекулативни четения от паметта: Операциите за четене могат да се изпълняват спекулативно (Load Store Unit ги обработва преди операциите за запис да са завършили); съществува прозрачен механизъм за отмяна при грешен ред.

Въпрос 3б

В какви примерни µops ще се декодира следната последователност и в какъв ред ще бъдат разпределени за изпълнение?

mov eax, mem32 ; зареждане от памет
and edx, 10 ; логическа операция с непосредствен операнд
imul eax, ecx ; умножение (използва резултата от ред 1)
mov mem32, eax ; съхраняване (използва резултата от ред 3)

Декодиране до µops (тройка 4-1-1):

Архитектурна инструкцияµopsТип
mov eax, mem32LOAD eax ← [mem32]1 µop — зареждане
and edx, 10AND edx, 101 µop — ALU
imul eax, ecxMUL eax ← eax × ecx1 µop (3–4 такта латентност)
mov mem32, eaxSTORE_ADDR [mem32] + STORE_DATA [mem32] ← eax2 µops — съхраняване

Ред на разпределение за изпълнение (OoO):

  1. LOAD eax и AND edx, 10 могат да стартират едновременно — независими операнди.
  2. MUL eax чака само LOAD eax да завърши (зависимост от данни: RAW).
  3. STORE_ADDR може да стартира веднага (адресът е известен), STORE_DATA чака резултата на MUL eax.

Извод: AND edx, 10 стартира паралелно с LOAD eax, без да изчаква MUL или MOV.


Лабораторно упражнение 5 — Системна архитектура. Управление на паметта в защитен режим

Въпрос 1

Стартирайте симулатора i486. Превключете МП в защитен режим. Каква е реакцията при следващата инструкция? Кои регистри трябва да се променят и как?

За превключване в защитен режим задължително трябва да се направи следното:

  1. Подготви GDT — в паметта трябва да съществува валидна Global Descriptor Table с минимум нулев дескриптор (индекс 0) и поне един кодов и един даннов дескриптор.
  2. Зареди GDTR — с инструкция LGDT m48 (48-битов операнд: 16-бит лимит + 32-бит базов адрес на GDT).
  3. Зареди CR0.PE = 1MOV CR0, reg с бит 0 = 1. В 32-битов режим: OR eax, 1 / MOV CR0, eax.
  4. Незабавно след това — far jump (JMP far) за изчистване на конвейера и зареждане на CS с валиден дескрипторен селектор.

Реакция при пропускане на стъпките: Ако LGDT не е изпълнен или GDT не е валидна, след MOV CR0, eax (с PE=1) и JMP far процесорът ще генерира изключение #GP (General Protection Fault) при опит да зареди CS от невалидна GDT, или #DF (Double Fault) ако IDT също не е инициализирана.


Въпрос 2

Съдържанието на кои регистри трябва да бъде променено, за да продължи правилно изпълнението след превключване?

След PE=1 всички сегментни регистри трябва да съдържат валидни дескрипторни селектори, сочещи към правилно инициализирани дескриптори в GDT:

РегистърДействие
CSЗарежда се чрез far JMP с код-сегментен селектор (DPL=0 за Ring 0); базов адрес = текущ физически адрес на кода
DS, ES, FS, GSЗареждат се с даннов селектор (MOV DS, ax и т.н.)
SSЗарежда се с стеков (записваем даннов) сегментен селектор
GDTRВече зареден преди PE=1
IDTRТрябва да сочи към валидна IDT (иначе при първото прекъсване → #DF)
ESPТрябва да сочи към валиден адрес в рамките на SS-сегмента

Ако останете в реален режим стойности (напр. DS = 0x0000), в защитен режим 0x0000 се интерпретира като нулев дескриптор → изключение #GP при всеки достъп до данни.


Въпрос 3

Как се изчисляват адресите на операндите и инструкциите в защитен режим?

В защитен режим всеки достъп до памет минава през двустепенна транслация:

Стъпка 1 — Логически → линеен адрес (сегментиране):

Линеен адрес = Дескриптор.База + Ефективен адрес (EA)
  • Сегментният регистър (CS, DS, SS…) съдържа 16-бит селектор
  • МП вика кешираната „сянка” на дескриптора (бит TI → GDT/LDT, Index → позиция × 8)
  • Проверки: P=1, лимит, тип, DPL

Стъпка 2 — Линеен → физически адрес (ако CR0.PG=1):

  • Линейният адрес се разделя на Dir[31..22] + Table[21..12] + Offset[11..0]
  • Dir → Page Directory Entry (базов адрес на таблица) → Page Table Entry (базов адрес на страница)
  • Физически адрес = PTE[31..12] + Offset[11..0]

При CR0.PG=0: линейен адрес = физически адрес директно.

Пример: MOV EAX, [EBX+8] при DS.Base = 0x00400000, EBX = 0x100:
EA = 0x100 + 8 = 0x108; линеен = 0x00400108; при PA=linear → физически = 0x00400108.


Въпрос 4

Каква ще бъде реакцията при разрешаване на странициране? Кои регистри трябва да се настроят?

Реакция без подготовка: При CR0.PG = 1 процесорът незабавно започва да транслира всички адреси чрез Page Directory и Page Tables. Ако CR3 сочи към невалидна структура → #PF (Page Fault, изключение #14), или ако IDT не е инициализирана → #DF.

Необходими структури:

  1. Page Directory (4 KB, изравнен на 4 KB) — 1024 PDE × 4 байта; PDE[i].P=1, PDE[i].Base = физически адрес на Page Table[i].
  2. Page Tables (по 4 KB за всяка) — 1024 PTE × 4 байта; PTE[j].P=1, PTE[j].Base = физически адрес на страницата.
  3. CR3 — физически адрес на Page Directory (битове 31..12; PCD и PWT = 0 за нормална работа).

Стъпки: подготви структурите → MOV CR3, eaxOR ecx, 0x80000000 / MOV CR0, ecx (вдига PG). Задължително е цялото изпълняемо ядро да бъде маппирано (идентично или с offset) преди PG=1.


Въпрос 5

Как при разрешено странициране се определят физическите адреси? Влияние на prefetch буферите и кеш паметта?

Физически адрес при CR0.PG=1:

  • Линеен адрес[31..22] → индекс в Page Directory → PDE → базов адрес на Page Table
  • Линеен адрес[21..12] → индекс в Page Table → PTE → базов адрес на страница (4 KB)
  • Физически = страница_база + линеен[11..0]
  • TLB кешира последните транслации; INVLPG или нов CR3 го инвалидира.

Влияние на prefetch буферите: Когато PE=0→1 или PG=0→1, в конвейера може да има предварително извлечени инструкции с вече изчислени адреси по стария режим. Именно затова far JMP е задължителен след PE=1 — той изчиства prefetch опашката. При PG=1 без flush може да се изпълни инструкция с физически адрес, изчислен без страничен превод → грешно изпълнение.

Влияние на кеш паметта: i486 има вътрешен 8 KB unified кеш. Ако в кеша са кеширани данни с физически адреси, след PG=1 линейните адреси се транслират и нов физически адрес може да се различава от стария → кешът трябва да бъде инвалидиран (или не трябва да има кеш-попадения по грешни адреси). Безопасно е да се зададе CD=1 преди включване на странициране, след което да се инвалидира кешът и да се пусне CD=0.


Лабораторно упражнение 5 (продължение) — Сегментни дескриптори и защити

Въпрос 1

Напишете стойностите на полетата на дескриптора за:

а) 32-битов кодов сегмент, Ring 3, базов адрес = 0x00001001, лимит = 8 KB, изпълнение+четене:

Лимит 8 KB = 0x2000 байта → при G=0 (байтова гранулярност) Limit = 0x1FFF (8192 − 1).

ПолеСтойностБележка
База [31..24] (байт 7)0x00Байт 3 от 0x00001001
G / D / 0 / AVL / Lim[19..16] (байт 6)0x40G=0, D=1 (32-bit), L=0, AVL=0, Lim[19..16]=0
P / DPL / S / Тип (байт 5)0xFAP=1, DPL=11b (Ring 3), S=1, Тип=1010b (код, R-X)
База [23..16] (байт 4)0x00
База [15..0] (байтове 3-2)0x1001
Лимит [15..0] (байтове 1-0)0x1FFF

Пълен дескриптор (байт 7 → байт 0): 00 40 FA 00 00 10 01 1F FF

б) 16-битов даннов сегмент само за четене, покрива цялото линейно пространство (4 GB):

При 16-битов сегмент (D=0) максималният лимит с G=1 е 0xFFFFF × 4 KB = 4 GB − 4 KB. За пълно 4 GB покритие с 16-битов сегмент е практически невъзможно в оригинален 16-битов режим — стандартният подход е D=1, G=1 и Limit=0xFFFFF.

ПолеСтойностБележка
G / D / L / AVL / Lim[19..16]0xCFG=1 (4 KB единици), D=0 (16-bit), Lim[19..16]=0xF
P / DPL / S / Тип0x90P=1, DPL=00b, S=1, Тип=0000b (данни, R-O)
База0x00000000
Лимит0xFFFFF (G=1 → 4 GB)

Въпрос 2

Компилирайте и изпълнете програмата от Приложение 1. Какво е началното състояние на управляващите и сегментните регистри след RESET? Сравнете с Protected Mode.

Състояние след RESET (реален режим):

РегистърСтойност при RESET
CR00x00000010 — PE=0, PG=0 (реален режим)
CS0xF000 (сегмент 0xF0000, EIP=0xFFF0 → BIOS entry)
DS, ES, FS, GS, SS0x0000
GDTRBase=0, Limit=0xFFFF (невалиден)
IDTRBase=0, Limit=0x03FF (реален режим IVT)
EFLAGS0x00000002 — IF=0, всички флагове 0

След превключване в защитен режим (очаквано):

РегистърСтойност
CR0PE=1 (бит 0 = 1)
CSСелектор към кодов дескриптор (напр. 0x0008)
DS, SS и др.Селектор към даннов/стеков дескриптор (напр. 0x0010)
GDTRЗареден с базов адрес и лимит на GDT

Инструкцията far jmp 0x0008:addr (код 0xEA) зарежда CS с нов селектор (0x0008 → 2-ри дескриптор в GDT) и изчиства конвейера. Без нея CS остава с реален адрес, който в P-режим се интерпретира като невалиден селектор → #GP.


Въпрос 3

Изследвайте защитните механизми в защитен режим.

а) Обръщение извън лимита на сегмента: При опит да се чете/пише по адрес, надхвърлящ Descriptor.Limit × (G ? 4096 : 1), МП генерира изключение #GP (General Protection, вектор 13) за даннови сегменти. За стекови сегменти (SS) се генерира #SS (Stack Fault, вектор 12). В стека са записани CS:EIP на грешната инструкция и 32-битов код на грешка (селектор с ненулев RPL/TI или 0 за #GP от лимит).

б) Нарушаване правата за достъп:

  • Запис в сегмент само за четене → #GP
  • Запис в кодов сегмент → #GP (кодовите сегменти никога не позволяват запис)
  • Четене от кодов сегмент с Тип=1000b (само изпълнение) → #GP; Тип=1001b (изпълнение+четене) → разрешено

в) Промяна на нивото на привилегия на кодовия сегмент: Ако DPL на кодовия сегмент стане ≠ CPL (текущото ниво), прескачането към него чрез far JMP е забранено (за непривилегировани/conforming сегменти). LGDT и LIDT са привилегировани инструкции (Ring 0); при CPL=3 те генерират #GP. LLDT също изисква Ring 0.


Въпрос 4

Изпълнете програмата на работния компютър с извеждане на съобщения за режима на МП.

В реален режим за извеждане на текст се използва int 0x10 (BIOS) или директен запис в портове. В защитен режим BIOS прекъсвания не са достъпни (IDT съдържа системни шлюзове, не BIOS вектори). Решението е директен запис в видеопамет:

; Адрес на символ (X, Y) в текстов режим 80×25:
; VideoAddr = 0xB8000 + 2*(80*Y + X)
; Байт 0: ASCII код; Байт 1: атрибут (цвят)
; Пример: извеждане на 'P' с бял текст на черен фон (атрибут 0x07)
mov edi, 0xB8000
mov byte [edi], 'P'
mov byte [edi+1], 0x07

За да работи в P-режим, DS трябва да сочи към даннов сегмент с база ≤ 0xB8000 и лимит, покриващ видеопаметта (или база = 0 и лимит = 4 GB).


Лабораторно упражнение 8 — Управление на задачите

Въпрос 1

Разучете програмата от Приложение 2.

Програмата от Приложение 2 демонстрира хардуерното превключване на задачи чрез TSS. Структурата е:

  1. Инициализация в реален режим: нулиране на регистрите, зареждане на GDT с дескриптори за кодов сегмент, даннов сегмент и TSS дескриптори за всяка задача.
  2. Превключване в защитен режим (PE=1, far JMP).
  3. Зареждане на TR (LTR) с TSS на начална задача.
  4. Извикване на втора задача чрез JMP far към TSS дескриптор — МП автоматично съхранява контекста на текущата задача в TSS и зарежда контекста на новата.
  5. Връщане при IRET с NT=1.

Ключови моменти: TSS за задача се описва от TSS дескриптор (S=0, Тип=9 или 11) в GDT. Полето Previous Task Link в TSS на извикваната задача се попълва от МП автоматично при CALL-тип превключване.


Въпрос 2

Изследвайте защитните механизми по отношение на TSS. В кои случаи се генерира прекъсване и какъв е типът му?

СитуацияИзключение
TSS дескриптор с P=0 (не е в паметта)#NP — Segment Not Present (вектор 11)
TSS лимит < 103 (твърде малък за 32-bit TSS)#TS — Invalid TSS (вектор 10)
TSS Тип ≠ 9 или 11 (невалиден за задача)#GP при опит за JMP/CALL
Опит за превключване към заета задача (Б=1 в TSS)#GP (битът Busy предпазва от рекурсия)
Изключение при зареждане на сегментни регистри от TSS#TS (невалиден TSS)
Нарушение на привилегии при достъп до TSS#GP

Кодът на грешката при #GP/#TS/#NP съдържа 16-битов идентификатор (TSS селектор с EXT=1 за external, IDT=0 за GDT/LDT).


Въпрос 3

Добавете трета задача с характерно съобщение. Осъществете вложено извикване на трите задачи.

Стъпки за добавяне на трета задача:

  1. Деклариране на TSS3 в данновия сегмент (структура от 104 байта за 32-bit TSS): задаване на EIP (адрес на код на задача 3), CS (код-сегментен селектор), SS0:ESP0 (Ring 0 стек), CR3.
  2. TSS3 дескриптор в GDT: S=0, Тип=9 (незает), P=1, DPL=0 (или 3 за потребителска задача), Limit ≥ 103, Base = адрес на TSS3.
  3. Вложено извикване (CALL-модел):
    • Задача 1 извиква задача 2 с CALL far [TSS2_selector:0]
    • Задача 2 извиква задача 3 с CALL far [TSS3_selector:0]
    • МП вдига NT=1 в задача 2 и 3; Previous Task Link = селектор на предходната
    • IRET в задача 3 → автоматично се превключва обратно към задача 2
    • IRET в задача 2 → обратно към задача 1

Въпрос 4

Изследвайте защитата по привилегия. Променете нивото на привилегия на задача. Каква е реакцията? Осъществете достъп чрез шлюз към задача.

При промяна на DPL в TSS дескриптора на задача на ниво 3 (непривилегирована):

  • JMP far към TSS: разрешено е само ако CPL ≤ DPL и RPL ≤ DPL. При CPL=0 (Ring 0) и DPL=3 → разрешено. При CPL=3 и DPL=0 → #GP.
  • CALL far към TSS: същите условия.

Шлюз към задача (Task Gate): Позволява задачи с по-ниска привилегия да извикват по-привилегирована задача. Task Gate дескриптор (Тип=5) се поставя в GDT или IDT и съдържа TSS селектора. CALL far към Task Gate при CPL > DPL_gate → #GP; при CPL ≤ DPL_gate → превключване. Така непривилегирован код (Ring 3) може да извика OS задача (Ring 0) само ако Task Gate е достъпен на Ring 3.


Лабораторно упражнение 9 — Обработка на прекъсвания и изключения

Въпрос 1

Допълнете програмата с обработчици на изключения 1–15. Попълнете IDT с шлюзове.

Процедурата за всяко изключение трябва:

  1. При изключения с код на грешка (8, 10–14, 17) — да го извади от стека (ADD ESP, 4).
  2. Да изведе номера на изключението на екрана (директен запис в видеопамет 0xB8000).
  3. При рестартируеми грешки (#PF, #GP) — IRET; при аборти (#DF) — halt.

Регистрация в IDT:

; Шаблон за Interrupt Gate в IDT (32-bit Protected Mode):
; Байтове 0-1: Offset[15..0]
; Байтове 2-3: Segment Selector (кодов сегмент Ring 0)
; Байт 4: 0x00
; Байт 5: 0x8E (P=1, DPL=0, Тип=1110b = 32-bit Interrupt Gate)
; Байтове 6-7: Offset[31..16]
; IDT[n] = { handler_lo, CS_selector, 0x00, 0x8E, handler_hi }

Interrupt Gate автоматично зачиства IF при влизане в обработчика (маскира маскируемите прекъсвания).


Въпрос 2

Изпълнете програмата в sim486. От защитен режим генерирайте различни изключения. Отбележете промените в стека и регистрите.

Типични изключения и как да се генерират програмно:

ИзключениеКак да се генерираПромени в стека
#DE (0) — деление на нулаMOV EAX, 0 / DIV EAXСтека: [ESP-4]=EIP на DIV, [ESP-8]=CS, [ESP-12]=EFLAGS
#DB (1) — debug/single stepВдигане TF=1 в EFLAGSКато #DE
#BP (3) — breakpointИнструкция INT 3Стека: EIP след INT 3
#OF (4) — overflowINTO при OF=1Стека: EIP след INTO
#UD (6) — невалидна оп.Невалиден опкод (напр. 0x0F 0x0B)Стека: EIP на невалидната инструкция
#GP (13)Достъп извън лимит / нарушение DPLСтека: EIP, CS, EFLAGS, + код на грешка
#PF (14)Достъп до невалидна страницаСтека: + Error code; CR2 = виновен адрес

При изключения с код на грешка в стека има допълнителни 4 байта преди EIP.


Въпрос 3

Установете режим на трасировка в защитен режим и програмирайте обработка на TF изключение (#DB).

; Включване на TF (Trap Flag) за single-step:
PUSHFD
OR DWORD [ESP], 0x100 ; вдигане на TF (бит 8)
POPFD
; Следващата инструкция → #DB (вектор 1)
; Обработчик на #DB (IDT[1]):
handler_DB:
; Тук се пише логика при всяка стъпка
; Съобщение на екрана, четене на EIP от стека
; TF се зачиства автоматично при влизане в обработчика (Interrupt Gate зачиства IF; TF се зачиства от процесора при #DB)
IRET ; TF се вдига отново след IRET → следваща стъпка

За да спрете трасировката: в обработчика зачистете TF бита в запазените EFLAGS в стека (AND DWORD [ESP+8], ~0x100).


Въпрос 4

Снемете с логически анализатор времедиаграмата на шината при прекъсване от таймера (IR0 на i8259A) в IBM PC/AT.

Последователност на сигналите при хардуерно маскируемо прекъсване:

  1. Таймерът активира IR0 (Input Request 0) на i8259A.
  2. i8259A активира INT → процесорът вижда INTR.
  3. При IF=1 процесорът завършва текущата инструкция и издава два INTA цикъла:
    • 1-ви INTA#: i8259A се „заключва” — замразява приоритетния арбитър.
    • 2-ри INTA#: i8259A поставя на шината вектора на прекъсването (0x08 за IR0 при ICW2=0x08).
  4. Процесорът чете вектора, умножава по 8 → IDT[0x08] → извлича Interrupt/Trap Gate → превключва стека, записва EFLAGS:CS:EIP и скача към обработчика.
  5. Обработчикът трябва да изпрати EOI (End Of Interrupt, код 0x20) на i8259A преди IRET, иначе IR0 остава маскиран.

Въпрос 5

Наблюдавайте с логически анализатор началното програмиране на i8259A. Определете режима на работа.

Инициализацията на i8259A се извършва с 2–4 Initialization Command Words (ICW) записани на порт 0x20 (Master PIC) или 0xA0 (Slave PIC):

КомандаПортТипична стойност в IBM PC/ATЗначение
ICW10x200x11Edge-triggered, cascade mode, ICW4 required
ICW20x210x08 (Master) / 0x70 (Slave)Базов вектор: IR0→INT 8, IR8→INT 70h
ICW30x210x04 (Master) / 0x02 (Slave)IR2 на Master е каскадиран Slave; Slave ID=2
ICW40x210x018086 режим (не MCS-80), нормален EOI

На логическия анализатор ще се наблюдават записи на портове 0x20 и 0x21 в горния ред, последователно при BIOS инициализация.


Въпрос 6

В програмата от Приложение 2 добавете задача, стартираща при прекъсване от таймера. Задачата да брои прекъсванията.

  1. Дефинирайте Task Gate в IDT[0x08] (вместо Interrupt Gate):
    IDT[8]: { 0x0000, TSS_timer_selector, 0x00, 0x85, 0x0000 }
    ; Тип = 0x85 = P=1, DPL=0, Тип=0101b (32-bit Task Gate)
  2. TSS на задачата-таймер трябва да е предварително инициализиран с EIP = адрес на обработчика, CS, SS:ESP.
  3. В обработчика:
    INC DWORD [timer_count] ; инкременти броячa
    ; Извеждане на стойността на екрана
    MOV AL, 0x20 ; EOI
    OUT 0x20, AL
    IRET ; При Task Gate → превключване обратно
  4. При Task Gate обработчикът работи в контекст на отделна задача; IRET с NT=1 превключва обратно към прекъснатата задача.

Лабораторно упражнение 10 — Изграждане на мултипроцесорни системи

Въпрос 1

Реализирайте семафорните P и V операции с XCHG. Как се осигурява неделимостта? Как се променя времедиаграмата при кеш операнд?

Семафор с XCHG:

; P операция (acquire / wait):
P_op:
MOV EAX, 1 ; 1 = "зает"
XCHG EAX, [semaphore] ; атомарен обмен; LOCK# се активира автоматично
TEST EAX, EAX
JNZ P_op ; ако семафорът е бил зает → повторен опит
RET
; V операция (release / signal):
V_op:
MOV DWORD [semaphore], 0 ; не изисква LOCK — един запис е атомарен по дефиниция
RET

Неделимост: XCHG с операнд в паметта автоматично активира LOCK# (без prefix LOCK) — за разлика от другите инструкции. По времедиаграмата LOCK# е нисък за целия цикъл четене+запис, а адресната шина остава заета. Другите процесори виждат LOCK# и не могат да заемат шината.

При кеш операнд: Ако операндът е в L1 кеш (и MESI протоколът позволява), LOCK# може да не се активира на шината — кешовата строчка се заключва локално. Времедиаграмата на шината не показва LOCK цикъл.


Въпрос 2

Решете същата задача с префикс LOCK. Предимства и недостатъци. Какво при LOCK пред инструкция без памет?

P_op:
MOV EAX, 1
LOCK XCHG EAX, [semaphore] ; явен LOCK (излишен за XCHG, но валиден)
TEST EAX, EAX
JNZ P_op

Алтернативно с BTS (по-четим код):

LOCK BTS DWORD [semaphore], 0 ; атомарно test-and-set бит 0
JC wait_loop ; ако е бил 1 → чакай

Предимства на LOCK prefix: Работи и с ADD, AND, OR, BTS, CMPXCHG и др. → по-гъвкав.
Недостатъци: Незначително по-бавен от XCHG (допълнителен префикс байт). При Pentium era на шина LOCK блокира всички останали транзакции.

LOCK пред инструкция без паметен операнд (напр. LOCK ADD EAX, EBX): В по-стари процесори поведението е непредсказуемо. От Pentium нататък е #UD (Invalid Opcode, вектор 6) — LOCK е валиден само с памет операнд.


Въпрос 3

Какви са новите функционални възможности на APIC-базираните мултипроцесорни системи? Построете клъстерен модел.

Функционални възможности на APIC спрямо i8259A:

Характеристикаi8259AAPIC
Брой прекъсвания8 (15 каскадирани)255 (IOAPIC)
Разпределение между CPUНеДа (маршрутизация)
Генериране на IPIНеДа (Inter-Processor Interrupts)
ПриоритетФиксиран / ROTПрограмируем (TPR, PPR)
СинхронизацияНеДа (INIT, SIPI за старт на AP)

Клъстерен модел на APIC шина:

  • Процесорите се групират в клъстери (до 4 CPU/клъстер, до 15 клъстера)
  • Всеки клъстер има клъстерен адрес (горни 4 бита) + локален адрес (долни 4 бита) в Cluster Destination Register
  • IOAPIC насочва прекъсвания към клъстер и вътре в него по маска
  • Предимства: по-малко трафик на APIC шината при голям брой CPU, по-добра мащабируемост спрямо плоския (flat) модел (max 8 CPU в flat)

Въпрос 4

Обяснете необходимостта от сериализиращи инструкции. Защо привилегированите инструкции трябва да са сериализирани?

Модерните процесори изпълняват инструкции извън ред (OoO) и спекулативно. Това означава, че запис в CR0 (например PE=1) може да бъде буфериран, докато следващи инструкции вече се изпълняват по стария режим.

Сериализиращите инструкции (CPUID, IRET, WRMSR, MOV CRn, MOV DRn, LGDT, LIDT, LLDT, LTR, INVD, INVLPG) гарантират, че:

  1. Всички предходни инструкции са завършили (резултатите са в архитектурното състояние) преди да стартира следващата.
  2. Конвейерът е изчистен (flush) — никакви спекулативни инструкции след тях не са изпълнени преди ефекта да е видим.

Привилегированите инструкции са сериализиращи защото те променят архитектурното глобално състояние (режим на работа, памет, прекъсвания). Ако MOV CR0 не беше сериализираща, код, изпълняван спекулативно преди PE=1, можеше да достъпи памет по реален режим адресиране дори след официалното превключване.


Въпрос 5

В какво се изразява проблемът за консистентността на кеш паметите в SMP системите? Какви средства са включени?

Проблемът: При SMP всеки процесор има свои L1/L2 кешове. Ако CPU-A кешира строчка X и я модифицира, без CPU-B да знае → CPU-B чете остаряла стойност на X от своя кеш или от паметта. Нарушава се кеш консистентността.

MESI протокол (хардуерно решение): Всяка кеш строчка е в едно от 4 състояния:

БукваСъстояниеОписание
M (Modified)Само в този кеш, различна от паметтаПри достъп от друг CPU → write-back + S
E (Exclusive)Само в този кеш, идентична с паметтаПри четене от друг CPU → S
S (Shared)В множество кешове, идентична с паметтаПри запис → M + Invalidate останалите
I (Invalid)Невалидна строчкаПри достъп → cache miss → зареждане

Механизъм: Процесорите “подслушват” (snoop) шината. При запис от CPU-A с LOCK# или при навлизане в M-состояние, CPU-B вижда сигнала HIT#/HITM# и инвалидира или актуализира своята строчка.

Програмни средства: MFENCE, SFENCE, LFENCE — memory barriers за гарантиране на ред на видимост на операции; CLFLUSH — принудително изхвърляне на строчка.


Въпрос 6

Проектирайте арбитражна схема за обща шина на два или повече i486/Pentium процесора.

Необходими сигнали:

  • HOLD (вход на CPU): заявка от арбитъра за освобождаване на шината
  • HLDA (изход на CPU): потвърждение, че CPU е освободил шината

Статичен приоритет (2 CPU):

Арбитър:
ако CPU_0 иска шина (BREQ_0) и CPU_1 иска (BREQ_1):
→ предай шината на CPU_0 (по-висок приоритет)
ако само CPU_1 иска:
→ предай на CPU_1

Динамичен приоритет (round-robin):

  • При всяко освобождаване на шината приоритетът се ротира между процесорите.
  • Имплементира се с D flip-flop за „последно обслужен” + комбинаторна логика.

Отчитане на LOCK#:

  • При активен LOCK# арбитърът не издава HOLD на текущия CPU до завършване на заключения цикъл.
  • Логика: HOLD_enable = NOT LOCK# AND (друг CPU иска шина)

За i486: сигналите BREQ, HOLD, HLDA, LOCK# са директно на изводите на чипа.


Лабораторно упражнение 13 — Пряк достъп до паметта (DMA)

Въпрос 1

Свържете логически анализатор към DMA контролера в IBM PC/AT. Снемете времедиаграмата на канал 2 при dir.

Канал 2 на DMA контролера в IBM PC/AT е свързан към дисковото устройство (флопи). При команда dir:

  1. Флопи контролерът активира DREQ2 (DMA Request, канал 2).
  2. DMA издава HRQ (Hold Request) → CPU вижда HOLD.
  3. CPU активира HLDA (Hold Acknowledge) и освобождава шината.
  4. DMA активира DACK2# (DMA Acknowledge).
  5. DMA управлява шината: издава адреси за памет (A7..A0 + Page Register за A15..A8) и управляващи сигнали IOR# / MEMW# (четене от флопи, запис в памет) или MEMR# / IOW# за обратното.
  6. Предаването продължава до Latch EOT (End Of Transfer) или до зануляване на брояча.
  7. DMA дезактивира HRQ → CPU поема шината обратно.

На анализатора се виждат: DREQ2↑ → HRQ↑ → HLDA↑ → DACK2#↓ → серия адресни+данни цикли → TC (Terminal Count) → DACK2#↑ → HRQ↓.


Въпрос 2

Снемете времедиаграмата на канал 0 при опресняване на паметта. Сравнете с канал 2.

Канал 0 на DMA в IBM PC/AT се използва за DRAM refresh (опресняване на динамична памет). Разлики спрямо канал 2:

ХарактеристикаКанал 0 (Refresh)Канал 2 (Флопи)
ИнициаторСамосхемен таймер (автоматично)Флопи контролер (при нужда)
Периодичност~15.6 µs (66 000 пъти/с)При поискване
ДанниНе се прехвърлят (Memory-to-Memory не е активен)Флопи → RAM или RAM → Флопи
Специален сигналMEMR# + MEMW# едновременно (refresh cycle)IOR#/MEMW# или MEMR#/IOW#
Дължина1 цикъл × адрес (без данни)Блок (n × 512 байта)

На анализатора refresh цикълът е много кратък и периодичен. Флопи предаването е по-дълго, но нередовно.


Въпрос 3

Напишете програма за прехвърляне памет→памет чрез DMA. Възможно ли е в IBM PC (канал 0 = refresh)?

Програма (реален режим, ISA DMA):

; Прехвърляне 256 байта от source (0x2000:0) към dest (0x3000:0)
; 1. Деактивирай канал 1 (или друг свободен)
MOV AL, 0x05 ; Mask bit за канал 1
OUT 0x0A, AL
; 2. Задай режим: Memory-to-Memory, канал 1, Single mode
MOV AL, 0x49 ; 0100 1001b = Read (от памет), Single, Auto, Inc, Channel 1
OUT 0x0B, AL
; 3. Изчисти FF/HF flip-flop
OUT 0x0C, AL
; 4. Адрес на destination (канал 1 → памет)
MOV AX, 0x0000 ; offset в страница
OUT 0x02, AL ; Low byte
MOV AL, AH
OUT 0x02, AL ; High byte
; 5. Брой байтове - 1
MOV AX, 0x00FF ; 255 → 256 байта
OUT 0x03, AL
MOV AL, AH
OUT 0x03, AL
; 6. Page register за канал 1
MOV AL, 0x30 ; страница 0x30 (физически адрес 0x30000+)
OUT 0x83, AL
; 7. Активирай канал 1
MOV AL, 0x01
OUT 0x0A, AL

Режим памет→памет: DMA 8237A поддържа Memory-to-Memory режим (канали 0 и 1), но в IBM PC канал 0 е резервиран за refresh и не може да се използва за прехвърляне. Следователно в стандартен IBM PC Memory-to-Memory DMA е практически недостъпен.


Въпрос 4

В какво се различава DMA за ISA от DMA за PCI?

ХарактеристикаISA DMA (8237A)PCI DMA (Bus Mastering)
АрхитектураЦентрален контролерРазпределен (всяко устройство е Bus Master)
Ширина на адреса16-bit (+ 8-bit page reg.) = 24-bit32-bit (или 64-bit с DAC)
Скорост~1.6 MB/s (ISA = 8 MHz, 16-bit)До теоретичен максимум на PCI (~133 MB/s)
АдресацияСамо долните 16 MB RAMЦялото 32-bit адресно пространство
УправлениеCPU програмира 8237A; 8237A управлява шинатаУстройството само управлява шина транзакции
СъвместимостНаследена (Sound Blaster, стари флопи)Нова (мрежови карти, SATA, USB контролери)
ПрекъсванеОтделно IRQ за TCЗавършване сигнализира с MSI или INTx#

В PCI Bus Mastering устройството заявява шина с REQ# → арбитърът дава GNT# → устройството извършва самото предаване като инициатор, без да ангажира DMA контролера.


Въпрос 5

Обосновете необходимостта от разпределената DMA схема в PCI.

В PCI архитектурата централизираният DMA контролер (8237A) е тясно място:

  1. Скоростта му е ограничена до ISA честота (~8 MHz, 8/16-bit) — несъвместима с PCI (33/66 MHz, 32/64-bit шина).
  2. Адресното пространство е ограничено — 8237A може да адресира само 24-бит → 16 MB. PCI устройства трябва да прехвърлят данни в/от целия 32-bit RAM.
  3. Централизацията е единична точка на отказ и сериен достъп — само едно устройство може да ползва DMA едновременно.

Разпределената DMA схема в PCI (Bus Mastering) решава всичко:

  • Всяко PCI устройство придобива шината самостоятелно чрез REQ#/GNT# арбитраж.
  • Множество устройства могат едновременно да планират предавания (арбитражът е пакетен).
  • Адресиране на целия PCI адрес простор (32/64 bit).
  • Скоростта е ограничена само от PCI шината (до 133 MB/s при 66 MHz/32-bit).