Skip to content

Commit 9c6eb53

Browse files
committed
Merge tag 'kvm-s390-next-5.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD
KVM: s390: Fixes and Features for 5.16 - SIGP Fixes - initial preparations for lazy destroy of secure VMs - storage key improvements/fixes - Log the guest CPNC
2 parents 7c8de08 + 3fd8417 commit 9c6eb53

File tree

12 files changed

+200
-77
lines changed

12 files changed

+200
-77
lines changed

arch/s390/include/asm/pgtable.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,8 +1074,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
10741074
pte_t res;
10751075

10761076
res = ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
1077+
/* At this point the reference through the mapping is still present */
10771078
if (mm_is_protected(mm) && pte_present(res))
1078-
uv_convert_from_secure(pte_val(res) & PAGE_MASK);
1079+
uv_convert_owned_from_secure(pte_val(res) & PAGE_MASK);
10791080
return res;
10801081
}
10811082

@@ -1091,8 +1092,9 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
10911092
pte_t res;
10921093

10931094
res = ptep_xchg_direct(vma->vm_mm, addr, ptep, __pte(_PAGE_INVALID));
1095+
/* At this point the reference through the mapping is still present */
10941096
if (mm_is_protected(vma->vm_mm) && pte_present(res))
1095-
uv_convert_from_secure(pte_val(res) & PAGE_MASK);
1097+
uv_convert_owned_from_secure(pte_val(res) & PAGE_MASK);
10961098
return res;
10971099
}
10981100

@@ -1116,8 +1118,9 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
11161118
} else {
11171119
res = ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
11181120
}
1121+
/* At this point the reference through the mapping is still present */
11191122
if (mm_is_protected(mm) && pte_present(res))
1120-
uv_convert_from_secure(pte_val(res) & PAGE_MASK);
1123+
uv_convert_owned_from_secure(pte_val(res) & PAGE_MASK);
11211124
return res;
11221125
}
11231126

arch/s390/include/asm/uv.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
#include <asm/page.h>
1919
#include <asm/gmap.h>
2020

21+
#define UVC_CC_OK 0
22+
#define UVC_CC_ERROR 1
23+
#define UVC_CC_BUSY 2
24+
#define UVC_CC_PARTIAL 3
25+
2126
#define UVC_RC_EXECUTED 0x0001
2227
#define UVC_RC_INV_CMD 0x0002
2328
#define UVC_RC_INV_STATE 0x0003
@@ -351,16 +356,17 @@ static inline int is_prot_virt_host(void)
351356
}
352357

353358
int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb);
354-
int uv_destroy_page(unsigned long paddr);
359+
int uv_destroy_owned_page(unsigned long paddr);
355360
int uv_convert_from_secure(unsigned long paddr);
361+
int uv_convert_owned_from_secure(unsigned long paddr);
356362
int gmap_convert_to_secure(struct gmap *gmap, unsigned long gaddr);
357363

358364
void setup_uv(void);
359365
#else
360366
#define is_prot_virt_host() 0
361367
static inline void setup_uv(void) {}
362368

363-
static inline int uv_destroy_page(unsigned long paddr)
369+
static inline int uv_destroy_owned_page(unsigned long paddr)
364370
{
365371
return 0;
366372
}
@@ -369,6 +375,11 @@ static inline int uv_convert_from_secure(unsigned long paddr)
369375
{
370376
return 0;
371377
}
378+
379+
static inline int uv_convert_owned_from_secure(unsigned long paddr)
380+
{
381+
return 0;
382+
}
372383
#endif
373384

374385
#endif /* _ASM_S390_UV_H */

