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

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

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

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

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

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

  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.


person Jack Humphries    schedule 23.12.2017    source источник
comment
Вы инициализируете виртуальную страницу APIC значениями виртуальных регистров APIC?   -  person prl    schedule 23.12.2017
comment
@prl Тьфу нет, я не знал, что мне нужно это сделать. Извините — разделение труда между VMM и CPU мне непонятно, поэтому я не знал, что мне нужно написать это в себе. Позвольте мне заставить это работать, и я доложу. Большое спасибо кстати :)   -  person Jack Humphries    schedule 23.12.2017
comment
И каждый раз, когда состояние виртуального APIC (в вашем VMM) изменяется, необходимо обновить соответствующие регистры на странице виртуального APIC.   -  person prl    schedule 23.12.2017
comment
@prl Отлично! Это сработало отлично. Теперь все работает. Не стесняйтесь написать ответ, чтобы я мог дать вам баллы, или я напишу его сам, если вы предпочитаете.   -  person Jack Humphries    schedule 24.12.2017
comment
@prl Еще один (надеюсь, быстрый) вопрос: сейчас я пытаюсь записать 64 бита в ICR, используя wrmsr с адресом 0x830. Я настроил страницу виртуального APIC в VMCS, но не страницу доступа к APIC, так как использую x2APIC. Поскольку я отправляю IPI на другое ядро, я ожидаю, что мне нужно будет эмулировать эту запись самостоятельно в VMM. К сожалению, когда я выполняю wrmsr, я получаю ошибку GP, хотя я ожидаю завершения записи APIC. Любые идеи по этому поводу? Я настроил растровое изображение MSR, чтобы оно не вызывало перехват на 0x830.   -  person Jack Humphries    schedule 24.12.2017
comment
Я думаю, что GP, потому что вы устанавливаете зарезервированный бит в ICR.   -  person prl    schedule 24.12.2017
comment
Я не думаю, что вы можете получить выход APIC-записи для доступа к MSR 830 в режиме x2apic. Специальная обработка применяется только к 808, 80b и 83f. Для 830, если соответствующий бит в битовой карте MSR равен 0, он обращается к фактическому регистру APIC, позволяя гостевому программному обеспечению напрямую выдавать IPI. Вероятно, это не то, что вам нужно, поэтому вам нужно установить бит в растровом изображении MSR на 1, чтобы получить выход из виртуальной машины.   -  person prl    schedule 24.12.2017
comment
Обратите внимание, я на самом деле не реализовал это сам. Мои комментарии основаны на информации в разделе 29.5.   -  person prl    schedule 24.12.2017
comment
@prl Я просмотрел источник KVM, и вы, похоже, правы. Они перехватывают все обращения MSR к регистрам x2APIC и затем обрабатывают их в KVM.   -  person Jack Humphries    schedule 30.12.2017


Ответы (1)


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

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

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

person Jack Humphries    schedule 24.12.2017
comment
Я прочитал документ, это хорошее резюме. Ссылка на вашу реализацию это дюна или что-то еще? - person wangt13; 26.08.2019
comment
@ закат.8 Ссылка не работает. Пожалуйста, исправьте это. - person Vladimir Pustovalov; 08.12.2020
comment
@VladimirPustovalov Я исправил. - person Jack Humphries; 09.12.2020