Skip to content

Commit f7866f5

Browse files
Claudio Imbrendafrankjaa
authored andcommitted
KVM: s390: pv: support for Destroy fast UVC
Add support for the Destroy Secure Configuration Fast Ultravisor call, and take advantage of it for asynchronous destroy. When supported, the protected guest is destroyed immediately using the new UVC, leaving only the memory to be cleaned up asynchronously. Signed-off-by: Claudio Imbrenda <[email protected]> Reviewed-by: Nico Boehr <[email protected]> Reviewed-by: Janosch Frank <[email protected]> Reviewed-by: Steffen Eiden <[email protected]> Link: https://lore.kernel.org/r/[email protected] Message-Id: <[email protected]> Signed-off-by: Janosch Frank <[email protected]>
1 parent afe20eb commit f7866f5

File tree

2 files changed

+63
-8
lines changed

2 files changed

+63
-8
lines changed

arch/s390/include/asm/uv.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#define UVC_CMD_INIT_UV 0x000f
3535
#define UVC_CMD_CREATE_SEC_CONF 0x0100
3636
#define UVC_CMD_DESTROY_SEC_CONF 0x0101
37+
#define UVC_CMD_DESTROY_SEC_CONF_FAST 0x0102
3738
#define UVC_CMD_CREATE_SEC_CPU 0x0120
3839
#define UVC_CMD_DESTROY_SEC_CPU 0x0121
3940
#define UVC_CMD_CONV_TO_SEC_STOR 0x0200
@@ -81,6 +82,7 @@ enum uv_cmds_inst {
8182
BIT_UVC_CMD_UNSHARE_ALL = 20,
8283
BIT_UVC_CMD_PIN_PAGE_SHARED = 21,
8384
BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22,
85+
BIT_UVC_CMD_DESTROY_SEC_CONF_FAST = 23,
8486
BIT_UVC_CMD_DUMP_INIT = 24,
8587
BIT_UVC_CMD_DUMP_CONFIG_STOR_STATE = 25,
8688
BIT_UVC_CMD_DUMP_CPU = 26,
@@ -230,6 +232,14 @@ struct uv_cb_nodata {
230232
u64 reserved20[4];
231233
} __packed __aligned(8);
232234

235+
/* Destroy Configuration Fast */
236+
struct uv_cb_destroy_fast {
237+
struct uv_cb_header header;
238+
u64 reserved08[2];
239+
u64 handle;
240+
u64 reserved20[5];
241+
} __packed __aligned(8);
242+
233243
/* Set Shared Access */
234244
struct uv_cb_share {
235245
struct uv_cb_header header;

arch/s390/kvm/pv.c

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ static int kvm_s390_pv_dispose_one_leftover(struct kvm *kvm,
203203
{
204204
int cc;
205205

206+
/* It used the destroy-fast UVC, nothing left to do here */
207+
if (!leftover->handle)
208+
goto done_fast;
206209
cc = uv_cmd_nodata(leftover->handle, UVC_CMD_DESTROY_SEC_CONF, rc, rrc);
207210
KVM_UV_EVENT(kvm, 3, "PROTVIRT DESTROY LEFTOVER VM: rc %x rrc %x", *rc, *rrc);
208211
WARN_ONCE(cc, "protvirt destroy leftover vm failed rc %x rrc %x", *rc, *rrc);
@@ -217,6 +220,7 @@ static int kvm_s390_pv_dispose_one_leftover(struct kvm *kvm,
217220
free_pages(leftover->stor_base, get_order(uv_info.guest_base_stor_len));
218221
free_pages(leftover->old_gmap_table, CRST_ALLOC_ORDER);
219222
vfree(leftover->stor_var);
223+
done_fast:
220224
atomic_dec(&kvm->mm->context.protected_count);
221225
return 0;
222226
}
@@ -250,6 +254,36 @@ static void kvm_s390_destroy_lower_2g(struct kvm *kvm)
250254
srcu_read_unlock(&kvm->srcu, srcu_idx);
251255
}
252256

257+
static int kvm_s390_pv_deinit_vm_fast(struct kvm *kvm, u16 *rc, u16 *rrc)
258+
{
259+
struct uv_cb_destroy_fast uvcb = {
260+
.header.cmd = UVC_CMD_DESTROY_SEC_CONF_FAST,
261+
.header.len = sizeof(uvcb),
262+
.handle = kvm_s390_pv_get_handle(kvm),
263+
};
264+
int cc;
265+
266+
cc = uv_call_sched(0, (u64)&uvcb);
267+
if (rc)
268+
*rc = uvcb.header.rc;
269+
if (rrc)
270+
*rrc = uvcb.header.rrc;
271+
WRITE_ONCE(kvm->arch.gmap->guest_handle, 0);
272+
KVM_UV_EVENT(kvm, 3, "PROTVIRT DESTROY VM FAST: rc %x rrc %x",
273+
uvcb.header.rc, uvcb.header.rrc);
274+
WARN_ONCE(cc, "protvirt destroy vm fast failed handle %llx rc %x rrc %x",
275+
kvm_s390_pv_get_handle(kvm), uvcb.header.rc, uvcb.header.rrc);
276+
/* Inteded memory leak on "impossible" error */
277+
if (!cc)
278+
kvm_s390_pv_dealloc_vm(kvm);
279+
return cc ? -EIO : 0;
280+
}
281+
282+
static inline bool is_destroy_fast_available(void)
283+
{
284+
return test_bit_inv(BIT_UVC_CMD_DESTROY_SEC_CONF_FAST, uv_info.inst_calls_list);
285+
}
286+
253287
/**
254288
* kvm_s390_pv_set_aside - Set aside a protected VM for later teardown.
255289
* @kvm: the VM
@@ -271,6 +305,7 @@ static void kvm_s390_destroy_lower_2g(struct kvm *kvm)
271305
int kvm_s390_pv_set_aside(struct kvm *kvm, u16 *rc, u16 *rrc)
272306
{
273307
struct pv_vm_to_be_destroyed *priv;
308+
int res = 0;
274309

275310
lockdep_assert_held(&kvm->lock);
276311
/*
@@ -283,14 +318,21 @@ int kvm_s390_pv_set_aside(struct kvm *kvm, u16 *rc, u16 *rrc)
283318
if (!priv)
284319
return -ENOMEM;
285320

286-
priv->stor_var = kvm->arch.pv.stor_var;
287-
priv->stor_base = kvm->arch.pv.stor_base;
288-
priv->handle = kvm_s390_pv_get_handle(kvm);
289-
priv->old_gmap_table = (unsigned long)kvm->arch.gmap->table;
290-
WRITE_ONCE(kvm->arch.gmap->guest_handle, 0);
291-
if (s390_replace_asce(kvm->arch.gmap)) {
321+
if (is_destroy_fast_available()) {
322+
res = kvm_s390_pv_deinit_vm_fast(kvm, rc, rrc);
323+
} else {
324+
priv->stor_var = kvm->arch.pv.stor_var;
325+
priv->stor_base = kvm->arch.pv.stor_base;
326+
priv->handle = kvm_s390_pv_get_handle(kvm);
327+
priv->old_gmap_table = (unsigned long)kvm->arch.gmap->table;
328+
WRITE_ONCE(kvm->arch.gmap->guest_handle, 0);
329+
if (s390_replace_asce(kvm->arch.gmap))
330+
res = -ENOMEM;
331+
}
332+
333+
if (res) {
292334
kfree(priv);
293-
return -ENOMEM;
335+
return res;
294336
}
295337

296338
kvm_s390_destroy_lower_2g(kvm);
@@ -471,6 +513,7 @@ static void kvm_s390_pv_mmu_notifier_release(struct mmu_notifier *subscription,
471513
{
472514
struct kvm *kvm = container_of(subscription, struct kvm, arch.pv.mmu_notifier);
473515
u16 dummy;
516+
int r;
474517

475518
/*
476519
* No locking is needed since this is the last thread of the last user of this
@@ -479,7 +522,9 @@ static void kvm_s390_pv_mmu_notifier_release(struct mmu_notifier *subscription,
479522
* unregistered. This means that if this notifier runs, then the
480523
* struct kvm is still valid.
481524
*/
482-
kvm_s390_cpus_from_pv(kvm, &dummy, &dummy);
525+
r = kvm_s390_cpus_from_pv(kvm, &dummy, &dummy);
526+
if (!r && is_destroy_fast_available() && kvm_s390_pv_get_handle(kvm))
527+
kvm_s390_pv_deinit_vm_fast(kvm, &dummy, &dummy);
483528
}
484529

485530
static const struct mmu_notifier_ops kvm_s390_pv_mmu_notifier_ops = {

0 commit comments

Comments
 (0)