diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 13574bf..5adf53c 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -238,6 +238,16 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
         if (ret < 0) {
             return ret;
         }
+
+        if (spapr->pvr_new) {
+            ret = fdt_setprop(fdt, offset, "cpu-version",
+                              &spapr->pvr_new, sizeof(spapr->pvr_new));
+            if (ret < 0) {
+                return ret;
+            }
+            /* Reset as the guest after reboot may give other PVR set */
+            spapr->pvr_new = 0;
+        }
     }
     return ret;
 }
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 9f6e7b8..509de89 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -3,6 +3,7 @@
 #include "helper_regs.h"
 #include "hw/ppc/spapr.h"
 #include "mmu-hash64.h"
+#include "cpu-models.h"
 
 static target_ulong h_random(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                            target_ulong opcode, target_ulong *args)
@@ -792,6 +793,78 @@ out:
     return ret;
 }
 
+static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
+                                                  sPAPREnvironment *spapr,
+                                                  target_ulong opcode,
+                                                  target_ulong *args)
+{
+    target_ulong list = args[0];
+    int i, number_of_option_vectors;
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+    bool cpu_match = false;
+    unsigned compat_cpu_level = 0, pvr_new;
+
+    /* Parse PVR list */
+    for ( ; ; ) {
+        uint32_t pvr, pvr_mask;
+
+        pvr_mask = ldl_phys(list);
+        list += 4;
+        pvr = ldl_phys(list);
+        list += 4;
+
+        if ((cpu->env.spr[SPR_PVR] & pvr_mask) == (pvr & pvr_mask)) {
+            cpu_match = true;
+            pvr_new = cpu->env.spr[SPR_PVR];
+        }
+
+        /* Is it a logical PVR? */
+        if ((pvr & CPU_POWERPC_LOGICAL_MASK) == CPU_POWERPC_LOGICAL_MASK) {
+            switch (pvr) {
+            case CPU_POWERPC_LOGICAL_2_05:
+                if ((pcc->pcr & POWERPC_ISA_COMPAT_2_05) &&
+                    (compat_cpu_level < 2050)) {
+                    compat_cpu_level = 2050;
+                    pvr_new = pvr;
+                }
+                break;
+            case CPU_POWERPC_LOGICAL_2_06:
+                if ((pcc->pcr & POWERPC_ISA_COMPAT_2_06) &&
+                    (compat_cpu_level < 2060)) {
+                    compat_cpu_level = 2060;
+                    pvr_new = pvr;
+                }
+                break;
+            case CPU_POWERPC_LOGICAL_2_06_PLUS:
+                if ((pcc->pcr & POWERPC_ISA_COMPAT_2_06) &&
+                    (compat_cpu_level < 2061)) {
+                    compat_cpu_level = 2061;
+                    pvr_new = pvr;
+                }
+                break;
+            }
+        }
+
+        if (~pvr_mask & pvr) {
+            break;
+        }
+    }
+
+    /* Parsing finished. Making decision whether to reboot or not */
+    if (cpu_match) {
+        return H_SUCCESS;
+    }
+    if (pvr_new == cpu->env.spr[SPR_PVR]) {
+        return H_SUCCESS;
+    }
+
+    cpu->env.spr[SPR_PVR] = pvr_new;
+    spapr->pvr_new = pvr_new;
+    qemu_system_reset_request();
+
+    return H_FUNCTION;
+}
+
 static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
 static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
 
@@ -879,6 +952,9 @@ static void hypercall_register_types(void)
     spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
 
     spapr_register_hypercall(H_SET_MODE, h_set_mode);
+
+    /* ibm,client-architecture-support support */
+    spapr_register_hypercall(KVMPPC_H_CAS, h_client_architecture_support);
 }
 
 type_init(hypercall_register_types)
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 995ddcf..e2158ff 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -44,6 +44,9 @@ typedef struct sPAPREnvironment {
         uint64_t middle_iterations, middle_chunks, middle_valid, middle_invalid;
         uint64_t final_chunks, final_valid, final_invalid;
     } migstats;
