↑↓ / PgUp PgDn / колесо — навигация
Hardware Deep Dive · Гвендолин-ночные-лекции

От кнопки до процесса

Полная анатомия запуска компьютера: куда течёт первый ампер, кто исполняет первую инструкцию, как биты становятся рабочим столом — и где именно виртуальная кнопка «Завершить работу» дотягивается до реального транзистора.

01
Глава 1

Питание: до первой инструкции

Компьютер начинает работать задолго до того, как «включится». И кнопка питания не включает блок питания — она лишь вежливо просит.

Питание · дежурный режим

Пока ты «выключен», ты уже включён

  • Воткнул вилку в розетку — в БП сразу запускается маленький дежурный преобразователь: линия +5VSB (standby, до 3 А) живёт всегда.
  • От +5VSB питаются: чипсет (его power-домен управления), Super I/O / Embedded Controller, микросхема сетевухи (ради Wake-on-LAN), часть USB-портов, CMOS-логика.
  • Часы (RTC) и хранение настроек — отдельная песня: домен RTC well питается от батарейки CR2032, когда вилка выдернута. Поэтому «сбросить BIOS» = вынуть батарейку.
  • То есть «выключенный» комп — это работающая микросеть из 3–5 живых чипов, ждущих события: кнопка, Wake-on-LAN, RTC-будильник, USB-пробуждение.

Разъём ATX 24-pin: провода-переговорщики

СигналЦветРоль
+5VSBфиолетовыйдежурное питание, живёт всегда
PS_ON#зелёныйпритянуть к земле = «включай основные линии»
PWR_OKсерыйответ БП: «напряжения стабильны, можно жить»
12V / 5V / 3.3Vжёлт/красн/оранжосновные силовые линии

Знак # = сигнал активен низким уровнем. Классика: замкнуть зелёный на чёрный скрепкой — БП стартует без всякой платы.

Питание · кнопка

Нажатие кнопки: самый примитивный сигнал в компьютере

  • Кнопка на корпусе — тупая механика: просто замыкает два пина PWR_BTN на колодке платы. Ни логики, ни напряжения — контакт.
  • Замыкание видит Super I/O / EC (живой от +5VSB). Он дебаунсит дребезг контакта и сообщает чипсету: «просили включиться».
  • Чипсет (его ACPI-логика) решает: из S5 → в S0. И притягивает PS_ON# к земле. Вот и всё «нажатие» — один транзистор утянул один провод вниз.
  • Тот же пин обрабатывает и «подержать 4 секунды» — аппаратный форс-выключатель работает даже при намертво зависшей ОС, потому что ОС в этой цепочке не участвует вообще.
Заметь: между пальцем и БП — ноль строчек софта. Это чистый автомат на логических элементах, спроектированный так, чтобы работать, когда всё остальное умерло.
Палецзамыкает контакты PWR_BTN → GND
Super I/O / ECдебаунс, событие «power button pressed»
Чипсет (ACPI power logic)переход S5→S0, тянет PS_ON# вниз
Блок питаниязапускает основные преобразователи 12/5/3.3 В
~100–500 мс спустяPWR_OK: «напряжения стабильны»
Питание · блок питания

Что происходит внутри БП за эти полсекунды

Тракт преобразования (современный ATX)

  • Фильтр + выпрямитель: 230 В AC → ~325 В DC (пульсирующий)
  • APFC: активный корректор мощности накачивает шину до стабильных ~400 В DC и делает потребление синусоидальным (чтобы сеть не гадить гармониками)
  • LLC-резонансный полумост: рубит 400 В на частоте ~100 кГц → маленький трансформатор (частота выше — железо меньше, вот почему БП не весит 10 кг)
  • Синхронное выпрямление: на выходе мосфеты вместо диодов → 12 В с КПД 90%+
  • DC-DC модули: 5 В и 3.3 В нынче делаются ИЗ 12 В отдельными понижайками
  • Soft-start: конденсаторы (миллифарады!) нельзя зарядить мгновенно — бросок тока сжёг бы всё. Заряд идёт плавно, это часть тех самых миллисекунд.
  • Пока идёт разгон, выходы «грязные». БП держит PWR_OK низким и поднимает его только когда все линии в допуске ±5% минимум 100 мс.
  • PWR_OK — критический сигнал: пока его нет, чипсет держит всю платформу в RESET. Ни одна цифровая схема не начнёт работать на плывущем питании.
  • Защиты (OCP/OVP/UVP/SCP) следят постоянно: КЗ на линии — БП мгновенно гасится и отпускает PWR_OK. Поэтому «комп резко вырубился» часто = сработала защита БП.
Питание · VRM

VRM: последняя миля — из 12 В в 1.1 В и триста ампер

CPU не ест 12 В. Он ест ~0.9–1.4 В, зато сотнями ампер. Преобразует это VRM — кольцо силовой электроники вокруг сокета.

  • Многофазный buck-конвертер: 12–20 «фаз», каждая — пара мосфетов + дроссель. Фазы работают со сдвигом, размазывая пульсации. PWM ~300–800 кГц на фазу.
  • SVID / SVI3: напряжение просит сам процессор, цифровой шиной, на лету: буст — «дай 1.35 В», простой — «хватит 0.7 В». Тысячи запросов в секунду.
  • Догрузка за наносекунды: при скачке нагрузки (все ядра проснулись) ток растёт на сотни ампер за микросекунды. Пока дроссели раскачиваются — ток отдают конденсаторы, включая крошечные керамические прямо под сокетом с обратной стороны платы.
  • Power sequencing: напряжения платы поднимаются в строгом порядке (сначала домены чипсета, потом память, потом ядра) — микросхемы дохнут, если «подать сзади» через защитные диоды.
