diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index b819897a4a9f..c9a93448f071 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -1965,8 +1965,8 @@ static int svm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
         break;
 
     default:
-        gdprintk(XENLOG_WARNING, "RDMSR 0x%08x unimplemented\n", msr);
-        goto gpf;
+        if ( guest_unhandled_msr(v, msr, msr_content, false) )
+            goto gpf;
     }
 
     HVM_DBG_LOG(DBG_LEVEL_MSR, "returns: ecx=%x, msr_value=%"PRIx64,
@@ -2151,10 +2151,8 @@ static int svm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
         break;
 
     default:
-        gdprintk(XENLOG_WARNING,
-                 "WRMSR 0x%08x val 0x%016"PRIx64" unimplemented\n",
-                 msr, msr_content);
-        goto gpf;
+        if ( guest_unhandled_msr(v, msr, &msr_content, true) )
+            goto gpf;
     }
 
     return X86EMUL_OKAY;
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 2d4475ee3de2..34524c7a6f00 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -3017,8 +3017,8 @@ static int vmx_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
             break;
         }
 
-        gdprintk(XENLOG_WARNING, "RDMSR 0x%08x unimplemented\n", msr);
-        goto gp_fault;
+        if ( guest_unhandled_msr(curr, msr, msr_content, false) )
+            goto gp_fault;
     }
 
 done:
@@ -3319,10 +3319,8 @@ static int vmx_msr_write_intercept(unsigned int msr, uint64_t msr_content)
              is_last_branch_msr(msr) )
             break;
 
-        gdprintk(XENLOG_WARNING,
-                 "WRMSR 0x%08x val 0x%016"PRIx64" unimplemented\n",
-                 msr, msr_content);
-        goto gp_fault;
+        if ( guest_unhandled_msr(v, msr, &msr_content, true) )
+            goto gp_fault;
     }
 
     return X86EMUL_OKAY;
diff --git a/xen/arch/x86/msr.c b/xen/arch/x86/msr.c
index be8e36386250..e624fc8694bf 100644
--- a/xen/arch/x86/msr.c
+++ b/xen/arch/x86/msr.c
@@ -164,6 +164,26 @@ int init_vcpu_msr_policy(struct vcpu *v)
     return 0;
 }
 
+/* Returns true if policy requires #GP to the guest. */
+bool guest_unhandled_msr(const struct vcpu *v, uint32_t msr,
+                         uint64_t *val, bool is_write)
+{
+    const struct msr_policy *mp = v->domain->arch.msr;
+
+    if ( unlikely(mp->ignore_msrs != MSR_UNHANDLED_NEVER) && !is_write )
+        *val = 0;
+
+    if ( likely(mp->ignore_msrs != MSR_UNHANDLED_SILENT) ) {
+        if ( is_write )
+            gdprintk(XENLOG_WARNING, "WRMSR 0x%08x val 0x%016"PRIx64
+                    " unimplemented\n", msr, *val);
+        else
+            gdprintk(XENLOG_WARNING, "RDMSR 0x%08x unimplemented\n", msr);
+    }
+
+    return (mp->ignore_msrs == MSR_UNHANDLED_NEVER);
+}
+
 int guest_rdmsr(struct vcpu *v, uint32_t msr, uint64_t *val)
 {
     const struct vcpu *curr = current;
diff --git a/xen/arch/x86/pv/emul-priv-op.c b/xen/arch/x86/pv/emul-priv-op.c
index dbceed8a05fd..96d90eb30adc 100644
--- a/xen/arch/x86/pv/emul-priv-op.c
+++ b/xen/arch/x86/pv/emul-priv-op.c
@@ -984,7 +984,8 @@ static int read_msr(unsigned int reg, uint64_t *val,
         }
         /* fall through */
     default:
-        gdprintk(XENLOG_WARNING, "RDMSR 0x%08x unimplemented\n", reg);
+        if ( !guest_unhandled_msr(curr, reg, val, false) )
+            return X86EMUL_OKAY;
         break;
 
     normal:
@@ -1146,9 +1147,8 @@ static int write_msr(unsigned int reg, uint64_t val,
         }
         /* fall through */
     default:
-        gdprintk(XENLOG_WARNING,
-                 "WRMSR 0x%08x val 0x%016"PRIx64" unimplemented\n",
-                 reg, val);
+        if ( !guest_unhandled_msr(curr, reg, &val, true) )
+            return X86EMUL_OKAY;
         break;
 
     invalid:
diff --git a/xen/include/asm-x86/msr.h b/xen/include/asm-x86/msr.h
index 16f95e734428..43a48e1a50ce 100644
--- a/xen/include/asm-x86/msr.h
+++ b/xen/include/asm-x86/msr.h
@@ -345,5 +345,6 @@ int init_vcpu_msr_policy(struct vcpu *v);
  */
 int guest_rdmsr(struct vcpu *v, uint32_t msr, uint64_t *val);
 int guest_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val);
-
+bool guest_unhandled_msr(const struct vcpu *v, uint32_t msr,
+                         uint64_t *val, bool is_write);
 #endif /* __ASM_MSR_H */
