Skip to content

Commit 342cd0a

Browse files
author
Christoffer Dall
committed
KVM: ARM: Hypervisor initialization
Sets up KVM code to handle all exceptions taken to Hyp mode. When the kernel is booted in Hyp mode, calling an hvc instruction with r0 pointing to the new vectors, the HVBAR is changed to the the vector pointers. This allows subsystems (like KVM here) to execute code in Hyp-mode with the MMU disabled. We initialize other Hyp-mode registers and enables the MMU for Hyp-mode from the id-mapped hyp initialization code. Afterwards, the HVBAR is changed to point to KVM Hyp vectors used to catch guest faults and to switch to Hyp mode to perform a world-switch into a KVM guest. Also provides memory mapping code to map required code pages, data structures, and I/O regions accessed in Hyp mode at the same virtual address as the host kernel virtual addresses, but which conforms to the architectural requirements for translations in Hyp mode. This interface is added in arch/arm/kvm/arm_mmu.c and comprises: - create_hyp_mappings(from, to); - create_hyp_io_mappings(from, to, phys_addr); - free_hyp_pmds(); Reviewed-by: Will Deacon <[email protected]> Reviewed-by: Marcelo Tosatti <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Christoffer Dall <[email protected]>
1 parent 749cf76 commit 342cd0a

File tree

9 files changed

+755
-0
lines changed

9 files changed

+755
-0
lines changed

arch/arm/include/asm/kvm_arm.h

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,128 @@
2121

2222
#include <linux/types.h>
2323

