Skip to content

Commit 7dd2157

Browse files
committed
Merge tag 'kvm-ppc-next-4.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc into HEAD
PPC KVM update for 4.20. The major new feature here is nested HV KVM support. This allows the HV KVM module to load inside a radix guest on POWER9 and run radix guests underneath it. These nested guests can run in supervisor mode and don't require any additional instructions to be emulated, unlike with PR KVM, and so performance is much better than with PR KVM, and is very close to the performance of a non-nested guest. A nested hypervisor (a guest with nested guests) can be migrated to another host and will bring all its nested guests along with it. A nested guest can also itself run guests, and so on down to any desired depth of nesting. Apart from that there are a series of updates for IOMMU handling from Alexey Kardashevskiy, a "one VM per core" mode for HV KVM for security-paranoid applications, and a small fix for PR KVM.
2 parents dd5bd0a + 901f8c3 commit 7dd2157

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+3933
-905
lines changed

Documentation/virtual/kvm/api.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,6 +1922,7 @@ registers, find a list below:
19221922
PPC | KVM_REG_PPC_TIDR | 64
19231923
PPC | KVM_REG_PPC_PSSCR | 64
19241924
PPC | KVM_REG_PPC_DEC_EXPIRY | 64
1925+
PPC | KVM_REG_PPC_PTCR | 64
19251926
PPC | KVM_REG_PPC_TM_GPR0 | 64
19261927
...
19271928
PPC | KVM_REG_PPC_TM_GPR31 | 64
@@ -2269,6 +2270,10 @@ The supported flags are:
22692270
The emulated MMU supports 1T segments in addition to the
22702271
standard 256M ones.
22712272

2273+
- KVM_PPC_NO_HASH
2274+
This flag indicates that HPT guests are not supported by KVM,
2275+
thus all guests must use radix MMU mode.
2276+
22722277
The "slb_size" field indicates how many SLB entries are supported
22732278

22742279
The "sps" array contains 8 entries indicating the supported base
@@ -4531,6 +4536,20 @@ With this capability, a guest may read the MSR_PLATFORM_INFO MSR. Otherwise,
45314536
a #GP would be raised when the guest tries to access. Currently, this
45324537
capability does not enable write permissions of this MSR for the guest.
45334538

4539+
7.16 KVM_CAP_PPC_NESTED_HV
4540+
4541+
Architectures: ppc
4542+
Parameters: none
4543+
Returns: 0 on success, -EINVAL when the implementation doesn't support
4544+
nested-HV virtualization.
4545+
4546+
HV-KVM on POWER9 and later systems allows for "nested-HV"
4547+
virtualization, which provides a way for a guest VM to run guests that
4548+
can run using the CPU's supervisor mode (privileged non-hypervisor
4549+
state). Enabling this capability on a VM depends on the CPU having
4550+
the necessary functionality and on the facility being enabled with a
4551+
kvm-hv module parameter.
4552+
45344553
8. Other capabilities.
45354554
----------------------
45364555

arch/powerpc/include/asm/asm-prototypes.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,25 @@ extern s32 patch__memset_nocache, patch__memcpy_nocache;
150150

151151
extern long flush_count_cache;
152152

153+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
154+
void kvmppc_save_tm_hv(struct kvm_vcpu *vcpu, u64 msr, bool preserve_nv);
155+
void kvmppc_restore_tm_hv(struct kvm_vcpu *vcpu, u64 msr, bool preserve_nv);
156+
#else
157+
static inline void kvmppc_save_tm_hv(struct kvm_vcpu *vcpu, u64 msr,
158+
bool preserve_nv) { }
159+
static inline void kvmppc_restore_tm_hv(struct kvm_vcpu *vcpu, u64 msr,
160+
bool preserve_nv) { }
161+
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
162+
163+
void kvmhv_save_host_pmu(void);
164+
void kvmhv_load_host_pmu(void);
165+
void kvmhv_save_guest_pmu(struct kvm_vcpu *vcpu, bool pmu_in_use);
166+
void kvmhv_load_guest_pmu(struct kvm_vcpu *vcpu);
167+
168+
int __kvmhv_vcpu_entry_p9(struct kvm_vcpu *vcpu);
169+
170+
long kvmppc_h_set_dabr(struct kvm_vcpu *vcpu, unsigned long dabr);
171+
long kvmppc_h_set_xdabr(struct kvm_vcpu *vcpu, unsigned long dabr,
172+
unsigned long dabrx);
173+
153174
#endif /* _ASM_POWERPC_ASM_PROTOTYPES_H */

