Как отправлять внешние прерывания гостю, когда включено следующее: Используйте тень TPR Виртуализируйте доступ к APIC Виртуализация регистра APIC Доставка с виртуальным прерыванием Подтверждение внешних прерываний Выход из внешних прерываний Процесс отправленного прерывания
Я пробовал состояние прерывания гостя vmcs 0x810, но не смог заставить его работать правильно. Моя цель - перенаправить внешние прерывания на гостя.
Закрытое голосование неверно, это абсолютно вопрос разработки программного обеспечения.
Спасибо за ответ, я спрашиваю, как вводить прерывания, пытался установить VIRR и max (RVI, вектор), но не сработало. Нужно ли очищать SVI каждый раз, когда я устанавливаю RVI? а как же ЭО?
@prl Я пробовал все, что мог придумать, но ничто не решило мою проблему, но я заметил, что SVI никогда не очищался, например: 1- 1st vmexit externalInterrupt vector 0x6C: Установите бит vIRR и RVI на max (RVI, Vector) RVI = 0x0 SVI =0x0 => RVI=0x6C SVI=0x0 2- 2-й vmexit externalInterrupt vector 0x6C: Установите бит vIRR и RVI на max(RVI,Vector) RVI=0x0 SVI=0x6C => RVI=0x6C SVI=0x6C В этот момент нет другого vmexit externalInterrupt, и устройства, использующие прерывания, такие как клавиатура, перестали работать. Означает ли это, что что-то не так, или мне просто нужно очистить SVI от всего, что я установил RVI?
Похоже на отсутствующий EOI.
@prl спасибо, в ожидании вас я проведу еще тесты и буду обновлять этот пост.
@prl Да, проблема с EOI, установка векторного растрового изображения EOI и отправка EOI в EOIexitHandler решили проблему, можно ли исправить ее без выхода из EOI? Я пытался установить TMR на уровень, и это не сработало.
Это всегда EOI...
@prl Да, я читал SDM, решение проблемы заключалось в том, чтобы использовать EOI vmexits для отправки EOI на хост apic, чтобы продолжать получать прерывания, что я могу сделать, чтобы не отправлять EOI в root, чтобы продолжать получать прерывания?
Да, извините, я неправильно понял то, что вы написали ранее. По какой-то причине с отключенным выходом EOI EOI не выходит правильно, но когда вы берете выход EOI и отправляете EOI в обработчике, он работает. Итак, мы должны выяснить, чем они отличаются друг от друга. Что делает ваш код, чего не делает виртуализация EOI...
Является ли это прерыванием MSI или происходит через IOAPIC? Я предполагаю, что 6c - это устаревший таймер (PIT)? Можете ли вы проверить, запрограммирован ли он как уровень или край в IOAPIC?
Я подумал о vTMR и попытался установить его на уровень, но это не помогло, но если выходы EOI не требуются, должно быть что-то отсутствует здесь, включая или исключая vTMR. Должен быть IOAPIC, потому что MSI не включен в это время, и это устаревший таймер.
Вот мое предположение: вероятно, виртуальный EOI в порядке; возможно, вы не выполняете физический EOI перед вводом прерывания, поэтому бит ISR в физическом APIC все еще установлен?
@prl Да, вы правы, отправка EOI во внешнем обработчике прерывания vmexit решила эту проблему, пробовал раньше и не делал, потому что я тестировал это с MP, теперь с SP все выглядит нормально, остается только проблема, когда есть MP, идентифицируя эту проблему и похоже, что это связано с выходами доступа/записи, можно ли продолжать спрашивать здесь, если не удается решить эту проблему? еще раз спасибо за ваше время и усилия.
Убедитесь, что у вас есть отдельная физическая страница памяти для виртуальной страницы APIC для каждого аппаратного потока. (Адрес страницы доступа к APIC может быть одинаковым для всех из них.)
@prl, когда я использую ept для отображения apicBase на страницу apicAccess и устанавливаю vmcs apicAccess на страницу apicAccess, даже SP перестает работать, но если я устанавливаю vmcs apicAccess на apicBase FEE00000 SP работает, а MP нет, для WriteExits я копирую написанное из Vapic в apic, а для AccessExits -LRead: использовать значение из apic для эмуляции instr. -LWrite: использовать PrevValue из Vapic, эмулировать instr и записывать результат как в Vapic, так и в apic. Можно ли продолжать использовать apicBase как vmcs apicAccess? и правильная ли обработка доступа/записи?
@prl Я решил это, проблема заключалась в чтении из vApic при эмуляции доступа, мне пришлось читать из apic.
Я никогда не устанавливал для адреса доступа APIC значение FEE00000, но не знаю, почему. Я полагаю, если это сработает, вы не увидите никакой разницы в поведении. Поскольку вы видите разницу в поведении, возможно, это нехорошо.
Вы можете не захотеть распространять записи из виртуального APIC в физический APIC, потому что они могут находиться в разных состояниях. Очевидно, что это верно, если у вас более одного гостя, потому что у каждого гостя есть свое состояние APIC. Но даже если у вас есть только один гость, по-прежнему проблематично требовать, чтобы виртуальный и физический серверы оставались синхронизированными.
@prl Я согласен, но пока у меня только один гость, и я хотел сделать это максимально простым способом и с меньшим количеством кода, а позже улучшу его, не путаясь в сложном коде, в котором я не уверен в большей части.
@prl после возобновления работы над моим гипервизором я заметил, что случайно отключил виртуализацию APIC, поэтому то, что я сказал об исправлении, совершенно неверно, вы не можете перенаправить гостевые записи на хост APIC, вместо этого мне пришлось эмулировать каждую запись, особенно запись ICR, в основном должен эмулировать INIT SIPI и использовать отправленные прерывания для фиксации без записи в хост APIC, за исключением NMI и вектора уведомления о отправленных прерываниях.
Чтобы внедрить прерывание в гостевую систему, когда включена доставка виртуального прерывания, выполните шаги, аналогичные тем, которые выполняет ЦП при обработке отправленного прерывания, как описано в томе 3 SDM, раздел 30.6, «Обработка отправленного прерывания», шаги 4, 5. , и 6.
Шаги:
Оценка ожидающих виртуальных прерываний будет выполняться ЦП при входе в ВМ.
См. также том 3 SDM, раздел 30.2, «Оценка и доставка виртуальных прерываний».
Вы спрашиваете, как VMM может вводить прерывания или как внешнее прерывание может быть отправлено гостю без выхода из виртуальной машины? В первом случае вы устанавливаете бит VIRR для вектора на странице виртуального APIC и устанавливаете для RVI значение max(RVI, вектор). В последнем случае вы настраиваете IOMMU для отправки прерываний.