24+
/* Hyp Configuration Register (HCR) bits */
25+
#define HCR_TGE (1 << 27)
26+
#define HCR_TVM (1 << 26)
27+
#define HCR_TTLB (1 << 25)
28+
#define HCR_TPU (1 << 24)
29+
#define HCR_TPC (1 << 23)
30+
#define HCR_TSW (1 << 22)
31+
#define HCR_TAC (1 << 21)
32+
#define HCR_TIDCP (1 << 20)
33+
#define HCR_TSC (1 << 19)
34+
#define HCR_TID3 (1 << 18)
35+
#define HCR_TID2 (1 << 17)
36+
#define HCR_TID1 (1 << 16)
37+
#define HCR_TID0 (1 << 15)
38+
#define HCR_TWE (1 << 14)
39+
#define HCR_TWI (1 << 13)
40+
#define HCR_DC (1 << 12)
41+
#define HCR_BSU (3 << 10)
42+
#define HCR_BSU_IS (1 << 10)
43+
#define HCR_FB (1 << 9)
44+
#define HCR_VA (1 << 8)
45+
#define HCR_VI (1 << 7)
46+
#define HCR_VF (1 << 6)
47+
#define HCR_AMO (1 << 5)
48+
#define HCR_IMO (1 << 4)
49+
#define HCR_FMO (1 << 3)
50+
#define HCR_PTW (1 << 2)
51+
#define HCR_SWIO (1 << 1)
52+
#define HCR_VM 1
53+
54+
/*
55+
* The bits we set in HCR:
56+
* TAC: Trap ACTLR
57+
* TSC: Trap SMC
58+
* TSW: Trap cache operations by set/way
59+
* TWI: Trap WFI
60+
* TIDCP: Trap L2CTLR/L2ECTLR
61+
* BSU_IS: Upgrade barriers to the inner shareable domain
62+
* FB: Force broadcast of all maintainance operations
63+
* AMO: Override CPSR.A and enable signaling with VA
64+
* IMO: Override CPSR.I and enable signaling with VI
65+
* FMO: Override CPSR.F and enable signaling with VF
66+
* SWIO: Turn set/way invalidates into set/way clean+invalidate
67+
*/
68+
#define HCR_GUEST_MASK (HCR_TSC | HCR_TSW | HCR_TWI | HCR_VM | HCR_BSU_IS | \
69+
HCR_FB | HCR_TAC | HCR_AMO | HCR_IMO | HCR_FMO | \
70+
HCR_SWIO | HCR_TIDCP)
71+
72+
/* Hyp System Control Register (HSCTLR) bits */
73+
#define HSCTLR_TE (1 << 30)
74+
#define HSCTLR_EE (1 << 25)
75+
#define HSCTLR_FI (1 << 21)
76+
#define HSCTLR_WXN (1 << 19)
77+
#define HSCTLR_I (1 << 12)
78+
#define HSCTLR_C (1 << 2)
79+
#define HSCTLR_A (1 << 1)
80+
#define HSCTLR_M 1
81+
#define HSCTLR_MASK (HSCTLR_M | HSCTLR_A | HSCTLR_C | HSCTLR_I | \
82+
HSCTLR_WXN | HSCTLR_FI | HSCTLR_EE | HSCTLR_TE)
83+
84+
/* TTBCR and HTCR Registers bits */
85+
#define TTBCR_EAE (1 << 31)
86+
#define TTBCR_IMP (1 << 30)
87+
#define TTBCR_SH1 (3 << 28)
88+
#define TTBCR_ORGN1 (3 << 26)
89+
#define TTBCR_IRGN1 (3 << 24)
90+
#define TTBCR_EPD1 (1 << 23)
91+
#define TTBCR_A1 (1 << 22)
92+
#define TTBCR_T1SZ (3 << 16)
93+
#define TTBCR_SH0 (3 << 12)
94+
#define TTBCR_ORGN0 (3 << 10)
95+
#define TTBCR_IRGN0 (3 << 8)
96+
#define TTBCR_EPD0 (1 << 7)
97+
#define TTBCR_T0SZ 3
98+
#define HTCR_MASK (TTBCR_T0SZ | TTBCR_IRGN0 | TTBCR_ORGN0 | TTBCR_SH0)
99+
100+
/* Hyp Debug Configuration Register bits */
101+
#define HDCR_TDRA (1 << 11)
102+
#define HDCR_TDOSA (1 << 10)
103+
#define HDCR_TDA (1 << 9)
104+
#define HDCR_TDE (1 << 8)
105+
#define HDCR_HPME (1 << 7)
106+
#define HDCR_TPM (1 << 6)
107+
#define HDCR_TPMCR (1 << 5)
108+
#define HDCR_HPMN_MASK (0x1F)
109+
110+
/*
111+
* The architecture supports 40-bit IPA as input to the 2nd stage translations
112+
* and PTRS_PER_S2_PGD becomes 1024, because each entry covers 1GB of address
113+
* space.
114+
*/
115+
#define KVM_PHYS_SHIFT (40)
116+
#define KVM_PHYS_SIZE (1ULL << KVM_PHYS_SHIFT)
117+
#define KVM_PHYS_MASK (KVM_PHYS_SIZE - 1ULL)
118+
#define PTRS_PER_S2_PGD (1ULL << (KVM_PHYS_SHIFT - 30))
119+
#define S2_PGD_ORDER get_order(PTRS_PER_S2_PGD * sizeof(pgd_t))
120+
#define S2_PGD_SIZE (1 << S2_PGD_ORDER)
121+
122+
/* Virtualization Translation Control Register (VTCR) bits */
123+
#define VTCR_SH0 (3 << 12)
124+
#define VTCR_ORGN0 (3 << 10)
125+
#define VTCR_IRGN0 (3 << 8)
126+
#define VTCR_SL0 (3 << 6)
127+
#define VTCR_S (1 << 4)
128+
#define VTCR_T0SZ (0xf)
129+
#define VTCR_MASK (VTCR_SH0 | VTCR_ORGN0 | VTCR_IRGN0 | VTCR_SL0 | \
130+
VTCR_S | VTCR_T0SZ)
131+
#define VTCR_HTCR_SH (VTCR_SH0 | VTCR_ORGN0 | VTCR_IRGN0)
132+
#define VTCR_SL_L2 (0 << 6) /* Starting-level: 2 */
133+
#define VTCR_SL_L1 (1 << 6) /* Starting-level: 1 */
134+
#define KVM_VTCR_SL0 VTCR_SL_L1
135+
/* stage-2 input address range defined as 2^(32-T0SZ) */
136+
#define KVM_T0SZ (32 - KVM_PHYS_SHIFT)
137+
#define KVM_VTCR_T0SZ (KVM_T0SZ & VTCR_T0SZ)
138+
#define KVM_VTCR_S ((KVM_VTCR_T0SZ << 1) & VTCR_S)
139+
140+
/* Virtualization Translation Table Base Register (VTTBR) bits */
141+
#if KVM_VTCR_SL0 == VTCR_SL_L2 /* see ARM DDI 0406C: B4-1720 */
142+
#define VTTBR_X (14 - KVM_T0SZ)
143+
#else
144+
#define VTTBR_X (5 - KVM_T0SZ)
145+
#endif
146+
147+
24148
#endif /* __ARM_KVM_ARM_H__ */