БП12 В
фаза 1FET + дроссель
фаза 2
фаза N12–20 штук
конденсаторысглаживание
CPU~1.2 В, 300 А
PWM-контроллерделит работу по фазам
⟵ SVID: «дай мне 1.28 В» — цифровая шина от CPU
P = U×I: снизить напряжение вдвое — токи вдвое выше. Потому VRM — самая горячая зона платы после самого CPU, и потому у дешёвых плат топовый камень троттлит «на ровном месте».
Питание · reset и клок

Пульс появился: тактирование и снятие RESET

  • Вся синхронная цифровая логика мертва без такта. Опорный генератор — кварц + клокген, даёт BCLK = 100 МГц на всю платформу.
  • Из этой сотни каждый потребитель умножает своё: CPU через PLL (100 × 45 = 4.5 ГГц), память своё, PCIe своё. Разгон по BCLK гонит ВСЁ сразу — потому он и умер как жанр.
  • PLL требуется время «захватить» частоту (lock) — ещё одна причина, почему всё стартует по очереди, а не разом.
  • Когда питание в допуске (PWR_OK), клоки стабильны, PLL залочены — чипсет отпускает линии RESET#. Платформа формально жива. Но CPU ещё не исполняет ничего — и вот тут начинается самое интересное.
Таймлайн включения (типичные ~0.5–1.5 с до первой инструкции):
PS_ON# ↓
soft-start БП, заряд кондёров
sequencing VRM-доменов
PWR_OK ↑
PLL lock, RESET# ↑
…но CPU ещё ждёт (гл. 2)
0 мс~1000 мс
Итог главы: от пальца до готового к работе кремния — цепочка из чистой электроники: кнопка → EC → чипсет → PS_ON# → БП → PWR_OK → sequencing → клоки → RESET снят. Софта здесь не существует. Он появится в следующей главе — и не там, где ты думаешь.
Глава 2

Прошивки: кто исполняет первую инструкцию

Спойлер: не твой процессор. В каждом ПК живёт второй, скрытый компьютер — и он всегда просыпается первым.

Прошивки · скрытый процессор

PSP / ME: компьютер внутри компьютера

  • Первым из reset выходит не x86. У AMD это PSP (Platform Security Processor, ядро ARM Cortex-A5 прямо на кристалле CPU), у Intel — ME (Management Engine, ядро x86-класса Quark внутри чипсета).
  • Он читает свою прошивку из той же SPI-флешки, проверяет её подпись зашитым в кремний ключом — это hardware root of trust, якорь всей цепочки доверия.
  • PSP инициализирует базовое: контроллеры, фьюзы, безопасность, помогает с инициализацией памяти — и только потом снимает reset с x86-ядер.
  • Твои ядра, все 16 штук на 5 ГГц, стоят и ждут разрешения от маленького ARM на 100-200 МГц. Иерархия, однако.
Тёмная сторона: этот сопроцессор работает всегда (даже в S5, пока есть дежурка), имеет доступ к памяти и сети, его прошивка закрыта. Отключить штатно нельзя. Параноики не зря нервничают — это самый привилегированный код в машине, ring −3 в народной классификации.

Порядок пробуждения (AMD, упрощённо)

1. PSP (ARM)выходит из reset, читает и проверяет свою прошивку из SPI
2. PSP: верификацияпроверяет подпись первых блоков BIOS (AGESA/PEI)
3. PSP: инфраструктурафьюзы, домены питания, подготовка к memory init
4. x86 BSPодин «загрузочный» x86-поток (Boot Strap Processor) выходит из reset
5. Остальные ядра (AP)спят до явной команды INIT-SIPI гораздо позже
Прошивки · носитель

SPI-флешка: сейф на 32 мегабайта

  • Весь стартовый код лежит в крошечной 8-ножечной микросхеме SPI NOR flash на 16–32 МБ рядом с чипсетом. Это и есть «BIOS-чип».
  • Внутри — регионы: дескриптор (карта самой флешки), регион ME/PSP-прошивки, регион UEFI, иногда GbE-конфиг сетевухи. Прошивка BIOS из ОС пишет именно сюда.
  • Шина SPI — медленная: десятки МГц, единицы МБ/с. Поэтому UEFI первым делом копирует себя в RAM... когда RAM появится. А до того исполняется прямо из флешки: XIP, execute-in-place.
  • Двойной BIOS на дорогих платах = вторая такая же флешка + логика переключения. «Кирпич» после неудачной прошивки — это когда убили единственную.

Как CPU вообще видит флешку?

x86 после reset начинает с адреса 0xFFFF_FFF0 — 16 байт до конца 32-битного пространства. RAM там нет и быть не может.

Чипсет аппаратно декодирует верхние адреса (~последние 16 МБ под 4 ГБ) в чтение SPI-флешки. CPU думает, что читает память — а чипсет незаметно ходит по SPI за каждым байтом.

По адресу FFFF_FFF0 лежит одна-единственная инструкция — прыжок в настоящий код. Эти 16 байт — reset vector, самые дорогие 16 байт в индустрии: их адрес не менялся с 386-го, 1986 год.

Прошивки · первые инструкции

