@@ -58,10 +58,27 @@ static uint64_t pte_index(struct kvm_vm *vm, vm_vaddr_t gva)
5858 return (gva >> vm -> page_shift ) & mask ;
5959}
6060
61- static uint64_t pte_addr (struct kvm_vm * vm , uint64_t entry )
61+ static uint64_t addr_pte (struct kvm_vm * vm , uint64_t pa , uint64_t attrs )
6262{
63- uint64_t mask = ((1UL << (vm -> va_bits - vm -> page_shift )) - 1 ) << vm -> page_shift ;
64- return entry & mask ;
63+ uint64_t pte ;
64+
65+ pte = pa & GENMASK (47 , vm -> page_shift );
66+ if (vm -> page_shift == 16 )
67+ pte |= FIELD_GET (GENMASK (51 , 48 ), pa ) << 12 ;
68+ pte |= attrs ;
69+
70+ return pte ;
71+ }
72+
73+ static uint64_t pte_addr (struct kvm_vm * vm , uint64_t pte )
74+ {
75+ uint64_t pa ;
76+
77+ pa = pte & GENMASK (47 , vm -> page_shift );
78+ if (vm -> page_shift == 16 )
79+ pa |= FIELD_GET (GENMASK (15 , 12 ), pte ) << 48 ;
80+
81+ return pa ;
6582}
6683
6784static uint64_t ptrs_per_pgd (struct kvm_vm * vm )
@@ -110,18 +127,18 @@ static void _virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
110127
111128 ptep = addr_gpa2hva (vm , vm -> pgd ) + pgd_index (vm , vaddr ) * 8 ;
112129 if (!* ptep )
113- * ptep = vm_alloc_page_table (vm ) | 3 ;
130+ * ptep = addr_pte ( vm , vm_alloc_page_table (vm ), 3 ) ;
114131
115132 switch (vm -> pgtable_levels ) {
116133 case 4 :
117134 ptep = addr_gpa2hva (vm , pte_addr (vm , * ptep )) + pud_index (vm , vaddr ) * 8 ;
118135 if (!* ptep )
119- * ptep = vm_alloc_page_table (vm ) | 3 ;
136+ * ptep = addr_pte ( vm , vm_alloc_page_table (vm ), 3 ) ;
120137 /* fall through */
121138 case 3 :
122139 ptep = addr_gpa2hva (vm , pte_addr (vm , * ptep )) + pmd_index (vm , vaddr ) * 8 ;
123140 if (!* ptep )
124- * ptep = vm_alloc_page_table (vm ) | 3 ;
141+ * ptep = addr_pte ( vm , vm_alloc_page_table (vm ), 3 ) ;
125142 /* fall through */
126143 case 2 :
127144 ptep = addr_gpa2hva (vm , pte_addr (vm , * ptep )) + pte_index (vm , vaddr ) * 8 ;
@@ -130,8 +147,7 @@ static void _virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
130147 TEST_FAIL ("Page table levels must be 2, 3, or 4" );
131148 }
132149
133- * ptep = paddr | 3 ;
134- * ptep |= (attr_idx << 2 ) | (1 << 10 ) /* Access Flag */ ;
150+ * ptep = addr_pte (vm , paddr , (attr_idx << 2 ) | (1 << 10 ) | 3 ); /* AF */
135151}
136152
137153void virt_arch_pg_map (struct kvm_vm * vm , uint64_t vaddr , uint64_t paddr )
@@ -226,7 +242,7 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
226242{
227243 struct kvm_vcpu_init default_init = { .target = -1 , };
228244 struct kvm_vm * vm = vcpu -> vm ;
229- uint64_t sctlr_el1 , tcr_el1 ;
245+ uint64_t sctlr_el1 , tcr_el1 , ttbr0_el1 ;
230246
231247 if (!init )
232248 init = & default_init ;
@@ -277,10 +293,13 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
277293 TEST_FAIL ("Unknown guest mode, mode: 0x%x" , vm -> mode );
278294 }
279295
296+ ttbr0_el1 = vm -> pgd & GENMASK (47 , vm -> page_shift );
297+
280298 /* Configure output size */
281299 switch (vm -> mode ) {
282300 case VM_MODE_P52V48_64K :
283301 tcr_el1 |= 6ul << 32 ; /* IPS = 52 bits */
302+ ttbr0_el1 |= FIELD_GET (GENMASK (51 , 48 ), vm -> pgd ) << 2 ;
284303 break ;
285304 case VM_MODE_P48V48_4K :
286305 case VM_MODE_P48V48_16K :
@@ -310,7 +329,7 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
310329 vcpu_set_reg (vcpu , KVM_ARM64_SYS_REG (SYS_SCTLR_EL1 ), sctlr_el1 );
311330 vcpu_set_reg (vcpu , KVM_ARM64_SYS_REG (SYS_TCR_EL1 ), tcr_el1 );
312331 vcpu_set_reg (vcpu , KVM_ARM64_SYS_REG (SYS_MAIR_EL1 ), DEFAULT_MAIR_EL1 );
313- vcpu_set_reg (vcpu , KVM_ARM64_SYS_REG (SYS_TTBR0_EL1 ), vm -> pgd );
332+ vcpu_set_reg (vcpu , KVM_ARM64_SYS_REG (SYS_TTBR0_EL1 ), ttbr0_el1 );
314333 vcpu_set_reg (vcpu , KVM_ARM64_SYS_REG (SYS_TPIDR_EL1 ), vcpu -> id );
315334}
316335
0 commit comments