Skip to content

Commit 6daf5a6

Browse files
committed
Merge branch 'vfio-ap' into features
Tony Krowiak says: =================== This patch series is for the changes required in the vfio_ap device driver to facilitate pass-through of crypto devices to a secure execution guest. In particular, it is critical that no data from the queues passed through to the SE guest is leaked when the guest is destroyed. There are also some new response codes returned from the PQAP(ZAPQ) and PQAP(TAPQ) commands that have been added to the architecture in support of pass-through of crypto devices to SE guests; these need to be accounted for when handling the reset of queues. =================== Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
2 parents cfd0121 + f88fb13 commit 6daf5a6

File tree

7 files changed

+135
-73
lines changed

7 files changed

+135
-73
lines changed

arch/s390/include/asm/kvm_host.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,9 @@ static inline int sie64a(struct kvm_s390_sie_block *sie_block, u64 *rsa)
10281028

10291029
extern char sie_exit;
10301030

1031+
bool kvm_s390_pv_is_protected(struct kvm *kvm);
1032+
bool kvm_s390_pv_cpu_is_protected(struct kvm_vcpu *vcpu);
1033+
10311034
extern int kvm_s390_gisc_register(struct kvm *kvm, u32 gisc);
10321035
extern int kvm_s390_gisc_unregister(struct kvm *kvm, u32 gisc);
10331036

arch/s390/include/asm/uv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@ static inline int is_prot_virt_host(void)
463463
return prot_virt_host;
464464
}
465465

466+
int uv_pin_shared(unsigned long paddr);
466467
int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb);
467468
int gmap_destroy_page(struct gmap *gmap, unsigned long gaddr);
468469
int uv_destroy_owned_page(unsigned long paddr);
@@ -475,6 +476,11 @@ void setup_uv(void);
475476
#define is_prot_virt_host() 0
476477
static inline void setup_uv(void) {}
477478

479+
static inline int uv_pin_shared(unsigned long paddr)
480+
{
481+
return 0;
482+
}
483+
478484
static inline int uv_destroy_owned_page(unsigned long paddr)
479485
{
480486
return 0;

arch/s390/kernel/uv.c

Lines changed: 2 additions & 1 deletion
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

arch/s390/kvm/kvm-s390.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -270,18 +270,6 @@ static inline u64 kvm_s390_pv_cpu_get_handle(struct kvm_vcpu *vcpu)
270270
return vcpu->arch.pv.handle;
271271
}
272272

273-
static inline bool kvm_s390_pv_is_protected(struct kvm *kvm)
274-
{
275-
lockdep_assert_held(&kvm->lock);
276-
return !!kvm_s390_pv_get_handle(kvm);
277-
}
278-
279-
static inline bool kvm_s390_pv_cpu_is_protected(struct kvm_vcpu *vcpu)
280-
{
281-
lockdep_assert_held(&vcpu->mutex);
282-
return !!kvm_s390_pv_cpu_get_handle(vcpu);
283-
}
284-
285273
/* implemented in interrupt.c */
286274
int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
287275
void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu);

arch/s390/kvm/pv.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@
1818
#include <linux/mmu_notifier.h>
1919
#include "kvm-s390.h"
2020

21+
bool kvm_s390_pv_is_protected(struct kvm *kvm)
22+
{
23+
lockdep_assert_held(&kvm->lock);
24+
return !!kvm_s390_pv_get_handle(kvm);
25+
}
26+
EXPORT_SYMBOL_GPL(kvm_s390_pv_is_protected);
27+
28+
bool kvm_s390_pv_cpu_is_protected(struct kvm_vcpu *vcpu)
29+
{
30+
lockdep_assert_held(&vcpu->mutex);
31+
return !!kvm_s390_pv_cpu_get_handle(vcpu);
32+
}
33+
EXPORT_SYMBOL_GPL(kvm_s390_pv_cpu_is_protected);
34+
2135
/**
2236
* struct pv_vm_to_be_destroyed - Represents a protected VM that needs to
2337
* be destroyed

drivers/s390/crypto/vfio_ap_ops.c

Lines changed: 106 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,12 @@
3030
#define AP_QUEUE_UNASSIGNED "unassigned"
3131
#define AP_QUEUE_IN_USE "in use"
3232

33-
#define MAX_RESET_CHECK_WAIT 200 /* Sleep max 200ms for reset check */
3433
#define AP_RESET_INTERVAL 20 /* Reset sleep interval (20ms) */
3534

