pi_desc
DECLARE_PER_CPU_ALIGNED(struct pi_desc, posted_msi_pi_desc);
return test_and_clear_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control);
static inline bool pi_test_and_clear_sn(struct pi_desc *pi_desc)
return test_and_clear_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control);
static inline bool pi_test_and_set_pir(int vector, struct pi_desc *pi_desc)
return test_and_set_bit(vector, pi_desc->pir);
static inline bool pi_is_pir_empty(struct pi_desc *pi_desc)
return bitmap_empty(pi_desc->pir, NR_VECTORS);
static inline void pi_set_sn(struct pi_desc *pi_desc)
set_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control);
static inline void pi_set_on(struct pi_desc *pi_desc)
set_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control);
static inline void pi_clear_on(struct pi_desc *pi_desc)
clear_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control);
static inline void pi_clear_sn(struct pi_desc *pi_desc)
clear_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control);
static inline bool pi_test_on(struct pi_desc *pi_desc)
return test_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control);
static inline bool pi_test_sn(struct pi_desc *pi_desc)
return test_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control);
static inline bool pi_test_pir(int vector, struct pi_desc *pi_desc)
return test_bit(vector, (unsigned long *)pi_desc->pir);
static inline void __pi_set_sn(struct pi_desc *pi_desc)
pi_desc->notifications |= BIT(POSTED_INTR_SN);
static inline void __pi_clear_sn(struct pi_desc *pi_desc)
pi_desc->notifications &= ~BIT(POSTED_INTR_SN);
struct pi_desc *pid = this_cpu_ptr(&posted_msi_pi_desc);
static inline bool pi_test_and_set_on(struct pi_desc *pi_desc)
return test_and_set_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control);
static inline bool pi_test_and_clear_on(struct pi_desc *pi_desc)
DEFINE_PER_CPU_ALIGNED(struct pi_desc, posted_msi_pi_desc);
struct pi_desc *pid = this_cpu_ptr(&posted_msi_pi_desc);
struct pi_desc *pi_desc, int vector)
if (pi_test_and_set_pir(vector, pi_desc))
if (pi_test_and_set_on(pi_desc))
struct pi_desc pi_desc;
vmx->nested.pi_desc = NULL;
vmx->nested.pi_desc =
(struct pi_desc *)(((void *)map->hva) +
vmx->nested.pi_desc = NULL;
if (!vmx->nested.pi_desc)
if (!pi_test_and_clear_on(vmx->nested.pi_desc))
max_irr = pi_find_highest_vector(vmx->nested.pi_desc);
__kvm_apic_update_irr(vmx->nested.pi_desc->pir,
if (vmx->nested.pi_pending && vmx->nested.pi_desc &&
pi_test_on(vmx->nested.pi_desc)) {
max_irr = pi_find_highest_vector(vmx->nested.pi_desc);
old.control = READ_ONCE(pi_desc->control);
} while (pi_try_set_control(pi_desc, &old.control, new.control));
if (!pi_is_pir_empty(pi_desc))
pi_set_on(pi_desc);
struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
struct pi_desc old, new;
WARN(pi_test_sn(pi_desc), "PI descriptor SN field set before blocking");
old.control = READ_ONCE(pi_desc->control);
} while (pi_try_set_control(pi_desc, &old.control, new.control));
struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
pi_set_sn(pi_desc);
if (pi_test_on(&vt->pi_desc))
struct pi_desc *pi = vcpu_to_pi_desc(vcpu);
struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
return pi_test_on(pi_desc) ||
(pi_test_sn(pi_desc) && !pi_is_pir_empty(pi_desc));
static struct pi_desc *vcpu_to_pi_desc(struct kvm_vcpu *vcpu)
return &(to_vt(vcpu)->pi_desc);
static int pi_try_set_control(struct pi_desc *pi_desc, u64 *pold, u64 new)
if (!try_cmpxchg64(&pi_desc->control, pold, new))
struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
struct pi_desc old, new;
if (pi_desc->nv != POSTED_INTR_WAKEUP_VECTOR && vcpu->cpu == cpu) {
if (pi_test_and_clear_sn(pi_desc))
if (pi_desc->nv == POSTED_INTR_WAKEUP_VECTOR) {
static inline int pi_find_highest_vector(struct pi_desc *pi_desc)
vec = find_last_bit(pi_desc->pir, 256);
if (pi_test_on(&vt->pi_desc)) {
APIC_VECTOR_MASK, &vt->pi_desc))
__vmx_deliver_posted_interrupt(vcpu, &tdx->vt.pi_desc, vector);
td_vmcs_write64(tdx, POSTED_INTR_DESC_ADDR, __pa(&tdx->vt.pi_desc));
tdx->vt.pi_desc.nv = POSTED_INTR_VECTOR;
__pi_set_sn(&tdx->vt.pi_desc);
__vmx_deliver_posted_interrupt(vcpu, &vt->pi_desc, vector);
vmcs_write64(POSTED_INTR_DESC_ADDR, __pa((&vmx->vt.pi_desc)));
vmx->vt.pi_desc.nv = POSTED_INTR_VECTOR;
__pi_set_sn(&vmx->vt.pi_desc);
if (pi_test_on(&vt->pi_desc)) {
pi_clear_on(&vt->pi_desc);
kvm_apic_update_irr(vcpu, vt->pi_desc.pir, &max_irr);
__pa(&vmx->vt.pi_desc) | PID_TABLE_ENTRY_VALID);
struct pi_desc *pi_desc;