Первый код x86: мир без памяти

  • BSP просыпается в real mode — режиме 8086 из 1978 года: 16 бит, сегменты, 1 МБ адресов. Каждый новейший процессор рождается древним стариком и молодеет по ходу загрузки.
  • Первые сотни инструкций — ассемблер в жёстких условиях: RAM нет, значит нет стека, значит нет вызовов функций, нет C. Только регистры и прыжки.
  • Решение красивое — Cache-as-RAM (CAR): кэш L2/L3 конфигурируется в режим no-fill/no-evict и превращается в честные ~стек и данные. Кэш становится оперативкой на время, пока настоящая оперативка не заговорит.
  • На CAR уже поднимается C-окружение и стартует ранняя фаза UEFI (SEC → PEI), чья главная задача — инициализировать контроллер памяти.
Адресное пространство при старте (без RAM):
0xFFFF_FFFF ↓
SPI flashзамаплена чипсетом
● 0xFFFF_FFF0 — reset vector
пустота: RAM ещё не существует
legacy-областьVGA, BIOS shadow
0x0 ↑
Порядок в первые мс:
  1. jmp из reset vector
  2. отключить прерывания
  3. включить CAR (кэш = RAM)
  4. поставить стек в кэш
  5. перейти в 32/64-bit режим
  6. запустить C-код PEI-фазы
  7. → memory training
Прошивки · инициализация памяти

Memory training: BIOS учится разговаривать с планками

  • Сначала — опрос: на каждой планке есть чип SPD (крошечная EEPROM), BIOS читает его по шине SMBus (I²C): объём, организация, тайминги, профили XMP/EXPO.
  • Но паспорта мало. На скоростях DDR5 каждая линия данных — это ВЧ-канал со своими отражениями и задержками (даже длина дорожек чуть разная). Контроллер должен откалиброваться под конкретные планки в конкретных слотах.
  • Training: write leveling, read/write DQ-калибровка, Vref-подбор, gate training — контроллер гоняет тестовые паттерны и двигает задержки каждой линии шагами в пикосекунды, ища центр «глаза» сигнала.
  • Это тот самый долгий первый старт с новыми планками (десятки секунд чёрного экрана на DDR5). Результат кэшируется (MRC cache) — потому второй старт быстрый. Смена настроек/планок/батарейки — и тренировка заново.
«Глаз» сигнала: зачем нужен training
после training: выборка в центре глаза
до: у края, битовые ошибки
открытая зона = моменты, когда бит читается достоверно
Масштаб задачи (DDR5-6000):
  • битовое окно ~166 пс
  • свет за это время: ~5 см
  • линий данных: 64+ на канал
  • параметров на подбор: сотни

Разница длин дорожек в 1 см — уже треть окна. Потому дорожки DDR на плате извиваются змейкой: это выравнивание длин, не украшение.

Прошивки · POST

Остальной POST: перепись населения

  • RAM есть → UEFI копирует себя в память и разворачивается фаза DXE: сотни драйверов-модулей (для флешки, USB, NVMe, сети, GOP-видео...).
  • PCIe enumeration: обход дерева bus/device/function, чтение Vendor/Device ID, раздача адресов через BAR-регистры — каждой железке нарезается кусок физического адресного пространства. MMIO: «регистры устройства как память».
  • Просыпаются остальные ядра: BSP шлёт им INIT-SIPI-SIPI, каждое AP-ядро повторяет путь «старик→современность» и паркуется в ожидании.
  • Строятся ACPI-таблицы — досье на платформу для будущей ОС: MADT (ядра/прерывания), FADT (регистры питания), DSDT (байткод-описание устройств). Запомни DSDT — она сыграет в главе про выключение.
  • Отдельно заводится SMM — режим системного менеджмента: невидимый для ОС код в спрятанной памяти (SMRAM), просыпается по SMI-прерыванию. Ring −2: правит железом за спиной у ядра ОС.

Что осталось от «пищит спикером»

Классический POST 90-х (проверка RAM, пищание кодами) практически мёртв: память проверяется тренингом, ошибки сыпятся в Q-code индикатор или диагностические светодиоды платы.

Порядок для дебага живой платы: светодиоды CPU→DRAM→VGA→BOOT. Висит на DRAM — привет, memory training. Висит на VGA — карта/райзер/моник. На BOOT — ушли в главу 3.

Тайминг всего POST

Холодный старт с NVMe: ~3–10 c до передачи управления загрузчику. Из них львиная доля — инициализация памяти и DXE-зоопарк. Fast Boot режет USB-опрос и legacy — потому клавиатура иногда «не успевает» в BIOS.

Глава 3

Загрузка ОС: от файла до рабочего стола

UEFI сделал своё дело и хочет уйти. Осталось найти, проверить и запустить того, кому передать королевство.

Загрузка · UEFI Boot Manager

Кого грузим: NVRAM, ESP и подписи

  • Порядок загрузки живёт в NVRAM-переменных UEFI (та же SPI-флешка): BootOrder, Boot0000... — по записи на каждую ОС. bcdedit /enum firmware покажет.
  • На диске ищется ESP — EFI System Partition, обычный FAT32 на ~100–500 МБ. UEFI умеет читать FAT32 и GPT сам — на этом его файловые таланты заканчиваются.
  • Для Windows берётся \EFI\Microsoft\Boot\bootmgfw.efi — обычный PE-файл (тот же формат, что .exe!), исполняемый прямо firmware-ой.
  • Secure Boot: перед запуском UEFI проверяет цифровую подпись файла по базе ключей (db/dbx). Цепочка доверия, начатая PSP на слайде 9, дотянулась до файла на диске: кремний → прошивка → загрузчик → (дальше ядро проверит драйверы).

