1212#include "kvm_util.h"
1313#include "processor.h"
1414#include <linux/bitfield.h>
15+ #include <linux/sizes.h>
1516
1617#define DEFAULT_ARM64_GUEST_STACK_VADDR_MIN 0xac0000
1718
@@ -58,13 +59,25 @@ static uint64_t pte_index(struct kvm_vm *vm, vm_vaddr_t gva)
5859 return (gva >> vm -> page_shift ) & mask ;
5960}
6061
62+ static inline bool use_lpa2_pte_format (struct kvm_vm * vm )
63+ {
64+ return (vm -> page_size == SZ_4K || vm -> page_size == SZ_16K ) &&
65+ (vm -> pa_bits > 48 || vm -> va_bits > 48 );
66+ }
67+
6168static uint64_t addr_pte (struct kvm_vm * vm , uint64_t pa , uint64_t attrs )
6269{
6370 uint64_t pte ;
6471
65- pte = pa & GENMASK (47 , vm -> page_shift );
66- if (vm -> page_shift == 16 )
67- pte |= FIELD_GET (GENMASK (51 , 48 ), pa ) << 12 ;
72+ if (use_lpa2_pte_format (vm )) {
73+ pte = pa & GENMASK (49 , vm -> page_shift );
74+ pte |= FIELD_GET (GENMASK (51 , 50 ), pa ) << 8 ;
75+ attrs &= ~GENMASK (9 , 8 );
76+ } else {
77+ pte = pa & GENMASK (47 , vm -> page_shift );
78+ if (vm -> page_shift == 16 )
79+ pte |= FIELD_GET (GENMASK (51 , 48 ), pa ) << 12 ;
80+ }
6881 pte |= attrs ;
6982
7083 return pte ;
@@ -74,9 +87,14 @@ static uint64_t pte_addr(struct kvm_vm *vm, uint64_t pte)
7487{
7588 uint64_t pa ;
7689
77- pa = pte & GENMASK (47 , vm -> page_shift );
78- if (vm -> page_shift == 16 )
79- pa |= FIELD_GET (GENMASK (15 , 12 ), pte ) << 48 ;
90+ if (use_lpa2_pte_format (vm )) {
91+ pa = pte & GENMASK (49 , vm -> page_shift );
92+ pa |= FIELD_GET (GENMASK (9 , 8 ), pte ) << 50 ;
93+ } else {
94+ pa = pte & GENMASK (47 , vm -> page_shift );
95+ if (vm -> page_shift == 16 )
96+ pa |= FIELD_GET (GENMASK (15 , 12 ), pte ) << 48 ;
97+ }
8098
8199 return pa ;
82100}
@@ -266,9 +284,6 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
266284
267285 /* Configure base granule size */
268286 switch (vm -> mode ) {
269- case VM_MODE_P52V48_4K :
270- TEST_FAIL ("AArch64 does not support 4K sized pages "
271- "with 52-bit physical address ranges" );
272287 case VM_MODE_PXXV48_4K :
273288 TEST_FAIL ("AArch64 does not support 4K sized pages "
274289 "with ANY-bit physical address ranges" );
@@ -278,12 +293,14 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
278293 case VM_MODE_P36V48_64K :
279294 tcr_el1 |= 1ul << 14 ; /* TG0 = 64KB */
280295 break ;
296+ case VM_MODE_P52V48_16K :
281297 case VM_MODE_P48V48_16K :
282298 case VM_MODE_P40V48_16K :
283299 case VM_MODE_P36V48_16K :
284300 case VM_MODE_P36V47_16K :
285301 tcr_el1 |= 2ul << 14 ; /* TG0 = 16KB */
286302 break ;
303+ case VM_MODE_P52V48_4K :
287304 case VM_MODE_P48V48_4K :
288305 case VM_MODE_P40V48_4K :
289306 case VM_MODE_P36V48_4K :
@@ -297,6 +314,8 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
297314
298315 /* Configure output size */
299316 switch (vm -> mode ) {
317+ case VM_MODE_P52V48_4K :
318+ case VM_MODE_P52V48_16K :
300319 case VM_MODE_P52V48_64K :
301320 tcr_el1 |= 6ul << 32 ; /* IPS = 52 bits */
302321 ttbr0_el1 |= FIELD_GET (GENMASK (51 , 48 ), vm -> pgd ) << 2 ;
@@ -325,6 +344,8 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
325344 /* TCR_EL1 |= IRGN0:WBWA | ORGN0:WBWA | SH0:Inner-Shareable */ ;
326345 tcr_el1 |= (1 << 8 ) | (1 << 10 ) | (3 << 12 );
327346 tcr_el1 |= (64 - vm -> va_bits ) /* T0SZ */ ;
347+ if (use_lpa2_pte_format (vm ))
348+ tcr_el1 |= (1ul << 59 ) /* DS */ ;
328349
329350 vcpu_set_reg (vcpu , KVM_ARM64_SYS_REG (SYS_SCTLR_EL1 ), sctlr_el1 );
330351 vcpu_set_reg (vcpu , KVM_ARM64_SYS_REG (SYS_TCR_EL1 ), tcr_el1 );
0 commit comments