diff --git a/iommu_ref_model/libiommu/include/iommu_ref_api.h b/iommu_ref_model/libiommu/include/iommu_ref_api.h index d876857..62f4d2e 100644 --- a/iommu_ref_model/libiommu/include/iommu_ref_api.h +++ b/iommu_ref_model/libiommu/include/iommu_ref_api.h @@ -19,7 +19,8 @@ extern int reset_iommu(uint8_t num_hpm, uint8_t hpmctr_bits, uint16_t eventID_ma uint8_t max_iommu_mode, uint32_t max_devid_mask, uint8_t gxl_writeable, uint8_t fctl_be_writeable, uint8_t fill_ats_trans_in_ioatc, capabilities_t capabilities, - fctl_t fctl); + fctl_t fctl, uint64_t sv57_bare_pg_sz, uint64_t sv48_bare_pg_sz, + uint64_t sv39_bare_pg_sz, uint64_t sv32_bare_pg_sz); extern void iommu_translate_iova(hb_to_iommu_req_t *req, iommu_to_hb_rsp_t *rsp_msg); extern void handle_page_request(ats_msg_t *pr); extern uint8_t handle_invalidation_completion(ats_msg_t *inv_cc); diff --git a/iommu_ref_model/libiommu/include/iommu_registers.h b/iommu_ref_model/libiommu/include/iommu_registers.h index 3848fd1..45739ce 100644 --- a/iommu_ref_model/libiommu/include/iommu_registers.h +++ b/iommu_ref_model/libiommu/include/iommu_registers.h @@ -791,6 +791,10 @@ extern uint8_t g_max_iommu_mode; extern uint8_t g_fill_ats_trans_in_ioatc; extern uint32_t g_max_devid_mask; extern uint8_t g_trans_for_debug; +extern uint64_t g_sv57_bare_pg_sz; +extern uint64_t g_sv48_bare_pg_sz; +extern uint64_t g_sv39_bare_pg_sz; +extern uint64_t g_sv32_bare_pg_sz; extern void process_commands(void); #endif //_IOMMU_REGS_H_ diff --git a/iommu_ref_model/libiommu/src/iommu_reg.c b/iommu_ref_model/libiommu/src/iommu_reg.c index 45b1273..adf4448 100644 --- a/iommu_ref_model/libiommu/src/iommu_reg.c +++ b/iommu_ref_model/libiommu/src/iommu_reg.c @@ -21,6 +21,10 @@ uint8_t g_fill_ats_trans_in_ioatc; uint32_t g_max_devid_mask; extern uint8_t g_iofence_wait_pending_inv; uint8_t g_trans_for_debug; +uint64_t g_sv57_bare_pg_sz; +uint64_t g_sv48_bare_pg_sz; +uint64_t g_sv39_bare_pg_sz; +uint64_t g_sv32_bare_pg_sz; uint8_t is_access_valid( @@ -849,7 +853,8 @@ reset_iommu(uint8_t num_hpm, uint8_t hpmctr_bits, uint16_t eventID_limit, uint8_t max_iommu_mode, uint32_t max_devid_mask, uint8_t gxl_writeable, uint8_t fctl_be_writeable, uint8_t fill_ats_trans_in_ioatc, capabilities_t capabilities, - fctl_t fctl) { + fctl_t fctl, uint64_t sv57_bare_pg_sz, uint64_t sv48_bare_pg_sz, + uint64_t sv39_bare_pg_sz, uint64_t sv32_bare_pg_sz) { int i; #ifdef DEBUG // Only PA upto 56 bits supported in RISC-V @@ -977,5 +982,9 @@ reset_iommu(uint8_t num_hpm, uint8_t hpmctr_bits, uint16_t eventID_limit, g_offset_to_size[i + MSI_DATA_0_OFFSET] = 4; g_offset_to_size[i + MSI_VEC_CTRL_0_OFFSET] = 4; } + g_sv57_bare_pg_sz = sv57_bare_pg_sz; + g_sv48_bare_pg_sz = sv48_bare_pg_sz; + g_sv39_bare_pg_sz = sv39_bare_pg_sz; + g_sv32_bare_pg_sz = sv32_bare_pg_sz; return 0; } diff --git a/iommu_ref_model/libiommu/src/iommu_second_stage_trans.c b/iommu_ref_model/libiommu/src/iommu_second_stage_trans.c index 4d30c41..77a6985 100644 --- a/iommu_ref_model/libiommu/src/iommu_second_stage_trans.c +++ b/iommu_ref_model/libiommu/src/iommu_second_stage_trans.c @@ -31,15 +31,19 @@ second_stage_address_translation( gpte->X = gpte->W = gpte->R = gpte->V = 1; gpte->N = 0; gpte->PBMT = PMA; - // Indicate G-stage page size as largest possible page size + // The translation range size returned in a Success response to + // an ATS translation request, when either stages of address + // translation are Bare, is implementation-defined. However, it + // is recommended that the translation range size be large, such + // as 2 MiB or 1 GiB. if ( g_reg_file.capabilities.Sv57x4 == 1 ) - *gst_page_sz = 512UL * 512UL * 512UL * 512UL * PAGESIZE; + *gst_page_sz = g_sv57_bare_pg_sz; else if ( g_reg_file.capabilities.Sv48x4 == 1 ) - *gst_page_sz = 512UL * 512UL * 512UL * PAGESIZE; + *gst_page_sz = g_sv48_bare_pg_sz; else if ( g_reg_file.capabilities.Sv39x4 == 1 && g_reg_file.fctl.gxl == 0) - *gst_page_sz = 512UL * 512UL * PAGESIZE; + *gst_page_sz = g_sv39_bare_pg_sz; else if ( g_reg_file.capabilities.Sv32x4 == 1 && g_reg_file.fctl.gxl == 1) - *gst_page_sz = 2UL * 512UL * PAGESIZE; + *gst_page_sz = g_sv32_bare_pg_sz; goto step_8; } diff --git a/iommu_ref_model/libiommu/src/iommu_two_stage_trans.c b/iommu_ref_model/libiommu/src/iommu_two_stage_trans.c index 8740e7f..4f7eb5e 100644 --- a/iommu_ref_model/libiommu/src/iommu_two_stage_trans.c +++ b/iommu_ref_model/libiommu/src/iommu_two_stage_trans.c @@ -27,16 +27,6 @@ two_stage_address_translation( uint64_t gst_page_sz; uint64_t pa_mask = ((1UL << (g_reg_file.capabilities.pas)) - 1); - // Indicate S/VS-stage page size as largest possible page size - if ( g_reg_file.capabilities.Sv57 == 1 ) - *page_sz = 512UL * 512UL * 512UL * 512UL * PAGESIZE; - else if ( g_reg_file.capabilities.Sv48 == 1 ) - *page_sz = 512UL * 512UL * 512UL * PAGESIZE; - else if ( g_reg_file.capabilities.Sv39 == 1 && SXL == 0) - *page_sz = 512UL * 512UL * PAGESIZE; - else if ( g_reg_file.capabilities.Sv32 == 1 && SXL == 1) - *page_sz = 2UL * 512UL * PAGESIZE; - *iotval2 = 0; // Walk page tables @@ -50,6 +40,19 @@ two_stage_address_translation( pte->N = 0; pte->PBMT = PMA; *pa = iova; + // The translation range size returned in a Success response to + // an ATS translation request, when either stages of address + // translation are Bare, is implementation-defined. However, it + // is recommended that the translation range size be large, such + // as 2 MiB or 1 GiB. + if ( g_reg_file.capabilities.Sv57 == 1 ) + *page_sz = g_sv57_bare_pg_sz; + else if ( g_reg_file.capabilities.Sv48 == 1 ) + *page_sz = g_sv48_bare_pg_sz; + else if ( g_reg_file.capabilities.Sv39 == 1 && SXL == 0) + *page_sz = g_sv39_bare_pg_sz; + else if ( g_reg_file.capabilities.Sv32 == 1 && SXL == 1) + *page_sz = g_sv32_bare_pg_sz; return 0; } diff --git a/iommu_ref_model/test/test_app.c b/iommu_ref_model/test/test_app.c index a97d0a4..825fdd7 100644 --- a/iommu_ref_model/test/test_app.c +++ b/iommu_ref_model/test/test_app.c @@ -28,6 +28,8 @@ main(void) { uint32_t i, j, test_num = 0; uint64_t DC_addr, exp_iotval2, iofence_PPN, iofence_data, spa, gpa; uint64_t gva, gpte_addr, pte_addr, PC_addr, temp; + uint64_t sv57_bare_sz, sv48_bare_sz, sv39_bare_sz, sv32_bare_sz; + uint64_t g_pg_sz, vs_pg_sz, exp_trn_sz, exp_pa; volatile uint64_t temp1; device_context_t DC; process_context_t PC; @@ -67,10 +69,12 @@ main(void) { cap.dbg = 1; cap.pas = 50; cap.pd20 = cap.pd17 = cap.pd8 = 1; - + sv57_bare_sz = sv48_bare_sz = sv39_bare_sz = 0x40000000; + sv32_bare_sz = 0x200000; fail_if( ( reset_iommu(8, 40, 0xff, 3, Off, DDT_3LVL, 0xFFFFFF, 0, 0, (FILL_IOATC_ATS_T2GPA | FILL_IOATC_ATS_ALWAYS), - cap, fctl) < 0 ) ); + cap, fctl, sv57_bare_sz, sv48_bare_sz, sv39_bare_sz, + sv32_bare_sz) < 0 ) ); for ( i = MSI_ADDR_0_OFFSET; i <= MSI_ADDR_7_OFFSET; i += 16 ) { write_register(i, 8, 0xFF); fail_if(( read_register(i, 8) != 0xFc )); @@ -1386,11 +1390,11 @@ main(void) { } else { temp = 0xFFF; } - fail_if( ( ((rsp.trsp.PPN * PAGESIZE) & ~temp) != (gpte.PPN * PAGESIZE) ) ); - fail_if( ( ((temp + 1) != PAGESIZE) && i == 0 ) ); - fail_if( ( ((temp + 1) != 512UL * PAGESIZE) && i == 1 ) ); - fail_if( ( ((temp + 1) != 512UL * 512UL * PAGESIZE) && i == 2 ) ); - fail_if( ( ((temp + 1) != 512UL * 512UL * 512UL * PAGESIZE) && i == 3 ) ); + g_pg_sz = (1UL << (i * 9UL)) * PAGESIZE; + exp_trn_sz = g_pg_sz > sv57_bare_sz ? sv57_bare_sz : g_pg_sz; + exp_pa = (((gpte.PPN * PAGESIZE) & ~(g_pg_sz - 1)) | (gpa & (g_pg_sz - 1))) & ~temp; + fail_if( (((rsp.trsp.PPN * PAGESIZE) & ~temp) != exp_pa) ); + fail_if( ((temp + 1) != exp_trn_sz) ); // Test for walking past max levels if ( i == 0 ) { @@ -1439,10 +1443,9 @@ main(void) { fail_if( ( rsp.trsp.S != 1 ) ); temp = rsp.trsp.PPN ^ (rsp.trsp.PPN + 1); temp = temp * PAGESIZE | 0xFFF; - fail_if( ( i == 0 && ((temp + 1) != 2 * 512UL * PAGESIZE) ) ); - fail_if( ( i == 1 && ((temp + 1) != 512UL * 512UL * PAGESIZE) ) ); - fail_if( ( i == 2 && ((temp + 1) != 512UL * 512UL * 512UL * PAGESIZE) ) ); - fail_if( ( i == 3 && ((temp + 1) != 512UL * 512UL * 512UL * 512UL * PAGESIZE) ) ); + exp_trn_sz = i == 3 ? sv57_bare_sz : i == 2 ? sv48_bare_sz : + i == 1 ? sv39_bare_sz : sv32_bare_sz; + fail_if( ((temp + 1) != exp_trn_sz) ); if ( i == 0 ) g_reg_file.fctl.gxl = 0; if ( i == 0 ) DC.tc.SXL = 0; } @@ -1665,11 +1668,11 @@ main(void) { } else { temp = 0xFFF; } - fail_if( ( ((rsp.trsp.PPN * PAGESIZE) & ~temp) != (pte.PPN * PAGESIZE) ) ); - fail_if( ( ((temp + 1) != PAGESIZE) && i == 0 ) ); - fail_if( ( ((temp + 1) != 512UL * PAGESIZE) && i == 1 ) ); - fail_if( ( ((temp + 1) != 512UL * 512UL * PAGESIZE) && i == 2 ) ); - fail_if( ( ((temp + 1) != 512UL * 512UL * 512UL * PAGESIZE) && i == 3 ) ); + vs_pg_sz = (1UL << (i * 9UL)) * PAGESIZE; + exp_trn_sz = vs_pg_sz > sv57_bare_sz ? sv57_bare_sz : vs_pg_sz; + exp_pa = (((pte.PPN * PAGESIZE) & ~temp) | (gva & (vs_pg_sz - 1))) & ~temp; + fail_if( (((rsp.trsp.PPN * PAGESIZE) & ~temp) != exp_pa) ); + fail_if( ((temp + 1) != exp_trn_sz) ); // Test for walking past max levels if ( i == 0 ) { @@ -1718,10 +1721,9 @@ main(void) { fail_if( ( rsp.trsp.S != 1 ) ); temp = rsp.trsp.PPN ^ (rsp.trsp.PPN + 1); temp = temp * PAGESIZE | 0xFFF; - fail_if( ( i == 0 && ((temp + 1) != 2 * 512UL * PAGESIZE) ) ); - fail_if( ( i == 1 && ((temp + 1) != 512UL * 512UL * PAGESIZE) ) ); - fail_if( ( i == 2 && ((temp + 1) != 512UL * 512UL * 512UL * PAGESIZE) ) ); - fail_if( ( i == 3 && ((temp + 1) != 512UL * 512UL * 512UL * 512UL * PAGESIZE) ) ); + exp_trn_sz = i == 3 ? sv57_bare_sz : i == 2 ? sv48_bare_sz : + i == 1 ? sv39_bare_sz : sv32_bare_sz; + fail_if( ((temp + 1) != exp_trn_sz) ); if ( i == 0 ) g_reg_file.fctl.gxl = 0; if ( i == 0 ) DC.tc.SXL = 0; }