Skip to content

Commit 3ff0327

Browse files
committed
Merge tag 'kvm-ppc-next-5.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc into kvm-next-5.6
PPC KVM update for 5.9 - Improvements and bug-fixes for secure VM support, giving reduced startup time and memory hotplug support. - Locking fixes in nested KVM code - Increase number of guests supported by HV KVM to 4094 - Preliminary POWER10 support
2 parents 43bd9ef + 81ab595 commit 3ff0327

16 files changed

+647
-244
lines changed

Documentation/powerpc/ultravisor.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,7 @@ Return values
895895
One of the following values:
896896

897897
* H_SUCCESS on success.
898+
* H_STATE if the VM is not in a position to switch to secure.
898899

899900
Description
900901
~~~~~~~~~~~
@@ -933,6 +934,8 @@ Return values
933934
* H_UNSUPPORTED if called from the wrong context (e.g.
934935
from an SVM or before an H_SVM_INIT_START
935936
hypercall).
937+
* H_STATE if the hypervisor could not successfully
938+
transition the VM to Secure VM.
936939

937940
Description
938941
~~~~~~~~~~~

arch/powerpc/include/asm/kvm_book3s_uvmem.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn);
2323
unsigned long kvmppc_h_svm_init_abort(struct kvm *kvm);
2424
void kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free,
2525
struct kvm *kvm, bool skip_page_out);
26+
int kvmppc_uvmem_memslot_create(struct kvm *kvm,
27+
const struct kvm_memory_slot *new);
28+
void kvmppc_uvmem_memslot_delete(struct kvm *kvm,
29+
const struct kvm_memory_slot *old);
2630
#else
2731
static inline int kvmppc_uvmem_init(void)
2832
{
@@ -82,5 +86,15 @@ static inline int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn)
8286
static inline void
8387
kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free,
8488
struct kvm *kvm, bool skip_page_out) { }
89+
90+
static inline int kvmppc_uvmem_memslot_create(struct kvm *kvm,
91+
const struct kvm_memory_slot *new)
92+
{
93+
return H_UNSUPPORTED;
94+
}
95+
96+
static inline void kvmppc_uvmem_memslot_delete(struct kvm *kvm,
97+
const struct kvm_memory_slot *old) { }
98+
8599
#endif /* CONFIG_PPC_UV */
86100
#endif /* __ASM_KVM_BOOK3S_UVMEM_H__ */

arch/powerpc/include/asm/kvm_ppc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ enum xlate_readwrite {
5959
};
6060

6161
extern int kvmppc_vcpu_run(struct kvm_vcpu *vcpu);
62-
extern int __kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu);
62+
extern int __kvmppc_vcpu_run(struct kvm_vcpu *vcpu);
6363
extern void kvmppc_handler_highmem(void);
6464

6565
extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu);

arch/powerpc/include/asm/reg.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,8 @@
474474
#ifndef SPRN_LPID
475475
#define SPRN_LPID 0x13F /* Logical Partition Identifier */
476476
#endif
477-
#define LPID_RSVD 0x3ff /* Reserved LPID for partn switching */
477+
#define LPID_RSVD_POWER7 0x3ff /* Reserved LPID for partn switching */
478+
#define LPID_RSVD 0xfff /* Reserved LPID for partn switching */
478479
#define SPRN_HMER 0x150 /* Hypervisor maintenance exception reg */
479480
#define HMER_DEBUG_TRIG (1ul << (63 - 17)) /* Debug trigger */
480481
#define SPRN_HMEER 0x151 /* Hyp maintenance exception enable reg */
@@ -1362,6 +1363,7 @@
13621363
#define PVR_ARCH_206p 0x0f100003
13631364
#define PVR_ARCH_207 0x0f000004
13641365
#define PVR_ARCH_300 0x0f000005
1366+
#define PVR_ARCH_31 0x0f000006
13651367

13661368
/* Macros for setting and retrieving special purpose registers */
13671369
#ifndef __ASSEMBLY__

arch/powerpc/kvm/book3s_64_mmu_hv.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,11 +260,15 @@ int kvmppc_mmu_hv_init(void)
260260
if (!mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE))
261261
return -EINVAL;
262262

