pciconf(8): dump AMD IOMMU Base Capability

Reviewed by:	emaste
Sponsored by:	Advanced Micro Devices (AMD)
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D44732
This commit is contained in:
Konstantin Belousov 2024-04-10 01:13:59 +03:00
parent 33adb388c7
commit 1e6db7be69
1 changed files with 115 additions and 0 deletions

View File

@ -376,6 +376,118 @@ cap_subvendor(int fd, struct pci_conf *p, uint8_t ptr)
printf("PCI Bridge subvendor=0x%04x subdevice=0x%04x", ssvid, ssid);
}
static const char *
cap_secdev_amdiommu_decode_vasize(uint32_t misc0)
{
switch (misc0 & PCIM_AMDIOMMU_MISC0_VASIZE_MASK) {
case PCIM_AMDIOMMU_MISC0_VASIZE_32:
return ("32bit");
case PCIM_AMDIOMMU_MISC0_VASIZE_40:
return ("40bit");
case PCIM_AMDIOMMU_MISC0_VASIZE_48:
return ("48bit");
case PCIM_AMDIOMMU_MISC0_VASIZE_64:
return ("64bit");
default:
return ("unknown");
}
}
static const char *
cap_secdev_amdiommu_decode_pasize(uint32_t misc0)
{
switch (misc0 & PCIM_AMDIOMMU_MISC0_PASIZE_MASK) {
case PCIM_AMDIOMMU_MISC0_PASIZE_40:
return ("40bit");
case PCIM_AMDIOMMU_MISC0_PASIZE_48:
return ("48bit");
case PCIM_AMDIOMMU_MISC0_PASIZE_52:
return ("52bit");
default:
return ("unknown");
}
}
static const char *
cap_secdev_amdiommu_decode_gvasize(uint32_t misc0)
{
switch (misc0 & PCIM_AMDIOMMU_MISC0_GVASIZE_MASK) {
case PCIM_AMDIOMMU_MISC0_GVASIZE_48:
return ("48bit");
case PCIM_AMDIOMMU_MISC0_GVASIZE_57:
return ("57bit");
default:
return ("unknown");
}
}
static void
cap_secdev(int fd, struct pci_conf *p, uint8_t ptr)
{
uint32_t cap_h;
uint32_t cap_type, cap_rev;
uint32_t base_low, base_high;
uint32_t range;
uint32_t misc0, misc1;
const char *delim;
cap_h = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_CAP_HEADER, 4);
cap_type = cap_h & PCIM_AMDIOMMU_CAP_TYPE_MASK;
cap_rev = cap_h & PCIM_AMDIOMMU_CAP_REV_MASK;
if (cap_type != PCIM_AMDIOMMU_CAP_TYPE_VAL ||
cap_rev != PCIM_AMDIOMMU_CAP_REV_VAL) {
printf("Secure Device Type=0x%1x Rev=0x%02x\n",
cap_type >> 16, cap_rev >> 19);
return;
}
base_low = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_BASE_LOW,
4);
base_high = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_BASE_HIGH,
4);
printf("AMD IOMMU Base Capability Base=%#018jx/%sabled",
(uintmax_t)(base_low & PCIM_AMDIOMMU_BASE_LOW_ADDRM) +
((uintmax_t)base_high << 32),
(base_low & PCIM_AMDIOMMU_BASE_LOW_EN) != 0 ? "En" : "Dis");
delim = "\n\t\t";
#define PRINTCAP(bit, name) \
if ((cap_h & PCIM_AMDIOMMU_CAP_ ##bit) != 0) { \
printf("%s%s", delim, #name); \
delim = ","; \
}
PRINTCAP(CAPEXT, CapExt);
PRINTCAP(EFR, EFRSup);
PRINTCAP(NPCACHE, NpCache);
PRINTCAP(HTTUN, HtTunnel);
PRINTCAP(IOTLB, IotlbSup);
#undef PRINTCAP
range = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_RANGE, 4);
printf("\n\t\tUnitId=%d", range & PCIM_AMDIOMMU_RANGE_UNITID_MASK);
if ((range & PCIM_AMDIOMMU_RANGE_RNGVALID) != 0) {
printf(" BusNum=%#06x FirstDev=%#06x LastDev=%#06x",
(range & PCIM_AMDIOMMU_RANGE_BUSNUM_MASK) >> 8,
(range & PCIM_AMDIOMMU_RANGE_FIRSTDEV_MASK) >> 16,
(range & PCIM_AMDIOMMU_RANGE_LASTDEV_MASK) >> 24);
}
misc0 = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_MISC0, 4);
printf("\n\t\tMsiNum=%d MsiNumPPR=%d HtAtsResv=%d",
misc0 & PCIM_AMDIOMMU_MISC0_MSINUM_MASK,
(misc0 & PCIM_AMDIOMMU_MISC0_MSINUMPPR_MASK) >> 27,
(misc0 & PCIM_AMDIOMMU_MISC0_HTATSRESV) != 0);
if ((cap_h & PCIM_AMDIOMMU_CAP_CAPEXT) != 0) {
misc1 = read_config(fd, &p->pc_sel,
ptr + PCIR_AMDIOMMU_MISC1, 4);
printf(" MsiNumGA=%d",
misc1 & PCIM_AMDIOMMU_MISC1_MSINUMGA_MASK);
}
printf("\n\t\tVAsize=%s PAsize=%s GVAsize=%s",
cap_secdev_amdiommu_decode_vasize(misc0),
cap_secdev_amdiommu_decode_pasize(misc0),
cap_secdev_amdiommu_decode_gvasize(misc0));
}
#define MAX_PAYLOAD(field) (128 << (field))
static const char *
@ -813,6 +925,9 @@ list_caps(int fd, struct pci_conf *p, int level)
case PCIY_SUBVENDOR:
cap_subvendor(fd, p, ptr);
break;
case PCIY_SECDEV:
cap_secdev(fd, p, ptr);
break;
case PCIY_EXPRESS:
express = 1;
cap_express(fd, p, ptr);