diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index a009625..fa62e2a 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2606,6 +2606,24 @@ enum xc_psr_cat_type {
 };
 typedef enum xc_psr_cat_type xc_psr_cat_type;
 
+enum xc_psr_feat_type {
+    XC_PSR_FEAT_UNKNOWN    = 0,
+    XC_PSR_FEAT_CAT_L3     = 1,
+    XC_PSR_FEAT_CAT_L2     = 2,
+};
+typedef enum xc_psr_feat_type xc_psr_feat_type;
+
+struct xc_psr_hw_info {
+    union {
+        struct {
+            uint32_t cos_max;
+            uint32_t cbm_len;
+            bool     cdp_enabled;
+        } xc_cat_info;
+    } u;
+};
+typedef struct xc_psr_hw_info xc_psr_hw_info;
+
 int xc_psr_cmt_attach(xc_interface *xch, uint32_t domid);
 int xc_psr_cmt_detach(xc_interface *xch, uint32_t domid);
 int xc_psr_cmt_get_domain_rmid(xc_interface *xch, uint32_t domid,
@@ -2627,9 +2645,8 @@ int xc_psr_cat_set_domain_data(xc_interface *xch, uint32_t domid,
 int xc_psr_cat_get_domain_data(xc_interface *xch, uint32_t domid,
                                xc_psr_cat_type type, uint32_t target,
                                uint64_t *data);
-int xc_psr_cat_get_info(xc_interface *xch, uint32_t socket, unsigned int lvl,
-                        uint32_t *cos_max, uint32_t *cbm_len,
-                        bool *cdp_enabled);
+int xc_psr_get_hw_info(xc_interface *xch, uint32_t socket,
+                       xc_psr_feat_type type, xc_psr_hw_info *hw_info);
 
 int xc_get_cpu_levelling_caps(xc_interface *xch, uint32_t *caps);
 int xc_get_cpu_featureset(xc_interface *xch, uint32_t index,
diff --git a/tools/libxc/xc_psr.c b/tools/libxc/xc_psr.c
index 0098a4d..af648eb 100644
--- a/tools/libxc/xc_psr.c
+++ b/tools/libxc/xc_psr.c
@@ -323,35 +323,43 @@ int xc_psr_cat_get_domain_data(xc_interface *xch, uint32_t domid,
     return rc;
 }
 
-int xc_psr_cat_get_info(xc_interface *xch, uint32_t socket, unsigned int lvl,
-                        uint32_t *cos_max, uint32_t *cbm_len, bool *cdp_enabled)
+int xc_psr_get_hw_info(xc_interface *xch, uint32_t socket,
+                       xc_psr_feat_type type, xc_psr_hw_info *hw_info)
 {
     int rc = -1;
     DECLARE_SYSCTL;
 
+    if ( !hw_info )
+        return rc;
+
     sysctl.cmd = XEN_SYSCTL_psr_alloc_op;
     sysctl.u.psr_alloc_op.target = socket;
 
-    switch ( lvl ) {
-    case 2:
+    switch ( type ) {
+    case XC_PSR_FEAT_CAT_L2:
         sysctl.u.psr_alloc_op.cmd = XEN_SYSCTL_PSR_CAT_get_l2_info;
         rc = xc_sysctl(xch, &sysctl);
         if ( !rc )
         {
-            *cos_max = sysctl.u.psr_alloc_op.u.l2_info.cos_max;
-            *cbm_len = sysctl.u.psr_alloc_op.u.l2_info.cbm_len;
-            *cdp_enabled = false;
+            hw_info->u.xc_cat_info.cos_max =
+                        sysctl.u.psr_alloc_op.u.l2_info.cos_max;
+            hw_info->u.xc_cat_info.cbm_len =
+                        sysctl.u.psr_alloc_op.u.l2_info.cbm_len;
+            hw_info->u.xc_cat_info.cdp_enabled = false;
         }
         break;
-    case 3:
+    case XC_PSR_FEAT_CAT_L3:
         sysctl.u.psr_alloc_op.cmd = XEN_SYSCTL_PSR_CAT_get_l3_info;
         rc = xc_sysctl(xch, &sysctl);
         if ( !rc )
         {
-            *cos_max = sysctl.u.psr_alloc_op.u.l3_info.cos_max;
-            *cbm_len = sysctl.u.psr_alloc_op.u.l3_info.cbm_len;
-            *cdp_enabled = sysctl.u.psr_alloc_op.u.l3_info.flags &
-                           XEN_SYSCTL_PSR_CAT_L3_CDP;
+            hw_info->u.xc_cat_info.cos_max =
+                        sysctl.u.psr_alloc_op.u.l3_info.cos_max;
+            hw_info->u.xc_cat_info.cbm_len =
+                        sysctl.u.psr_alloc_op.u.l3_info.cbm_len;
+            hw_info->u.xc_cat_info.cdp_enabled =
+                        sysctl.u.psr_alloc_op.u.l3_info.flags &
+                        XEN_SYSCTL_PSR_CAT_L3_CDP;
         }
         break;
     default:
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 45a9978..7575ccd 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -911,6 +911,13 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, const libxl_mac *src);
  * If this is defined, the L2 Cache Allocation Technology feature is supported.
  */
 #define LIBXL_HAVE_PSR_L2_CAT 1
+
+/*
+ * LIBXL_HAVE_PSR_MBA
+ *
+ * If this is defined, the Memory Bandwidth Allocation feature is supported.
+ */
+#define LIBXL_HAVE_PSR_MBA 1
 #endif
 
 /*
@@ -2173,8 +2180,9 @@ int libxl_psr_cat_get_cbm(libxl_ctx *ctx, uint32_t domid,
  * On success, the function returns an array of elements in 'info',
  * and the length in 'nr'.
  */
-int libxl_psr_cat_get_info(libxl_ctx *ctx, libxl_psr_cat_info **info,
-                           int *nr, unsigned int lvl);
+int libxl_psr_get_hw_info(libxl_ctx *ctx, libxl_psr_hw_info **info,
+                          int *nr, libxl_psr_feat_type type, int lvl);
+void libxl_psr_hw_info_list_free(libxl_psr_hw_info *list, int nr);
 void libxl_psr_cat_info_list_free(libxl_psr_cat_info *list, int nr);
 #endif
 
diff --git a/tools/libxl/libxl_psr.c b/tools/libxl/libxl_psr.c
index d28ace0..2fe42b7 100644
--- a/tools/libxl/libxl_psr.c
+++ b/tools/libxl/libxl_psr.c
@@ -352,17 +352,64 @@ int libxl_psr_cat_get_cbm(libxl_ctx *ctx, uint32_t domid,
     return rc;
 }
 
-int libxl_psr_cat_get_info(libxl_ctx *ctx, libxl_psr_cat_info **info,
-                           int *nr, unsigned int lvl)
+static inline xc_psr_feat_type libxl__psr_feat_type_to_libxc_psr_feat_type(
+    libxl_psr_feat_type type, int lvl)
+{
+    xc_psr_feat_type xc_type = XC_PSR_FEAT_UNKNOWN;
+
+    switch (type) {
+    case LIBXL_PSR_FEAT_TYPE_CAT_INFO:
+        if (lvl == 3)
+            xc_type = XC_PSR_FEAT_CAT_L3;
+        if (lvl == 2)
+            xc_type = XC_PSR_FEAT_CAT_L2;
+        break;
+    default:
+        break;
+    }
+
+    return xc_type;
+}
+
+static inline int libxc__psr_hw_info_to_libxl_psr_hw_info(
+    libxl_psr_feat_type type, xc_psr_hw_info *xc_hw_info,
+    libxl_psr_hw_info *xl_hw_info)
+{
+    switch (type) {
+    case LIBXL_PSR_FEAT_TYPE_CAT_INFO:
+        xl_hw_info->u.cat_info.cos_max = xc_hw_info->u.xc_cat_info.cos_max;
+        xl_hw_info->u.cat_info.cbm_len = xc_hw_info->u.xc_cat_info.cbm_len;
+        xl_hw_info->u.cat_info.cdp_enabled =
+                                        xc_hw_info->u.xc_cat_info.cdp_enabled;
+        break;
+    default:
+        return -1;
+    }
+
+    return 0;
+}
+
+int libxl_psr_get_hw_info(libxl_ctx *ctx, libxl_psr_hw_info **info,
+                          int *nr, libxl_psr_feat_type type, int lvl)
 {
     GC_INIT(ctx);
     int rc;
     int i = 0, socketid, nr_sockets;
     libxl_bitmap socketmap;
-    libxl_psr_cat_info *ptr;
+    libxl_psr_hw_info *ptr;
+    xc_psr_feat_type xc_type;
+    xc_psr_hw_info hw_info;
 
     libxl_bitmap_init(&socketmap);
 
+    if ( lvl != 3 && lvl != 2) {
+        LOGE(ERROR, "input lvl %d is wrong!\n", lvl);
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    xc_type = libxl__psr_feat_type_to_libxc_psr_feat_type(type, lvl);
+
     rc = libxl__count_physical_sockets(gc, &nr_sockets);
     if (rc) {
         LOGE(ERROR, "failed to get system socket count");
@@ -376,17 +423,24 @@ int libxl_psr_cat_get_info(libxl_ctx *ctx, libxl_psr_cat_info **info,
         goto out;
     }
 
-    ptr = libxl__malloc(NOGC, nr_sockets * sizeof(libxl_psr_cat_info));
+    ptr = libxl__malloc(NOGC, nr_sockets * sizeof(libxl_psr_hw_info));
 
     libxl_for_each_set_bit(socketid, socketmap) {
         ptr[i].id = socketid;
-        if (xc_psr_cat_get_info(ctx->xch, socketid, lvl, &ptr[i].cos_max,
-                                &ptr[i].cbm_len, &ptr[i].cdp_enabled)) {
+        if (xc_psr_get_hw_info(ctx->xch, socketid, xc_type, &hw_info)) {
             libxl__psr_cat_log_err_msg(gc, errno);
             rc = ERROR_FAIL;
             free(ptr);
             goto out;
         }
+
+        if (libxc__psr_hw_info_to_libxl_psr_hw_info(type, &hw_info, &ptr[i])) {
+            LOGE(ERROR, "Input type %d is wrong!\n", type);
+            rc = ERROR_FAIL;
+            free(ptr);
+            goto out;
+        }
+
         i++;
     }
 
@@ -398,6 +452,15 @@ out:
     return rc;
 }
 
+void libxl_psr_hw_info_list_free(libxl_psr_hw_info *list, int nr)
+{
+    int i;
+
+    for (i = 0; i < nr; i++)
+        libxl_psr_hw_info_dispose(&list[i]);
+    free(list);
+}
+
 void libxl_psr_cat_info_list_free(libxl_psr_cat_info *list, int nr)
 {
     int i;
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 5a401b8..a15d9ef 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -908,3 +908,18 @@ libxl_psr_cat_info = Struct("psr_cat_info", [
     ("cbm_len", uint32),
     ("cdp_enabled", bool),
     ])
+
+libxl_psr_feat_type = Enumeration("psr_feat_type", [
+    (1, "CAT_INFO"),
+    ])
+
+libxl_psr_hw_info = Struct("psr_hw_info", [
+    ("id", uint32),
+    ("u", KeyedUnion(None, libxl_psr_feat_type, "type",
+           [("cat_info", Struct(None, [
+                                          ("cos_max",     uint32),
+                                          ("cbm_len",     uint32),
+                                          ("cdp_enabled", bool),
+                                   ])),
+           ]))
+    ])
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 58b4eef..5bf56e8 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -9337,11 +9337,12 @@ static int psr_l3_cat_hwinfo(void)
     int rc, nr;
     unsigned int i;
     uint32_t l3_cache_size;
-    libxl_psr_cat_info *info;
+    libxl_psr_hw_info *info;
 
     printf("Cache Allocation Technology (CAT): L3\n");
 
-    rc = libxl_psr_cat_get_info(ctx, &info, &nr, 3);
+    rc = libxl_psr_get_hw_info(ctx, &info, &nr,
+                               LIBXL_PSR_FEAT_TYPE_CAT_INFO, 3);
     if (rc) {
         fprintf(stderr, "Failed to get l3 cat info\n");
         return rc;
@@ -9357,15 +9358,15 @@ static int psr_l3_cat_hwinfo(void)
         printf("%-16s: %u\n", "Socket ID", info[i].id);
         printf("%-16s: %uKB\n", "L3 Cache", l3_cache_size);
         printf("%-16s: %s\n", "CDP Status",
-               info[i].cdp_enabled ? "Enabled" : "Disabled");
-        printf("%-16s: %u\n", "Maximum COS", info[i].cos_max);
-        printf("%-16s: %u\n", "CBM length", info[i].cbm_len);
+               info[i].u.cat_info.cdp_enabled ? "Enabled" : "Disabled");
+        printf("%-16s: %u\n", "Maximum COS", info[i].u.cat_info.cos_max);
+        printf("%-16s: %u\n", "CBM length", info[i].u.cat_info.cbm_len);
         printf("%-16s: %#llx\n", "Default CBM",
-               (1ull << info[i].cbm_len) - 1);
+               (1ull << info[i].u.cat_info.cbm_len) - 1);
     }
 
 out:
-    libxl_psr_cat_info_list_free(info, nr);
+    libxl_psr_hw_info_list_free(info, nr);
     return rc;
 }
 
@@ -9436,7 +9437,7 @@ static int psr_cat_print_domain_cbm(uint32_t domid, uint32_t socketid,
     return 0;
 }
 
-static int psr_cat_print_socket(uint32_t domid, libxl_psr_cat_info *info,
+static int psr_cat_print_socket(uint32_t domid, libxl_psr_hw_info *info,
                                 unsigned int lvl)
 {
     int rc;
@@ -9456,22 +9457,25 @@ static int psr_cat_print_socket(uint32_t domid, libxl_psr_cat_info *info,
         printf("%-16s: %uKB\n", "L3 Cache", l3_cache_size);
     }
 
-    printf("%-16s: %#llx\n", "Default CBM", (1ull << info->cbm_len) - 1);
-    if (info->cdp_enabled)
+    printf("%-16s: %#llx\n", "Default CBM",
+                    (1ull << info->u.cat_info.cbm_len) - 1);
+    if (info->u.cat_info.cdp_enabled)
         printf("%5s%25s%16s%16s\n", "ID", "NAME", "CBM (code)", "CBM (data)");
     else
         printf("%5s%25s%16s\n", "ID", "NAME", "CBM");
 
-    return psr_cat_print_domain_cbm(domid, info->id, info->cdp_enabled, lvl);
+    return psr_cat_print_domain_cbm(domid, info->id,
+                                    info->u.cat_info.cdp_enabled, lvl);
 }
 
 static int psr_cat_show(uint32_t domid, unsigned int lvl)
 {
     int i, nr;
     int rc;
-    libxl_psr_cat_info *info;
+    libxl_psr_hw_info *info;
 
-    rc = libxl_psr_cat_get_info(ctx, &info, &nr, lvl);
+    rc = libxl_psr_get_hw_info(ctx, &info, &nr,
+                               LIBXL_PSR_FEAT_TYPE_CAT_INFO, lvl);
     if (rc) {
         fprintf(stderr, "Failed to get %s cat info\n", (lvl == 3)?"L3":"L2");
         return rc;
@@ -9484,7 +9488,7 @@ static int psr_cat_show(uint32_t domid, unsigned int lvl)
     }
 
 out:
-    libxl_psr_cat_info_list_free(info, nr);
+    libxl_psr_hw_info_list_free(info, nr);
     return rc;
 }
 
@@ -9493,11 +9497,12 @@ static int psr_l2_cat_hwinfo(void)
     int rc;
     unsigned int i;
     int nr;
-    libxl_psr_cat_info *info;
+    libxl_psr_hw_info *info;
 
     printf("Cache Allocation Technology (CAT): L2\n");
 
-    rc = libxl_psr_cat_get_info(ctx, &info, &nr, 2);
+    rc = libxl_psr_get_hw_info(ctx, &info, &nr,
+                               LIBXL_PSR_FEAT_TYPE_CAT_INFO, 2);
     if (rc) {
         fprintf(stderr, "Failed to get l2 cat info\n");
         return rc;
@@ -9506,13 +9511,13 @@ static int psr_l2_cat_hwinfo(void)
     for (i = 0; i < nr; i++) {
         /* There is no CMT on L2 cache so far. */
         printf("%-16s: %u\n", "Socket ID", info[i].id);
-        printf("%-16s: %u\n", "Maximum COS", info[i].cos_max);
-        printf("%-16s: %u\n", "CBM length", info[i].cbm_len);
+        printf("%-16s: %u\n", "Maximum COS", info[i].u.cat_info.cos_max);
+        printf("%-16s: %u\n", "CBM length", info[i].u.cat_info.cbm_len);
         printf("%-16s: %#llx\n", "Default CBM",
-               (1ull << info[i].cbm_len) - 1);
+               (1ull << info[i].u.cat_info.cbm_len) - 1);
     }
 
-    libxl_psr_cat_info_list_free(info, nr);
+    libxl_psr_hw_info_list_free(info, nr);
     return rc;
 }
 
