Понимание страницы виртуального APIC для x2APIC

Я пишу VMM и пытаюсь поддерживать виртуальный доступ к регистрам x2APIC с помощью гостевой ОС, работающей в режиме без полномочий root.

Я хочу начать с простых действий, таких как чтение локального идентификатора APIC из гостевой ОС. Я попытался добавить поддержку для этого в моем VMM, но значение, которое я прочитал, кажется неправильным.

К сожалению, я не могу найти много информации в Интернете о виртуальной странице APIC. Я прочитал главу 29 руководства Intel (Виртуализация APIC и виртуальные прерывания), и вот что я делаю:

  1. В элементах управления виртуальными процессорами на основе вторичного процессора я установил следующие биты в 1: (я устанавливаю бит 9 ниже, так как в конечном итоге хочу поддерживать опубликованные IPI)

    1. SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE (бит 4)
    2. SECONDARY_EXEC_APIC_REGISTER_VIRT (бит 8)
    3. SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY (бит 9)
  2. В растровом изображении MSR я отключаю перехваты для 0x802, который является локальным регистром APIC ID.

  3. В моей гостевой ОС я использую rdmsr читать 0x802,

Я выполняю шаг 3 на двух потоках, которые закреплены на разных ядрах. Они оба читают значение 2621447225 из реестра. Это кажется неправильным, поскольку потоки закреплены на разных ядрах и поэтому должны считывать разные локальные идентификаторы APIC (и число 2621447225 действительно большой). Что я делаю неправильно?

Вот некоторая дополнительная информация для вашей справки:

В разделе 29.5 (Виртуализация доступа APIC на основе MSR) руководства Intel говорится:

If “APIC-register virtualization” is 1 and ECX contains a value in the range 800H–8FFH, the instruction reads the 8 bytes from offset X on the virtual-APIC page into EDX:EAX, where X = (ECX & FFH) « 4. This occurs even if the local APIC is not in x2APIC mode (no general-protection fault occurs because the local APIC is not in x2APIC mode).

X Смещение имеет смысл для меня: адрес MSR 0x802 будет 0x2 когда и с 0xFF, а также 0x2 станет 0x20 когда смещено влево 4 бита. 0x20 это смещение на странице физического APIC, если вы обращались к xAPIC через его регистры с отображением в памяти. Затем считываются 8 байтов (т.е. 64 бита), поэтому младшие 32 бита являются локальным идентификатором APIC для x2APIC.

1 ответ

Решение

Я смог понять это с помощью @prl. Мне пришлось самостоятельно выделить страницу виртуального APIC для каждого ядра, а затем инициализировать каждую страницу по отдельности с помощью локального идентификатора APIC соответствующего ядра.

Затем я добавил физический адрес страницы в VMCS (в ядре Linux определена константа, называемая VIRTUAL_APIC_PAGE_ADDR который содержит смещение в VMCS). Я не осознавал, что должен был инициализировать страницу, поскольку это не было сделано автоматически.

Редактировать: я внедрил работающую систему виртуализации в Linux с поддержкой виртуализации x2APIC и опубликовал обработку прерываний, и написал об этих двух темах в этом документе. Документ должен быть довольно простым, и он содержит ссылку на мою реализацию.

Другие вопросы по тегам