Skip to content

Commit

Permalink
MSI stay pending when masked and are released when unmasked
Browse files Browse the repository at this point in the history
  • Loading branch information
ved-rivos committed Dec 25, 2024
1 parent a509008 commit 67c4ecf
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 8 deletions.
1 change: 1 addition & 0 deletions iommu_ref_model/libiommu/include/iommu_interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
#define MSI_VEC_CTRL_MASK_BIT 1

extern void generate_interrupt(uint8_t unit);
extern void release_pending_interrupt(uint8_t vec);
#endif // __IOMMU_INTERRUPT_H__
43 changes: 35 additions & 8 deletions iommu_ref_model/libiommu/src/iommu_interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,29 @@
// Author: [email protected]

#include "iommu.h"
// MSI pending bit array.
uint8_t msi_pending[16] = {0};
static void
do_msi(
uint32_t msi_data, uint64_t msi_addr) {
uint8_t status;
status = write_memory((char *)&msi_data, msi_addr, 4);
if ( status & ACCESS_FAULT ) {
// If an access fault is detected on a MSI write using msi_addr_x,
// then the IOMMU reports a "IOMMU MSI write access fault" (cause 273) fault,
// with TTYP set to 0 and iotval set to the value of msi_addr_x.
report_fault(273, msi_addr, 0, TTYPE_NONE, 0, 0, 0, 0, 0);
}
return;
}
void
generate_interrupt(
uint8_t unit) {

msi_addr_t msi_addr;
uint32_t msi_data;
msi_vec_ctrl_t msi_vec_ctrl;
uint8_t vec, status;
uint8_t vec;

// Interrupt pending status register (ipsr)
// This 32-bits register (RW1C) reports the pending interrupts
Expand Down Expand Up @@ -74,15 +89,27 @@ generate_interrupt(
// When the mask bit M is 1, the corresponding interrupt vector is
// masked and the IOMMU is prohibited from sending the associated
// message.
if ( msi_vec_ctrl.m == 1 )
if ( msi_vec_ctrl.m == 1 ) {
// Pending messages for that vector are later generated if the
// corresponding mask bit is cleared to 0.
msi_pending[vec] = 1;
return;
status = write_memory((char *)&msi_data, msi_addr.raw, 4);
if ( status & ACCESS_FAULT ) {
// If an access fault is detected on a MSI write using msi_addr_x,
// then the IOMMU reports a "IOMMU MSI write access fault" (cause 273) fault,
// with TTYP set to 0 and iotval set to the value of msi_addr_x.
report_fault(273, msi_addr.raw, 0, TTYPE_NONE, 0, 0, 0, 0, 0);
}
do_msi(msi_data, msi_addr.raw);
}
return;
}
void
release_pending_interrupt(
uint8_t vec) {
msi_addr_t msi_addr;
uint32_t msi_data;

if ( msi_pending[vec] == 1 ) {
msi_addr.raw = g_reg_file.msi_cfg_tbl[vec].msi_addr.raw;
msi_data = g_reg_file.msi_cfg_tbl[vec].msi_data;
do_msi(msi_data, msi_addr.raw);
msi_pending[vec] = 0;
}
return;
}
4 changes: 4 additions & 0 deletions iommu_ref_model/libiommu/src/iommu_reg.c
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,10 @@ write_register(
x = (offset - MSI_ADDR_0_OFFSET) / 16;
if ( x >= (1UL << g_num_vec_bits) )
break;
if ( msi_vec_ctrl_temp.m == 1 &&
g_reg_file.msi_cfg_tbl[x].msi_vec_ctrl.m == 0 ) {
release_pending_interrupt(x);
}
g_reg_file.msi_cfg_tbl[x].msi_vec_ctrl.m = msi_vec_ctrl_temp.m;
break;
}
Expand Down

0 comments on commit 67c4ecf

Please sign in to comment.