Въпроси и задачи — отговори
Въпросите са от Ръководство за лабораторни упражнения по Микропроцесорни системи, Рускова Н., ТУ-Варна, 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) повишава ефективността по два начина:
-
Предсказване на условни преходи (BTB): Всеки условен преход се записва в Branch Target Buffer с адрес и история (взет/невзет). При повторно срещане на прехода BTB директно подава предсказания адрес на IFU, без да изчаква пресмятането на условието. Алгоритмите с 2-bit saturating counter се приближават до 95% точност при типични цикли.
-
Предсказване на адреса при
RET(RSB — Return Stack Buffer): ПриCALLадресът на следващата инструкция се записва в RSB (стеков буфер). ПриRETRSB директно връща предсказания адрес, без да го чете от стека в паметта. Точността е практически 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, mem32 | LOAD eax ← [mem32] | 1 µop — зареждане |
and edx, 10 | AND edx, 10 | 1 µop — ALU |
imul eax, ecx | MUL eax ← eax × ecx | 1 µop (3–4 такта латентност) |
mov mem32, eax | STORE_ADDR [mem32] + STORE_DATA [mem32] ← eax | 2 µops — съхраняване |
Ред на разпределение за изпълнение (OoO):
LOAD eaxиAND edx, 10могат да стартират едновременно — независими операнди.MUL eaxчака самоLOAD eaxда завърши (зависимост от данни: RAW).STORE_ADDRможе да стартира веднага (адресът е известен),STORE_DATAчака резултата наMUL eax.
Извод: AND edx, 10 стартира паралелно с LOAD eax, без да изчаква MUL или MOV.
Лабораторно упражнение 5 — Системна архитектура. Управление на паметта в защитен режим
Въпрос 1
Стартирайте симулатора i486. Превключете МП в защитен режим. Каква е реакцията при следващата инструкция? Кои регистри трябва да се променят и как?
За превключване в защитен режим задължително трябва да се направи следното:
- Подготви GDT — в паметта трябва да съществува валидна Global Descriptor Table с минимум нулев дескриптор (индекс 0) и поне един кодов и един даннов дескриптор.
- Зареди GDTR — с инструкция
LGDT m48(48-битов операнд: 16-бит лимит + 32-бит базов адрес на GDT). - Зареди CR0.PE = 1 —
MOV CR0, regс бит 0 = 1. В 32-битов режим:OR eax, 1 / MOV CR0, eax. - Незабавно след това — 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.
Необходими структури:
- Page Directory (4 KB, изравнен на 4 KB) — 1024 PDE × 4 байта; PDE[i].P=1, PDE[i].Base = физически адрес на Page Table[i].
- Page Tables (по 4 KB за всяка) — 1024 PTE × 4 байта; PTE[j].P=1, PTE[j].Base = физически адрес на страницата.
- CR3 — физически адрес на Page Directory (битове 31..12; PCD и PWT = 0 за нормална работа).
Стъпки: подготви структурите → MOV CR3, eax → OR 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) | 0x40 | G=0, D=1 (32-bit), L=0, AVL=0, Lim[19..16]=0 |
| P / DPL / S / Тип (байт 5) | 0xFA | P=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] | 0xCF | G=1 (4 KB единици), D=0 (16-bit), Lim[19..16]=0xF |
| P / DPL / S / Тип | 0x90 | P=1, DPL=00b, S=1, Тип=0000b (данни, R-O) |
| База | 0x00000000 | |
| Лимит | 0xFFFFF (G=1 → 4 GB) |
Въпрос 2
Компилирайте и изпълнете програмата от Приложение 1. Какво е началното състояние на управляващите и сегментните регистри след RESET? Сравнете с Protected Mode.
Състояние след RESET (реален режим):
| Регистър | Стойност при RESET |
|---|---|
| CR0 | 0x00000010 — PE=0, PG=0 (реален режим) |
| CS | 0xF000 (сегмент 0xF0000, EIP=0xFFF0 → BIOS entry) |
| DS, ES, FS, GS, SS | 0x0000 |
| GDTR | Base=0, Limit=0xFFFF (невалиден) |
| IDTR | Base=0, Limit=0x03FF (реален режим IVT) |
| EFLAGS | 0x00000002 — IF=0, всички флагове 0 |
След превключване в защитен режим (очаквано):
| Регистър | Стойност |
|---|---|
| CR0 | PE=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, 0xB8000mov byte [edi], 'P'mov byte [edi+1], 0x07За да работи в P-режим, DS трябва да сочи към даннов сегмент с база ≤ 0xB8000 и лимит, покриващ видеопаметта (или база = 0 и лимит = 4 GB).
Лабораторно упражнение 8 — Управление на задачите
Въпрос 1
Разучете програмата от Приложение 2.
Програмата от Приложение 2 демонстрира хардуерното превключване на задачи чрез TSS. Структурата е:
- Инициализация в реален режим: нулиране на регистрите, зареждане на GDT с дескриптори за кодов сегмент, даннов сегмент и TSS дескриптори за всяка задача.
- Превключване в защитен режим (PE=1, far JMP).
- Зареждане на TR (
LTR) с TSS на начална задача. - Извикване на втора задача чрез
JMP farкъм TSS дескриптор — МП автоматично съхранява контекста на текущата задача в TSS и зарежда контекста на новата. - Връщане при
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
Добавете трета задача с характерно съобщение. Осъществете вложено извикване на трите задачи.
Стъпки за добавяне на трета задача:
- Деклариране на TSS3 в данновия сегмент (структура от 104 байта за 32-bit TSS): задаване на EIP (адрес на код на задача 3), CS (код-сегментен селектор), SS0:ESP0 (Ring 0 стек), CR3.
- TSS3 дескриптор в GDT: S=0, Тип=9 (незает), P=1, DPL=0 (или 3 за потребителска задача), Limit ≥ 103, Base = адрес на TSS3.
- Вложено извикване (CALL-модел):
- Задача 1 извиква задача 2 с
CALL far [TSS2_selector:0] - Задача 2 извиква задача 3 с
CALL far [TSS3_selector:0] - МП вдига NT=1 в задача 2 и 3; Previous Task Link = селектор на предходната
IRETв задача 3 → автоматично се превключва обратно към задача 2IRETв задача 2 → обратно към задача 1
- Задача 1 извиква задача 2 с
Въпрос 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 с шлюзове.
Процедурата за всяко изключение трябва:
- При изключения с код на грешка (8, 10–14, 17) — да го извади от стека (
ADD ESP, 4). - Да изведе номера на изключението на екрана (директен запис в видеопамет 0xB8000).
- При рестартируеми грешки (#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) — overflow | INTO при 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:PUSHFDOR 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.
Последователност на сигналите при хардуерно маскируемо прекъсване:
- Таймерът активира IR0 (Input Request 0) на i8259A.
- i8259A активира INT → процесорът вижда INTR.
- При IF=1 процесорът завършва текущата инструкция и издава два INTA цикъла:
- 1-ви INTA#: i8259A се „заключва” — замразява приоритетния арбитър.
- 2-ри INTA#: i8259A поставя на шината вектора на прекъсването (0x08 за IR0 при ICW2=0x08).
- Процесорът чете вектора, умножава по 8 → IDT[0x08] → извлича Interrupt/Trap Gate → превключва стека, записва EFLAGS:CS:EIP и скача към обработчика.
- Обработчикът трябва да изпрати 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 | Значение |
|---|---|---|---|
| ICW1 | 0x20 | 0x11 | Edge-triggered, cascade mode, ICW4 required |
| ICW2 | 0x21 | 0x08 (Master) / 0x70 (Slave) | Базов вектор: IR0→INT 8, IR8→INT 70h |
| ICW3 | 0x21 | 0x04 (Master) / 0x02 (Slave) | IR2 на Master е каскадиран Slave; Slave ID=2 |
| ICW4 | 0x21 | 0x01 | 8086 режим (не MCS-80), нормален EOI |
На логическия анализатор ще се наблюдават записи на портове 0x20 и 0x21 в горния ред, последователно при BIOS инициализация.
Въпрос 6
В програмата от Приложение 2 добавете задача, стартираща при прекъсване от таймера. Задачата да брои прекъсванията.
- Дефинирайте 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)
- TSS на задачата-таймер трябва да е предварително инициализиран с EIP = адрес на обработчика, CS, SS:ESP.
- В обработчика:
INC DWORD [timer_count] ; инкременти броячa; Извеждане на стойността на екранаMOV AL, 0x20 ; EOIOUT 0x20, ALIRET ; При Task Gate → превключване обратно
- При 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:
| Характеристика | i8259A | APIC |
|---|---|---|
| Брой прекъсвания | 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) гарантират, че:
- Всички предходни инструкции са завършили (резултатите са в архитектурното състояние) преди да стартира следващата.
- Конвейерът е изчистен (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:
- Флопи контролерът активира DREQ2 (DMA Request, канал 2).
- DMA издава HRQ (Hold Request) → CPU вижда HOLD.
- CPU активира HLDA (Hold Acknowledge) и освобождава шината.
- DMA активира DACK2# (DMA Acknowledge).
- DMA управлява шината: издава адреси за памет (A7..A0 + Page Register за A15..A8) и управляващи сигнали IOR# / MEMW# (четене от флопи, запис в памет) или MEMR# / IOW# за обратното.
- Предаването продължава до Latch EOT (End Of Transfer) или до зануляване на брояча.
- 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-bit | 32-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) е тясно място:
- Скоростта му е ограничена до ISA честота (~8 MHz, 8/16-bit) — несъвместима с PCI (33/66 MHz, 32/64-bit шина).
- Адресното пространство е ограничено — 8237A може да адресира само 24-бит → 16 MB. PCI устройства трябва да прехвърлят данни в/от целия 32-bit RAM.
- Централизацията е единична точка на отказ и сериен достъп — само едно устройство може да ползва DMA едновременно.
Разпределената DMA схема в PCI (Bus Mastering) решава всичко:
- Всяко PCI устройство придобива шината самостоятелно чрез REQ#/GNT# арбитраж.
- Множество устройства могат едновременно да планират предавания (арбитражът е пакетен).
- Адресиране на целия PCI адрес простор (32/64 bit).
- Скоростта е ограничена само от PCI шината (до 133 MB/s при 66 MHz/32-bit).