bootmgfw → winload: эстафета внутри Windows

bootmgfw.efiчитает BCD (меню ОС), гибернацию отдаёт winresume, обычный старт — дальше
winload.efiгрузит в память: ntoskrnl.exe, hal.dll, ELAM-антивирус, boot-драйверы, куст реестра SYSTEM
ExitBootServices()точка невозврата: сервисы UEFI гасятся, вся власть — будущему ядру
ntoskrnl.exeKiSystemStartup — ядро NT начинает дышать

Твоя ремарка про «HAL, к которому диспетчер прикручен вплотную» — вот момент их встречи: winload грузит ntoskrnl и hal парой, и с 2020-х hal.dll — уже форвардер внутрь ядра.

Загрузка · ядро NT

Ядро просыпается: две фазы и дерево процессов

  • Фаза 0: ядро строит себя: менеджер памяти размечает физические страницы, включаются структуры планировщика, обрабатываются ACPI-таблицы (вот и досье пригодилось), стартуют прерывания.
  • Фаза 1: PnP-менеджер начинает перечисление устройств заново, уже по-взрослому: строит дерево devnode, на каждое устройство навешивает стек драйверов (шинный + функциональный + фильтры).
  • I/O в NT — это IRP-пакеты, путешествующие вниз по стеку драйверов. Тот самый застрявший IRP из нашей ночной саги про неубиваемые процессы — вот где он живёт.
  • Ядро запускает первый процесс пользовательского режима — и дальше растёт дерево.
Session 0 — служебная (сервисы), Session 1 — твоя. Разделили после эпохи, когда сервисы могли рисовать окна на рабочем столе юзера — привет, shatter-атаки.
ntoskrnl (ядро) smss.exe (сессии) Session 0: csrss + wininit Session 1: csrss + winlogon services.exeSCM, все службы lsass.exeпароли, токены LogonUI → пароль/PIN userinit → explorer.exe Рабочий стол. Приехали. svchost'ы, драйверные службы, планировщики — всё дети services.exe
Загрузка · что такое процесс

Процесс: во что всё это превратилось

  • Процесс в NT — это структура EPROCESS в ядре: своё виртуальное адресное пространство (карта VAD + таблицы страниц из главы про RAM), таблица хэндлов, токен безопасности, квоты.
  • Исполняются не процессы, а потоки (ETHREAD). Планировщик (диспетчер!) раздаёт им кванты на ядрах: 32 уровня приоритета, preemption, boost'ы для интерактивных.
  • Каждые ~1–15 мс — прерывание таймера, планировщик решает «кто следующий». Переключение контекста = сохранить регистры одного потока, загрузить другого, переключить CR3 (корень таблиц страниц) — и TLB частично инвалидируется, это его скрытая цена.
  • Твой двойной клик по .exe: CreateProcess → ядро строит EPROCESS → маппит образ → создаёт первый поток → тот попадает в очередь планировщика → «программа запустилась».

Итого: полный стек одного клика

СлойКто
Тыдвойной клик
user modeexplorer → CreateProcess → ntdll → syscall
kernelEPROCESS, VAD, страницы, поток, планировщик
CPUµops, кэши, TLB, спекуляция
RAMACT/RD, row buffer, refresh
ЭлектроныVRM держит 1.2 В, БП держит 12 В, розетка держит всех

Верх этой таблицы существует миллисекунды, низ — миллиарды тактов. И всё это — один клик.

Глава 4

Стык миров: как пиксель выключает транзистор

Ты просил показать место, где виртуальная кнопка «Завершить работу» дотягивается до физики. Вот оно, с точностью до регистра.

Стык · софтовая половина

Сверху вниз: от клика до последнего syscall

  • Клик по «Завершить работу» — explorer зовёт ExitWindowsEx(EWX_SHUTDOWN).
  • Запрос уходит в csrss/winlogon: всем GUI-приложениям рассылается WM_QUERYENDSESSIONWM_ENDSESSION. У каждого ~5 секунд на «сохраниться и умереть», потом экран «приложение не отвечает».
  • Службы получают SERVICE_CONTROL_SHUTDOWN, у них свой таймаут. Потом вызывается NtShutdownSystem — всё, дальше только ядро.
  • Ядро: гасит процессы, флашит грязные страницы кэша на диск (вот почему нельзя рубить питание — write-back из главы про RAM/NVMe ещё не доехал), драйверы получают IRP_MJ_SHUTDOWN и переводят устройства в D3, файловые системы демонтируются.
  • Остался последний шаг — и он уже не про софт.

ACPI: договор между ОС и железом

Ещё при загрузке ядро прочитало ACPI-таблицы. В таблице FADT написано: «регистр управления питанием PM1a_CNT живёт по такому-то адресу ввода-вывода». В байткоде DSDT лежит пакет \_S5 — пара магических цифр SLP_TYP для перехода в состояние S5 (soft-off) именно этой платы.

То есть плата при старте оставила ОС записку: «захочешь меня выключить — запиши вот эти цифры вот в этот регистр». ОС хранила её всю сессию.

S-состояния: S0 работаем · S3 сон (RAM под током) · S4 гибернация (RAM на диск) · S5 soft-off (жива только дежурка).

Стык · момент истины

