diff options
-rw-r--r-- | arch/powerpc/include/asm/opal-api.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/xive.h | 3 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_xive.c | 48 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_xive.h | 15 | ||||
-rw-r--r-- | arch/powerpc/sysdev/xive/native.c | 18 |
5 files changed, 57 insertions, 28 deletions
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index 233c7504b1f2..fc926743647e 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h | |||
@@ -1073,6 +1073,7 @@ enum { | |||
1073 | /* Flags for OPAL_XIVE_GET/SET_VP_INFO */ | 1073 | /* Flags for OPAL_XIVE_GET/SET_VP_INFO */ |
1074 | enum { | 1074 | enum { |
1075 | OPAL_XIVE_VP_ENABLED = 0x00000001, | 1075 | OPAL_XIVE_VP_ENABLED = 0x00000001, |
1076 | OPAL_XIVE_VP_SINGLE_ESCALATION = 0x00000002, | ||
1076 | }; | 1077 | }; |
1077 | 1078 | ||
1078 | /* "Any chip" replacement for chip ID for allocation functions */ | 1079 | /* "Any chip" replacement for chip ID for allocation functions */ |
diff --git a/arch/powerpc/include/asm/xive.h b/arch/powerpc/include/asm/xive.h index b619a5585cd6..e602903c3029 100644 --- a/arch/powerpc/include/asm/xive.h +++ b/arch/powerpc/include/asm/xive.h | |||
@@ -111,9 +111,10 @@ extern void xive_native_disable_queue(u32 vp_id, struct xive_q *q, u8 prio); | |||
111 | 111 | ||
112 | extern void xive_native_sync_source(u32 hw_irq); | 112 | extern void xive_native_sync_source(u32 hw_irq); |
113 | extern bool is_xive_irq(struct irq_chip *chip); | 113 | extern bool is_xive_irq(struct irq_chip *chip); |
114 | extern int xive_native_enable_vp(u32 vp_id); | 114 | extern int xive_native_enable_vp(u32 vp_id, bool single_escalation); |
115 | extern int xive_native_disable_vp(u32 vp_id); | 115 | extern int xive_native_disable_vp(u32 vp_id); |
116 | extern int xive_native_get_vp_info(u32 vp_id, u32 *out_cam_id, u32 *out_chip_id); | 116 | extern int xive_native_get_vp_info(u32 vp_id, u32 *out_cam_id, u32 *out_chip_id); |
117 | extern bool xive_native_has_single_escalation(void); | ||
117 | 118 | ||
118 | #else | 119 | #else |
119 | 120 | ||
diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c index 6cff5bdfd6b7..a102efeabf05 100644 --- a/arch/powerpc/kvm/book3s_xive.c +++ b/arch/powerpc/kvm/book3s_xive.c | |||
@@ -112,19 +112,21 @@ static int xive_attach_escalation(struct kvm_vcpu *vcpu, u8 prio) | |||
112 | return -EIO; | 112 | return -EIO; |
113 | } | 113 | } |
114 | 114 | ||
115 | /* | 115 | if (xc->xive->single_escalation) |
116 | * Future improvement: start with them disabled | 116 | name = kasprintf(GFP_KERNEL, "kvm-%d-%d", |
117 | * and handle DD2 and later scheme of merged escalation | 117 | vcpu->kvm->arch.lpid, xc->server_num); |
118 | * interrupts | 118 | else |
119 | */ | 119 | name = kasprintf(GFP_KERNEL, "kvm-%d-%d-%d", |
120 | name = kasprintf(GFP_KERNEL, "kvm-%d-%d-%d", | 120 | vcpu->kvm->arch.lpid, xc->server_num, prio); |
121 | vcpu->kvm->arch.lpid, xc->server_num, prio); | ||
122 | if (!name) { | 121 | if (!name) { |
123 | pr_err("Failed to allocate escalation irq name for queue %d of VCPU %d\n", | 122 | pr_err("Failed to allocate escalation irq name for queue %d of VCPU %d\n", |
124 | prio, xc->server_num); | 123 | prio, xc->server_num); |
125 | rc = -ENOMEM; | 124 | rc = -ENOMEM; |
126 | goto error; | 125 | goto error; |
127 | } | 126 | } |
127 | |||
128 | pr_devel("Escalation %s irq %d (prio %d)\n", name, xc->esc_virq[prio], prio); | ||
129 | |||
128 | rc = request_irq(xc->esc_virq[prio], xive_esc_irq, | 130 | rc = request_irq(xc->esc_virq[prio], xive_esc_irq, |
129 | IRQF_NO_THREAD, name, vcpu); | 131 | IRQF_NO_THREAD, name, vcpu); |
130 | if (rc) { | 132 | if (rc) { |
@@ -191,12 +193,12 @@ static int xive_check_provisioning(struct kvm *kvm, u8 prio) | |||
191 | 193 | ||
192 | pr_devel("Provisioning prio... %d\n", prio); | 194 | pr_devel("Provisioning prio... %d\n", prio); |
193 | 195 | ||
194 | /* Provision each VCPU and enable escalations */ | 196 | /* Provision each VCPU and enable escalations if needed */ |
195 | kvm_for_each_vcpu(i, vcpu, kvm) { | 197 | kvm_for_each_vcpu(i, vcpu, kvm) { |
196 | if (!vcpu->arch.xive_vcpu) | 198 | if (!vcpu->arch.xive_vcpu) |
197 | continue; | 199 | continue; |
198 | rc = xive_provision_queue(vcpu, prio); | 200 | rc = xive_provision_queue(vcpu, prio); |
199 | if (rc == 0) | 201 | if (rc == 0 && !xive->single_escalation) |
200 | xive_attach_escalation(vcpu, prio); | 202 | xive_attach_escalation(vcpu, prio); |
201 | if (rc) | 203 | if (rc) |
202 | return rc; | 204 | return rc; |
@@ -1081,6 +1083,7 @@ int kvmppc_xive_connect_vcpu(struct kvm_device *dev, | |||
1081 | /* Allocate IPI */ | 1083 | /* Allocate IPI */ |
1082 | xc->vp_ipi = xive_native_alloc_irq(); | 1084 | xc->vp_ipi = xive_native_alloc_irq(); |
1083 | if (!xc->vp_ipi) { | 1085 | if (!xc->vp_ipi) { |
1086 | pr_err("Failed to allocate xive irq for VCPU IPI\n"); | ||
1084 | r = -EIO; | 1087 | r = -EIO; |
1085 | goto bail; | 1088 | goto bail; |
1086 | } | 1089 | } |
@@ -1091,18 +1094,33 @@ int kvmppc_xive_connect_vcpu(struct kvm_device *dev, | |||
1091 | goto bail; | 1094 | goto bail; |
1092 | 1095 | ||
1093 | /* | 1096 | /* |
1097 | * Enable the VP first as the single escalation mode will | ||
1098 | * affect escalation interrupts numbering | ||
1099 | */ | ||
1100 | r = xive_native_enable_vp(xc->vp_id, xive->single_escalation); | ||
1101 | if (r) { | ||
1102 | pr_err("Failed to enable VP in OPAL, err %d\n", r); | ||
1103 | goto bail; | ||
1104 | } | ||
1105 | |||
1106 | /* | ||
1094 | * Initialize queues. Initially we set them all for no queueing | 1107 | * Initialize queues. Initially we set them all for no queueing |
1095 | * and we enable escalation for queue 0 only which we'll use for | 1108 | * and we enable escalation for queue 0 only which we'll use for |
1096 | * our mfrr change notifications. If the VCPU is hot-plugged, we | 1109 | * our mfrr change notifications. If the VCPU is hot-plugged, we |
1097 | * do handle provisioning however. | 1110 | * do handle provisioning however based on the existing "map" |
1111 | * of enabled queues. | ||
1098 | */ | 1112 | */ |
1099 | for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) { | 1113 | for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) { |
1100 | struct xive_q *q = &xc->queues[i]; | 1114 | struct xive_q *q = &xc->queues[i]; |
1101 | 1115 | ||
1116 | /* Single escalation, no queue 7 */ | ||
1117 | if (i == 7 && xive->single_escalation) | ||
1118 | break; | ||
1119 | |||
1102 | /* Is queue already enabled ? Provision it */ | 1120 | /* Is queue already enabled ? Provision it */ |
1103 | if (xive->qmap & (1 << i)) { | 1121 | if (xive->qmap & (1 << i)) { |
1104 | r = xive_provision_queue(vcpu, i); | 1122 | r = xive_provision_queue(vcpu, i); |
1105 | if (r == 0) | 1123 | if (r == 0 && !xive->single_escalation) |
1106 | xive_attach_escalation(vcpu, i); | 1124 | xive_attach_escalation(vcpu, i); |
1107 | if (r) | 1125 | if (r) |
1108 | goto bail; | 1126 | goto bail; |
@@ -1122,11 +1140,6 @@ int kvmppc_xive_connect_vcpu(struct kvm_device *dev, | |||
1122 | if (r) | 1140 | if (r) |
1123 | goto bail; | 1141 | goto bail; |
1124 | 1142 | ||
1125 | /* Enable the VP */ | ||
1126 | r = xive_native_enable_vp(xc->vp_id); | ||
1127 | if (r) | ||
1128 | goto bail; | ||
1129 | |||
1130 | /* Route the IPI */ | 1143 | /* Route the IPI */ |
1131 | r = xive_native_configure_irq(xc->vp_ipi, xc->vp_id, 0, XICS_IPI); | 1144 | r = xive_native_configure_irq(xc->vp_ipi, xc->vp_id, 0, XICS_IPI); |
1132 | if (!r) | 1145 | if (!r) |
@@ -1473,6 +1486,7 @@ static int xive_set_source(struct kvmppc_xive *xive, long irq, u64 addr) | |||
1473 | 1486 | ||
1474 | pr_devel(" val=0x016%llx (server=0x%x, guest_prio=%d)\n", | 1487 | pr_devel(" val=0x016%llx (server=0x%x, guest_prio=%d)\n", |
1475 | val, server, guest_prio); | 1488 | val, server, guest_prio); |
1489 | |||
1476 | /* | 1490 | /* |
1477 | * If the source doesn't already have an IPI, allocate | 1491 | * If the source doesn't already have an IPI, allocate |
1478 | * one and get the corresponding data | 1492 | * one and get the corresponding data |
@@ -1761,6 +1775,8 @@ static int kvmppc_xive_create(struct kvm_device *dev, u32 type) | |||
1761 | if (xive->vp_base == XIVE_INVALID_VP) | 1775 | if (xive->vp_base == XIVE_INVALID_VP) |
1762 | ret = -ENOMEM; | 1776 | ret = -ENOMEM; |
1763 | 1777 | ||
1778 | xive->single_escalation = xive_native_has_single_escalation(); | ||
1779 | |||
1764 | if (ret) { | 1780 | if (ret) { |
1765 | kfree(xive); | 1781 | kfree(xive); |
1766 | return ret; | 1782 | return ret; |
diff --git a/arch/powerpc/kvm/book3s_xive.h b/arch/powerpc/kvm/book3s_xive.h index 6ba63f8e8a61..a08ae6fd4c51 100644 --- a/arch/powerpc/kvm/book3s_xive.h +++ b/arch/powerpc/kvm/book3s_xive.h | |||
@@ -120,6 +120,8 @@ struct kvmppc_xive { | |||
120 | u32 q_order; | 120 | u32 q_order; |
121 | u32 q_page_order; | 121 | u32 q_page_order; |
122 | 122 | ||
123 | /* Flags */ | ||
124 | u8 single_escalation; | ||
123 | }; | 125 | }; |
124 | 126 | ||
125 | #define KVMPPC_XIVE_Q_COUNT 8 | 127 | #define KVMPPC_XIVE_Q_COUNT 8 |
@@ -201,25 +203,20 @@ static inline struct kvmppc_xive_src_block *kvmppc_xive_find_source(struct kvmpp | |||
201 | * is as follow. | 203 | * is as follow. |
202 | * | 204 | * |
203 | * Guest request for 0...6 are honored. Guest request for anything | 205 | * Guest request for 0...6 are honored. Guest request for anything |
204 | * higher results in a priority of 7 being applied. | 206 | * higher results in a priority of 6 being applied. |
205 | * | ||
206 | * However, when XIRR is returned via H_XIRR, 7 is translated to 0xb | ||
207 | * in order to match AIX expectations | ||
208 | * | 207 | * |
209 | * Similar mapping is done for CPPR values | 208 | * Similar mapping is done for CPPR values |
210 | */ | 209 | */ |
211 | static inline u8 xive_prio_from_guest(u8 prio) | 210 | static inline u8 xive_prio_from_guest(u8 prio) |
212 | { | 211 | { |
213 | if (prio == 0xff || prio < 8) | 212 | if (prio == 0xff || prio < 6) |
214 | return prio; | 213 | return prio; |
215 | return 7; | 214 | return 6; |
216 | } | 215 | } |
217 | 216 | ||
218 | static inline u8 xive_prio_to_guest(u8 prio) | 217 | static inline u8 xive_prio_to_guest(u8 prio) |
219 | { | 218 | { |
220 | if (prio == 0xff || prio < 7) | 219 | return prio; |
221 | return prio; | ||
222 | return 0xb; | ||
223 | } | 220 | } |
224 | 221 | ||
225 | static inline u32 __xive_read_eq(__be32 *qpage, u32 msk, u32 *idx, u32 *toggle) | 222 | static inline u32 __xive_read_eq(__be32 *qpage, u32 msk, u32 *idx, u32 *toggle) |
diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c index ebc244b08d67..d22aeb0b69e1 100644 --- a/arch/powerpc/sysdev/xive/native.c +++ b/arch/powerpc/sysdev/xive/native.c | |||
@@ -42,6 +42,7 @@ static u32 xive_provision_chip_count; | |||
42 | static u32 xive_queue_shift; | 42 | static u32 xive_queue_shift; |
43 | static u32 xive_pool_vps = XIVE_INVALID_VP; | 43 | static u32 xive_pool_vps = XIVE_INVALID_VP; |
44 | static struct kmem_cache *xive_provision_cache; | 44 | static struct kmem_cache *xive_provision_cache; |
45 | static bool xive_has_single_esc; | ||
45 | 46 | ||
46 | int xive_native_populate_irq_data(u32 hw_irq, struct xive_irq_data *data) | 47 | int xive_native_populate_irq_data(u32 hw_irq, struct xive_irq_data *data) |
47 | { | 48 | { |
@@ -571,6 +572,10 @@ bool __init xive_native_init(void) | |||
571 | break; | 572 | break; |
572 | } | 573 | } |
573 | 574 | ||
575 | /* Do we support single escalation */ | ||
576 | if (of_get_property(np, "single-escalation-support", NULL) != NULL) | ||
577 | xive_has_single_esc = true; | ||
578 | |||
574 | /* Configure Thread Management areas for KVM */ | 579 | /* Configure Thread Management areas for KVM */ |
575 | for_each_possible_cpu(cpu) | 580 | for_each_possible_cpu(cpu) |
576 | kvmppc_set_xive_tima(cpu, r.start, tima); | 581 | kvmppc_set_xive_tima(cpu, r.start, tima); |
@@ -667,12 +672,15 @@ void xive_native_free_vp_block(u32 vp_base) | |||
667 | } | 672 | } |
668 | EXPORT_SYMBOL_GPL(xive_native_free_vp_block); | 673 | EXPORT_SYMBOL_GPL(xive_native_free_vp_block); |
669 | 674 | ||
670 | int xive_native_enable_vp(u32 vp_id) | 675 | int xive_native_enable_vp(u32 vp_id, bool single_escalation) |
671 | { | 676 | { |
672 | s64 rc; | 677 | s64 rc; |
678 | u64 flags = OPAL_XIVE_VP_ENABLED; | ||
673 | 679 | ||
680 | if (single_escalation) | ||
681 | flags |= OPAL_XIVE_VP_SINGLE_ESCALATION; | ||
674 | for (;;) { | 682 | for (;;) { |
675 | rc = opal_xive_set_vp_info(vp_id, OPAL_XIVE_VP_ENABLED, 0); | 683 | rc = opal_xive_set_vp_info(vp_id, flags, 0); |
676 | if (rc != OPAL_BUSY) | 684 | if (rc != OPAL_BUSY) |
677 | break; | 685 | break; |
678 | msleep(1); | 686 | msleep(1); |
@@ -710,3 +718,9 @@ int xive_native_get_vp_info(u32 vp_id, u32 *out_cam_id, u32 *out_chip_id) | |||
710 | return 0; | 718 | return 0; |
711 | } | 719 | } |
712 | EXPORT_SYMBOL_GPL(xive_native_get_vp_info); | 720 | EXPORT_SYMBOL_GPL(xive_native_get_vp_info); |
721 | |||
722 | bool xive_native_has_single_escalation(void) | ||
723 | { | ||
724 | return xive_has_single_esc; | ||
725 | } | ||
726 | EXPORT_SYMBOL_GPL(xive_native_has_single_escalation); | ||