@@ -5,6 +5,7 @@
#include <linux/cpufeature.h>
#include <linux/types.h>
+#include <linux/device.h>
#include <vdso/limits.h>
#include <asm/vmx.h>
@@ -69,6 +70,7 @@ enum tdx_map_type {
void __init tdx_early_init(void);
bool cpuid_has_tdx_guest(void);
+void __init tdx_filter_init(void);
/* Helper function used to communicate with the TDX module */
u64 __tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
@@ -96,6 +98,8 @@ int tdx_hcall_get_quote(u64 data);
extern void (*tdx_event_notify_handler)(void);
+bool tdx_guest_dev_authorized(struct device *dev);
+
/*
* To support I/O port access in decompressor or early kernel init
* code, since #VE exception handler cannot be used, use paravirt
@@ -169,6 +173,11 @@ static inline int tdx_hcall_gpa_intent(phys_addr_t gpa, int numpages,
return -ENODEV;
}
+static inline bool tdx_guest_dev_authorized(struct device *dev)
+{
+ return dev->authorized;
+}
+
#endif /* CONFIG_INTEL_TDX_GUEST */
#if defined(CONFIG_KVM_GUEST) && defined(CONFIG_INTEL_TDX_GUEST)
@@ -128,7 +128,7 @@ obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o
obj-$(CONFIG_X86_PMEM_LEGACY_DEVICE) += pmem.o
obj-$(CONFIG_JAILHOUSE_GUEST) += jailhouse.o
-obj-$(CONFIG_INTEL_TDX_GUEST) += tdcall.o tdx.o
+obj-$(CONFIG_INTEL_TDX_GUEST) += tdcall.o tdx.o tdx-filter.o
obj-$(CONFIG_EISA) += eisa.o
obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o
@@ -11,6 +11,9 @@
#include <linux/cc_platform.h>
#include <linux/mem_encrypt.h>
#include <linux/processor.h>
+#include <linux/device.h>
+
+#include <asm/tdx.h>
#include <asm/tdx.h>
@@ -24,3 +27,20 @@ bool cc_platform_has(enum cc_attr attr)
return false;
}
EXPORT_SYMBOL_GPL(cc_platform_has);
+
+/*
+ * cc_guest_dev_authorized() - Used to get ARCH specific authorized status
+ * of the given device.
+ * @dev - device structure
+ *
+ * Return True to allow the device or False to deny it.
+ *
+ */
+bool cc_guest_dev_authorized(struct device *dev)
+{
+ if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+ return tdx_guest_dev_authorized(dev);
+
+ return dev->authorized;
+}
+EXPORT_SYMBOL_GPL(cc_guest_dev_authorized);
@@ -84,6 +84,7 @@ bool intel_cc_platform_has(enum cc_attr attr)
case CC_ATTR_GUEST_MEM_ENCRYPT:
case CC_ATTR_GUEST_SHARED_MAPPING_INIT:
case CC_ATTR_MEM_ENCRYPT:
+ case CC_ATTR_GUEST_DEVICE_FILTER:
return cpu_feature_enabled(X86_FEATURE_TDX_GUEST);
default:
return false;
new file mode 100644
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Intel Corporation
+ */
+#define pr_fmt(fmt) "TDX: " fmt
+
+#include <linux/acpi.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/cc_platform.h>
+#include <linux/export.h>
+#include <uapi/linux/virtio_ids.h>
+
+#include <asm/tdx.h>
+#include <asm/cmdline.h>
+
+/*
+ * Allow list for PCI bus
+ *
+ * NOTE: Device ID is duplicated here. But for small list
+ * of devices, it is easier to maintain the duplicated list
+ * here verses exporting the device ID table from the driver
+ * and use it.
+ */
+struct pci_device_id pci_allow_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, VIRTIO_TRANS_ID_NET) },
+ { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, VIRTIO_TRANS_ID_BLOCK) },
+ { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, VIRTIO_TRANS_ID_CONSOLE) },
+ { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, VIRTIO_TRANS_ID_9P) },
+ { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, VIRTIO1_ID_NET) },
+ { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, VIRTIO1_ID_BLOCK) },
+ { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, VIRTIO1_ID_CONSOLE) },
+ { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, VIRTIO1_ID_9P) },
+ { 0, },
+};
+
+bool tdx_guest_dev_authorized(struct device *dev)
+{
+ if (!dev_is_pci(dev))
+ return dev->authorized;
+
+ if (pci_match_id(pci_allow_ids, to_pci_dev(dev)))
+ return true;
+
+ return dev_default_authorization;
+}
+
+void __init tdx_filter_init(void)
+{
+ if (!cc_platform_has(CC_ATTR_GUEST_DEVICE_FILTER))
+ return;
+
+ dev_default_authorization = false;
+
+ pr_info("Enabled TDX guest device filter\n");
+}
@@ -797,6 +797,8 @@ void __init tdx_early_init(void)
tdx_get_info();
+ tdx_filter_init();
+
pv_ops.irq.safe_halt = tdx_safe_halt;
pv_ops.irq.halt = tdx_halt;
@@ -94,6 +94,16 @@ enum cc_attr {
*/
CC_ATTR_GUEST_SHARED_MAPPING_INIT,
+ /**
+ * @CC_ATTR_GUEST_DEVICE_FILTER: Filter device enumeration as per
+ * platform specific allow list.
+ *
+ * The platform/OS is running as a guest/virtual machine and allows or
+ * dis-allows device enumeration as per platform specific allow list.
+ *
+ * Examples include TDX guest.
+ */
+ CC_ATTR_GUEST_DEVICE_FILTER,
};
#ifdef CONFIG_ARCH_HAS_CC_PLATFORM
@@ -990,4 +990,15 @@ extern long sysfs_deprecated;
#define sysfs_deprecated 0
#endif
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_ARCH_HAS_CC_PLATFORM
+bool cc_guest_dev_authorized(struct device *dev);
+#else
+static inline bool cc_guest_dev_authorized(struct device *dev)
+{
+ return dev->authorized;
+}
+#endif /* CONFIG_ARCH_HAS_CC_PLATFORM */
+#endif /* __ASSEMBLY__ */
+
#endif /* _DEVICE_H_ */
@@ -81,4 +81,12 @@
#define VIRTIO_TRANS_ID_RNG 1005 /* transitional virtio rng */
#define VIRTIO_TRANS_ID_9P 1009 /* transitional virtio 9p console */
+/*
+ * Virtio IDS (for PCI rev ID > 1)
+ */
+#define VIRTIO1_ID_NET 1041 /* transitional virtio net */
+#define VIRTIO1_ID_BLOCK 1042 /* transitional virtio block */
+#define VIRTIO1_ID_CONSOLE 1043 /* transitional virtio console */
+#define VIRTIO1_ID_9P 1049 /* transitional virtio 9p console */
+
#endif /* _LINUX_VIRTIO_IDS_H */