263-
/* POWER7 has 10-bit LPIDs (12-bit in POWER8) */
264263
host_lpid = 0;
265264
if (cpu_has_feature(CPU_FTR_HVMODE))
266265
host_lpid = mfspr(SPRN_LPID);
267-
rsvd_lpid = LPID_RSVD;
266+
267+
/* POWER8 and above have 12-bit LPIDs (10-bit in POWER7) */
268+
if (cpu_has_feature(CPU_FTR_ARCH_207S))
269+
rsvd_lpid = LPID_RSVD;
270+
else
271+
rsvd_lpid = LPID_RSVD_POWER7;
268272

269273
kvmppc_init_lpid(rsvd_lpid + 1);
270274

arch/powerpc/kvm/book3s_64_mmu_radix.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ int kvmppc_mmu_walk_radix_tree(struct kvm_vcpu *vcpu, gva_t eaddr,
161161
return -EINVAL;
162162
/* Read the entry from guest memory */
163163
addr = base + (index * sizeof(rpte));
164+
vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
164165
ret = kvm_read_guest(kvm, addr, &rpte, sizeof(rpte));
166+
srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
165167
if (ret) {
166168
if (pte_ret_p)
167169
*pte_ret_p = addr;
@@ -237,7 +239,9 @@ int kvmppc_mmu_radix_translate_table(struct kvm_vcpu *vcpu, gva_t eaddr,
237239

238240
/* Read the table to find the root of the radix tree */
239241
ptbl = (table & PRTB_MASK) + (table_index * sizeof(entry));
242+
vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
240243
ret = kvm_read_guest(kvm, ptbl, &entry, sizeof(entry));
244+
srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
241245
if (ret)
242246
return ret;
243247

arch/powerpc/kvm/book3s_hv.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -343,13 +343,18 @@ static void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 pvr)
343343
vcpu->arch.pvr = pvr;
344344
}
345345

346+
/* Dummy value used in computing PCR value below */
347+
#define PCR_ARCH_31 (PCR_ARCH_300 << 1)
348+
346349
static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
347350
{
348351
unsigned long host_pcr_bit = 0, guest_pcr_bit = 0;
349352
struct kvmppc_vcore *vc = vcpu->arch.vcore;
350353

351354
/* We can (emulate) our own architecture version and anything older */
352-
if (cpu_has_feature(CPU_FTR_ARCH_300))
355+
if (cpu_has_feature(CPU_FTR_ARCH_31))
356+
host_pcr_bit = PCR_ARCH_31;
357+
else if (cpu_has_feature(CPU_FTR_ARCH_300))
353358
host_pcr_bit = PCR_ARCH_300;
354359
else if (cpu_has_feature(CPU_FTR_ARCH_207S))
355360
host_pcr_bit = PCR_ARCH_207;
@@ -375,6 +380,9 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
375380
case PVR_ARCH_300:
376381
guest_pcr_bit = PCR_ARCH_300;
377382
break;
383+
case PVR_ARCH_31:
384+
guest_pcr_bit = PCR_ARCH_31;
385+
break;
378386
default:
379387
return -EINVAL;
380388
}
@@ -2355,7 +2363,7 @@ static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu)
23552363
* to trap and then we emulate them.
23562364
*/
23572365
vcpu->arch.hfscr = HFSCR_TAR | HFSCR_EBB | HFSCR_PM | HFSCR_BHRB |
2358-
HFSCR_DSCR | HFSCR_VECVSX | HFSCR_FP;
2366+
HFSCR_DSCR | HFSCR_VECVSX | HFSCR_FP | HFSCR_PREFIX;
23592367
if (cpu_has_feature(CPU_FTR_HVMODE)) {
23602368
vcpu->arch.hfscr &= mfspr(SPRN_HFSCR);
23612369
if (cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST))
@@ -4552,16 +4560,14 @@ static void kvmppc_core_commit_memory_region_hv(struct kvm *kvm,
45524560

45534561
switch (change) {
45544562
case KVM_MR_CREATE:
4555-
if (kvmppc_uvmem_slot_init(kvm, new))
4556-
return;
4557-
uv_register_mem_slot(kvm->arch.lpid,
4558-
new->base_gfn << PAGE_SHIFT,
4559-
new->npages * PAGE_SIZE,
4560-
0, new->id);
4563+
/*
4564+
* @TODO kvmppc_uvmem_memslot_create() can fail and
4565+
* return error. Fix this.
4566+
*/
4567+
kvmppc_uvmem_memslot_create(kvm, new);
45614568
break;
45624569
case KVM_MR_DELETE:
4563-
uv_unregister_mem_slot(kvm->arch.lpid, old->id);
4564-
kvmppc_uvmem_slot_free(kvm, old);
4570+
kvmppc_uvmem_memslot_delete(kvm, old);
45654571
break;
45664572
default:
45674573
/* TODO: Handle KVM_MR_MOVE */

arch/powerpc/kvm/book3s_hv_nested.c

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -233,20 +233,21 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu)
233233

234234
/* copy parameters in */
235235
hv_ptr = kvmppc_get_gpr(vcpu, 4);
236+
regs_ptr = kvmppc_get_gpr(vcpu, 5);
237+
vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
236238
err = kvm_vcpu_read_guest(vcpu, hv_ptr, &l2_hv,
237-
sizeof(struct hv_guest_state));
239+
sizeof(struct hv_guest_state)) ||
240+
kvm_vcpu_read_guest(vcpu, regs_ptr, &l2_regs,
241+
sizeof(struct pt_regs));
242+
srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
238243
if (err)
239244
return H_PARAMETER;
245+
240246
if (kvmppc_need_byteswap(vcpu))
241247
byteswap_hv_regs(&l2_hv);
242248
if (l2_hv.version != HV_GUEST_STATE_VERSION)
243249
return H_P2;
244250

