*/
 #define VTCR_EL2_FLAGS         (VTCR_EL2_TG0_64K | VTCR_EL2_SH0_INNER | \
                                 VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \
-                                VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B | \
-                                VTCR_EL2_RES1)
+                                VTCR_EL2_SL0_LVL1 | VTCR_EL2_RES1)
 #define VTTBR_X                (38 - VTCR_EL2_T0SZ_40B)
 #else
 /*
  */
 #define VTCR_EL2_FLAGS         (VTCR_EL2_TG0_4K | VTCR_EL2_SH0_INNER | \
                                 VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \
-                                VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B | \
-                                VTCR_EL2_RES1)
+                                VTCR_EL2_SL0_LVL1 | VTCR_EL2_RES1)
 #define VTTBR_X                (37 - VTCR_EL2_T0SZ_40B)
 #endif
 
 
 
 extern u32 __kvm_get_mdcr_el2(void);
 
-extern void __init_stage2_translation(void);
+extern u32 __init_stage2_translation(void);
 
 #endif
 
 
 int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
                               struct kvm_device_attr *attr);
 
-/* #define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__) */
-
 static inline void __cpu_init_stage2(void)
 {
-       kvm_call_hyp(__init_stage2_translation);
+       u32 parange = kvm_call_hyp(__init_stage2_translation);
+
+       WARN_ONCE(parange < 40,
+                 "PARange is %d bits, unsupported configuration!", parange);
 }
 
 #endif /* __ARM64_KVM_HOST_H__ */
 
 #include <asm/kvm_asm.h>
 #include <asm/kvm_hyp.h>
 
-void __hyp_text __init_stage2_translation(void)
+u32 __hyp_text __init_stage2_translation(void)
 {
        u64 val = VTCR_EL2_FLAGS;
+       u64 parange;
        u64 tmp;
 
        /*
         * bits in VTCR_EL2. Amusingly, the PARange is 4 bits, while
         * PS is only 3. Fortunately, bit 19 is RES0 in VTCR_EL2...
         */
-       val |= (read_sysreg(id_aa64mmfr0_el1) & 7) << 16;
+       parange = read_sysreg(id_aa64mmfr0_el1) & 7;
+       val |= parange << 16;
+
+       /* Compute the actual PARange... */
+       switch (parange) {
+       case 0:
+               parange = 32;
+               break;
+       case 1:
+               parange = 36;
+               break;
+       case 2:
+               parange = 40;
+               break;
+       case 3:
+               parange = 42;
+               break;
+       case 4:
+               parange = 44;
+               break;
+       case 5:
+       default:
+               parange = 48;
+               break;
+       }
+
+       /*
+        * ... and clamp it to 40 bits, unless we have some braindead
+        * HW that implements less than that. In all cases, we'll
+        * return that value for the rest of the kernel to decide what
+        * to do.
+        */
+       val |= 64 - (parange > 40 ? 40 : parange);
 
        /*
         * Read the VMIDBits bits from ID_AA64MMFR1_EL1 and set the VS
                        VTCR_EL2_VS_8BIT;
 
        write_sysreg(val, vtcr_el2);
+
+       return parange;
 }