diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig
index 9cdd04721a..ed0ece85c7 100644
--- a/xen/arch/x86/Kconfig
+++ b/xen/arch/x86/Kconfig
@@ -144,6 +144,19 @@ config INTEL_VMX
 	  If your system includes a processor with Intel VT-x support, say Y.
 	  If in doubt, say Y.
 
+menu "Emulated HVM devices support"
+       visible if EXPERT
+       depends on HVM
+
+config X86_HVM_PMTIMER
+	bool "ACPI PM timer emulation support"
+	default y
+	help
+	  Build pmtimer driver that emulates ACPI PM timer for HVM/PVH guests.
+
+	  If unsure, say Y.
+endmenu
+
 config XEN_SHSTK
 	bool "Supervisor Shadow Stacks"
 	depends on HAS_AS_CET_SS
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 78a13e6812..b340818ee2 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -742,11 +742,16 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
 
 static bool emulation_flags_ok(const struct domain *d, uint32_t emflags)
 {
-#ifdef CONFIG_HVM
+    const uint32_t disabled_emu_mask = X86_EMU_PM;
+
+#if defined(CONFIG_X86_HVM_PMTIMER)
     /* This doesn't catch !CONFIG_HVM case but it is better than nothing */
     BUILD_BUG_ON(X86_EMU_ALL != XEN_X86_EMU_ALL);
 #endif
 
+    if ( emflags & disabled_emu_mask )
+        return false;
+
     if ( is_hvm_domain(d) )
     {
         if ( is_hardware_domain(d) &&
diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile
index 4c1fa5c6c2..3af8963218 100644
--- a/xen/arch/x86/hvm/Makefile
+++ b/xen/arch/x86/hvm/Makefile
@@ -18,7 +18,7 @@ obj-y += irq.o
 obj-y += monitor.o
 obj-y += mtrr.o
 obj-y += nestedhvm.o
-obj-y += pmtimer.o
+obj-$(CONFIG_X86_HVM_PMTIMER) += pmtimer.o
 obj-y += quirks.o
 obj-y += rtc.o
 obj-y += save.o
diff --git a/xen/arch/x86/include/asm/acpi.h b/xen/arch/x86/include/asm/acpi.h
index 217819dd61..eb2e4a1ede 100644
--- a/xen/arch/x86/include/asm/acpi.h
+++ b/xen/arch/x86/include/asm/acpi.h
@@ -150,8 +150,13 @@ void acpi_mmcfg_init(void);
 /* Incremented whenever we transition through S3. Value is 1 during boot. */
 extern uint32_t system_reset_counter;
 
+#ifdef CONFIG_X86_HVM_PMTIMER
 void hvm_acpi_power_button(struct domain *d);
 void hvm_acpi_sleep_button(struct domain *d);
+#else
+static inline void hvm_acpi_power_button(struct domain *d) {}
+static inline void hvm_acpi_sleep_button(struct domain *d) {}
+#endif
 
 /* suspend/resume */
 void save_rest_processor_state(void);
diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
index b79d6badd7..8550473997 100644
--- a/xen/arch/x86/include/asm/domain.h
+++ b/xen/arch/x86/include/asm/domain.h
@@ -463,7 +463,6 @@ struct arch_domain
 #ifdef CONFIG_HVM
 #define X86_EMU_LAPIC    XEN_X86_EMU_LAPIC
 #define X86_EMU_HPET     XEN_X86_EMU_HPET
-#define X86_EMU_PM       XEN_X86_EMU_PM
 #define X86_EMU_RTC      XEN_X86_EMU_RTC
 #define X86_EMU_IOAPIC   XEN_X86_EMU_IOAPIC
 #define X86_EMU_PIC      XEN_X86_EMU_PIC
@@ -474,7 +473,6 @@ struct arch_domain
 #else
 #define X86_EMU_LAPIC    0
 #define X86_EMU_HPET     0
-#define X86_EMU_PM       0
 #define X86_EMU_RTC      0
 #define X86_EMU_IOAPIC   0
 #define X86_EMU_PIC      0
@@ -484,6 +482,12 @@ struct arch_domain
 #define X86_EMU_VPCI     0
 #endif
 
+#ifdef CONFIG_X86_HVM_PMTIMER
+#define X86_EMU_PM       XEN_X86_EMU_PM
+#else
+#define X86_EMU_PM       0
+#endif
+
 #define X86_EMU_PIT     XEN_X86_EMU_PIT
 
 /* This must match XEN_X86_EMU_ALL in xen.h */
diff --git a/xen/arch/x86/include/asm/hvm/domain.h b/xen/arch/x86/include/asm/hvm/domain.h
index 333501d5f2..a4fddf7754 100644
--- a/xen/arch/x86/include/asm/hvm/domain.h
+++ b/xen/arch/x86/include/asm/hvm/domain.h
@@ -80,8 +80,10 @@ struct hvm_domain {
      * in public header files.
      * Internally, however, we will be using hvm_hw_acpi.
      */
+#ifdef CONFIG_X86_HVM_PMTIMER
 #define hvm_hw_acpi hvm_hw_pmtimer
     struct hvm_hw_acpi     acpi;
+#endif
 
     /* VCPU which is current target for 8259 interrupts. */
     struct vcpu           *i8259_target;
diff --git a/xen/arch/x86/include/asm/hvm/vpt.h b/xen/arch/x86/include/asm/hvm/vpt.h
index 0b92b28625..f24ef08925 100644
--- a/xen/arch/x86/include/asm/hvm/vpt.h
+++ b/xen/arch/x86/include/asm/hvm/vpt.h
@@ -187,10 +187,20 @@ void rtc_deinit(struct domain *d);
 void rtc_reset(struct domain *d);
 void rtc_update_clock(struct domain *d);
 
+#ifdef CONFIG_X86_HVM_PMTIMER
 void pmtimer_init(struct vcpu *v);
 void pmtimer_deinit(struct domain *d);
 void pmtimer_reset(struct domain *d);
 int pmtimer_change_ioport(struct domain *d, uint64_t version);
+#else
+static inline void pmtimer_init(struct vcpu *v) {}
+static inline void pmtimer_deinit(struct domain *d) {}
+static inline void pmtimer_reset(struct domain *d) {}
+static inline int pmtimer_change_ioport(struct domain *d, uint64_t version)
+{
+    return -ENODEV;
+}
+#endif
 
 void hpet_init(struct domain *d);
 void hpet_deinit(struct domain *d);
