Skip to content

Commit 69fd387

Browse files
committed
Merge tag 'kvm-s390-next-6.6-1' of https://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD
- PV crypto passthrough enablement (Tony, Steffen, Viktor, Janosch) Allows a PV guest to use crypto cards. Card access is governed by the firmware and once a crypto queue is "bound" to a PV VM every other entity (PV or not) looses access until it is not bound anymore. Enablement is done via flags when creating the PV VM. - Guest debug fixes (Ilya)
2 parents 1814db8 + 899e220 commit 69fd387

File tree

14 files changed

+482
-91
lines changed

14 files changed

+482
-91
lines changed

arch/s390/include/asm/kvm_host.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,8 @@ struct kvm_s390_cpu_model {
817817
__u64 *fac_list;
818818
u64 cpuid;
819819
unsigned short ibc;
820+
/* subset of available UV-features for pv-guests enabled by user space */
821+
struct kvm_s390_vm_cpu_uv_feat uv_feat_guest;
820822
};
821823

822824
typedef int (*crypto_hook)(struct kvm_vcpu *vcpu);
@@ -1028,6 +1030,9 @@ static inline int sie64a(struct kvm_s390_sie_block *sie_block, u64 *rsa)
10281030

10291031
extern char sie_exit;
10301032

1033+
bool kvm_s390_pv_is_protected(struct kvm *kvm);
1034+
bool kvm_s390_pv_cpu_is_protected(struct kvm_vcpu *vcpu);
1035+
10311036
extern int kvm_s390_gisc_register(struct kvm *kvm, u32 gisc);
10321037
extern int kvm_s390_gisc_unregister(struct kvm *kvm, u32 gisc);
10331038