arch/s390/kernel/uv.c

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ static int uv_pin_shared(unsigned long paddr)
100100
*
101101
* @paddr: Absolute host address of page to be destroyed
102102
*/
103-
int uv_destroy_page(unsigned long paddr)
103+
static int uv_destroy_page(unsigned long paddr)
104104
{
105105
struct uv_cb_cfs uvcb = {
106106
.header.cmd = UVC_CMD_DESTR_SEC_STOR,
@@ -120,6 +120,22 @@ int uv_destroy_page(unsigned long paddr)
120120
return 0;
121121
}
122122

123+
/*
124+
* The caller must already hold a reference to the page
125+
*/
126+
int uv_destroy_owned_page(unsigned long paddr)
127+
{
128+
struct page *page = phys_to_page(paddr);
129+
int rc;
130+
131+
get_page(page);
132+
rc = uv_destroy_page(paddr);
133+
if (!rc)
134+
clear_bit(PG_arch_1, &page->flags);
135+
put_page(page);
136+
return rc;
137+
}
138+
123139
/*
124140
* Requests the Ultravisor to encrypt a guest page and make it
125141
* accessible to the host for paging (export).
@@ -139,6 +155,22 @@ int uv_convert_from_secure(unsigned long paddr)
139155
return 0;
140156
}
141157

158+
/*
159+
* The caller must already hold a reference to the page
160+
*/
161+
int uv_convert_owned_from_secure(unsigned long paddr)
162+
{
163+
struct page *page = phys_to_page(paddr);
164+
int rc;
165+
166+
get_page(page);
167+
rc = uv_convert_from_secure(paddr);
168+
if (!rc)
169+
clear_bit(PG_arch_1, &page->flags);
170+
put_page(page);
171+
return rc;
172+
}
173+
142174
/*
143175
* Calculate the expected ref_count for a page that would otherwise have no
144176
* further pins. This was cribbed from similar functions in other places in
@@ -165,7 +197,7 @@ static int make_secure_pte(pte_t *ptep, unsigned long addr,
165197
{
166198
pte_t entry = READ_ONCE(*ptep);
167199
struct page *page;
168-
int expected, rc = 0;
200+
int expected, cc = 0;
169201

170202
if (!pte_present(entry))
171203
return -ENXIO;
@@ -181,12 +213,25 @@ static int make_secure_pte(pte_t *ptep, unsigned long addr,
181213
if (!page_ref_freeze(page, expected))
182214
return -EBUSY;
183215
set_bit(PG_arch_1, &page->flags);
184-
rc = uv_call(0, (u64)uvcb);
216+
/*
217+
* If the UVC does not succeed or fail immediately, we don't want to
218+
* loop for long, or we might get stall notifications.
219+
* On the other hand, this is a complex scenario and we are holding a lot of
220+
* locks, so we can't easily sleep and reschedule. We try only once,
221+
* and if the UVC returned busy or partial completion, we return
222+
* -EAGAIN and we let the callers deal with it.
223+
*/
224+
cc = __uv_call(0, (u64)uvcb);
185225
page_ref_unfreeze(page, expected);
186-
/* Return -ENXIO if the page was not mapped, -EINVAL otherwise */
187-
if (rc)
188-
rc = uvcb->rc == 0x10a ? -ENXIO : -EINVAL;
189-
return rc;
226+
/*
227+
* Return -ENXIO if the page was not mapped, -EINVAL for other errors.
228+
* If busy or partially completed, return -EAGAIN.
229+
*/
230+
if (cc == UVC_CC_OK)
231+
return 0;
232+
else if (cc == UVC_CC_BUSY || cc == UVC_CC_PARTIAL)
233+
return -EAGAIN;
234+
return uvcb->rc == 0x10a ? -ENXIO : -EINVAL;
190235
}
191236

192237
/*
@@ -212,7 +257,7 @@ int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb)
212257
uaddr = __gmap_translate(gmap, gaddr);
213258
if (IS_ERR_VALUE(uaddr))
214259
goto out;
215-
vma = find_vma(gmap->mm, uaddr);
260+
vma = vma_lookup(gmap->mm, uaddr);
216261
if (!vma)
217262
goto out;
218263
/*
@@ -239,6 +284,10 @@ int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb)
239284
mmap_read_unlock(gmap->mm);
240285

241286
if (rc == -EAGAIN) {
287+
/*
288+
* If we are here because the UVC returned busy or partial
289+
* completion, this is just a useless check, but it is safe.
290+
*/
242291
wait_on_page_writeback(page);
243292
} else if (rc == -EBUSY) {
244293
/*

arch/s390/kvm/intercept.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,11 @@ static int handle_pv_uvc(struct kvm_vcpu *vcpu)
518518
*/
519519
if (rc == -EINVAL)
520520
return 0;
521+
/*
522+
* If we got -EAGAIN here, we simply return it. It will eventually
523+
* get propagated all the way to userspace, which should then try
524+
* again.
525+
*/
521526
return rc;
522527
}
523528