Одна инструкция OUT — и мир гаснет

Софт
клик «Завершить работу»пиксели, user mode
NtShutdownSystemядро гасит мир, флашит кэши
hal: запись в PM1a_CNTout dx, ax · SLP_TYP|SLP_EN
регистр в чипсетефизические триггеры, бит SLP_EN
Железо
ACPI-автомат чипсетаsequencing выключения доменов
PS_ON# отпущен ↑тот самый зелёный провод
БП глушит 12/5/3.3остаётся +5VSB
Стык миров — одна инструкция процессора: запись пары битов в порт ввода-вывода.
Слева от неё — миллионы строк кода. Справа — только триггеры, провод и силовая электроника.
Симметрия запуска и выключения: включение — железо будит софт (кнопка → PS_ON# → ... → explorer). Выключение — софт усыпляет железо (explorer → ... → PM1a_CNT → PS_ON#). Один и тот же зелёный провод, пройденный в обе стороны. А «подержать кнопку 4 секунды» — аварийный обход всей левой половины схемы.
Глава 5

CPU: фабрика с конвейером

Внутри «процессора» давно нет одного процессора. Там город: фабрики-ядра, склады-кэши, своя железная дорога и таможня с переводчиком.

CPU · план кристалла

Что на самом деле лежит под крышкой

  • Ядра — лишь часть площади. Рядом: L3-кэш (огромный, десятки МБ), IMC (контроллер памяти — тот самый из главы про RAM), корневые порты PCIe, iGPU, контроллеры USB — половина «материнки» давно переехала в CPU.
  • Внутренняя магистраль: у Intel — кольцо/mesh, у AMD — Infinity Fabric. По ней ядра, кэш и контроллеры обмениваются кэш-линиями. Её частота — скрытый король задержек памяти (FCLK).
  • Чиплеты AMD: ядра лежат в CCD-кристаллах (по 8 ядер), а IMC/PCIe/USB — в отдельном IOD-кристалле, связанном IF-линками. Дёшево в производстве, но межчиплетный хоп добавляет наносекунды — вот откуда «латентность у райзенов повыше».
  • Твой 7900XTX, кстати, чиплетный тем же манером: GCD с шейдерами + шесть MCD с кэшем и контроллерами GDDR6 вокруг.

Частоты: почему «5 ГГц» — это не скорость

  • База/буст: частота плавает сотни раз в секунду: сколько ядер нагружено, сколько ватт, сколько градусов. «5.7 ГГц» на коробке — одно ядро, холод, удача.
  • Лимиты: PPT/TDC/EDC (ватты, амперы), термальный потолок. Упёрся в любой — частота вниз. Троттлинг это не «поломка», это штатный регулятор.
  • Гонка ГГц умерла ~в 2005: тепло растёт ~квадратично от напряжения, а без роста напряжения выше не тактуется. Потому ядер стало много, а ГГц — почти стоят 20 лет.
  • Отсюда же: AVX-нагрузка жрёт столько, что под неё частота отдельно снижается. «Мой камень медленнее под тяжёлой математикой» — не баг, физика.
CPU · конвейер

Путь инструкции: x86 снаружи, RISC внутри

Fetch16–32 байта/такт из L1i
Decodex86 → µops (перевод!)
Rename16 рег. → 300+ физических
Scheduler (OoO)исполняем что ГОТОВО, а не «по порядку»
Exec portsALU×6, load/store, FMA
Retireв порядке программы
Branch predictorугадывает ветвления с точностью ~95–99% и подсказывает Fetch, что грузить дальше
промах предсказания = слить конвейер, ~15–20 тактов в помойку. Потому сортированные данные обрабатываются быстрее несортированных.
  • x86 — это фасад. Декодер переводит CISC-инструкции в микрооперации (µops), и дальше живёт RISC-машина. Твой «x86-процессор» не исполнял x86 напрямую со времён Pentium Pro (1995).
  • Out-of-Order: ждёшь данные из RAM 300 тактов? Конвейер в это время исполняет всё независимое, что нашлось в окне из ~500 инструкций вперёд. Легальный обгон по обочине.
  • Спекуляция: предсказатель ветвлений угадывает «if» до вычисления условия, и CPU исполняет угаданную ветку авансом. Ошибся — результаты выкидываются... почти: следы в кэше остались. Так родился Spectre — цена, которую мы платим за скорость по сей день (и патчи её со скрипом возвращают).
  • SMT: два потока на ядро — это не два ядра, а два фронта, деляшие одни исполнительные порты: пока один ждёт память, второй жуёт. +15–30%, не ×2.
CPU · кэши

Кэши: вся архитектура — это сокрытие ста наносекунд

  • RAM отвечает ~80–100 нс = 400+ тактов. Без кэшей CPU 99% времени стоял бы. Иерархия: L1 (48К, 4 такта) → L2 (1–2М, ~14) → L3 (32–96М, ~50).
  • Единица всего — кэш-линия 64 байта. Отсюда правила жизни: ходи по памяти последовательно (prefetcher подхватит), держи горячие данные компактно, и не клади два счётчика разных потоков в одну линию — false sharing, ядра будут рвать линию друг у друга через MESI-протокол.
  • MESI: каждая линия в каждом кэше в состоянии Modified/Exclusive/Shared/Invalid. Запись в Shared-линию = разослать всем «инвалидируй». Вот физическая цена «просто добавь mutex».
  • AMD X3D — L3 наращён третьим этажом (96+ МБ): игры, где рабочий набор внезапно влез в кэш, получают +20–30% из ниоткуда. Лучшая иллюстрация того, насколько всё упирается в память.

Задержки в человеческом масштабе

Пусть 1 такт = 1 секунда. Тогда:

КудаРеально«По-человечески»
Регистр0 тактовмысль
L14 тактавзять со стола · 4 с
L214сходить к шкафу · 14 с
L3~50сходить к соседу · 1 мин
RAM~400сходить в магазин · 7 мин
NVMe~400 000отпуск · 4.5 суток
HDD seek~40 000 000выйти на пенсию · 1.5 года
Глава 6

RAM: триллионы дырявых ведёрок

Каждый бит твоей оперативки — конденсатор, из которого утекает заряд. Вся DRAM — это бесконечное переливание воды, притворяющееся памятью.

RAM · путь адреса

Формат адреса: одна цифра — три разборки

1. Виртуальный адрес (x86-64, страницы 4К) — то, что видит программа: 63–48 PML4 [47:39] PDPT [38:30] PD [29:21] PT [20:12] offset [11:0] → 4 уровня таблиц, TLB кэширует 2. Физический адрес → биты полей кэша (L1, 64Б линия): tag (сравнение) set index (какой набор) offset в линии [5:0] 3. Тот же физический адрес → поля контроллера памяти (промах кэшей): row (~64К строк) bank group bank column channel rank ← биты канала берут из младших: соседние линии → разные каналы Один и тот же адрес три подсистемы нарезают по-своему. Программа не видит ни одной из этих разборок.
RAM · внутри банка

ACT → RD → PRE: разговор с конденсаторами

  • ACT: строка целиком (~8 КБ!) выливается в row buffer — усилители на краю матрицы ловят «чуть выше/ниже половины» и раздувают до честных 0/1. Чтение разрушает заряд — буфер потом перезапишет строку обратно.
  • RD/WR + column: из открытой строки выщёлкиваются нужные 64 байта, едут burst-пакетом (DDR5: 32 бита × 16). CL — такты ожидания этого щелчка.
  • PRE: закрыть строку, подготовить банк. Тайминги с коробки CL-tRCD-tRP — это цены трёх этих шагов. Row hit = только CL; row miss = вся троица.
  • Refresh: заряд утекает сам — каждые 64 мс каждая строка принудительно перечитывается. ~2–5% пропускной способности уходит на переливание ведёрок.
  • Контроллер жонглирует очередями и переупорядочивает запросы ради row hit'ов — RAM отдаёт максимум только тому, кто ходит предсказуемо.

Почему латентность стоит 20 лет

DDR2-800 CL5 = 12.5 нс до данных. DDR5-6000 CL30 = 10 нс. За 20 лет — минус 20%. Пропускная способность выросла в 10 раз, задержка — почти нет: скорость света и RC-константы конденсаторной матрицы не масштабируются техпроцессом.

Вся индустрия строит обходы: кэши толще (X3D), prefetch умнее, OoO глубже. Латентность RAM — гравитация вычислений.

Rowhammer, до кучи

Молотишь по одной строке миллионы раз — электромагнитные наводки подтекают заряд СОСЕДНИХ строк, и биты флипаются без доступа к ним. Дыра в безопасности из чистой физики. Лечат Target Row Refresh'ем, гонка щита и меча идёт до сих пор.

Глава 7

Материнка: город и его дороги

Северный мост умер и переехал в CPU. Южный выжил, сменил имя на «чипсет» и стал большим USB-хабом с амбициями.

Материнка · мосты

Эволюция мостов: как север переехал в процессор

Было (эпоха Core 2, ~2008)

  • Северный мост: контроллер памяти + AGP/PCIe для видео + шина FSB к CPU. Горячий, с радиатором.
  • Южный мост: SATA, USB, звук, сеть, LPC — вся медленная периферия.
  • Каждое обращение к RAM ходило через FSB и северный мост: +десятки нс задержки.

Стало (сейчас)

  • Северный мост целиком внутри CPU: IMC, PCIe root (линии на видео и первый M.2 — напрямую из процессора!), USB-контроллеры.
  • Чипсет (бывший южный) = коммутатор остального: доп. PCIe, SATA, USB-порты, сеть, звук.
  • Связь CPU↔чипсет: у Intel — DMI (~PCIe x8), у AMD — PCIe x4-линк. Это бутылочное горлышко: всё, что висит на чипсете, делит один канал.
DDR52 канала
CPUядра · L3 · IMC · PCIe root · USB(= бывший северный мост)
GPU x16
M.2 #1 x4
DMI / PCIe x4 — горлышко!
SATA ×4
Чипсет (PCH / X670)(= бывший южный мост)
USB-порты
M.2 #2, #3
LAN · Wi-Fi · звук
Два NVMe на чипсетных M.2 + быстрая сеть = все толкаются в одном x4-линке. Потому первый M.2 (процессорный) — всегда лучший слот для системника.
Материнка · шины

Каталог дорог: от автобана до просёлка

ШинаСкоростьКто на ней живётЗаметки
PCIe 5.0 x16~63 ГБ/свидеокартапоколение ×2 = скорость ×2; x16/x8/x4/x1 — число полос
PCIe 4.0/5.0 x4~8/16 ГБ/сNVMe SSDтот самый M.2
DDR5, 2 канала~90 ГБ/сRAM ↔ IMCно латентность ~80 нс — гл. 6
USB4 / 3.x / 2.040 Гбит → 480 Мбитперифериязоопарк имён USB 3.2 Gen2x1 — маркетинговое преступление
SATA III0.55 ГБ/сстарые SSD, HDDлегаси-протокол AHCI: одна очередь, 32 команды
SPI~единицы МБ/сBIOS-флешка, TPMмедленно — но при старте больше некому
SMBus / I²C~100 КБ/сSPD планок, датчики, VRM-телеметриядвухпроводный просёлок из 1982
eSPI / LPC~десятки МБ/сSuper I/O: вентиляторы, кнопка, COMнаследник ISA. Да, того самого, 1981
Правило платы: чем медленнее шина — тем она старше и живучее. PCIe меняет поколение раз в 3 года, а SMBus с 1995-го не трогали: по нему всего лишь спрашивают у планки паспорт и у датчика температуру — куда спешить. Эволюция жрёт автобаны и не замечает просёлков.
Глава 8

GPU: десять тысяч студентов

CPU — четыре профессора, решающие что угодно. GPU — десять тысяч студентов, решающих одно и то же. Вопрос лишь в том, какая у тебя задача.

GPU · архитектура

SIMT: латентность не прячут — её топят в параллелизме

  • Ядро GPU примитивно: ни OoO, ни предсказателя, ни больших кэшей. Зато их тысячи (7900XTX: 6144 шейдерных ALU в 48 WGP).
  • SIMT: потоки пачками по 32/64 (wave) исполняют одну инструкцию на всех. Ветвление внутри пачки = исполнить ОБЕ ветки с масками. Потому GPU-код боится if'ов.
  • Ожидание памяти не прячется кэшами — перекрывается: на каждом WGP крутятся 10+ wave'ов, память ждёт один — исполняется другой. Нужны десятки тысяч потоков, чтобы GPU не скучал.
  • VRAM: GDDR6 на 7900XTX — шина 384 бита, ~960 ГБ/с (в 10 раз шире DDR5!). Плюс 96 МБ Infinity Cache. ГПУ — это в первую очередь машина пропускной способности.
  • Твой RenderMeshInstanced из Гвендолин — ровно эта философия: одна команда, тысяча волков, нулевые накладные на штуку.

CPU vs GPU: разделение труда

CPUGPU
Ядра8–16 сложныхтысячи простых
Силалатентность одной задачипропускная способность миллиона
Ветвленияпредсказывает 98%страдает
Памятькэши прячутпараллелизм топит
Родная задачалогика, сим, ОСпиксели, матрицы, нейронки

Потому нейронки живут на GPU: перемножение матриц — миллионы одинаковых умножений без ветвлений, идеальный студенческий субботник.

GPU · путь кадра

Путь кадра: от Update() до пикселя на матрице

Игра / движокUnity: draw calls, состояния, буферы
API (DX12/Vulkan)командные списки, тонкая обёртка
Драйвер UMDuser-mode: компиляция шейдеров, валидация
Драйвер KMDkernel-mode: очереди, память, ring buffer
GPU front-endчитает команды DMA из ring buffer
Конвейерvertex → raster → pixel shader → ROP
Фреймбуферготовый кадр в VRAM
Сканаутdisplay engine стримит в DP/HDMI
  • CPU и GPU асинхронны: процессор готовит кадр N+1, пока карта рисует N. «Упор в CPU» = карта простаивает, ждёт команд; «упор в GPU» = процессор ждёт очередь. Профайлер Unity показывает ровно это.
  • Present и vsync: готовый кадр меняется местами с показываемым (flip). Vsync ждёт кадрового гасящего импульса — привет, латентность; VRR (FreeSync) вместо этого двигает сам импульс.
  • Компиляция шейдеров: HLSL → DXIL → ISA конкретного GPU происходит на машине игрока (у каждой архитектуры свой машинный код!). Первая встреча с шейдером = компиляция = статтер. Потому игры «прогревают кэш шейдеров».
  • PCIe — узкое место потоков данных: текстуры и меши едут 30 ГБ/с при VRAM в 960. Отсюда стриминг, DirectStorage, и вечное «положи ассеты в VRAM заранее».
Глава 9

NVMe: память, которая притворяется диском

Внутри SSD нет ничего дискового. Там матрица ловушек для электронов и маленький компьютер, который врёт операционке о том, где что лежит.

NVMe · NAND

NAND: бит — это пойманные электроны

  • Ячейка — транзистор с ловушкой заряда: электроны загоняются туда сквозь изолятор туннелированием и сидят годами без питания. Количество заряда сдвигает порог открытия — это и читается.
  • SLC→MLC→TLC→QLC: 1→4 бита на ячейку = различать 2→16 уровней заряда. Плотность ×4, зато скорость записи и ресурс — вниз на порядки. Знакомая песня? Та же аналоговая ловушка, что и «255 уровней» в нашем ночном споре про фотоны)))
  • Геометрия: страница (~16 КБ) — минимум чтения/записи, блок (сотни страниц, мегабайты) — минимум... стирания. Перезаписать страницу на месте нельзя — только стереть весь блок целиком.
  • Каждая запись изнашивает изолятор: TLC живёт ~1–3К циклов стирания, QLC — сотни. 3D NAND: слои ячеек этажами (200+), плотность растёт вверх, раз вширь уже некуда.