arch/s390/include/asm/uv.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ enum uv_cmds_inst {
9999
enum uv_feat_ind {
100100
BIT_UV_FEAT_MISC = 0,
101101
BIT_UV_FEAT_AIV = 1,
102+
BIT_UV_FEAT_AP = 4,
103+
BIT_UV_FEAT_AP_INTR = 5,
102104
};
103105

104106
struct uv_cb_header {
@@ -159,7 +161,15 @@ struct uv_cb_cgc {
159161
u64 guest_handle;
160162
u64 conf_base_stor_origin;
161163
u64 conf_virt_stor_origin;
162-
u64 reserved30;
164+
u8 reserved30[6];
165+
union {
166+
struct {
167+
u16 : 14;
168+
u16 ap_instr_intr : 1;
169+
u16 ap_allow_instr : 1;
170+
};
171+
u16 raw;
172+
} flags;
163173
u64 guest_stor_origin;
164174
u64 guest_stor_len;
165175
u64 guest_sca;
@@ -397,6 +407,13 @@ struct uv_info {
397407

398408
extern struct uv_info uv_info;
399409

410+
static inline bool uv_has_feature(u8 feature_bit)
411+
{
412+
if (feature_bit >= sizeof(uv_info.uv_feature_indications) * 8)
413+
return false;
414+
return test_bit_inv(feature_bit, &uv_info.uv_feature_indications);
415+
}
416+
400417
#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
401418
extern int prot_virt_guest;
402419

@@ -463,6 +480,7 @@ static inline int is_prot_virt_host(void)
463480
return prot_virt_host;
464481
}
465482

483+
int uv_pin_shared(unsigned long paddr);
466484
int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb);
467485
int gmap_destroy_page(struct gmap *gmap, unsigned long gaddr);
468486
int uv_destroy_owned_page(unsigned long paddr);
@@ -475,6 +493,11 @@ void setup_uv(void);
475493
#define is_prot_virt_host() 0
476494
static inline void setup_uv(void) {}
477495

496+
static inline int uv_pin_shared(unsigned long paddr)
497+
{
498+
return 0;
499+
}
500+
478501
static inline int uv_destroy_owned_page(unsigned long paddr)
479502
{
480503
return 0;

arch/s390/include/uapi/asm/kvm.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,22 @@ struct kvm_s390_vm_cpu_subfunc {
159159
__u8 reserved[1728];
160160
};
161161

162+
#define KVM_S390_VM_CPU_PROCESSOR_UV_FEAT_GUEST 6
163+
#define KVM_S390_VM_CPU_MACHINE_UV_FEAT_GUEST 7
164+
165+
#define KVM_S390_VM_CPU_UV_FEAT_NR_BITS 64
166+
struct kvm_s390_vm_cpu_uv_feat {
167+
union {
168+
struct {
169+
__u64 : 4;
170+
__u64 ap : 1; /* bit 4 */
171+
__u64 ap_intr : 1; /* bit 5 */
172+
__u64 : 58;
173+
};
174+
__u64 feat;
175+
};
176+
};
177+
162178
/* kvm attributes for crypto */
163179
#define KVM_S390_VM_CRYPTO_ENABLE_AES_KW 0
164180
#define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1

arch/s390/kernel/uv.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ void __init setup_uv(void)
8888
* Requests the Ultravisor to pin the page in the shared state. This will
8989
* cause an intercept when the guest attempts to unshare the pinned page.
9090
*/
91-
static int uv_pin_shared(unsigned long paddr)
91+
int uv_pin_shared(unsigned long paddr)
9292
{
9393
struct uv_cb_cfs uvcb = {
9494
.header.cmd = UVC_CMD_PIN_PAGE_SHARED,
@@ -100,6 +100,7 @@ static int uv_pin_shared(unsigned long paddr)
100100
return -EINVAL;
101101
return 0;
102102
}
103+
EXPORT_SYMBOL_GPL(uv_pin_shared);
103104

104105
/*
105106
* Requests the Ultravisor to destroy a guest page and make it
@@ -257,7 +258,7 @@ static bool should_export_before_import(struct uv_cb_header *uvcb, struct mm_str
257258
* shared page from a different protected VM will automatically also
258259
* transfer its ownership.
259260
*/
260-
if (test_bit_inv(BIT_UV_FEAT_MISC, &uv_info.uv_feature_indications))
261+
if (uv_has_feature(BIT_UV_FEAT_MISC))
261262
return false;
262263
if (uvcb->cmd == UVC_CMD_UNPIN_PAGE_SHARED)
263264
return false;

arch/s390/kvm/intercept.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,21 @@ static int handle_itdb(struct kvm_vcpu *vcpu)
228228

229229
#define per_event(vcpu) (vcpu->arch.sie_block->iprcc & PGM_PER)
230230

231+
static bool should_handle_per_event(const struct kvm_vcpu *vcpu)
232+
{
233+
if (!guestdbg_enabled(vcpu) || !per_event(vcpu))
234+
return false;
235+
if (guestdbg_sstep_enabled(vcpu) &&
236+
vcpu->arch.sie_block->iprcc != PGM_PER) {
237+
/*
238+
* __vcpu_run() will exit after delivering the concurrently
239+
* indicated condition.
240+
*/
241+
return false;
242+
}
243+
return true;
244+
}
245+
231246
static int handle_prog(struct kvm_vcpu *vcpu)
232247
{
233248
psw_t psw;
@@ -242,7 +257,7 @@ static int handle_prog(struct kvm_vcpu *vcpu)
242257
if (kvm_s390_pv_cpu_is_protected(vcpu))
243258
return -EOPNOTSUPP;
244259

245-
if (guestdbg_enabled(vcpu) && per_event(vcpu)) {
260+
if (should_handle_per_event(vcpu)) {
246261
rc = kvm_s390_handle_per_event(vcpu);
247262
if (rc)
248263
return rc;
@@ -571,6 +586,19 @@ static int handle_pv_notification(struct kvm_vcpu *vcpu)
571586
return handle_instruction(vcpu);
572587
}
573588

589+
static bool should_handle_per_ifetch(const struct kvm_vcpu *vcpu, int rc)
590+
{
591+
/* Process PER, also if the instruction is processed in user space. */
592+
if (!(vcpu->arch.sie_block->icptstatus & 0x02))
593+
return false;
594+
if (rc != 0 && rc != -EOPNOTSUPP)
595+
return false;
596+
if (guestdbg_sstep_enabled(vcpu) && vcpu->arch.local_int.pending_irqs)
597+
/* __vcpu_run() will exit after delivering the interrupt. */
598+
return false;
599+
return true;
600+
}
601+
574602
int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
575603
{
576604
int rc, per_rc = 0;
@@ -605,8 +633,8 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
605633
rc = handle_partial_execution(vcpu);
606634
break;
607635
case ICPT_KSS:
608-
rc = kvm_s390_skey_check_enable(vcpu);
609-
break;
636+
/* Instruction will be redriven, skip the PER check. */
637+
return kvm_s390_skey_check_enable(vcpu);
610638
case ICPT_MCHKREQ:
611639
case ICPT_INT_ENABLE:
612640
/*
@@ -633,9 +661,7 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
633661
return -EOPNOTSUPP;
634662
}
635663

636-
/* process PER, also if the instruction is processed in user space */
637-
if (vcpu->arch.sie_block->icptstatus & 0x02 &&
638-
(!rc || rc == -EOPNOTSUPP))
664+
if (should_handle_per_ifetch(vcpu, rc))
639665
per_rc = kvm_s390_handle_per_ifetch_icpt(vcpu);
640666
return per_rc ? per_rc : rc;
641667
}

arch/s390/kvm/interrupt.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,6 +1392,7 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
13921392
{
13931393
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
13941394
int rc = 0;
1395+
bool delivered = false;
13951396
unsigned long irq_type;
13961397
unsigned long irqs;
13971398

@@ -1465,6 +1466,19 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
14651466
WARN_ONCE(1, "Unknown pending irq type %ld", irq_type);
14661467
clear_bit(irq_type, &li->pending_irqs);
14671468
}
1469+
delivered |= !rc;
1470+
}
1471+
1472+
/*
1473+
* We delivered at least one interrupt and modified the PC. Force a
1474+
* singlestep event now.
1475+
*/
1476+
if (delivered && guestdbg_sstep_enabled(vcpu)) {
1477+
struct kvm_debug_exit_arch *debug_exit = &vcpu->run->debug.arch;
1478+
1479+
debug_exit->addr = vcpu->arch.sie_block->gpsw.addr;
1480+
debug_exit->type = KVM_SINGLESTEP;
1481+
vcpu->guest_debug |= KVM_GUESTDBG_EXIT_PENDING;
14681482
}
14691483

14701484
set_intercept_indicators(vcpu);

0 commit comments

Comments
 (0)