On 2/23/22 23:35, Joao Martins wrote:
> On 2/23/22 21:22, Michael S. Tsirkin wrote:
>>> +static void x86_update_above_4g_mem_start(PCMachineState *pcms,
>>> + uint64_t pci_hole64_size)
>>> +{
>>> + X86MachineState *x86ms = X86_MACHINE(pcms);
>>> + uint32_t eax, vendor[3];
>>> +
>>> + host_cpuid(0x0, 0, &eax, &vendor[0], &vendor[2], &vendor[1]);
>>> + if (!IS_AMD_VENDOR(vendor)) {
>>> + return;
>>> + }
>>
>> Wait a sec, should this actually be tying things to the host CPU ID?
>> It's really about what we present to the guest though,
>> isn't it?
>
> It was the easier catch all to use cpuid without going into
> Linux UAPI specifics. But it doesn't have to tie in there, it is only
> for systems with an IOMMU present.
>
>> Also, can't we tie this to whether the AMD IOMMU is present?
>>
> I think so, I can add that. Something like a amd_iommu_exists() helper
> in util/vfio-helpers.c which checks if there's any sysfs child entries
> that start with ivhd in /sys/class/iommu/. Given that this HT region is
> hardcoded in iommu reserved regions since >=4.11 (to latest) I don't think
> it's
> even worth checking the range exists in:
>
> /sys/kernel/iommu_groups/0/reserved_regions
>
> (Also that sysfs ABI is >= 4.11 only)
Here's what I have staged in local tree, to address your comment.
Naturally the first chunk is what's affected by this patch the rest is a
precedessor patch to introduce qemu_amd_iommu_is_present(). Seems to pass
all the tests and what not.
I am not entirely sure this is the right place to put such a helper, open
to suggestions. wrt to the naming of the helper, I tried to follow the rest
of the file's style.
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index a9be5d33a291..2ea4430d5dcc 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -868,10 +868,8 @@ static void x86_update_above_4g_mem_start(PCMachineState
*pcms,
uint64_t pci_hole64_size)
{
X86MachineState *x86ms = X86_MACHINE(pcms);
- uint32_t eax, vendor[3];
- host_cpuid(0x0, 0, &eax, &vendor[0], &vendor[2], &vendor[1]);
- if (!IS_AMD_VENDOR(vendor)) {
+ if (!qemu_amd_iommu_is_present()) {
return;
}
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 7bcce3bceb0f..eb4ea071ecec 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -637,6 +637,15 @@ char *qemu_get_host_name(Error **errp);
*/
size_t qemu_get_host_physmem(void);
+/**
+ * qemu_amd_iommu_is_present:
+ *
+ * Operating system agnostic way of querying if an AMD IOMMU
+ * is present.
+ *
+ */
+bool qemu_amd_iommu_is_present(void);
+
/*
* Toggle write/execute on the pages marked MAP_JIT
* for the current thread.
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index f2be7321c59f..54cef21217c4 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -982,3 +982,32 @@ size_t qemu_get_host_physmem(void)
#endif
return 0;
}
+
+bool qemu_amd_iommu_is_present(void)
+{
+ bool found = false;
+#ifdef CONFIG_LINUX
+ struct dirent *entry;
+ char *path;
+ DIR *dir;
+
+ path = g_strdup_printf("/sys/class/iommu");
+ dir = opendir(path);
+ if (!dir) {
+ g_free(path);
+ return found;
+ }
+
+ do {
+ entry = readdir(dir);
+ if (entry && !strncmp(entry->d_name, "ivhd", 4)) {
+ found = true;
+ break;
+ }
+ } while (entry);
+
+ g_free(path);
+ closedir(dir);
+#endif
+ return found;
+}
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index af559ef3398d..c08826e7e19b 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -652,3 +652,8 @@ size_t qemu_get_host_physmem(void)
}
return 0;
}
+
+bool qemu_amd_iommu_is_present(void)
+{
+ return false;
+}