diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index 22650d7..66c9cab 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -1468,6 +1468,12 @@ long arch_do_domctl(
                               PSR_TYPE_L2_CBM);
             break;
 
+        case XEN_DOMCTL_PSR_SET_MBA_THRTL:
+            ret = psr_set_val(d, domctl->u.psr_alloc.target,
+                              domctl->u.psr_alloc.data,
+                              PSR_TYPE_MBA_THRTL);
+            break;
+
         case XEN_DOMCTL_PSR_GET_L3_CBM:
             ret = psr_get_val(d, domctl->u.psr_alloc.target,
                               &val32, PSR_TYPE_L3_CBM);
diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
index 1d0a215..c6d4e31 100644
--- a/xen/arch/x86/psr.c
+++ b/xen/arch/x86/psr.c
@@ -137,7 +137,10 @@ static const struct feat_props {
                           uint32_t data[], unsigned int array_len);
 
     /* write_msr is used to write out feature MSR register. */
-    void (*write_msr)(unsigned int cos, uint32_t val, enum psr_type type);
+    uint32_t (*write_msr)(unsigned int cos, uint32_t val, enum psr_type type);
+
+    /* check_val is used to check if input val fulfills SDM requirement. */
+    bool (*check_val)(const struct feat_node *feat, unsigned long val);
 } *feat_props[FEAT_TYPE_NUM];
 
 /*
@@ -274,29 +277,6 @@ static enum psr_feat_type psr_type_to_feat_type(enum psr_type type)
     return feat_type;
 }
 
-static bool psr_check_cbm(unsigned int cbm_len, unsigned long cbm)
-{
-    unsigned int first_bit, zero_bit;
-
-    /* Set bits should only in the range of [0, cbm_len]. */
-    if ( cbm & (~0ul << cbm_len) )
-        return false;
-
-    /* At least one bit need to be set. */
-    if ( cbm == 0 )
-        return false;
-
-    first_bit = find_first_bit(&cbm, cbm_len);
-    zero_bit = find_next_zero_bit(&cbm, cbm_len, first_bit);
-
-    /* Set bits should be contiguous. */
-    if ( zero_bit < cbm_len &&
-         find_next_bit(&cbm, cbm_len, zero_bit) < cbm_len )
-        return false;
-
-    return true;
-}
-
 /* Implementation of allocation features' functions. */
 static bool cat_init_feature(const struct cpuid_leaf *regs,
                             struct feat_node *feat,
@@ -426,11 +406,36 @@ static bool cat_get_feat_info(const struct feat_node *feat,
     return true;
 }
 
+static bool cat_check_cbm(const struct feat_node *feat, unsigned long cbm)
+{
+    unsigned int first_bit, zero_bit;
+    unsigned int cbm_len = feat->cat.cbm_len;
+
+    /*
+     * Set bits should only in the range of [0, cbm_len].
+     * And, at least one bit need to be set.
+     */
+    if ( cbm & (~0ul << cbm_len) || cbm == 0 )
+        return false;
+
+    first_bit = find_first_bit(&cbm, cbm_len);
+    zero_bit = find_next_zero_bit(&cbm, cbm_len, first_bit);
+
+    /* Set bits should be contiguous. */
+    if ( zero_bit < cbm_len &&
+         find_next_bit(&cbm, cbm_len, zero_bit) < cbm_len )
+        return false;
+
+    return true;
+}
+
 /* L3 CAT props */
-static void l3_cat_write_msr(unsigned int cos, uint32_t val,
-                             enum psr_type type)
+static uint32_t l3_cat_write_msr(unsigned int cos, uint32_t val,
+                                 enum psr_type type)
 {
     wrmsrl(MSR_IA32_PSR_L3_MASK(cos), val);
+
+    return val;
 }
 
 static const struct feat_props l3_cat_props = {
@@ -439,6 +444,7 @@ static const struct feat_props l3_cat_props = {
     .alt_type = PSR_TYPE_UNKNOWN,
     .get_feat_info = cat_get_feat_info,
     .write_msr = l3_cat_write_msr,
+    .check_val = cat_check_cbm,
 };
 
 /* L3 CDP props */
@@ -453,13 +459,15 @@ static bool l3_cdp_get_feat_info(const struct feat_node *feat,
     return true;
 }
 
-static void l3_cdp_write_msr(unsigned int cos, uint32_t val,
-                             enum psr_type type)
+static uint32_t l3_cdp_write_msr(unsigned int cos, uint32_t val,
+                                 enum psr_type type)
 {
     wrmsrl(((type == PSR_TYPE_L3_DATA) ?
             MSR_IA32_PSR_L3_MASK_DATA(cos) :
             MSR_IA32_PSR_L3_MASK_CODE(cos)),
            val);
+
+    return val;
 }
 
 static const struct feat_props l3_cdp_props = {
@@ -469,13 +477,16 @@ static const struct feat_props l3_cdp_props = {
     .alt_type = PSR_TYPE_L3_CBM,
     .get_feat_info = l3_cdp_get_feat_info,
     .write_msr = l3_cdp_write_msr,
+    .check_val = cat_check_cbm,
 };
 
 /* L2 CAT props */
-static void l2_cat_write_msr(unsigned int cos, uint32_t val,
-                             enum psr_type type)
+static uint32_t l2_cat_write_msr(unsigned int cos, uint32_t val,
+                                 enum psr_type type)
 {
     wrmsrl(MSR_IA32_PSR_L2_MASK(cos), val);
+
+    return val;
 }
 
 static const struct feat_props l2_cat_props = {
@@ -484,6 +495,7 @@ static const struct feat_props l2_cat_props = {
     .alt_type = PSR_TYPE_UNKNOWN,
     .get_feat_info = cat_get_feat_info,
     .write_msr = l2_cat_write_msr,
+    .check_val = cat_check_cbm,
 };
 
 /* MBA props */
@@ -502,9 +514,23 @@ static bool mba_get_feat_info(const struct feat_node *feat,
     return true;
 }
 
-static void mba_write_msr(unsigned int cos, uint32_t val,
-                          enum psr_type type)
+static uint32_t mba_write_msr(unsigned int cos, uint32_t val,
+                              enum psr_type type)
+{
+    wrmsrl(MSR_IA32_PSR_MBA_MASK(cos), val);
+
+    /* Read actual value set by hardware. */
+    rdmsrl(MSR_IA32_PSR_MBA_MASK(cos), val);
+
+    return val;
+}
+
+static bool mba_check_thrtl(const struct feat_node *feat, unsigned long thrtl)
 {
+    if ( thrtl > feat->mba.thrtl_max )
+        return false;
+
+    return true;
 }
 
 static const struct feat_props mba_props = {
@@ -513,6 +539,7 @@ static const struct feat_props mba_props = {
     .alt_type = PSR_TYPE_UNKNOWN,
     .get_feat_info = mba_get_feat_info,
     .write_msr = mba_write_msr,
+    .check_val = mba_check_thrtl,
 };
 
 static bool __init parse_psr_bool(const char *s, const char *delim,
@@ -978,7 +1005,7 @@ static int insert_val_into_array(uint32_t val[],
     if ( array_len < props->cos_num )
         return -ENOSPC;
 
-    if ( !psr_check_cbm(feat->cat.cbm_len, new_val) )
+    if ( !props->check_val(feat, new_val) )
         return -EINVAL;
 
     /*
@@ -1210,25 +1237,39 @@ static unsigned int get_socket_cpu(unsigned int socket)
 struct cos_write_info
 {
     unsigned int cos;
-    struct feat_node *feature;
+    struct feat_node **features;
     const uint32_t *val;
-    const struct feat_props *props;
+    unsigned int array_len;
+    const struct feat_props **props;
 };
 
 static void do_write_psr_msrs(void *data)
 {
     const struct cos_write_info *info = data;
-    struct feat_node *feat = info->feature;
-    const struct feat_props *props = info->props;
-    unsigned int i, cos = info->cos, cos_num = props->cos_num;
+    unsigned int i, index = 0, cos = info->cos;
+    const uint32_t *val_array = info->val;
 
-    for ( i = 0; i < cos_num; i++ )
+    for ( i = 0; i < ARRAY_SIZE(feat_props); i++ )
     {
-        if ( feat->cos_reg_val[cos * cos_num + i] != info->val[i] )
+        struct feat_node *feat = info->features[i];
+        const struct feat_props *props = info->props[i];
+        unsigned int cos_num, j;
+
+        if ( !feat || !props )
+            continue;
+
+        cos_num = props->cos_num;
+        if ( info->array_len < index + cos_num )
+            return;
+
+        for ( j = 0; j < cos_num; j++ )
         {
-            feat->cos_reg_val[cos * cos_num + i] = info->val[i];
-            props->write_msr(cos, info->val[i], props->type[i]);
+            if ( feat->cos_reg_val[cos * cos_num + j] != val_array[index + j] )
+                feat->cos_reg_val[cos * cos_num + j] =
+                    props->write_msr(cos, val_array[index + j], props->type[j]);
         }
+
+        index += cos_num;
     }
 }
 
@@ -1236,30 +1277,19 @@ static int write_psr_msrs(unsigned int socket, unsigned int cos,
                           const uint32_t val[], unsigned int array_len,
                           enum psr_feat_type feat_type)
 {
-    int ret;
     struct psr_socket_info *info = get_socket_info(socket);
     struct cos_write_info data =
     {
         .cos = cos,
-        .feature = info->features[feat_type],
-        .props = feat_props[feat_type],
+        .features = info->features,
+        .val = val,
+        .array_len = array_len,
+        .props = feat_props,
     };
 
     if ( cos > info->features[feat_type]->cos_max )
         return -EINVAL;
 
-    /* Skip to the feature's value head. */
-    ret = skip_prior_features(&array_len, feat_type);
-    if ( ret < 0 )
-        return ret;
-
-    val += ret;
-
-    if ( array_len < feat_props[feat_type]->cos_num )
-        return -ENOSPC;
-
-    data.val = val;
-
     if ( socket == cpu_to_socket(smp_processor_id()) )
         do_write_psr_msrs(&data);
     else
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index ec6d2de..714b3e8 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -1156,6 +1156,7 @@ struct xen_domctl_psr_alloc {
 #define XEN_DOMCTL_PSR_GET_L3_DATA    5
 #define XEN_DOMCTL_PSR_SET_L2_CBM     6
 #define XEN_DOMCTL_PSR_GET_L2_CBM     7
+#define XEN_DOMCTL_PSR_SET_MBA_THRTL  8
 #define XEN_DOMCTL_PSR_GET_MBA_THRTL  9
     uint32_t cmd;       /* IN: XEN_DOMCTL_PSR_* */
     uint32_t target;    /* IN */
