intel_iommu: Declare registers for PRI

Signed-off-by: Clement Mathieu--Drif <clement.mathieu--drif@eviden.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20250901111630.1018573-5-clement.mathieu--drif@eviden.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
CLEMENT MATHIEU--DRIF 2025-09-01 11:17:23 +00:00 committed by Michael S. Tsirkin
parent fadc6b0402
commit b84e1e0730

View file

@ -3386,6 +3386,27 @@ static void vtd_handle_iectl_write(IntelIOMMUState *s)
}
}
static void vtd_handle_prs_write(IntelIOMMUState *s)
{
uint32_t prs = vtd_get_long_raw(s, DMAR_PRS_REG);
if (!(prs & VTD_PR_STATUS_PPR) && !(prs & VTD_PR_STATUS_PRO)) {
vtd_set_clear_mask_long(s, DMAR_PECTL_REG, VTD_PR_PECTL_IP, 0);
}
}
static void vtd_handle_pectl_write(IntelIOMMUState *s)
{
uint32_t pectl = vtd_get_long_raw(s, DMAR_PECTL_REG);
if ((pectl & VTD_PR_PECTL_IP) && !(pectl & VTD_PR_PECTL_IM)) {
/*
* If IP field was 1 when software clears the IM field,
* the interrupt is generated along with clearing the IP field.
*/
vtd_set_clear_mask_long(s, DMAR_PECTL_REG, VTD_PR_PECTL_IP, 0);
vtd_generate_interrupt(s, DMAR_PEADDR_REG, DMAR_PEDATA_REG);
}
}
static uint64_t vtd_mem_read(void *opaque, hwaddr addr, unsigned size)
{
IntelIOMMUState *s = opaque;
@ -3428,6 +3449,11 @@ static uint64_t vtd_mem_read(void *opaque, hwaddr addr, unsigned size)
val = s->iq >> 32;
break;
case DMAR_PEUADDR_REG:
assert(size == 4);
val = vtd_get_long_raw(s, DMAR_PEUADDR_REG);
break;
default:
if (size == 4) {
val = vtd_get_long(s, addr);
@ -3491,6 +3517,11 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
vtd_handle_iotlb_write(s);
break;
case DMAR_PEUADDR_REG:
assert(size == 4);
vtd_set_long(s, addr, val);
break;
/* Invalidate Address Register, 64-bit */
case DMAR_IVA_REG:
if (size == 4) {
@ -3671,6 +3702,18 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
vtd_set_long(s, addr, val);
break;
case DMAR_PRS_REG:
assert(size == 4);
vtd_set_long(s, addr, val);
vtd_handle_prs_write(s);
break;
case DMAR_PECTL_REG:
assert(size == 4);
vtd_set_long(s, addr, val);
vtd_handle_pectl_write(s);
break;
default:
if (size == 4) {
vtd_set_long(s, addr, val);
@ -4722,6 +4765,18 @@ static void vtd_init(IntelIOMMUState *s)
* Interrupt remapping registers.
*/
vtd_define_quad(s, DMAR_IRTA_REG, 0, 0xfffffffffffff80fULL, 0);
/* Page request registers */
if (s->ecap & VTD_ECAP_PRS) {
vtd_define_quad(s, DMAR_PQH_REG, 0, 0x7ffe0ULL, 0);
vtd_define_quad(s, DMAR_PQT_REG, 0, 0x7ffe0ULL, 0);
vtd_define_quad(s, DMAR_PQA_REG, 0, 0xfffffffffffff007ULL, 0);
vtd_define_long(s, DMAR_PRS_REG, 0, 0, 0x3UL);
vtd_define_long(s, DMAR_PECTL_REG, 0, 0x80000000UL, 0);
vtd_define_long(s, DMAR_PEDATA_REG, 0, 0xffffUL, 0);
vtd_define_long(s, DMAR_PEADDR_REG, 0, 0xfffffffcUL, 0);
vtd_define_long(s, DMAR_PEUADDR_REG, 0, 0xffffffffUL, 0);
}
}
/* Should not reset address_spaces when reset because devices will still use