arch/s390/kvm/interrupt.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3053,13 +3053,14 @@ static void __airqs_kick_single_vcpu(struct kvm *kvm, u8 deliverable_mask)
30533053
int vcpu_idx, online_vcpus = atomic_read(&kvm->online_vcpus);
30543054
struct kvm_s390_gisa_interrupt *gi = &kvm->arch.gisa_int;
30553055
struct kvm_vcpu *vcpu;
3056+
u8 vcpu_isc_mask;
30563057

30573058
for_each_set_bit(vcpu_idx, kvm->arch.idle_mask, online_vcpus) {
30583059
vcpu = kvm_get_vcpu(kvm, vcpu_idx);
30593060
if (psw_ioint_disabled(vcpu))
30603061
continue;
3061-
deliverable_mask &= (u8)(vcpu->arch.sie_block->gcr[6] >> 24);
3062-
if (deliverable_mask) {
3062+
vcpu_isc_mask = (u8)(vcpu->arch.sie_block->gcr[6] >> 24);
3063+
if (deliverable_mask & vcpu_isc_mask) {
30633064
/* lately kicked but not yet running */
30643065
if (test_and_set_bit(vcpu_idx, gi->kicked_mask))
30653066
return;

arch/s390/kvm/kvm-s390.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2487,8 +2487,8 @@ long kvm_arch_vm_ioctl(struct file *filp,
24872487
case KVM_S390_PV_COMMAND: {
24882488
struct kvm_pv_cmd args;
24892489

2490-
/* protvirt means user sigp */
2491-
kvm->arch.user_cpu_state_ctrl = 1;
2490+
/* protvirt means user cpu state */
2491+
kvm_s390_set_user_cpu_state_ctrl(kvm);
24922492
r = 0;
24932493
if (!is_prot_virt_host()) {
24942494
r = -EINVAL;
@@ -3363,6 +3363,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
33633363

33643364
int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
33653365
{
3366+
clear_bit(vcpu->vcpu_idx, vcpu->kvm->arch.gisa_int.kicked_mask);
33663367
return kvm_s390_vcpu_has_irq(vcpu, 0);
33673368
}
33683369

@@ -3801,7 +3802,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
38013802
vcpu_load(vcpu);
38023803

38033804
/* user space knows about this interface - let it control the state */
3804-
vcpu->kvm->arch.user_cpu_state_ctrl = 1;
3805+
kvm_s390_set_user_cpu_state_ctrl(vcpu->kvm);
38053806

38063807
switch (mp_state->mp_state) {
38073808
case KVM_MP_STATE_STOPPED:
@@ -4254,6 +4255,7 @@ static void sync_regs_fmt2(struct kvm_vcpu *vcpu)
42544255
if (kvm_run->kvm_dirty_regs & KVM_SYNC_DIAG318) {
42554256
vcpu->arch.diag318_info.val = kvm_run->s.regs.diag318;
42564257
vcpu->arch.sie_block->cpnc = vcpu->arch.diag318_info.cpnc;
4258+
VCPU_EVENT(vcpu, 3, "setting cpnc to %d", vcpu->arch.diag318_info.cpnc);
42574259
}
42584260
/*
42594261
* If userspace sets the riccb (e.g. after migration) to a valid state,

arch/s390/kvm/kvm-s390.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,15 @@ static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm)
208208
return kvm->arch.user_cpu_state_ctrl != 0;
209209
}
210210

211+
static inline void kvm_s390_set_user_cpu_state_ctrl(struct kvm *kvm)
212+
{
213+
if (kvm->arch.user_cpu_state_ctrl)
214+
return;
215+
216+
VM_EVENT(kvm, 3, "%s", "ENABLE: Userspace CPU state control");
217+
kvm->arch.user_cpu_state_ctrl = 1;
218+
}
219+
211220
/* implemented in pv.c */
212221
int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc);
213222
int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc);

arch/s390/kvm/priv.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,8 @@ static int handle_sske(struct kvm_vcpu *vcpu)
397397
mmap_read_unlock(current->mm);
398398
if (rc == -EFAULT)
399399
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
400+
if (rc == -EAGAIN)
401+
continue;
400402
if (rc < 0)
401403
return rc;
402404
start += PAGE_SIZE;

arch/s390/kvm/pv.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,17 @@
1616

1717
int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
1818
{
19-
int cc = 0;
19+
int cc;
2020

21-
if (kvm_s390_pv_cpu_get_handle(vcpu)) {
22-
cc = uv_cmd_nodata(kvm_s390_pv_cpu_get_handle(vcpu),
23-
UVC_CMD_DESTROY_SEC_CPU, rc, rrc);
21+
if (!kvm_s390_pv_cpu_get_handle(vcpu))
22+
return 0;
23+
24+
cc = uv_cmd_nodata(kvm_s390_pv_cpu_get_handle(vcpu), UVC_CMD_DESTROY_SEC_CPU, rc, rrc);
25+
26+
KVM_UV_EVENT(vcpu->kvm, 3, "PROTVIRT DESTROY VCPU %d: rc %x rrc %x",
27+
vcpu->vcpu_id, *rc, *rrc);
28+
WARN_ONCE(cc, "protvirt destroy cpu failed rc %x rrc %x", *rc, *rrc);
2429

25-
KVM_UV_EVENT(vcpu->kvm, 3,
26-
"PROTVIRT DESTROY VCPU %d: rc %x rrc %x",
27-
vcpu->vcpu_id, *rc, *rrc);
28-
WARN_ONCE(cc, "protvirt destroy cpu failed rc %x rrc %x",
29-
*rc, *rrc);
30-
}
3130
/* Intended memory leak for something that should never happen. */
3231
if (!cc)
3332
free_pages(vcpu->arch.pv.stor_base,
@@ -196,7 +195,7 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc)
196195
uvcb.conf_base_stor_origin = (u64)kvm->arch.pv.stor_base;
197196
uvcb.conf_virt_stor_origin = (u64)kvm->arch.pv.stor_var;
198197

199-
cc = uv_call(0, (u64)&uvcb);
198+
cc = uv_call_sched(0, (u64)&uvcb);
200199
*rc = uvcb.header.rc;
201200
*rrc = uvcb.header.rrc;
202201
KVM_UV_EVENT(kvm, 3, "PROTVIRT CREATE VM: handle %llx len %llx rc %x rrc %x",

arch/s390/kvm/sigp.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -151,22 +151,10 @@ static int __sigp_stop_and_store_status(struct kvm_vcpu *vcpu,
151151
static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter,
152152
u64 *status_reg)
153153
{
154-
unsigned int i;
155-
struct kvm_vcpu *v;
156-
bool all_stopped = true;
157-
158-
kvm_for_each_vcpu(i, v, vcpu->kvm) {
159-
if (v == vcpu)
160-
continue;
161-
if (!is_vcpu_stopped(v))
162-
all_stopped = false;
163-
}
164-
165154
*status_reg &= 0xffffffff00000000UL;
166155

167156
/* Reject set arch order, with czam we're always in z/Arch mode. */
168-
*status_reg |= (all_stopped ? SIGP_STATUS_INVALID_PARAMETER :
169-
SIGP_STATUS_INCORRECT_STATE);
157+
*status_reg |= SIGP_STATUS_INVALID_PARAMETER;
170158
return SIGP_CC_STATUS_STORED;
171159
}
172160

0 commit comments

Comments
 (0)