arch/powerpc/include/asm/book3s/64/mmu-hash.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,18 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
203203
BUG();
204204
}
205205

206+
static inline unsigned int ap_to_shift(unsigned long ap)
207+
{
208+
int psize;
209+
210+
for (psize = 0; psize < MMU_PAGE_COUNT; psize++) {
211+
if (mmu_psize_defs[psize].ap == ap)
212+
return mmu_psize_defs[psize].shift;
213+
}
214+
215+
return -1;
216+
}
217+
206218
static inline unsigned long get_sllp_encoding(int psize)
207219
{
208220
unsigned long sllp;

arch/powerpc/include/asm/book3s/64/tlbflush-radix.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ extern void radix__flush_tlb_lpid_page(unsigned int lpid,
5353
unsigned long addr,
5454
unsigned long page_size);
5555
extern void radix__flush_pwc_lpid(unsigned int lpid);
56+
extern void radix__flush_tlb_lpid(unsigned int lpid);
5657
extern void radix__local_flush_tlb_lpid(unsigned int lpid);
5758
extern void radix__local_flush_tlb_lpid_guest(unsigned int lpid);
5859

arch/powerpc/include/asm/hvcall.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,11 @@
322322
#define H_GET_24X7_DATA 0xF07C
323323
#define H_GET_PERF_COUNTER_INFO 0xF080
324324

325+
/* Platform-specific hcalls used for nested HV KVM */
326+
#define H_SET_PARTITION_TABLE 0xF800
327+
#define H_ENTER_NESTED 0xF804
328+
#define H_TLB_INVALIDATE 0xF808
329+
325330
/* Values for 2nd argument to H_SET_MODE */
326331
#define H_SET_MODE_RESOURCE_SET_CIABR 1
327332
#define H_SET_MODE_RESOURCE_SET_DAWR 2
@@ -461,6 +466,42 @@ struct h_cpu_char_result {
461466
u64 behaviour;
462467
};
463468

469+
/* Register state for entering a nested guest with H_ENTER_NESTED */
470+
struct hv_guest_state {
471+
u64 version; /* version of this structure layout */
472+
u32 lpid;
473+
u32 vcpu_token;
474+
/* These registers are hypervisor privileged (at least for writing) */
475+
u64 lpcr;
476+
u64 pcr;
477+
u64 amor;
478+
u64 dpdes;
479+
u64 hfscr;
480+
s64 tb_offset;
481+
u64 dawr0;
482+
u64 dawrx0;
483+
u64 ciabr;
484+
u64 hdec_expiry;
485+
u64 purr;
486+
u64 spurr;
487+
u64 ic;
488+
u64 vtb;
489+
u64 hdar;
490+
u64 hdsisr;
491+
u64 heir;
492+
u64 asdr;
493+
/* These are OS privileged but need to be set late in guest entry */
494+
u64 srr0;
495+
u64 srr1;
496+
u64 sprg[4];
497+
u64 pidr;
498+
u64 cfar;
499+
u64 ppr;
500+
};
501+
502+
/* Latest version of hv_guest_state structure */
503+
#define HV_GUEST_STATE_VERSION 1
504+
464505
#endif /* __ASSEMBLY__ */
465506
#endif /* __KERNEL__ */
466507
#endif /* _ASM_POWERPC_HVCALL_H */

arch/powerpc/include/asm/kvm_asm.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@
8484
#define BOOK3S_INTERRUPT_INST_STORAGE 0x400
8585
#define BOOK3S_INTERRUPT_INST_SEGMENT 0x480
8686
#define BOOK3S_INTERRUPT_EXTERNAL 0x500
87-
#define BOOK3S_INTERRUPT_EXTERNAL_LEVEL 0x501
8887
#define BOOK3S_INTERRUPT_EXTERNAL_HV 0x502
8988
#define BOOK3S_INTERRUPT_ALIGNMENT 0x600
9089
#define BOOK3S_INTERRUPT_PROGRAM 0x700
@@ -134,8 +133,7 @@
134133
#define BOOK3S_IRQPRIO_EXTERNAL 14
135134
#define BOOK3S_IRQPRIO_DECREMENTER 15
136135
#define BOOK3S_IRQPRIO_PERFORMANCE_MONITOR 16
137-
#define BOOK3S_IRQPRIO_EXTERNAL_LEVEL 17
138-
#define BOOK3S_IRQPRIO_MAX 18
136+
#define BOOK3S_IRQPRIO_MAX 17
139137

140138
#define BOOK3S_HFLAG_DCBZ32 0x1
141139
#define BOOK3S_HFLAG_SLB 0x2

arch/powerpc/include/asm/kvm_book3s.h

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,37 @@ extern int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hc);
188188
extern int kvmppc_book3s_radix_page_fault(struct kvm_run *run,
189189
struct kvm_vcpu *vcpu,
190190
unsigned long ea, unsigned long dsisr);
191+
extern int kvmppc_mmu_walk_radix_tree(struct kvm_vcpu *vcpu, gva_t eaddr,
192+
struct kvmppc_pte *gpte, u64 root,
193+
u64 *pte_ret_p);
194+
extern int kvmppc_mmu_radix_translate_table(struct kvm_vcpu *vcpu, gva_t eaddr,
195+
struct kvmppc_pte *gpte, u64 table,
196+
int table_index, u64 *pte_ret_p);
191197
extern int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
192198
struct kvmppc_pte *gpte, bool data, bool iswrite);
199+
extern void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, unsigned long gpa,
200+
unsigned int shift, struct kvm_memory_slot *memslot,
201+
unsigned int lpid);
202+
extern bool kvmppc_hv_handle_set_rc(struct kvm *kvm, pgd_t *pgtable,
203+
bool writing, unsigned long gpa,
204+
unsigned int lpid);
205+
extern int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu,
206+
unsigned long gpa,
207+
struct kvm_memory_slot *memslot,
208+
bool writing, bool kvm_ro,
209+
pte_t *inserted_pte, unsigned int *levelp);
193210
extern int kvmppc_init_vm_radix(struct kvm *kvm);
194211
extern void kvmppc_free_radix(struct kvm *kvm);
212+
extern void kvmppc_free_pgtable_radix(struct kvm *kvm, pgd_t *pgd,
213+
unsigned int lpid);
195214
extern int kvmppc_radix_init(void);
196215
extern void kvmppc_radix_exit(void);
197216
extern int kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
198217
unsigned long gfn);
218+
extern void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte,
219+
unsigned long gpa, unsigned int shift,
220+
struct kvm_memory_slot *memslot,
221+
unsigned int lpid);
199222
extern int kvm_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
200223
unsigned long gfn);
201224
extern int kvm_test_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
@@ -271,6 +294,21 @@ static inline void kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu) {}
271294
static inline void kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu) {}
272295
#endif
273296