Пороговые уровни: SLC vs QLC (почему QLC медленный и смертный) SLC (1 бит): 0 1 зазор огромный — быстро, надёжно QLC (4 бита): 16 уровней: писать = ювелирно докапывать заряд итерациями Запись QLC-страницы: программируй → проверь → докинь заряд → проверь → ... Потому прямая запись в QLC в разы медленнее чтения, и контроллер маскирует это pSLC-кэшем (следующий слайд). Дежавю: деление диапазона на 16 уровней — ровно то, что убивает и аналоговые вычисления. SNR — злой бог.
NVMe · контроллер

FTL: маленький лжец, на котором всё держится

  • ОС говорит «запиши в сектор 12345». Но перезаписи на месте в NAND нет. Контроллер пишет в свежую страницу, а в таблице FTL помечает: «LBA 12345 теперь вон там». Старая версия — мусор.
  • Garbage collection: фоном контроллер собирает живые страницы из полумёртвых блоков, переписывает компактно и стирает освободившееся. Твой SSD дефрагментирует сам себя, втайне, постоянно.
  • TRIM: ОС подсказывает «эти LBA я удалила» — иначе контроллер таскал бы мёртвые данные при GC вечно. Удалённый файл физически исчезает не при удалении, а когда GC доберётся.
  • Write amplification: одна твоя гигабайтная запись = 1.5–3 ГБ реальных записей в NAND (GC, переносы). На заполненном диске — хуже: GC задыхается без свободных блоков. Потому SSD, забитый под 95%, деградирует и по скорости, и по ресурсу.
  • Mapping-таблица живёт в DRAM-чипе на SSD (гигабайт на терабайт). Дешёвые DRAM-less берут кусок твоей RAM (HMB) — и всё равно тормозят на случайной записи.