arch/arm/include/asm/kvm_asm.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,25 @@
5454
#define ARM_EXCEPTION_DATA_ABORT 4
5555
#define ARM_EXCEPTION_IRQ 5
5656
#define ARM_EXCEPTION_FIQ 6
57+
#define ARM_EXCEPTION_HVC 7
58+
59+
#ifndef __ASSEMBLY__
60+
struct kvm_vcpu;
61+
62+
extern char __kvm_hyp_init[];
63+
extern char __kvm_hyp_init_end[];
64+
65+
extern char __kvm_hyp_exit[];
66+
extern char __kvm_hyp_exit_end[];
67+
68+
extern char __kvm_hyp_vector[];
69+
70+
extern char __kvm_hyp_code_start[];
71+
extern char __kvm_hyp_code_end[];
72+
73+
extern void __kvm_flush_vm_context(void);
74+
75+
extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
76+
#endif
5777

5878
#endif /* __ARM_KVM_ASM_H__ */

arch/arm/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,5 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
111111
struct kvm_one_reg;
112112
int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
113113
int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
114+
u64 kvm_call_hyp(void *hypfn, ...);
114115
#endif /* __ARM_KVM_HOST_H__ */

arch/arm/include/asm/kvm_mmu.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (C) 2012 - Virtual Open Systems and Columbia University
3+
* Author: Christoffer Dall <[email protected]>
4+
*
5+
* This program is free software; you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License, version 2, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, write to the Free Software
16+
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17+
*/
18+
19+
#ifndef __ARM_KVM_MMU_H__
20+
#define __ARM_KVM_MMU_H__
21+
22+
int create_hyp_mappings(void *from, void *to);
23+
int create_hyp_io_mappings(void *from, void *to, phys_addr_t);
24+
void free_hyp_pmds(void);
25+
26+
phys_addr_t kvm_mmu_get_httbr(void);
27+
int kvm_mmu_init(void);
28+
void kvm_clear_hyp_idmap(void);
29+
#endif /* __ARM_KVM_MMU_H__ */

arch/arm/include/asm/pgtable-3level-hwdef.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
#define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0)
3333
#define PMD_BIT4 (_AT(pmdval_t, 0))
3434
#define PMD_DOMAIN(x) (_AT(pmdval_t, 0))
35+
#define PMD_APTABLE_SHIFT (61)
36+
#define PMD_APTABLE (_AT(pgdval_t, 3) << PGD_APTABLE_SHIFT)
37+
#define PMD_PXNTABLE (_AT(pgdval_t, 1) << 59)
3538

3639
/*
3740
* - section
@@ -41,6 +44,7 @@
4144
#define PMD_SECT_S (_AT(pmdval_t, 3) << 8)
4245
#define PMD_SECT_AF (_AT(pmdval_t, 1) << 10)
4346
#define PMD_SECT_nG (_AT(pmdval_t, 1) << 11)
47+
#define PMD_SECT_PXN (_AT(pmdval_t, 1) << 53)
4448
#define PMD_SECT_XN (_AT(pmdval_t, 1) << 54)
4549
#define PMD_SECT_AP_WRITE (_AT(pmdval_t, 0))
4650
#define PMD_SECT_AP_READ (_AT(pmdval_t, 0))

0 commit comments

Comments
 (0)