Архитектура x86-64 довольно сложна; он не только имеет 64-битный режим и 32-битный режим, он имеет два основных режима (длительный и устаревший), каждый из которых имеет несколько подрежимов (см. статья Википедии ).
В устаревшем режиме ЦПУ по сути эмулирует 32-разрядный ЦП. Он имеет различные подрежимы (реальный, защищенный и т. Д.), Но не может переключаться, используя 64-битные инструкции или адресацию. Как правило, в этом режиме будет работать ОС, не поддерживающая 64-разрядную версию.
В длинном режиме процессор имеет 64-битные возможности, но также может работать в 32- и 16-битных режимах «совместимости». Переключение режимов контролируется флагами L и D в дескрипторе сегмента кода (см. «Расширение x86 для 64-битного мира» в , этот PDF ) - по сути, различные разделы памяти могут быть помечены как содержащий 64-, 32- или 16-битный код, и процессор переключается в соответствующий режим для сегмента кода, который в данный момент выполняется. Сегменты кода ядра могут быть помечены как 64- или 32-битные независимо от сегментов кода для запуска приложений.
Так что в принципе все просто. На практике, я уверен, что есть множество сложностей, о которых я не знаю (я действительно не очень много знаю о процессе переключения контекста), но пока ОС «знает», что она работает на 64-битной Процессор и настраивает дескрипторы сегментов кода соответствующим образом, нет принципиальной проблемы с запуском 64-битных процессов под 32-битным ядром.
Кстати, OS X также могла запускать 64-битные процессы под 32-битным ядром на процессорах PowerPC G5, начиная с версии 10.3. Процессоры PPC имеют совершенно другую архитектуру, и я понятия не имею, как там работает переключение режимов.