pSLC-кэш: спринтер с одышкой

Свободный TLC/QLC контроллер временно использует как SLC (1 бит на ячейку — быстро!). Первые ~100–400 ГБ заливки летят на 5–7 ГБ/с, потом кэш кончается — и скорость падает до честной QLC-записи, порой ниже SATA. Тот самый «залил 300 гигов, а оно сдохло до 400 МБ/с».

Очереди: чем NVMe убил SATA

SATA/AHCINVMe
Очередей1до 65 535
Глубина3265 535
Путьчерез SATA-контроллерPCIe прямо в CPU
Латентность~100 мкс~10–20 мкс

Протокол спроектирован под параллельную природу NAND, а не под один вращающийся блин. Очередь на ядро, без глобальных локов.

Итоги · скорости

Вся пирамида на одном слайде

УровеньЛатентностьПропускная способностьГлавная боль
Регистры0 тактових 16 (виртуально 300+)
L1 / L2 / L31 / 4 / 15 нсТБ/сразмер; false sharing
RAM DDR5~80 нс~90 ГБ/слатентность стоит 20 лет
VRAM GDDR6~200+ нс~960 ГБ/сшироко, но далеко
NVMe (PCIe 4)~15–80 мкс7 ГБ/с**пока жив pSLC; QD1 — правда жизни
SATA SSD~100 мкс0.55 ГБ/спотолок протокола 2008 года
HDD~10 мс0.2 ГБ/смеханика: головка едет физически
Интернет~10–100 мс≤1 ГБ/сскорость света + провайдер
Каждая ступень — на 2–3 порядка медленнее предыдущей по латентности. Вся инженерия компьютера — это прослойки, прячущие эти обрывы: кэши прячут RAM, RAM прячет SSD (page cache!), SSD прячет сам себя (pSLC), и все вместе прячут то, что данные на самом деле — конденсаторы, ловушки и намагниченность.
Итоги · костыли