+
+    uint32_t pvr_new;
+
 } sPAPREnvironment;
 
 #define H_SUCCESS         0
@@ -304,7 +307,9 @@ typedef struct sPAPREnvironment {
 #define KVMPPC_HCALL_BASE       0xf000
 #define KVMPPC_H_RTAS           (KVMPPC_HCALL_BASE + 0x0)
 #define KVMPPC_H_LOGICAL_MEMOP  (KVMPPC_HCALL_BASE + 0x1)
-#define KVMPPC_HCALL_MAX        KVMPPC_H_LOGICAL_MEMOP
+/* Client Architecture support */
+#define KVMPPC_H_CAS            (KVMPPC_HCALL_BASE + 0x2)
+#define KVMPPC_HCALL_MAX        KVMPPC_H_CAS
 
 extern sPAPREnvironment *spapr;
 
diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h
index 49ba4a4..a4e8763 100644
--- a/target-ppc/cpu-models.h
+++ b/target-ppc/cpu-models.h
@@ -583,6 +583,13 @@ enum {
     CPU_POWERPC_RS64II             = 0x00340000,
     CPU_POWERPC_RS64III            = 0x00360000,
     CPU_POWERPC_RS64IV             = 0x00370000,
+
+    /* Logical CPUs */
+    CPU_POWERPC_LOGICAL_MASK       = 0x0F000000,
+    CPU_POWERPC_LOGICAL_2_05       = 0x0F000002,
+    CPU_POWERPC_LOGICAL_2_06       = 0x0F000003,
+    CPU_POWERPC_LOGICAL_2_06_PLUS  = 0x0F100003,
+
 #endif /* defined(TARGET_PPC64) */
     /* Original POWER */
     /* XXX: should be POWER (RIOS), RSC3308, RSC4608,
@@ -745,4 +752,10 @@ enum {
     POWERPC_SVR_8641D              = 0x80900121,
 };
 
+/* Processor Compatibility Register (PCR) */
+enum {
+    POWERPC_ISA_COMPAT_2_05 = 1ULL << 62,
+    POWERPC_ISA_COMPAT_2_06 = 1ULL << 61,
+};
+
 #endif
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 0ae8b09..702ae96 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -55,6 +55,7 @@ typedef struct PowerPCCPUClass {
 
     uint32_t pvr;
     uint32_t pvr_mask;
+    uint64_t pcr;
     uint32_t svr;
     uint64_t insns_flags;
     uint64_t insns_flags2;
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index e8cc3c8..645f54d 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7249,6 +7249,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
     dc->desc = "POWER7";
     pcc->pvr = CPU_POWERPC_POWER7_BASE;
     pcc->pvr_mask = CPU_POWERPC_POWER7_MASK;
+    pcc->pcr = POWERPC_ISA_COMPAT_2_05 | POWERPC_ISA_COMPAT_2_06;
     pcc->init_proc = init_proc_POWER7;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
@@ -7286,6 +7287,7 @@ POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)
     dc->desc = "POWER7+";
     pcc->pvr = CPU_POWERPC_POWER7P_BASE;
     pcc->pvr_mask = CPU_POWERPC_POWER7P_MASK;
+    pcc->pcr = POWERPC_ISA_COMPAT_2_05 | POWERPC_ISA_COMPAT_2_06;
     pcc->init_proc = init_proc_POWER7;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
@@ -7323,6 +7325,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
     dc->desc = "POWER8";
     pcc->pvr = CPU_POWERPC_POWER8_BASE;
     pcc->pvr_mask = CPU_POWERPC_POWER8_MASK;
+    pcc->pcr = POWERPC_ISA_COMPAT_2_05 | POWERPC_ISA_COMPAT_2_06;
     pcc->init_proc = init_proc_POWER7;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