245-
regs_ptr = kvmppc_get_gpr(vcpu, 5);
246-
err = kvm_vcpu_read_guest(vcpu, regs_ptr, &l2_regs,
247-
sizeof(struct pt_regs));
248-
if (err)
249-
return H_PARAMETER;
250251
if (kvmppc_need_byteswap(vcpu))
251252
byteswap_pt_regs(&l2_regs);
252253
if (l2_hv.vcpu_token >= NR_CPUS)
@@ -323,12 +324,12 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu)
323324
byteswap_hv_regs(&l2_hv);
324325
byteswap_pt_regs(&l2_regs);
325326
}
327+
vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
326328
err = kvm_vcpu_write_guest(vcpu, hv_ptr, &l2_hv,
327-
sizeof(struct hv_guest_state));
328-
if (err)
329-
return H_AUTHORITY;
330-
err = kvm_vcpu_write_guest(vcpu, regs_ptr, &l2_regs,
329+
sizeof(struct hv_guest_state)) ||
330+
kvm_vcpu_write_guest(vcpu, regs_ptr, &l2_regs,
331331
sizeof(struct pt_regs));
332+
srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
332333
if (err)
333334
return H_AUTHORITY;
334335

@@ -508,12 +509,16 @@ long kvmhv_copy_tofrom_guest_nested(struct kvm_vcpu *vcpu)
508509
goto not_found;
509510

510511
/* Write what was loaded into our buffer back to the L1 guest */
512+
vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
511513
rc = kvm_vcpu_write_guest(vcpu, gp_to, buf, n);
514+
srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
512515
if (rc)
513516
goto not_found;
514517
} else {
515518
/* Load the data to be stored from the L1 guest into our buf */
519+
vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
516520
rc = kvm_vcpu_read_guest(vcpu, gp_from, buf, n);
521+
srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
517522
if (rc)
518523
goto not_found;
519524

@@ -548,9 +553,12 @@ static void kvmhv_update_ptbl_cache(struct kvm_nested_guest *gp)
548553

549554
ret = -EFAULT;
550555
ptbl_addr = (kvm->arch.l1_ptcr & PRTB_MASK) + (gp->l1_lpid << 4);
551-
if (gp->l1_lpid < (1ul << ((kvm->arch.l1_ptcr & PRTS_MASK) + 8)))
556+
if (gp->l1_lpid < (1ul << ((kvm->arch.l1_ptcr & PRTS_MASK) + 8))) {
557+
int srcu_idx = srcu_read_lock(&kvm->srcu);
552558
ret = kvm_read_guest(kvm, ptbl_addr,
553559
&ptbl_entry, sizeof(ptbl_entry));
560+
srcu_read_unlock(&kvm->srcu, srcu_idx);
561+
}
554562
if (ret) {
555563
gp->l1_gr_to_hr = 0;
556564
gp->process_table = 0;

0 commit comments

Comments
 (0)