Поскольку процессор x86-64 может напрямую запускать код x86-32, а запись в eax
обнуляет старшие биты rax
, поэтому номер системного вызова будет правильным. Какую еще работу должно выполнять ядро для запуска программы x86-32?
Что делает ядро Linux x86-64, когда ему нужно запустить программу x86-32?
- Он переводит ЦП в режим совместимости, очищая бит
L
в дескрипторе сегмента в GDT и используяiret
для установкиcs:rip
в 32-битный сегмент кода при переходе в пользовательское пространство. Конечно, для некоторых системных вызовов, таких какmmap
, нужны специальные параметры, чтобы убедиться, что выделенная память находится в пределах младших 32 бит виртуального адресного пространства, и различия ABI для структур... 19.03.2018
Ответы:
Какую еще работу должно выполнять ядро для запуска программы x86-32?
Все 64-битные параметры должны быть разделены (например, переданы в edx:eax
вместо только rax
). Механизм, используемый для вызова API ядра, совершенно другой (int 0x80
против syscall
). Схема стека (которая имеет значение для таких вещей, как отправка сигналов обратно обработчикам сигналов в пользовательском пространстве) отличается. Управление виртуальной памятью должно учитывать, что пользовательское пространство не может использовать 64-битные указатели. Для TLS используются разные сегментные регистры (gs
для 32-разрядных, fs
для 64-разрядных).
В основном это настолько отличается, что вы получаете полностью отдельный код входа/выхода системного вызова и диспетчеризации (где оба интерфейса вызывают одни и те же внутренние функции после обработки параметров и соглашений о вызовах).
ia32_sys_call_table[]
являются собственными 64-битными функциями системных вызовов, которые также находятся в собственной таблице диспетчеризации системных вызовов, но многие из них являются функциями-оболочками, которые обрабатывают такие вещи, какsys_llseek(2)
принимает отдельные аргументыunsigned long offset_high
иunsigned long offset_low
или учитывает различия в макете структуры. (На самом делеsys_llseek
существует только для 32-битных; для 64-битныхlseek
одного аргумента достаточно.). 19.03.2018int 0x80
ABI; оно всегда возвращается в пользовательское пространство черезiret
, восстанавливая 32-битный или 64-битный сегмент кода, из которого выполнялось пользовательское пространство). 19.03.2018