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;
+}

Reply via email to