Skip to content

Commit

Permalink
complete UINTR coding / VMX support for UINTR
Browse files Browse the repository at this point in the history
  • Loading branch information
Stanislav Shwartsman committed Nov 21, 2023
1 parent f99ba26 commit 1356a02
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 6 deletions.
4 changes: 4 additions & 0 deletions bochs/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,10 @@ typedef Bit32u bx_phy_address;
#define BX_SUPPORT_AVX 0
#define BX_SUPPORT_EVEX 0

#if BX_SUPPORT_UINTR && BX_SUPPORT_X86_64 == 0
#error "UINTR require x86-64 support"
#endif

#if BX_SUPPORT_SVM && BX_SUPPORT_X86_64 == 0
#error "SVM require x86-64 support"
#endif
Expand Down
1 change: 1 addition & 0 deletions bochs/cpu/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -4451,6 +4451,7 @@ class BOCHSAPI BX_CPU_C : public logfunctions {
BX_SMF void handleAvxModeChange(void);
#endif
#if BX_SUPPORT_UINTR && BX_SUPPORT_X86_64
BX_SMF void send_uipi(Bit32u notification_destination, Bit32u notification_vector);
BX_SMF void uintr_uirr_update();
BX_SMF void uintr_control();
BX_SMF bool uintr_masked();
Expand Down
45 changes: 41 additions & 4 deletions bochs/cpu/uintr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,52 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SENDUIPI_Gq(bxInstruction_c *i)
// should be done atomically using RMW

if (send_notify) {
// if in X2APIC mode:
// send IPI [vector=notification_vector] to 32-bit APIC_ID=[notification_destination]
// else:
// send IPI [vector=notification_vector] to 8-bit APIC_ID=[notification_destination >> 8]
send_uipi(notification_destination, notification_vector);
}

BX_NEXT_TRACE(i);
}

#include "apic.h"

void BX_CPU_C::send_uipi(Bit32u notification_destination, Bit32u notification_vector)
{
#if BX_SUPPORT_VMX
VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs;
if (vm->vmexec_ctrls2 & VMX_VM_EXEC_CTRL2_TPR_SHADOW) {
if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES)) {
// virtualize sending of an XAPIC-mode IPI by:
// - writing to VICR_HI[31:24] = 8 bit destination APIC_ID from NDST[15:8]
// VICR_HI[23:00] = 0
VMX_Write_Virtual_APIC(BX_LAPIC_ICR_HI, (notification_destination & 0xff00) << 16);

// - writing to VICR_LO[31:08] = 0 (indicating a physically addressed fixed-mode IPI)
// VICR_HI[07:00] = notification_vector
VMX_Write_Virtual_APIC(BX_LAPIC_ICR_LO, notification_vector);
}
else {
// virtualize sending of an X2APIC-mode IPI by:
// - writing 64-bit value into VICR
// VICR[7:0] = notification_vector
// VICR[31:8] = 0 (indicating a physically addressed fixed-mode IPI)
// VICR[64:32] = 32-bit notification destination
VMX_Write_Virtual_X2APIC(BX_LAPIC_ICR_LO, GET64_FROM_HI32_LO32(notification_destination, notification_vector));
}

VMexit(VMX_VMEXIT_APIC_WRITE, BX_LAPIC_ICR_LO); // trap-like vmexit
return;
}
#endif

// sending of IPI is done by writing to the local APIC's ICR register:
// ICR[7:0] = notification_vector
// ICR[64:32] = the APIC_ID from NDST[15:8] (legacy apic mode) or NDST[31:0] (x2apic mode)
// ICR[31:8] = 0 (indicating a physically addressed fixed-mode IPI)
#if BX_SUPPORT_APIC
BX_CPU_THIS_PTR lapic.send_ipi(x2apic_mode() ? notification_destination : (notification_destination >> 8), notification_vector);
#endif
}

void BX_CPU_C::process_uintr_notification()
{
#if BX_SUPPORT_VMX
Expand Down
9 changes: 7 additions & 2 deletions bochs/cpu/vmx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,7 @@ VMX_error_code BX_CPU_C::VMenterLoadCheckVmControls(void)
unsigned push_error = (vm->vmentry_interr_info >> 11) & 1;
unsigned error_code = push_error ? vm->vmentry_excep_err_code : 0;

unsigned push_error_reference = 0;
unsigned push_error_reference = false;
if (event_type == BX_HARDWARE_EXCEPTION && vector < BX_CPU_HANDLED_EXCEPTIONS)
push_error_reference = exceptions_info[vector].push_error;

Expand Down Expand Up @@ -2277,7 +2277,12 @@ void BX_CPU_C::VMenterInjectEvents(void)
vm->idt_vector_info = vm->vmentry_interr_info & ~0x80000000;
vm->idt_vector_error_code = error_code;

interrupt(vector, type, push_error, error_code);
#if BX_SUPPORT_UINTR
if (BX_CPU_THIS_PTR cr4.get_UINTR() && long64_mode() && vector == BX_CPU_THIS_PTR uintr.uinv)
process_uintr_notification();
else
#endif
interrupt(vector, type, push_error, error_code);

BX_CPU_THIS_PTR last_exception_type = 0; // error resolved
}
Expand Down

0 comments on commit 1356a02

Please sign in to comment.