297+
long kvmhv_nested_init(void);
298+
void kvmhv_nested_exit(void);
299+
void kvmhv_vm_nested_init(struct kvm *kvm);
300+
long kvmhv_set_partition_table(struct kvm_vcpu *vcpu);
301+
void kvmhv_set_ptbl_entry(unsigned int lpid, u64 dw0, u64 dw1);
302+
void kvmhv_release_all_nested(struct kvm *kvm);
303+
long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu);
304+
long kvmhv_do_nested_tlbie(struct kvm_vcpu *vcpu);
305+
int kvmhv_run_single_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu,
306+
u64 time_limit, unsigned long lpcr);
307+
void kvmhv_save_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr);
308+
void kvmhv_restore_hv_return_state(struct kvm_vcpu *vcpu,
309+
struct hv_guest_state *hr);
310+
long int kvmhv_nested_page_fault(struct kvm_vcpu *vcpu);
311+
274312
void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac);
275313

276314
extern int kvm_irq_bypass;
@@ -301,12 +339,12 @@ static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num)
301339

302340
static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val)
303341
{
304-
vcpu->arch.cr = val;
342+
vcpu->arch.regs.ccr = val;
305343
}
306344

307345
static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu)
308346
{
309-
return vcpu->arch.cr;
347+
return vcpu->arch.regs.ccr;
310348
}
311349

312350
static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, ulong val)
@@ -384,9 +422,6 @@ extern int kvmppc_h_logical_ci_store(struct kvm_vcpu *vcpu);
384422
/* TO = 31 for unconditional trap */
385423
#define INS_TW 0x7fe00008
386424

387-
/* LPIDs we support with this build -- runtime limit may be lower */
388-
#define KVMPPC_NR_LPIDS (LPID_RSVD + 1)
389-
390425
#define SPLIT_HACK_MASK 0xff000000
391426
#define SPLIT_HACK_OFFS 0xfb000000
392427

0 commit comments

Comments
 (0)