|
@@ -20,9 +20,10 @@
|
|
|
#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;
|
|
|
|
|
|
/*
|
|
@@ -30,7 +31,39 @@ void __hyp_text __init_stage2_translation(void)
|
|
|
* 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
|
|
@@ -42,4 +75,6 @@ void __hyp_text __init_stage2_translation(void)
|
|
|
VTCR_EL2_VS_8BIT;
|
|
|
|
|
|
write_sysreg(val, vtcr_el2);
|
|
|
+
|
|
|
+ return parange;
|
|
|
}
|