Музей действующих костылей

Наследие 1981–86

  • Real mode: каждый CPU стартует как 8086 (1978)
  • Reset vector на своём месте с 386-го
  • Линия A20: до недавнего времени — костыль с контроллером клавиатуры ради софта 1981 года
  • eSPI/Super I/O — правнук шины ISA

Костыли скорости

  • Memory training + его кэш: RAM слишком быстра, чтобы просто работать
  • pSLC-кэш: QLC слишком медленный, чтобы его показывать
  • Спекуляция: быстрее — исполнить и, может, выкинуть (цена: Spectre)
  • Refresh: DRAM забывает — будем напоминать 15 раз в секунду

Костыли доверия

  • PSP/ME: тайный сопроцессор, ring −3, код закрыт
  • SMM: невидимый режим, правящий за спиной ОС
  • SMBus без защиты: SPD планки можно перешить (RAM с «неправильным» паспортом)
  • Rowhammer: физика против криптографии — физика ведёт
Общий закон: ничто в компьютере не выбрасывается — оно инкапсулируется. Каждый слой врёт слою выше, что мир проще, чем есть: FTL врёт про сектора, IMC врёт про байты, ОС врёт про память, x86-декодер врёт про x86. Компьютер — это башня из добросовестной лжи, и она РАБОТАЕТ.
Финал

Полный маршрут: 10 порядков величины

Розетка → дежурка → кнопка → PS_ON# → soft-start → VRM → клоки → PSP → reset vector → CAR → memory training → DXE → bootmgfw → ntoskrnl → smss → winlogon → explorer → твой двойной клик → CreateProcess → µops → кэш-линии → row buffer → пиксель на экране. От 50 герц розетки до 5 гигагерц ядра — десять порядков частоты, и ни одного слоя, который можно выкинуть.

А выключение — тот же путь обратно, вплоть до одной инструкции out, отпускающей зелёный провод.