3635
static int vfio_ap_mdev_reset_queues(struct ap_queue_table *qtable);
3736
static struct vfio_ap_queue *vfio_ap_find_queue(int apqn);
3837
static const struct vfio_device_ops vfio_ap_matrix_dev_ops;
39-
static int vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q);
38+
static void vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q);
4039

4140
/**
4241
* get_update_locks_for_kvm: Acquire the locks required to dynamically update a
@@ -360,6 +359,28 @@ static int vfio_ap_validate_nib(struct kvm_vcpu *vcpu, dma_addr_t *nib)
360359
return 0;
361360
}
362361

362+
static int ensure_nib_shared(unsigned long addr, struct gmap *gmap)
363+
{
364+
int ret;
365+
366+
/*
367+
* The nib has to be located in shared storage since guest and
368+
* host access it. vfio_pin_pages() will do a pin shared and
369+
* if that fails (possibly because it's not a shared page) it
370+
* calls export. We try to do a second pin shared here so that
371+
* the UV gives us an error code if we try to pin a non-shared
372+
* page.
373+
*
374+
* If the page is already pinned shared the UV will return a success.
375+
*/
376+
ret = uv_pin_shared(addr);
377+
if (ret) {
378+
/* vfio_pin_pages() likely exported the page so let's re-import */
379+
gmap_convert_to_secure(gmap, addr);
380+
}
381+
return ret;
382+
}
383+
363384
/**
364385
* vfio_ap_irq_enable - Enable Interruption for a APQN
365386
*
@@ -423,6 +444,14 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q,
423444
h_nib = page_to_phys(h_page) | (nib & ~PAGE_MASK);
424445
aqic_gisa.gisc = isc;
425446

447+
/* NIB in non-shared storage is a rc 6 for PV guests */
448+
if (kvm_s390_pv_cpu_is_protected(vcpu) &&
449+
ensure_nib_shared(h_nib & PAGE_MASK, kvm->arch.gmap)) {
450+
vfio_unpin_pages(&q->matrix_mdev->vdev, nib, 1);
451+
status.response_code = AP_RESPONSE_INVALID_ADDRESS;
452+
return status;
453+
}
454+
426455
nisc = kvm_s390_gisc_register(kvm, isc);
427456
if (nisc < 0) {
428457
VFIO_AP_DBF_WARN("%s: gisc registration failed: nisc=%d, isc=%d, apqn=%#04x\n",
@@ -675,7 +704,7 @@ static bool vfio_ap_mdev_filter_matrix(unsigned long *apm, unsigned long *aqm,
675704
*/
676705
apqn = AP_MKQID(apid, apqi);
677706
q = vfio_ap_mdev_get_queue(matrix_mdev, apqn);
678-
if (!q || q->reset_rc) {
707+
if (!q || q->reset_status.response_code) {
679708
clear_bit_inv(apid,
680709
matrix_mdev->shadow_apcb.apm);
681710
break;
@@ -1608,19 +1637,21 @@ static int apq_status_check(int apqn, struct ap_queue_status *status)
16081637
{
16091638
switch (status->response_code) {
16101639
case AP_RESPONSE_NORMAL:
1640+
case AP_RESPONSE_DECONFIGURED:
1641+
return 0;
16111642
case AP_RESPONSE_RESET_IN_PROGRESS:
1612-
if (status->queue_empty && !status->irq_enabled)
1613-
return 0;
1643+
case AP_RESPONSE_BUSY:
16141644
return -EBUSY;
1615-
case AP_RESPONSE_DECONFIGURED:
1645+
case AP_RESPONSE_ASSOC_SECRET_NOT_UNIQUE:
1646+
case AP_RESPONSE_ASSOC_FAILED:
16161647
/*
1617-
* If the AP queue is deconfigured, any subsequent AP command
1618-
* targeting the queue will fail with the same response code. On the
1619-
* other hand, when an AP adapter is deconfigured, the associated
1620-
* queues are reset, so let's return a value indicating the reset
1621-
* for which we're waiting completed successfully.
1648+
* These asynchronous response codes indicate a PQAP(AAPQ)
1649+
* instruction to associate a secret with the guest failed. All
1650+
* subsequent AP instructions will end with the asynchronous
1651+
* response code until the AP queue is reset; so, let's return
1652+
* a value indicating a reset needs to be performed again.
16221653
*/
1623-
return 0;
1654+
return -EAGAIN;
16241655
default:
16251656
WARN(true,
16261657
"failed to verify reset of queue %02x.%04x: TAPQ rc=%u\n",
@@ -1630,91 +1661,105 @@ static int apq_status_check(int apqn, struct ap_queue_status *status)
16301661
}
16311662
}
16321663

1633-
static int apq_reset_check(struct vfio_ap_queue *q)
1664+
#define WAIT_MSG "Waited %dms for reset of queue %02x.%04x (%u, %u, %u)"
1665+
1666+
static void apq_reset_check(struct work_struct *reset_work)
16341667
{
1635-
int ret;
1636-
int iters = MAX_RESET_CHECK_WAIT / AP_RESET_INTERVAL;
1668+
int ret = -EBUSY, elapsed = 0;
16371669
struct ap_queue_status status;
1670+
struct vfio_ap_queue *q;
16381671

1639-
for (; iters > 0; iters--) {
1672+
q = container_of(reset_work, struct vfio_ap_queue, reset_work);
1673+
memcpy(&status, &q->reset_status, sizeof(status));
1674+
while (true) {
16401675
msleep(AP_RESET_INTERVAL);
1676+
elapsed += AP_RESET_INTERVAL;
16411677
status = ap_tapq(q->apqn, NULL);
16421678
ret = apq_status_check(q->apqn, &status);
1643-
if (ret != -EBUSY)
1644-
return ret;
1679+
if (ret == -EIO)
1680+
return;
1681+
if (ret == -EBUSY) {
1682+
pr_notice_ratelimited(WAIT_MSG, elapsed,
1683+
AP_QID_CARD(q->apqn),
1684+
AP_QID_QUEUE(q->apqn),
1685+
status.response_code,
1686+
status.queue_empty,
1687+
status.irq_enabled);
1688+
} else {
1689+
if (q->reset_status.response_code == AP_RESPONSE_RESET_IN_PROGRESS ||
1690+
q->reset_status.response_code == AP_RESPONSE_BUSY ||
1691+
q->reset_status.response_code == AP_RESPONSE_STATE_CHANGE_IN_PROGRESS ||
1692+
ret == -EAGAIN) {
1693+
status = ap_zapq(q->apqn, 0);
1694+
memcpy(&q->reset_status, &status, sizeof(status));
1695+
continue;
1696+
}
1697+
/*
1698+
* When an AP adapter is deconfigured, the
1699+
* associated queues are reset, so let's set the
1700+
* status response code to 0 so the queue may be
1701+
* passed through (i.e., not filtered)
1702+
*/
1703+
if (status.response_code == AP_RESPONSE_DECONFIGURED)
1704+
q->reset_status.response_code = 0;
1705+
if (q->saved_isc != VFIO_AP_ISC_INVALID)
1706+
vfio_ap_free_aqic_resources(q);
1707+
break;
1708+
}
16451709
}
1646-
WARN_ONCE(iters <= 0,
1647-
"timeout verifying reset of queue %02x.%04x (%u, %u, %u)",
1648-
AP_QID_CARD(q->apqn), AP_QID_QUEUE(q->apqn),
1649-
status.queue_empty, status.irq_enabled, status.response_code);
1650-
return ret;
16511710
}
16521711

1653-
static int vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q)
1712+
static void vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q)
16541713
{
16551714
struct ap_queue_status status;
1656-
int ret;
16571715

16581716
if (!q)
1659-
return 0;
1660-
retry_zapq:
1717+
return;
16611718
status = ap_zapq(q->apqn, 0);
1662-
q->reset_rc = status.response_code;
1719+
memcpy(&q->reset_status, &status, sizeof(status));
16631720
switch (status.response_code) {
16641721
case AP_RESPONSE_NORMAL:
1665-
ret = 0;
1666-
/* if the reset has not completed, wait for it to take effect */
1667-
if (!status.queue_empty || status.irq_enabled)
1668-
ret = apq_reset_check(q);
1669-
break;
16701722
case AP_RESPONSE_RESET_IN_PROGRESS:
1723+
case AP_RESPONSE_BUSY:
1724+
case AP_RESPONSE_STATE_CHANGE_IN_PROGRESS:
16711725
/*
1672-
* There is a reset issued by another process in progress. Let's wait
1673-
* for that to complete. Since we have no idea whether it was a RAPQ or
1674-
* ZAPQ, then if it completes successfully, let's issue the ZAPQ.
1726+
* Let's verify whether the ZAPQ completed successfully on a work queue.
16751727
*/
1676-
ret = apq_reset_check(q);
1677-
if (ret)
1678-
break;
1679-
goto retry_zapq;
1728+
queue_work(system_long_wq, &q->reset_work);
1729+
break;
16801730
case AP_RESPONSE_DECONFIGURED:
16811731
/*
16821732
* When an AP adapter is deconfigured, the associated
1683-
* queues are reset, so let's return a value indicating the reset
1684-
* completed successfully.
1733+
* queues are reset, so let's set the status response code to 0
1734+
* so the queue may be passed through (i.e., not filtered).
16851735
*/
1686-
ret = 0;
1736+
q->reset_status.response_code = 0;
1737+
vfio_ap_free_aqic_resources(q);
16871738
break;
16881739
default:
16891740
WARN(true,
16901741
"PQAP/ZAPQ for %02x.%04x failed with invalid rc=%u\n",
16911742
AP_QID_CARD(q->apqn), AP_QID_QUEUE(q->apqn),
16921743
status.response_code);
1693-
return -EIO;
16941744
}
1695-
1696-
vfio_ap_free_aqic_resources(q);
1697-
1698-
return ret;
16991745
}
17001746

17011747
static int vfio_ap_mdev_reset_queues(struct ap_queue_table *qtable)
17021748
{
1703-
int ret, loop_cursor, rc = 0;
1749+
int ret = 0, loop_cursor;
17041750
struct vfio_ap_queue *q;
17051751

1752+
hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode)
1753+
vfio_ap_mdev_reset_queue(q);
1754+
17061755
hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode) {
1707-
ret = vfio_ap_mdev_reset_queue(q);
1708-
/*
1709-
* Regardless whether a queue turns out to be busy, or
1710-
* is not operational, we need to continue resetting
1711-
* the remaining queues.
1712-
*/
1713-
if (ret)
1714-
rc = ret;
1756+
flush_work(&q->reset_work);
1757+
1758+
if (q->reset_status.response_code)
1759+
ret = -EIO;
17151760
}
17161761

1717-
return rc;
1762+
return ret;
17181763
}
17191764

17201765
static int vfio_ap_mdev_open_device(struct vfio_device *vdev)
@@ -2038,6 +2083,8 @@ int vfio_ap_mdev_probe_queue(struct ap_device *apdev)
20382083

20392084
q->apqn = to_ap_queue(&apdev->device)->qid;
20402085
q->saved_isc = VFIO_AP_ISC_INVALID;
2086+
memset(&q->reset_status, 0, sizeof(q->reset_status));
2087+
INIT_WORK(&q->reset_work, apq_reset_check);
20412088
matrix_mdev = get_update_locks_by_apqn(q->apqn);
20422089

20432090
if (matrix_mdev) {
@@ -2087,6 +2134,7 @@ void vfio_ap_mdev_remove_queue(struct ap_device *apdev)
20872134
}
20882135

20892136
vfio_ap_mdev_reset_queue(q);
2137+
flush_work(&q->reset_work);
20902138
dev_set_drvdata(&apdev->device, NULL);
20912139
kfree(q);
20922140
release_update_locks_for_mdev(matrix_mdev);

drivers/s390/crypto/vfio_ap_private.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ struct ap_matrix_mdev {
133133
* @apqn: the APQN of the AP queue device
134134
* @saved_isc: the guest ISC registered with the GIB interface
135135
* @mdev_qnode: allows the vfio_ap_queue struct to be added to a hashtable
136-
* @reset_rc: the status response code from the last reset of the queue
136+
* @reset_status: the status from the last reset of the queue
137+
* @reset_work: work to wait for queue reset to complete
137138
*/
138139
struct vfio_ap_queue {
139140
struct ap_matrix_mdev *matrix_mdev;
@@ -142,7 +143,8 @@ struct vfio_ap_queue {
142143
#define VFIO_AP_ISC_INVALID 0xff
143144
unsigned char saved_isc;
144145
struct hlist_node mdev_qnode;
145-
unsigned int reset_rc;
146+
struct ap_queue_status reset_status;
147+
struct work_struct reset_work;
146148
};
147149

148150
int vfio_ap_mdev_register(void);

0 commit comments

Comments
 (0)