diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 78d146e8a163..c18920703503 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -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)
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 3d8876f60d5b..2b6f7b0065f5 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -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
diff --git a/arch/x86/kernel/cc_platform.c b/arch/x86/kernel/cc_platform.c
index 3fd2c628e028..3544ed78dd16 100644
--- a/arch/x86/kernel/cc_platform.c
+++ b/arch/x86/kernel/cc_platform.c
@@ -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);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 7fbb7f6eb523..1d405750bc16 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -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;
diff --git a/arch/x86/kernel/tdx-filter.c b/arch/x86/kernel/tdx-filter.c
new file mode 100644
index 000000000000..534cc2cf5851
--- /dev/null
+++ b/arch/x86/kernel/tdx-filter.c
@@ -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");
+}
diff --git a/arch/x86/kernel/tdx.c b/arch/x86/kernel/tdx.c
index aeeab647e62d..b1d660bd98c6 100644
--- a/arch/x86/kernel/tdx.c
+++ b/arch/x86/kernel/tdx.c
@@ -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;
 
diff --git a/include/linux/cc_platform.h b/include/linux/cc_platform.h
index d39370cfbda1..a0b608bba1ee 100644
--- a/include/linux/cc_platform.h
+++ b/include/linux/cc_platform.h
@@ -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
diff --git a/include/linux/device.h b/include/linux/device.h
index c97b1e59d23a..125590e80c35 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -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_ */
diff --git a/include/uapi/linux/virtio_ids.h b/include/uapi/linux/virtio_ids.h
index 80d76b75bccd..68c68d449ea5 100644
--- a/include/uapi/linux/virtio_ids.h
+++ b/include/uapi/linux/virtio_ids.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 */
